Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt49
-rw-r--r--GNUmakefile1
-rw-r--r--SConstruct11
-rw-r--r--build_files/buildbot/config/user-config-i686.py8
-rw-r--r--build_files/buildbot/config/user-config-player-i686.py8
-rw-r--r--build_files/buildbot/config/user-config-player-x86_64.py8
-rw-r--r--build_files/buildbot/config/user-config-x86_64.py8
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/scons/config/linux-config.py2
-rw-r--r--build_files/scons/config/win32-mingw-config.py4
-rw-r--r--build_files/scons/config/win64-mingw-config.py2
-rw-r--r--build_files/scons/tools/Blender.py2
-rw-r--r--build_files/scons/tools/btools.py2
-rw-r--r--doc/python_api/sphinx_doc_gen.py11
-rw-r--r--extern/libmv/CMakeLists.txt13
-rw-r--r--extern/libmv/libmv-capi.cpp4
-rw-r--r--extern/libmv/libmv-capi.h8
-rw-r--r--extern/libmv/libmv/multiview/euclidean_resection.cc31
-rw-r--r--extern/libmv/libmv/multiview/euclidean_resection.h3
-rw-r--r--extern/libmv/libmv/multiview/fundamental.cc4
-rw-r--r--extern/libmv/libmv/multiview/homography.cc2
-rw-r--r--extern/libmv/libmv/numeric/levenberg_marquardt.h10
-rw-r--r--extern/libmv/libmv/simple_pipeline/detect.cc2
-rw-r--r--extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc1
-rw-r--r--extern/libmv/libmv/simple_pipeline/intersect.cc1
-rw-r--r--extern/libmv/libmv/simple_pipeline/pipeline.cc4
-rw-r--r--extern/libmv/libmv/simple_pipeline/resect.cc5
-rw-r--r--extern/libmv/libmv/tracking/track_region.cc213
-rw-r--r--extern/libmv/libmv/tracking/track_region.h6
-rw-r--r--extern/libmv/third_party/ceres/CMakeLists.txt48
-rw-r--r--extern/libmv/third_party/ceres/ChangeLog608
-rw-r--r--extern/libmv/third_party/ceres/SConscript6
-rwxr-xr-xextern/libmv/third_party/ceres/bundle.sh55
-rw-r--r--extern/libmv/third_party/ceres/files.txt22
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h4
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/cost_function.h2
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/crs_matrix.h65
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/fpclassify.h88
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h3
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/macros.h31
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h71
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/port.h6
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/iteration_callback.h36
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/jet.h163
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/loss_function.h79
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h6
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/problem.h6
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/rotation.h62
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/solver.h229
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/types.h68
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/array_utils.cc (renamed from extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h)54
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/array_utils.h65
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc16
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h16
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc6
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h8
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc8
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h8
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_structure.cc2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc8
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/collections_port.h50
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc18
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc28
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h28
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc20
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/corrector.cc2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc130
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cxsparse.h90
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc86
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.h95
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc6
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc14
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/detect_structure.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc691
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h163
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/evaluator.cc82
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/evaluator.h31
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/file.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py186
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc10
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/graph.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc23
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h10
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc11
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc574
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc144
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h86
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc101
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc30
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_solver.h26
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/loss_function.cc64
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/minimizer.h68
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/mutex.h98
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/parameter_block.h19
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc184
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h65
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem_impl.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/program.cc77
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/program.h21
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h84
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/random.h29
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/residual_block.cc7
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc41
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc159
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h38
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h38
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc18
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver.cc52
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc296
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver_impl.h14
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc166
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h36
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/split.cc1
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/split.h21
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc1
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/stringprintf.h14
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc157
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/suitesparse.h82
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc10
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc550
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h67
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc27
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h148
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/types.cc35
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility.cc4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc36
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h14
-rw-r--r--[-rwxr-xr-x]extern/libmv/third_party/ceres/mkfiles.sh0
-rw-r--r--extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch12
-rw-r--r--extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch50
-rw-r--r--extern/libmv/third_party/ceres/patches/msvc_isfinite.patch15
-rw-r--r--extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch199
-rw-r--r--extern/libmv/third_party/ceres/patches/series4
-rw-r--r--intern/audaspace/FX/AUD_IIRFilterReader.cpp2
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.cpp4
-rw-r--r--intern/audaspace/Python/AUD_PyAPI.cpp132
-rw-r--r--intern/audaspace/Python/AUD_PyAPI.h8
-rw-r--r--intern/audaspace/intern/AUD_IFactory.h2
-rw-r--r--intern/audaspace/intern/AUD_IReader.h2
-rw-r--r--intern/audaspace/intern/AUD_IWriter.h2
-rw-r--r--intern/audaspace/intern/AUD_PyInit.h2
-rw-r--r--intern/cycles/CMakeLists.txt1
-rw-r--r--intern/cycles/app/CMakeLists.txt3
-rw-r--r--intern/cycles/blender/addon/__init__.py2
-rw-r--r--intern/cycles/blender/addon/properties.py10
-rw-r--r--intern/cycles/blender/addon/ui.py9
-rw-r--r--intern/cycles/blender/blender_python.cpp2
-rw-r--r--intern/cycles/blender/blender_session.cpp6
-rw-r--r--intern/cycles/blender/blender_shader.cpp4
-rw-r--r--intern/cycles/blender/blender_sync.cpp4
-rw-r--r--intern/cycles/blender/blender_util.h4
-rw-r--r--intern/cycles/bvh/CMakeLists.txt3
-rw-r--r--intern/cycles/device/CMakeLists.txt3
-rw-r--r--intern/cycles/device/device.h1
-rw-r--r--intern/cycles/device/device_cpu.cpp5
-rw-r--r--intern/cycles/device/device_cuda.cpp5
-rw-r--r--intern/cycles/device/device_multi.cpp8
-rw-r--r--intern/cycles/device/device_opencl.cpp5
-rw-r--r--intern/cycles/kernel/CMakeLists.txt3
-rw-r--r--intern/cycles/kernel/kernel_camera.h24
-rw-r--r--intern/cycles/kernel/kernel_montecarlo.h17
-rw-r--r--intern/cycles/kernel/osl/CMakeLists.txt3
-rw-r--r--intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp41
-rw-r--r--intern/cycles/kernel/osl/nodes/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/osl/nodes/node_gradient_texture.osl15
-rw-r--r--intern/cycles/kernel/osl/nodes/node_magic_texture.osl63
-rw-r--r--intern/cycles/kernel/osl/nodes/node_mix.osl4
-rw-r--r--intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl24
-rw-r--r--intern/cycles/kernel/osl/nodes/node_rgb_ramp.osl44
-rw-r--r--intern/cycles/kernel/osl/nodes/node_texture.h2
-rw-r--r--intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl43
-rw-r--r--intern/cycles/kernel/osl/nodes/oslutil.h3
-rw-r--r--intern/cycles/kernel/svm/bsdf.h6
-rw-r--r--intern/cycles/kernel/svm/bsdf_diffuse.h5
-rw-r--r--intern/cycles/kernel/svm/bsdf_microfacet.h6
-rw-r--r--intern/cycles/kernel/svm/bsdf_ward.h9
-rw-r--r--intern/cycles/kernel/svm/bsdf_westin.h4
-rw-r--r--intern/cycles/kernel/svm/svm_hsv.h4
-rw-r--r--intern/cycles/kernel/svm/svm_noise.h2
-rw-r--r--intern/cycles/render/CMakeLists.txt4
-rw-r--r--intern/cycles/render/camera.cpp2
-rw-r--r--intern/cycles/render/integrator.cpp2
-rw-r--r--intern/cycles/render/nodes.cpp15
-rw-r--r--intern/cycles/render/osl.cpp156
-rw-r--r--intern/cycles/render/osl.h13
-rw-r--r--intern/cycles/render/session.cpp27
-rw-r--r--intern/cycles/render/session.h9
-rw-r--r--intern/cycles/render/tile.cpp30
-rw-r--r--intern/cycles/render/tile.h8
-rw-r--r--intern/cycles/subd/CMakeLists.txt3
-rw-r--r--intern/cycles/util/CMakeLists.txt3
-rw-r--r--intern/cycles/util/util_math.h4
-rw-r--r--intern/cycles/util/util_task.cpp33
-rw-r--r--intern/dualcon/intern/Projections.cpp4
-rw-r--r--intern/dualcon/intern/dualcon_c_api.cpp2
-rw-r--r--intern/dualcon/intern/octree.cpp12
-rw-r--r--intern/ghost/GHOST_C-api.h3
-rw-r--r--intern/ghost/GHOST_IWindow.h2
-rw-r--r--intern/ghost/GHOST_Rect.h3
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp14
-rw-r--r--intern/ghost/intern/GHOST_EventManager.cpp12
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm60
-rw-r--r--intern/ghost/intern/GHOST_SystemPaths.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp17
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h6
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.cpp6
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp10
-rw-r--r--intern/ghost/intern/GHOST_Window.h8
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm6
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.cpp4
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp4
-rw-r--r--intern/ghost/test/multitest/EventToBuf.c3
-rw-r--r--intern/guardedalloc/test/simpletest/memtest.c9
-rw-r--r--intern/iksolver/intern/IK_QJacobianSolver.h4
-rw-r--r--intern/iksolver/intern/IK_QSegment.h4
-rw-r--r--intern/iksolver/intern/IK_QTask.h4
-rw-r--r--intern/iksolver/intern/IK_Solver.cpp6
-rw-r--r--intern/iksolver/intern/MT_ExpMap.h4
-rw-r--r--intern/iksolver/intern/TNT/cmat.h2
-rw-r--r--intern/iksolver/intern/TNT/vec.h2
-rw-r--r--intern/itasc/kdl/utilities/utility_io.cpp6
-rw-r--r--intern/memutil/MEM_CacheLimiter.h69
-rw-r--r--intern/memutil/MEM_SmartPtr.h6
-rw-r--r--intern/mikktspace/mikktspace.c3
-rw-r--r--intern/opencolorio/ocio_capi.cpp27
-rw-r--r--intern/opencolorio/ocio_capi.h2
-rw-r--r--intern/opencolorio/ocio_capi_stub.cpp10
-rw-r--r--intern/raskter/CMakeLists.txt3
-rw-r--r--intern/raskter/raskter.c1884
-rw-r--r--intern/raskter/raskter.h70
-rw-r--r--intern/raskter/raskter_kdtree.c836
-rw-r--r--intern/raskter/raskter_kdtree.h129
-rw-r--r--intern/raskter/raskter_mt.c290
-rw-r--r--intern/smoke/intern/smoke_API.cpp5
-rw-r--r--intern/string/STR_String.h24
-rw-r--r--intern/string/intern/STR_String.cpp1
-rwxr-xr-xrelease/bin/blender-softwaregl25
-rw-r--r--release/datafiles/startup.blendbin400648 -> 408624 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/brown00.pngbin0 -> 22195 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/gray00.pngbin0 -> 18513 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/gray01.pngbin0 -> 9915 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/gray02.pngbin0 -> 7197 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/gray03.pngbin0 -> 16109 bytes
-rwxr-xr-xrelease/scripts/freestyle/style_modules/ChainingIterators.py731
-rwxr-xr-xrelease/scripts/freestyle/style_modules/Functions0D.py92
-rwxr-xr-xrelease/scripts/freestyle/style_modules/Functions1D.py45
-rwxr-xr-xrelease/scripts/freestyle/style_modules/PredicatesB1D.py70
-rwxr-xr-xrelease/scripts/freestyle/style_modules/PredicatesU0D.py103
-rwxr-xr-xrelease/scripts/freestyle/style_modules/PredicatesU1D.py381
-rwxr-xr-xrelease/scripts/freestyle/style_modules/anisotropic_diffusion.py74
-rwxr-xr-xrelease/scripts/freestyle/style_modules/apriori_and_causal_density.py45
-rwxr-xr-xrelease/scripts/freestyle/style_modules/apriori_density.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/backbone_stretcher.py36
-rwxr-xr-xrelease/scripts/freestyle/style_modules/blueprint_circles.py46
-rwxr-xr-xrelease/scripts/freestyle/style_modules/blueprint_ellipses.py46
-rwxr-xr-xrelease/scripts/freestyle/style_modules/blueprint_squares.py45
-rwxr-xr-xrelease/scripts/freestyle/style_modules/cartoon.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/contour.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/curvature2d.py60
-rwxr-xr-xrelease/scripts/freestyle/style_modules/external_contour.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/external_contour_sketchy.py48
-rwxr-xr-xrelease/scripts/freestyle/style_modules/external_contour_smooth.py44
-rwxr-xr-xrelease/scripts/freestyle/style_modules/extra-lines.sml3
-rw-r--r--release/scripts/freestyle/style_modules/freestyle_init.py2
-rwxr-xr-xrelease/scripts/freestyle/style_modules/haloing.py50
-rwxr-xr-xrelease/scripts/freestyle/style_modules/ignore_small_occlusions.py41
-rwxr-xr-xrelease/scripts/freestyle/style_modules/invisible_lines.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/japanese_bigbrush.py60
-rwxr-xr-xrelease/scripts/freestyle/style_modules/logical_operators.py36
-rwxr-xr-xrelease/scripts/freestyle/style_modules/long_anisotropically_dense.py81
-rwxr-xr-xrelease/scripts/freestyle/style_modules/multiple_parameterization.py51
-rwxr-xr-xrelease/scripts/freestyle/style_modules/nature.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/near_lines.py44
-rwxr-xr-xrelease/scripts/freestyle/style_modules/occluded_by_specific_object.py45
-rw-r--r--release/scripts/freestyle/style_modules/parameter_editor.py1273
-rwxr-xr-xrelease/scripts/freestyle/style_modules/polygonalize.py40
-rwxr-xr-xrelease/scripts/freestyle/style_modules/qi0.py41
-rwxr-xr-xrelease/scripts/freestyle/style_modules/qi0_not_external_contour.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/qi1.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/qi2.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/sequentialsplit_sketchy.py68
-rwxr-xr-xrelease/scripts/freestyle/style_modules/shaders.py1343
-rwxr-xr-xrelease/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py48
-rwxr-xr-xrelease/scripts/freestyle/style_modules/sketchy_topology_broken.py89
-rwxr-xr-xrelease/scripts/freestyle/style_modules/sketchy_topology_preserved.py49
-rwxr-xr-xrelease/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py41
-rwxr-xr-xrelease/scripts/freestyle/style_modules/split_at_tvertices.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/stroke_texture.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/suggestive.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py62
-rwxr-xr-xrelease/scripts/freestyle/style_modules/tipremover.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/tvertex_remover.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/uniformpruning_zsort.py40
-rw-r--r--release/scripts/startup/bl_operators/__init__.py1
-rw-r--r--release/scripts/startup/bl_operators/freestyle.py133
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py572
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py49
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py15
-rw-r--r--release/text/readme.html2
-rw-r--r--release/windows/contrib/vfapi/vfapi-plugin.c18
-rw-r--r--source/blender/CMakeLists.txt2
-rw-r--r--source/blender/SConscript1
-rw-r--r--source/blender/blenfont/intern/blf_font.c10
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c2
-rw-r--r--source/blender/blenkernel/BKE_blender.h4
-rw-r--r--source/blender/blenkernel/BKE_colortools.h2
-rw-r--r--source/blender/blenkernel/BKE_curve.h2
-rw-r--r--source/blender/blenkernel/BKE_group.h4
-rw-r--r--source/blender/blenkernel/BKE_key.h50
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h74
-rw-r--r--source/blender/blenkernel/BKE_main.h1
-rw-r--r--source/blender/blenkernel/BKE_object.h1
-rw-r--r--source/blender/blenkernel/BKE_property.h27
-rw-r--r--source/blender/blenkernel/BKE_sca.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt6
-rw-r--r--source/blender/blenkernel/SConscript2
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c6
-rw-r--r--source/blender/blenkernel/intern/action.c472
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c24
-rw-r--r--source/blender/blenkernel/intern/collision.c2
-rw-r--r--source/blender/blenkernel/intern/colortools.c6
-rw-r--r--source/blender/blenkernel/intern/constraint.c55
-rw-r--r--source/blender/blenkernel/intern/curve.c27
-rw-r--r--source/blender/blenkernel/intern/customdata.c28
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c4
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c2
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c4
-rw-r--r--source/blender/blenkernel/intern/group.c70
-rw-r--r--source/blender/blenkernel/intern/icons.c4
-rw-r--r--source/blender/blenkernel/intern/idcode.c1
-rw-r--r--source/blender/blenkernel/intern/idprop.c4
-rw-r--r--source/blender/blenkernel/intern/image.c37
-rw-r--r--source/blender/blenkernel/intern/implicit.c4
-rw-r--r--source/blender/blenkernel/intern/key.c95
-rw-r--r--source/blender/blenkernel/intern/library.c15
-rw-r--r--source/blender/blenkernel/intern/linestyle.c1005
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c4
-rw-r--r--source/blender/blenkernel/intern/material.c3
-rw-r--r--source/blender/blenkernel/intern/mball.c18
-rw-r--r--source/blender/blenkernel/intern/mesh.c7
-rw-r--r--source/blender/blenkernel/intern/modifier.c2
-rw-r--r--source/blender/blenkernel/intern/object.c169
-rw-r--r--source/blender/blenkernel/intern/particle.c4
-rw-r--r--source/blender/blenkernel/intern/property.c65
-rw-r--r--source/blender/blenkernel/intern/sca.c25
-rw-r--r--source/blender/blenkernel/intern/scene.c16
-rw-r--r--source/blender/blenkernel/intern/softbody.c4
-rw-r--r--source/blender/blenkernel/intern/sound.c1
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c16
-rw-r--r--source/blender/blenkernel/intern/text.c2
-rw-r--r--source/blender/blenkernel/intern/tracking.c34
-rw-r--r--source/blender/blenlib/BLI_dynstr.h7
-rw-r--r--source/blender/blenlib/BLI_endian_switch.h38
-rw-r--r--source/blender/blenlib/BLI_fileops_types.h2
-rw-r--r--source/blender/blenlib/BLI_math_base.h4
-rw-r--r--source/blender/blenlib/BLI_math_color.h2
-rw-r--r--source/blender/blenlib/BLI_math_vector.h1
-rw-r--r--source/blender/blenlib/BLI_rect.h28
-rw-r--r--source/blender/blenlib/BLI_string.h6
-rw-r--r--source/blender/blenlib/CMakeLists.txt1
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c2
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c11
-rw-r--r--source/blender/blenlib/intern/boxpack2d.c16
-rw-r--r--source/blender/blenlib/intern/bpath.c8
-rw-r--r--source/blender/blenlib/intern/fileops.c22
-rw-r--r--source/blender/blenlib/intern/freetypefont.c3
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c15
-rw-r--r--source/blender/blenlib/intern/math_matrix.c18
-rw-r--r--source/blender/blenlib/intern/math_rotation.c4
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c9
-rw-r--r--source/blender/blenlib/intern/noise.c3
-rw-r--r--source/blender/blenlib/intern/path_util.c2
-rw-r--r--source/blender/blenlib/intern/pbvh.c4
-rw-r--r--source/blender/blenlib/intern/rct.c37
-rw-r--r--source/blender/blenlib/intern/scanfill.c4
-rw-r--r--source/blender/blenlib/intern/storage.c2
-rw-r--r--source/blender/blenlib/intern/string_cursor_utf8.c2
-rw-r--r--source/blender/blenlib/intern/uvproject.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c315
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c6
-rw-r--r--source/blender/blenloader/intern/writefile.c215
-rw-r--r--source/blender/bmesh/bmesh_class.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c12
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h6
-rw-r--r--source/blender/bmesh/operators/bmo_create.c2
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c2
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c146
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c4
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c14
-rw-r--r--source/blender/collada/ImageExporter.cpp2
-rw-r--r--source/blender/collada/collada.cpp1
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp2
-rw-r--r--source/blender/compositor/intern/COM_NodeBase.h2
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h2
-rw-r--r--source/blender/compositor/intern/COM_OutputSocket.h2
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp3
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp6
-rw-r--r--source/blender/compositor/operations/COM_DespeckleOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp2
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c151
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c5
-rw-r--r--source/blender/editors/animation/anim_deps.c2
-rw-r--r--source/blender/editors/animation/anim_filter.c130
-rw-r--r--source/blender/editors/animation/anim_markers.c4
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c7
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c30
-rw-r--r--source/blender/editors/armature/poseobject.c104
-rw-r--r--source/blender/editors/curve/editcurve.c15
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c24
-rw-r--r--source/blender/editors/include/ED_anim_api.h2
-rw-r--r--source/blender/editors/include/ED_armature.h1
-rw-r--r--source/blender/editors/include/ED_curve.h2
-rw-r--r--source/blender/editors/include/ED_mball.h2
-rw-r--r--source/blender/editors/include/ED_mesh.h2
-rw-r--r--source/blender/editors/include/ED_screen.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h131
-rw-r--r--source/blender/editors/include/UI_interface.h13
-rw-r--r--source/blender/editors/include/UI_resources.h3
-rw-r--r--source/blender/editors/include/UI_view2d.h18
-rw-r--r--source/blender/editors/interface/interface.c64
-rw-r--r--source/blender/editors/interface/interface_draw.c104
-rw-r--r--source/blender/editors/interface/interface_handlers.c375
-rw-r--r--source/blender/editors/interface/interface_intern.h16
-rw-r--r--source/blender/editors/interface/interface_layout.c6
-rw-r--r--source/blender/editors/interface/interface_panel.c24
-rw-r--r--source/blender/editors/interface/interface_regions.c67
-rw-r--r--source/blender/editors/interface/interface_style.c12
-rw-r--r--source/blender/editors/interface/interface_templates.c124
-rw-r--r--source/blender/editors/interface/interface_widgets.c280
-rw-r--r--source/blender/editors/interface/resources.c19
-rw-r--r--source/blender/editors/interface/view2d.c141
-rw-r--r--source/blender/editors/interface/view2d_ops.c82
-rw-r--r--source/blender/editors/io/io_collada.c54
-rw-r--r--source/blender/editors/mask/mask_add.c4
-rw-r--r--source/blender/editors/mask/mask_draw.c8
-rw-r--r--source/blender/editors/mesh/editface.c4
-rw-r--r--source/blender/editors/mesh/editmesh_add.c65
-rw-r--r--source/blender/editors/mesh/editmesh_bvh.c4
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c16
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c4
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c12
-rw-r--r--source/blender/editors/mesh/editmesh_select.c21
-rw-r--r--source/blender/editors/mesh/editmesh_slide.c8
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c145
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c15
-rw-r--r--source/blender/editors/mesh/mesh_data.c183
-rw-r--r--source/blender/editors/mesh/mesh_intern.h8
-rw-r--r--source/blender/editors/mesh/mesh_ops.c7
-rw-r--r--source/blender/editors/mesh/meshtools.c96
-rw-r--r--source/blender/editors/metaball/mball_edit.c3
-rw-r--r--source/blender/editors/object/object_add.c6
-rw-r--r--source/blender/editors/object/object_bake.c3
-rw-r--r--source/blender/editors/object/object_edit.c20
-rw-r--r--source/blender/editors/object/object_lattice.c4
-rw-r--r--source/blender/editors/object/object_modifier.c19
-rw-r--r--source/blender/editors/object/object_select.c2
-rw-r--r--source/blender/editors/object/object_shapekey.c22
-rw-r--r--source/blender/editors/physics/particle_edit.c14
-rw-r--r--source/blender/editors/render/CMakeLists.txt1
-rw-r--r--source/blender/editors/render/SConscript2
-rw-r--r--source/blender/editors/render/render_intern.h16
-rw-r--r--source/blender/editors/render/render_internal.c12
-rw-r--r--source/blender/editors/render/render_ops.c17
-rw-r--r--source/blender/editors/render/render_preview.c8
-rw-r--r--source/blender/editors/render/render_shading.c615
-rw-r--r--source/blender/editors/screen/area.c54
-rw-r--r--source/blender/editors/screen/glutil.c20
-rw-r--r--source/blender/editors/screen/screen_edit.c6
-rw-r--r--source/blender/editors/screen/screen_ops.c61
-rw-r--r--source/blender/editors/screen/screendump.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c109
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c19
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c6
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_action/action_edit.c4
-rw-r--r--source/blender/editors/space_action/action_select.c5
-rw-r--r--source/blender/editors/space_buttons/buttons_header.c2
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c4
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c2
-rw-r--r--source/blender/editors/space_clip/clip_draw.c8
-rw-r--r--source/blender/editors/space_clip/clip_editor.c8
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c6
-rw-r--r--source/blender/editors/space_clip/clip_ops.c8
-rw-r--r--source/blender/editors/space_clip/space_clip.c4
-rw-r--r--source/blender/editors/space_console/space_console.c2
-rw-r--r--source/blender/editors/space_file/file_intern.h1
-rw-r--r--source/blender/editors/space_file/file_ops.c41
-rw-r--r--source/blender/editors/space_file/file_panels.c19
-rw-r--r--source/blender/editors/space_file/filelist.c3
-rw-r--r--source/blender/editors/space_file/filesel.c8
-rw-r--r--source/blender/editors/space_file/fsmenu.c189
-rw-r--r--source/blender/editors/space_file/fsmenu.h8
-rw-r--r--source/blender/editors/space_file/space_file.c3
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c6
-rw-r--r--source/blender/editors/space_graph/graph_draw.c4
-rw-r--r--source/blender/editors/space_graph/graph_edit.c4
-rw-r--r--source/blender/editors/space_graph/graph_select.c2
-rw-r--r--source/blender/editors/space_image/image_buttons.c28
-rw-r--r--source/blender/editors/space_image/image_draw.c4
-rw-r--r--source/blender/editors/space_image/image_edit.c8
-rw-r--r--source/blender/editors/space_image/image_ops.c10
-rw-r--r--source/blender/editors/space_image/space_image.c8
-rw-r--r--source/blender/editors/space_info/info_stats.c2
-rw-r--r--source/blender/editors/space_logic/logic_buttons.c8
-rw-r--r--source/blender/editors/space_logic/logic_window.c2658
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c4
-rw-r--r--source/blender/editors/space_nla/nla_channels.c1
-rw-r--r--source/blender/editors/space_nla/nla_edit.c7
-rw-r--r--source/blender/editors/space_nla/nla_select.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c79
-rw-r--r--source/blender/editors/space_node/node_draw.c20
-rw-r--r--source/blender/editors/space_node/node_edit.c4
-rw-r--r--source/blender/editors/space_node/node_select.c4
-rw-r--r--source/blender/editors/space_node/node_templates.c2
-rw-r--r--source/blender/editors/space_node/node_view.c15
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c14
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c20
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c45
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c24
-rw-r--r--source/blender/editors/space_text/text_draw.c2
-rw-r--r--source/blender/editors/space_text/text_header.c5
-rw-r--r--source/blender/editors/space_text/text_ops.c13
-rw-r--r--source/blender/editors/space_text/text_python.c4
-rw-r--r--source/blender/editors/space_time/time_ops.c2
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c8
-rw-r--r--source/blender/editors/space_view3d/drawobject.c72
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c79
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c68
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c25
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c37
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c180
-rw-r--r--source/blender/editors/transform/transform.c118
-rw-r--r--source/blender/editors/transform/transform_conversions.c25
-rw-r--r--source/blender/editors/transform/transform_snap.c14
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c2
-rw-r--r--source/blender/freestyle/CMakeLists.txt45
-rw-r--r--source/blender/freestyle/FRS_freestyle.h86
-rw-r--r--source/blender/freestyle/FRS_freestyle_config.h17
-rw-r--r--source/blender/freestyle/SConscript82
-rwxr-xr-xsource/blender/freestyle/intern/application/AppCanvas.cpp198
-rwxr-xr-xsource/blender/freestyle/intern/application/AppCanvas.h71
-rwxr-xr-xsource/blender/freestyle/intern/application/AppConfig.cpp92
-rwxr-xr-xsource/blender/freestyle/intern/application/AppConfig.h105
-rw-r--r--source/blender/freestyle/intern/application/AppView.cpp179
-rw-r--r--source/blender/freestyle/intern/application/AppView.h229
-rwxr-xr-xsource/blender/freestyle/intern/application/Controller.cpp979
-rwxr-xr-xsource/blender/freestyle/intern/application/Controller.h253
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp666
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h104
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp421
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h45
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h39
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp71
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h23
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp740
-rwxr-xr-xsource/blender/freestyle/intern/geometry/BBox.h141
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Bezier.cpp118
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Bezier.h73
-rwxr-xr-xsource/blender/freestyle/intern/geometry/FastGrid.cpp62
-rwxr-xr-xsource/blender/freestyle/intern/geometry/FastGrid.h85
-rwxr-xr-xsource/blender/freestyle/intern/geometry/FitCurve.cpp603
-rwxr-xr-xsource/blender/freestyle/intern/geometry/FitCurve.h101
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Geom.h78
-rwxr-xr-xsource/blender/freestyle/intern/geometry/GeomCleaner.cpp240
-rwxr-xr-xsource/blender/freestyle/intern/geometry/GeomCleaner.h219
-rwxr-xr-xsource/blender/freestyle/intern/geometry/GeomUtils.cpp753
-rwxr-xr-xsource/blender/freestyle/intern/geometry/GeomUtils.h310
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Grid.cpp392
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Grid.h392
-rw-r--r--source/blender/freestyle/intern/geometry/GridHelpers.cpp56
-rw-r--r--source/blender/freestyle/intern/geometry/GridHelpers.h199
-rwxr-xr-xsource/blender/freestyle/intern/geometry/HashGrid.cpp41
-rwxr-xr-xsource/blender/freestyle/intern/geometry/HashGrid.h109
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Noise.cpp264
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Noise.h77
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Polygon.h214
-rwxr-xr-xsource/blender/freestyle/intern/geometry/SweepLine.h325
-rwxr-xr-xsource/blender/freestyle/intern/geometry/VecMat.h899
-rwxr-xr-xsource/blender/freestyle/intern/geometry/matrix_util.cpp265
-rwxr-xr-xsource/blender/freestyle/intern/geometry/matrix_util.h69
-rwxr-xr-xsource/blender/freestyle/intern/geometry/normal_cycle.cpp87
-rwxr-xr-xsource/blender/freestyle/intern/geometry/normal_cycle.h110
-rwxr-xr-xsource/blender/freestyle/intern/image/GaussianFilter.cpp96
-rwxr-xr-xsource/blender/freestyle/intern/image/GaussianFilter.h146
-rwxr-xr-xsource/blender/freestyle/intern/image/Image.h389
-rwxr-xr-xsource/blender/freestyle/intern/image/ImagePyramid.cpp166
-rwxr-xr-xsource/blender/freestyle/intern/image/ImagePyramid.h92
-rw-r--r--source/blender/freestyle/intern/python/BPy_BBox.cpp100
-rw-r--r--source/blender/freestyle/intern/python/BPy_BBox.h38
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp166
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h36
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp193
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp262
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.h18
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.cpp609
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.h147
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.cpp509
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.h22
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp599
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.h37
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.cpp280
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.h36
-rw-r--r--source/blender/freestyle/intern/python/BPy_Id.cpp222
-rw-r--r--source/blender/freestyle/intern/python/BPy_Id.h36
-rw-r--r--source/blender/freestyle/intern/python/BPy_IntegrationType.cpp250
-rw-r--r--source/blender/freestyle/intern/python/BPy_IntegrationType.h28
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface0D.cpp354
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface0D.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface1D.cpp337
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface1D.h36
-rw-r--r--source/blender/freestyle/intern/python/BPy_Iterator.cpp229
-rw-r--r--source/blender/freestyle/intern/python/BPy_Iterator.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_MediumType.cpp99
-rw-r--r--source/blender/freestyle/intern/python/BPy_MediumType.h42
-rw-r--r--source/blender/freestyle/intern/python/BPy_Nature.cpp312
-rw-r--r--source/blender/freestyle/intern/python/BPy_Nature.h33
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.cpp682
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.cpp330
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp658
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeAttribute.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeShader.cpp297
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeShader.h40
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp126
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp117
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp184
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp236
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewMap.cpp195
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewMap.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.cpp353
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.h35
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp79
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp81
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp80
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp80
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/Director.cpp304
-rw-r--r--source/blender/freestyle/intern/python/Director.h49
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp278
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp338
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h32
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp195
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp400
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp153
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp249
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp416
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp202
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp517
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp463
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h32
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp171
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp373
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp240
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h31
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp167
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h32
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp205
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h35
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp131
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp236
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp171
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h32
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp151
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp181
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp197
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp266
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp140
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h34
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp91
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp93
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp113
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp92
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp98
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp96
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp90
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp96
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp98
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp106
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp96
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp97
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp90
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp108
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp102
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp117
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp106
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp92
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp103
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp91
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp90
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp84
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h31
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp215
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp159
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp189
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp158
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp160
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp159
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp165
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp159
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp172
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp165
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp96
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp89
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp89
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp89
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp89
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp96
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp91
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp93
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp91
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp95
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp289
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp210
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp203
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp210
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp216
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp210
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp235
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp222
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp99
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp96
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp109
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp110
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp114
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp95
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp107
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp107
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp95
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp93
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp101
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp99
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp99
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp86
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp78
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp78
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp79
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp95
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp89
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp89
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp81
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp78
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp78
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp88
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h29
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/DrawingStyle.h82
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/FrsMaterial.h304
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp336
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/IndexedFaceSet.h233
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/LineRep.cpp58
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/LineRep.h130
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/Node.h97
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeCamera.cpp120
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeCamera.h192
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp34
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h70
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeGroup.cpp122
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeGroup.h84
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeLight.cpp80
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeLight.h86
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeShape.cpp51
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeShape.h89
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeTransform.cpp166
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeTransform.h107
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp31
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/OrientedLineRep.h67
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/Rep.cpp1
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/Rep.h133
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp86
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h105
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/SceneVisitor.cpp1
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/SceneVisitor.h98
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/TriangleRep.cpp59
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/TriangleRep.h106
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/VertexRep.cpp29
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/VertexRep.h87
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp92
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedFunctions0D.h209
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp110
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedFunctions1D.h288
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedPredicates1D.h84
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp435
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h222
-rwxr-xr-xsource/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp1170
-rwxr-xr-xsource/blender/freestyle/intern/stroke/BasicStrokeShaders.h890
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Canvas.cpp455
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Canvas.h196
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Chain.cpp151
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Chain.h87
-rwxr-xr-xsource/blender/freestyle/intern/stroke/ChainingIterators.cpp170
-rwxr-xr-xsource/blender/freestyle/intern/stroke/ChainingIterators.h394
-rwxr-xr-xsource/blender/freestyle/intern/stroke/ContextFunctions.cpp60
-rwxr-xr-xsource/blender/freestyle/intern/stroke/ContextFunctions.h124
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Curve.cpp863
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Curve.h467
-rwxr-xr-xsource/blender/freestyle/intern/stroke/CurveAdvancedIterators.h378
-rwxr-xr-xsource/blender/freestyle/intern/stroke/CurveIterators.h299
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Modifiers.h71
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Module.h72
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Operators.cpp1236
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Operators.h311
-rwxr-xr-xsource/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp89
-rwxr-xr-xsource/blender/freestyle/intern/stroke/PSStrokeRenderer.h63
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Predicates0D.h172
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Predicates1D.h540
-rwxr-xr-xsource/blender/freestyle/intern/stroke/QInformationMap.h58
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Stroke.cpp947
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Stroke.h592
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h142
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeIO.cpp55
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeIO.h47
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeIterators.h229
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeLayer.cpp64
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeLayer.h76
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeRenderer.cpp121
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeRenderer.h132
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeRep.cpp751
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeRep.h138
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeShader.h124
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeTesselator.cpp88
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeTesselator.h67
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StyleModule.h172
-rwxr-xr-xsource/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp73
-rwxr-xr-xsource/blender/freestyle/intern/stroke/TextStrokeRenderer.h68
-rwxr-xr-xsource/blender/freestyle/intern/system/BaseIterator.h90
-rwxr-xr-xsource/blender/freestyle/intern/system/BaseObject.cpp1
-rwxr-xr-xsource/blender/freestyle/intern/system/BaseObject.h73
-rwxr-xr-xsource/blender/freestyle/intern/system/Cast.h44
-rwxr-xr-xsource/blender/freestyle/intern/system/Exception.cpp24
-rwxr-xr-xsource/blender/freestyle/intern/system/Exception.h64
-rwxr-xr-xsource/blender/freestyle/intern/system/FreestyleConfig.h90
-rwxr-xr-xsource/blender/freestyle/intern/system/Id.h126
-rwxr-xr-xsource/blender/freestyle/intern/system/Interpreter.h56
-rw-r--r--source/blender/freestyle/intern/system/Iterator.cpp1
-rw-r--r--source/blender/freestyle/intern/system/Iterator.h41
-rw-r--r--source/blender/freestyle/intern/system/PointerSequence.h97
-rwxr-xr-xsource/blender/freestyle/intern/system/Precision.h39
-rwxr-xr-xsource/blender/freestyle/intern/system/ProgressBar.h85
-rwxr-xr-xsource/blender/freestyle/intern/system/PseudoNoise.cpp109
-rwxr-xr-xsource/blender/freestyle/intern/system/PseudoNoise.h58
-rwxr-xr-xsource/blender/freestyle/intern/system/PythonInterpreter.cpp25
-rwxr-xr-xsource/blender/freestyle/intern/system/PythonInterpreter.h180
-rwxr-xr-xsource/blender/freestyle/intern/system/RandGen.cpp86
-rwxr-xr-xsource/blender/freestyle/intern/system/RandGen.h48
-rw-r--r--source/blender/freestyle/intern/system/RenderMonitor.h47
-rwxr-xr-xsource/blender/freestyle/intern/system/StringUtils.cpp74
-rwxr-xr-xsource/blender/freestyle/intern/system/StringUtils.h62
-rwxr-xr-xsource/blender/freestyle/intern/system/TimeStamp.cpp25
-rwxr-xr-xsource/blender/freestyle/intern/system/TimeStamp.h71
-rwxr-xr-xsource/blender/freestyle/intern/system/TimeUtils.h58
-rw-r--r--source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp108
-rw-r--r--source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h67
-rw-r--r--source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp120
-rw-r--r--source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h67
-rw-r--r--source/blender/freestyle/intern/view_map/BoxGrid.cpp210
-rw-r--r--source/blender/freestyle/intern/view_map/BoxGrid.h376
-rw-r--r--source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp277
-rw-r--r--source/blender/freestyle/intern/view_map/CulledOccluderSource.h63
-rwxr-xr-xsource/blender/freestyle/intern/view_map/FEdgeXDetector.cpp767
-rwxr-xr-xsource/blender/freestyle/intern/view_map/FEdgeXDetector.h203
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions0D.cpp357
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions0D.h500
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions1D.cpp231
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions1D.h555
-rw-r--r--source/blender/freestyle/intern/view_map/GridDensityProvider.h131
-rw-r--r--source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp74
-rw-r--r--source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h54
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Interface0D.h360
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Interface1D.h226
-rw-r--r--source/blender/freestyle/intern/view_map/OccluderSource.cpp132
-rw-r--r--source/blender/freestyle/intern/view_map/OccluderSource.h70
-rw-r--r--source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp109
-rw-r--r--source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h67
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Silhouette.cpp370
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Silhouette.h1471
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp272
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h123
-rw-r--r--source/blender/freestyle/intern/view_map/SphericalGrid.cpp221
-rw-r--r--source/blender/freestyle/intern/view_map/SphericalGrid.h388
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SteerableViewMap.cpp267
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SteerableViewMap.h153
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp736
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h218
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMap.cpp703
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMap.h1506
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h691
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapBuilder.cpp2333
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapBuilder.h248
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapIO.cpp1245
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapIO.h116
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapIterators.h549
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapTesselator.cpp36
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapTesselator.h196
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/Curvature.cpp646
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/Curvature.h156
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/Nature.h79
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WEdge.cpp752
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WEdge.h991
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WFillGrid.cpp60
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WFillGrid.h80
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WSFillGrid.cpp60
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WSFillGrid.h79
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdge.cpp296
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdge.h582
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp46
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h51
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp386
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h171
-rw-r--r--source/blender/gpu/GPU_buffers.h5
-rw-r--r--source/blender/gpu/GPU_draw.h4
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c109
-rw-r--r--source/blender/gpu/intern/gpu_draw.c36
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp2
-rw-r--r--source/blender/imbuf/CMakeLists.txt3
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h1
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h5
-rw-r--r--source/blender/imbuf/intern/IMB_colormanagement_intern.h3
-rw-r--r--source/blender/imbuf/intern/colormanagement.c211
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp6
-rw-r--r--source/blender/imbuf/intern/iris.c14
-rw-r--r--source/blender/imbuf/intern/jpeg.c4
-rw-r--r--source/blender/imbuf/intern/moviecache.c2
-rw-r--r--source/blender/imbuf/intern/scaling.c2
-rw-r--r--source/blender/makesdna/DNA_ID.h1
-rw-r--r--source/blender/makesdna/DNA_action_types.h1
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h133
-rw-r--r--source/blender/makesdna/DNA_key_types.h2
-rw-r--r--source/blender/makesdna/DNA_linestyle_types.h433
-rw-r--r--source/blender/makesdna/DNA_material_types.h15
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h6
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h8
-rw-r--r--source/blender/makesdna/DNA_scene_types.h34
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/makesdna/intern/makesdna.c4
-rw-r--r--source/blender/makesrna/RNA_access.h35
-rw-r--r--source/blender/makesrna/RNA_enum_types.h5
-rw-r--r--source/blender/makesrna/SConscript1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/makesrna.c1
-rw-r--r--source/blender/makesrna/intern/rna_ID.c13
-rw-r--r--source/blender/makesrna/intern/rna_access.c4
-rw-r--r--source/blender/makesrna/intern/rna_action.c6
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c5
-rw-r--r--source/blender/makesrna/intern/rna_animation.c2
-rw-r--r--source/blender/makesrna/intern/rna_animation_api.c1
-rw-r--r--source/blender/makesrna/intern/rna_armature.c4
-rw-r--r--source/blender/makesrna/intern/rna_armature_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_camera_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_color.c38
-rw-r--r--source/blender/makesrna/intern/rna_controller.c2
-rw-r--r--source/blender/makesrna/intern/rna_controller_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_curve.c6
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c4
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c2
-rw-r--r--source/blender/makesrna/intern/rna_image.c4
-rw-r--r--source/blender/makesrna/intern/rna_internal.h24
-rw-r--r--source/blender/makesrna/intern/rna_key.c6
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c1082
-rw-r--r--source/blender/makesrna/intern/rna_main.c7
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c201
-rw-r--r--source/blender/makesrna/intern/rna_mask.c4
-rw-r--r--source/blender/makesrna/intern/rna_material.c8
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c57
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c4
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c5
-rw-r--r--source/blender/makesrna/intern/rna_nla.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c4
-rw-r--r--source/blender/makesrna/intern/rna_object.c8
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c14
-rw-r--r--source/blender/makesrna/intern/rna_particle.c2
-rw-r--r--source/blender/makesrna/intern/rna_pose.c18
-rw-r--r--source/blender/makesrna/intern/rna_property.c4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c465
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_screen.c4
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c2
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c8
-rw-r--r--source/blender/makesrna/intern/rna_texture_api.c10
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c8
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c25
-rw-r--r--source/blender/makesrna/intern/rna_wm.c8
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c6
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c4
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c8
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c12
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c64
-rw-r--r--source/blender/nodes/composite/node_composite_util.c2
-rw-r--r--source/blender/nodes/texture/node_texture_util.c2
-rw-r--r--source/blender/python/SConscript1
-rw-r--r--source/blender/python/intern/CMakeLists.txt1
-rw-r--r--source/blender/python/intern/bpy.c5
-rw-r--r--source/blender/python/intern/bpy_app_ffmpeg.c4
-rw-r--r--source/blender/python/intern/bpy_interface.c27
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c3
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c2
-rw-r--r--source/blender/render/CMakeLists.txt1
-rw-r--r--source/blender/render/SConscript1
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h3
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h7
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h3
-rw-r--r--source/blender/render/intern/include/render_result.h2
-rw-r--r--source/blender/render/intern/include/render_types.h10
-rw-r--r--source/blender/render/intern/include/renderdatabase.h2
-rw-r--r--source/blender/render/intern/raytrace/rayobject_rtbuild.cpp2
-rw-r--r--source/blender/render/intern/raytrace/rayobject_vbvh.cpp4
-rw-r--r--source/blender/render/intern/source/convertblender.c160
-rw-r--r--source/blender/render/intern/source/gammaCorrectionTables.c2
-rw-r--r--source/blender/render/intern/source/imagetexture.c14
-rw-r--r--source/blender/render/intern/source/initrender.c4
-rw-r--r--source/blender/render/intern/source/occlusion.c1
-rw-r--r--source/blender/render/intern/source/pipeline.c148
-rw-r--r--source/blender/render/intern/source/render_result.c21
-rw-r--r--source/blender/render/intern/source/render_texture.c13
-rw-r--r--source/blender/render/intern/source/rendercore.c31
-rw-r--r--source/blender/render/intern/source/renderdatabase.c27
-rw-r--r--source/blender/render/intern/source/shadbuf.c7
-rw-r--r--source/blender/render/intern/source/shadeinput.c195
-rw-r--r--source/blender/render/intern/source/shadeoutput.c6
-rw-r--r--source/blender/windowmanager/CMakeLists.txt1
-rw-r--r--source/blender/windowmanager/SConscript1
-rw-r--r--source/blender/windowmanager/WM_api.h18
-rw-r--r--source/blender/windowmanager/WM_types.h1
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c13
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c4
-rw-r--r--source/blender/windowmanager/intern/wm_files.c3
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c4
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c15
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c3
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c8
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c12
-rw-r--r--source/blender/windowmanager/intern/wm_window.c8
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c10
-rw-r--r--source/creator/CMakeLists.txt10
-rw-r--r--source/creator/creator.c8
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp12
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp4
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.cpp4
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp2
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h2
-rw-r--r--source/gameengine/CMakeLists.txt2
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp14
-rw-r--r--source/gameengine/Converter/BL_ArmatureActuator.cpp12
-rw-r--r--source/gameengine/Converter/BL_ArmatureActuator.h4
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.cpp14
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.h6
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.cpp12
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.h4
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp8
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.h4
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp70
-rw-r--r--source/gameengine/Converter/BL_DeformableGameObject.h2
-rw-r--r--source/gameengine/Converter/BL_MeshDeformer.cpp2
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.cpp2
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.h2
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.cpp4
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.cpp2
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.h2
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.cpp12
-rw-r--r--source/gameengine/Converter/BlenderWorldInfo.cpp6
-rw-r--r--source/gameengine/Converter/BlenderWorldInfo.h10
-rw-r--r--source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp2
-rw-r--r--source/gameengine/Converter/KX_BlenderScalarInterpolator.h2
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp28
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp2
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.cpp2
-rw-r--r--source/gameengine/Converter/KX_ConvertProperties.cpp4
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp12
-rw-r--r--source/gameengine/Converter/KX_IpoConvert.cpp8
-rw-r--r--source/gameengine/Expressions/BoolValue.cpp2
-rw-r--r--source/gameengine/Expressions/BoolValue.h2
-rw-r--r--source/gameengine/Expressions/EXP_C-Api.cpp4
-rw-r--r--source/gameengine/Expressions/EXP_C-Api.h2
-rw-r--r--source/gameengine/Expressions/FloatValue.cpp2
-rw-r--r--source/gameengine/Expressions/InputParser.cpp4
-rw-r--r--source/gameengine/Expressions/IntValue.cpp2
-rw-r--r--source/gameengine/Expressions/KX_HashedPtr.h2
-rw-r--r--source/gameengine/Expressions/ListValue.cpp36
-rw-r--r--source/gameengine/Expressions/ListValue.h2
-rw-r--r--source/gameengine/Expressions/Operator2Expr.cpp6
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp18
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h48
-rw-r--r--source/gameengine/Expressions/StringValue.h2
-rw-r--r--source/gameengine/Expressions/Value.cpp12
-rw-r--r--source/gameengine/Expressions/Value.h26
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.h2
-rw-r--r--source/gameengine/GameLogic/SCA_IController.cpp10
-rw-r--r--source/gameengine/GameLogic/SCA_IInputDevice.cpp4
-rw-r--r--source/gameengine/GameLogic/SCA_IInputDevice.h24
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.cpp6
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.h2
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.h4
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.cpp12
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickSensor.cpp22
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardManager.h2
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp23
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.h2
-rw-r--r--source/gameengine/GameLogic/SCA_MouseManager.h2
-rw-r--r--source/gameengine/GameLogic/SCA_MouseSensor.cpp10
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp14
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.h12
-rw-r--r--source/gameengine/GameLogic/SCA_PythonKeyboard.cpp8
-rw-r--r--source/gameengine/GameLogic/SCA_PythonKeyboard.h2
-rw-r--r--source/gameengine/GameLogic/SCA_PythonMouse.cpp12
-rw-r--r--source/gameengine/GameLogic/SCA_PythonMouse.h14
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.cpp14
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.h6
-rw-r--r--source/gameengine/GameLogic/SCA_RandomSensor.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_TimeEventManager.cpp2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.cpp2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.h4
-rw-r--r--source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp6
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawImage.cpp2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.cpp2
-rw-r--r--source/gameengine/GamePlayer/common/bmfont.cpp2
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp10
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp14
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp18
-rw-r--r--source/gameengine/Ketsji/BL_Shader.h2
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp10
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp6
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h2
-rw-r--r--source/gameengine/Ketsji/KX_ArmatureSensor.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_ArmatureSensor.h2
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h8
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp38
-rw-r--r--source/gameengine/Ketsji/KX_Camera.h8
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_CameraIpoSGController.h6
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.h2
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.h2
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp58
-rw-r--r--source/gameengine/Ketsji/KX_FontObject.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp174
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h82
-rw-r--r--source/gameengine/Ketsji/KX_IInterpolator.h2
-rw-r--r--source/gameengine/Ketsji/KX_IScalarInterpolator.h2
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp46
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h8
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_Light.h4
-rw-r--r--source/gameengine/Ketsji/KX_LightIpoSGController.h6
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.cpp24
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.h6
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp20
-rw-r--r--source/gameengine/Ketsji/KX_ObstacleSimulation.cpp14
-rw-r--r--source/gameengine/Ketsji/KX_ObstacleSimulation.h8
-rw-r--r--source/gameengine/Ketsji/KX_ParentActuator.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_ParentActuator.h2
-rw-r--r--source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.cpp22
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.h20
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.cpp18
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.h6
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp133
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.cpp18
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.h20
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp252
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.h14
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.h6
-rw-r--r--source/gameengine/Ketsji/KX_PythonSeq.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_RadarSensor.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.h2
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h6
-rw-r--r--source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h2
-rw-r--r--source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h2
-rw-r--r--source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_SG_NodeRelationships.h12
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp55
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h40
-rw-r--r--source/gameengine/Ketsji/KX_SceneActuator.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_SceneActuator.h2
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp20
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.h12
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.cpp32
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.h12
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.h2
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp20
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.h4
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.cpp34
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.cpp52
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.h30
-rw-r--r--source/gameengine/Ketsji/KX_WorldIpoController.h6
-rw-r--r--source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h2
-rw-r--r--source/gameengine/Network/NG_NetworkScene.h4
-rw-r--r--source/gameengine/Physics/Bullet/CcdGraphicController.h2
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp14
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h4
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp27
-rw-r--r--source/gameengine/Physics/common/PHY_DynamicTypes.h12
-rw-r--r--source/gameengine/Physics/common/PHY_IController.h2
-rw-r--r--source/gameengine/Physics/common/PHY_IMotionState.h2
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_2DFilterManager.cpp4
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.cpp4
-rw-r--r--source/gameengine/Rasterizer/RAS_Deformer.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_FramingManager.cpp14
-rw-r--r--source/gameengine/Rasterizer/RAS_FramingManager.h8
-rw-r--r--source/gameengine/Rasterizer/RAS_IRasterizer.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_IRenderTools.h30
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.cpp8
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp4
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h2
-rw-r--r--source/gameengine/SceneGraph/SG_Controller.h8
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.cpp2
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.h8
-rw-r--r--source/gameengine/SceneGraph/SG_Node.cpp2
-rw-r--r--source/gameengine/SceneGraph/SG_Node.h18
-rw-r--r--source/gameengine/SceneGraph/SG_ParentRelation.h2
-rw-r--r--source/gameengine/SceneGraph/SG_Spatial.cpp4
-rw-r--r--source/gameengine/SceneGraph/SG_Spatial.h12
-rw-r--r--source/gameengine/SceneGraph/SG_Tree.cpp2
-rw-r--r--source/gameengine/VideoTexture/BlendType.h13
-rw-r--r--source/gameengine/VideoTexture/FilterBase.cpp10
-rw-r--r--source/gameengine/VideoTexture/FilterBase.h12
-rw-r--r--source/gameengine/VideoTexture/FilterBlueScreen.cpp10
-rw-r--r--source/gameengine/VideoTexture/FilterColor.cpp12
-rw-r--r--source/gameengine/VideoTexture/FilterNormal.cpp10
-rw-r--r--source/gameengine/VideoTexture/ImageBase.cpp48
-rw-r--r--source/gameengine/VideoTexture/ImageBase.h36
-rw-r--r--source/gameengine/VideoTexture/ImageBuff.cpp16
-rw-r--r--source/gameengine/VideoTexture/ImageMix.cpp6
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp26
-rw-r--r--source/gameengine/VideoTexture/ImageViewport.cpp18
-rw-r--r--source/gameengine/VideoTexture/ImageViewport.h12
-rw-r--r--source/gameengine/VideoTexture/PyTypeList.cpp8
-rw-r--r--source/gameengine/VideoTexture/PyTypeList.h14
-rw-r--r--source/gameengine/VideoTexture/Texture.cpp36
-rw-r--r--source/gameengine/VideoTexture/Texture.h8
-rw-r--r--source/gameengine/VideoTexture/VideoBase.cpp29
-rw-r--r--source/gameengine/VideoTexture/VideoBase.h28
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp22
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.h2
-rw-r--r--source/gameengine/VideoTexture/blendVideoTex.cpp20
-rw-r--r--source/tests/bl_rna_wiki_reference.py47
-rw-r--r--source/tests/bl_run_operators.py109
1458 files changed, 106941 insertions, 13062 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 83e094b4375..62240515c4a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -378,6 +378,8 @@ endif()
if(WITH_GHOST_SDL OR WITH_HEADLESS)
set(WITH_GHOST_XDND OFF)
+ set(WITH_X11_XF86VMODE OFF)
+ set(WITH_X11_XINPUT OFF)
endif()
if(MINGW)
@@ -563,7 +565,14 @@ if(UNIX AND NOT APPLE)
endif()
mark_as_advanced(FFMPEG)
- set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include ${FFMPEG}/include/ffmpeg)
+
+ # lame, but until we have propper find module for ffmpeg
+ set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include)
+ if(EXISTS "${FFMPEG}/include/ffmpeg/")
+ set(FFMPEG_INCLUDE_DIRS "${FFMPEG_INCLUDE_DIRS} ${FFMPEG}/include/ffmpeg")
+ endif()
+ # end lameness
+
mark_as_advanced(FFMPEG_LIBRARIES)
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS")
@@ -1104,7 +1113,7 @@ elseif(WIN32)
set(PLATFORM_LINKFLAGS_DEBUG "/NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib")
# used in many places so include globally, like OpenGL
- blender_include_dirs("${PTHREADS_INCLUDE_DIRS}")
+ blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}")
elseif(CMAKE_COMPILER_IS_GNUCC)
# keep GCC specific stuff here
@@ -1243,8 +1252,8 @@ elseif(WIN32)
set(BOOST_POSTFIX "mgw47-mt-s-1_49")
set(BOOST_DEBUG_POSTFIX "mgw47-mt-sd-1_49")
else()
- set(BOOST_POSTFIX "mgw46-mt-s-1_47")
- set(BOOST_DEBUG_POSTFIX "mgw46-mt-sd-1_47")
+ set(BOOST_POSTFIX "mgw46-mt-s-1_49")
+ set(BOOST_DEBUG_POSTFIX "mgw46-mt-sd-1_49")
endif()
set(BOOST_LIBRARIES
optimized boost_date_time-${BOOST_POSTFIX} boost_filesystem-${BOOST_POSTFIX}
@@ -1725,6 +1734,13 @@ if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_WRITE_STRINGS -Wwrite-strings)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_LOGICAL_OP -Wlogical-op)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEF -Wundef)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_NULL -Wnonnull) # C only
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
# # this causes too many warnings, disable
# ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEFINED -Wundef)
@@ -1739,9 +1755,14 @@ if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
-
- # # this causes too many warnings, disable
- # ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEFINED -Wundef)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_DECLARATIONS -Wmissing-declarations)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_LOGICAL_OP -Wlogical-op)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEF -Wundef)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEFINED -Wundef)
# flags to undo strict flags
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
@@ -1760,13 +1781,15 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_MACROS -Wunused-macros)
- ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS C_WARN_ALL -Wall)
- ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
- ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
- ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
- ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_OVERLOADED_VIRTUAL -Wno-overloaded-virtual) # we get a lot of these, if its a problem a dev needs to look into it.
- ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_OVERLOADED_VIRTUAL -Wno-overloaded-virtual) # we get a lot of these, if its a problem a dev needs to look into it.
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_MACROS -Wunused-macros)
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
diff --git a/GNUmakefile b/GNUmakefile
index 1f1de3f6b99..7b333a5fc77 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -173,6 +173,7 @@ help:
@echo " * check_cppcheck - run blender source through cppcheck (C & C++)"
@echo " * check_splint - run blenders source through splint (C only)"
@echo " * check_sparse - run blenders source through sparse (C only)"
+ @echo " * check_smatch - run blenders source through smatch (C only)"
@echo " * check_spelling_c - check for spelling errors (C/C++ only)"
@echo " * check_spelling_py - check for spelling errors (Python only)"
@echo ""
diff --git a/SConstruct b/SConstruct
index 517f507ec61..7676b44f759 100644
--- a/SConstruct
+++ b/SConstruct
@@ -871,9 +871,13 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
if env['WITH_BF_OIIO'] and env['OURPLATFORM'] != 'win32-mingw':
dllsources.append('${LCGDIR}/openimageio/bin/OpenImageIO.dll')
- if env['WITH_BF_OCIO'] and env['OURPLATFORM'] != 'win32-mingw':
- dllsources.append('${LCGDIR}/opencolorio/bin/OpenColorIO.dll')
+ if env['WITH_BF_OCIO']:
+ if not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'):
+ dllsources.append('${LCGDIR}/opencolorio/bin/OpenColorIO.dll')
+ else:
+ dllsources.append('${LCGDIR}/opencolorio/bin/libOpenColorIO.dll')
+
dllsources.append('#source/icons/blender.exe.manifest')
windlls = env.Install(dir=env['BF_INSTALLDIR'], source = dllsources)
@@ -903,6 +907,9 @@ if env['OURPLATFORM'] == 'win64-mingw':
if(env['WITH_BF_OPENMP']):
dllsources.append('${LCGDIR}/binaries/libgomp-1.dll')
+
+ if env['WITH_BF_OCIO']:
+ dllsources.append('${LCGDIR}/opencolorio/bin/libOpenColorIO.dll')
dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb64.dll')
dllsources.append('${LCGDIR}/binaries/libgcc_s_sjlj-1.dll')
diff --git a/build_files/buildbot/config/user-config-i686.py b/build_files/buildbot/config/user-config-i686.py
index b07dd505369..9d27fbe46fc 100644
--- a/build_files/buildbot/config/user-config-i686.py
+++ b/build_files/buildbot/config/user-config-i686.py
@@ -106,6 +106,14 @@ BF_OIIO_INC = '${BF_OIIO}/include'
BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a'
BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
+# Color management
+WITH_BF_OCIO = True
+WITH_BF_STATICOCIO = True
+BF_OCIO = '/opt/ocio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
WITH_BF_BOOST = True
WITH_BF_STATICBOOST = True
BF_BOOST = '/opt/boost'
diff --git a/build_files/buildbot/config/user-config-player-i686.py b/build_files/buildbot/config/user-config-player-i686.py
index 6c5c5f89ad4..e23fc70262f 100644
--- a/build_files/buildbot/config/user-config-player-i686.py
+++ b/build_files/buildbot/config/user-config-player-i686.py
@@ -82,6 +82,14 @@ WITH_BF_STATIC3DMOUSE = True
BF_3DMOUSE = '/home/sources/staticlibs/spnav'
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32'
+# Color management
+WITH_BF_OCIO = True
+WITH_BF_STATICOCIO = True
+BF_OCIO = '/opt/ocio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
# JACK
WITH_BF_JACK = True
diff --git a/build_files/buildbot/config/user-config-player-x86_64.py b/build_files/buildbot/config/user-config-player-x86_64.py
index 60c8060e78e..3c09603473e 100644
--- a/build_files/buildbot/config/user-config-player-x86_64.py
+++ b/build_files/buildbot/config/user-config-player-x86_64.py
@@ -82,6 +82,14 @@ WITH_BF_STATIC3DMOUSE = True
BF_3DMOUSE = '/home/sources/staticlibs/spnav'
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64'
+# Color management
+WITH_BF_OCIO = True
+WITH_BF_STATICOCIO = True
+BF_OCIO = '/opt/ocio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
# JACK
WITH_BF_JACK = True
diff --git a/build_files/buildbot/config/user-config-x86_64.py b/build_files/buildbot/config/user-config-x86_64.py
index 5905a9c29dd..070e62b2f20 100644
--- a/build_files/buildbot/config/user-config-x86_64.py
+++ b/build_files/buildbot/config/user-config-x86_64.py
@@ -106,6 +106,14 @@ BF_OIIO_INC = '${BF_OIIO}/include'
BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a'
BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
+# Color management
+WITH_BF_OCIO = True
+WITH_BF_STATICOCIO = True
+BF_OCIO = '/opt/ocio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
WITH_BF_BOOST = True
WITH_BF_STATICBOOST = True
BF_BOOST = '/opt/boost'
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index b834cd37a8a..ae07743191b 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -42,6 +42,7 @@ set(WITH_MOD_OCEANSIM OFF CACHE FORCE BOOL)
set(WITH_AUDASPACE OFF CACHE FORCE BOOL)
set(WITH_OPENAL OFF CACHE FORCE BOOL)
set(WITH_OPENCOLLADA OFF CACHE FORCE BOOL)
+set(WITH_OPENCOLORIO OFF CACHE FORCE BOOL)
set(WITH_OPENMP OFF CACHE FORCE BOOL)
set(WITH_PYTHON_INSTALL OFF CACHE FORCE BOOL)
set(WITH_RAYOPTIMIZATION OFF CACHE FORCE BOOL)
diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py
index 5c16baa2ee8..45f6602e4dd 100644
--- a/build_files/scons/config/linux-config.py
+++ b/build_files/scons/config/linux-config.py
@@ -239,7 +239,7 @@ WITH_BF_CYCLES = WITH_BF_OIIO and WITH_BF_BOOST
WITH_BF_CYCLES_CUDA_BINARIES = False
BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc'
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30']
WITH_BF_OPENMP = True
diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py
index 95b2329f426..327fb07ac7a 100644
--- a/build_files/scons/config/win32-mingw-config.py
+++ b/build_files/scons/config/win32-mingw-config.py
@@ -159,7 +159,7 @@ BF_OIIO_INC = BF_OIIO + '/include'
BF_OIIO_LIB = 'OpenImageIO'
BF_OIIO_LIBPATH = BF_OIIO + '/lib'
-WITH_BF_OCIO = False
+WITH_BF_OCIO = True
BF_OCIO = LIBDIR + '/opencolorio'
BF_OCIO_INC = BF_OCIO + '/include'
BF_OCIO_LIB = 'OpenColorIO'
@@ -168,7 +168,7 @@ BF_OCIO_LIBPATH = BF_OCIO + '/lib'
WITH_BF_BOOST = True
BF_BOOST = LIBDIR + '/boost'
BF_BOOST_INC = BF_BOOST + '/include'
-BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_47 boost_filesystem-mgw46-mt-s-1_47 boost_regex-mgw46-mt-s-1_47 boost_system-mgw46-mt-s-1_47 boost_thread-mgw46-mt-s-1_47'
+BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_49 boost_filesystem-mgw46-mt-s-1_49 boost_regex-mgw46-mt-s-1_49 boost_system-mgw46-mt-s-1_49 boost_thread-mgw46-mt-s-1_49'
BF_BOOST_LIBPATH = BF_BOOST + '/lib'
#Ray trace optimization
diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py
index c2bf2df6d00..020e5ad3a61 100644
--- a/build_files/scons/config/win64-mingw-config.py
+++ b/build_files/scons/config/win64-mingw-config.py
@@ -159,7 +159,7 @@ BF_OIIO_INC = '${BF_OIIO}/include'
BF_OIIO_LIB = 'OpenImageIO'
BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
-WITH_BF_OCIO = False
+WITH_BF_OCIO = True
BF_OCIO = LIBDIR + '/opencolorio'
BF_OCIO_INC = '${BF_OCIO}/include'
BF_OCIO_LIB = 'OpenColorIO'
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index 1e114a43ae0..8f515f906f0 100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -332,7 +332,7 @@ def propose_priorities():
def creator(env):
sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources
- incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', env['BF_OPENGL_INC']]
+ incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', '#/source/blender/freestyle', env['BF_OPENGL_INC']]
defs = []
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index 633492ba0ee..6d7a25acc11 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -593,7 +593,7 @@ def read_opts(env, cfg, args):
('BF_BOOST_LIB_STATIC', 'Boost static library', ''),
(BoolVariable('WITH_GHOST_XDND', 'Build with drag-n-drop support on Linux platforms using XDND protocol', True)),
- (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', True))
+ (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', False))
) # end of opts.AddOptions()
return localopts
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 186f67b0df6..24223ad1ad0 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -261,6 +261,7 @@ else:
"mathutils",
"mathutils.geometry",
"mathutils.noise",
+ "Freestyle",
]
# ------
@@ -446,6 +447,7 @@ if ARGS.sphinx_build_pdf:
ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
MethodDescriptorType = type(dict.get)
GetSetDescriptorType = type(int.real)
+StaticMethodType = type(staticmethod(lambda: None))
from types import MemberDescriptorType
_BPY_STRUCT_FAKE = "bpy_struct"
@@ -906,6 +908,12 @@ def pymodule2sphinx(basepath, module_name, module, title):
if type(descr) == GetSetDescriptorType:
py_descr2sphinx(" ", fw, descr, module_name, type_name, key)
+ for key, descr in descr_items:
+ if type(descr) == StaticMethodType:
+ descr = getattr(value, key)
+ write_indented_lines(" ", fw, descr.__doc__ or "Undocumented", False)
+ fw("\n")
+
fw("\n\n")
file.close()
@@ -1524,7 +1532,7 @@ def write_rst_contents(basepath):
# mathutils
"mathutils", "mathutils.geometry", "mathutils.noise",
# misc
- "bgl", "blf", "gpu", "aud", "bpy_extras",
+ "Freestyle", "bgl", "blf", "gpu", "aud", "bpy_extras",
# bmesh
"bmesh", "bmesh.types", "bmesh.utils",
)
@@ -1668,6 +1676,7 @@ def write_rst_importable_modules(basepath):
"mathutils" : "Math Types & Utilities",
"mathutils.geometry": "Geometry Utilities",
"mathutils.noise" : "Noise Utilities",
+ "Freestyle" : "Freestyle Data Types & Operators",
}
for mod_name, mod_descr in importable_modules.items():
if mod_name not in EXCLUDE_MODULES:
diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt
index 60cd84d89d4..602372f6ff7 100644
--- a/extern/libmv/CMakeLists.txt
+++ b/extern/libmv/CMakeLists.txt
@@ -40,19 +40,6 @@ set(INC_SYS
${ZLIB_INCLUDE_DIRS}
)
-
-# XXX - FIXME
-# this is a momentary hack to find unwind.h in 10.6.sdk
-if(APPLE)
- if(${CMAKE_OSX_DEPLOYMENT_TARGET} STREQUAL "10.6")
- list(APPEND INC_SYS
- ${CMAKE_OSX_SYSROOT}/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin10/4.2.1/include
- )
- endif()
-endif()
-# XXX - END
-
-
set(SRC
libmv-capi.cpp
libmv/image/array_nd.cc
diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp
index 3d3b7398c9b..0f73234f49c 100644
--- a/extern/libmv/libmv-capi.cpp
+++ b/extern/libmv/libmv-capi.cpp
@@ -523,7 +523,7 @@ int libmv_refineParametersAreValid(int parameters) {
LIBMV_REFINE_RADIAL_DISTORTION_K1));
}
-void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntrinsics *intrinsics,
+static void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntrinsics *intrinsics,
libmv::EuclideanReconstruction *reconstruction, int refine_intrinsics,
reconstruct_progress_update_cb progress_update_callback, void *callback_customdata)
{
@@ -1027,7 +1027,7 @@ void libmv_InvertIntrinsics(double focal_length, double principal_x, double prin
/* ************ point clouds ************ */
-void libmvTransformToMat4(libmv::Mat3 &R, libmv::Vec3 &S, libmv::Vec3 &t, double M[4][4])
+static void libmvTransformToMat4(libmv::Mat3 &R, libmv::Vec3 &S, libmv::Vec3 &t, double M[4][4])
{
for (int j = 0; j < 3; ++j)
for (int k = 0; k < 3; ++k)
diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h
index fc3b6f94f62..5253ba76a21 100644
--- a/extern/libmv/libmv-capi.h
+++ b/extern/libmv/libmv-capi.h
@@ -147,14 +147,14 @@ void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmvIntr
/* dsitortion */
void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- unsigned char *src, unsigned char *dst, int width, int height, int channels);
+ unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
void libmv_undistortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- float *src, float *dst, int width, int height, int channels);
+ float *src, float *dst, int width, int height, float overscan, int channels);
void libmv_distortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- unsigned char *src, unsigned char *dst, int width, int height, int channels);
+ unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
void libmv_distortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- float *src, float *dst, int width, int height, int channels);
+ float *src, float *dst, int width, int height, float overscan, int channels);
/* utils */
void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
diff --git a/extern/libmv/libmv/multiview/euclidean_resection.cc b/extern/libmv/libmv/multiview/euclidean_resection.cc
index 92862515d7e..6cad4cac049 100644
--- a/extern/libmv/libmv/multiview/euclidean_resection.cc
+++ b/extern/libmv/libmv/multiview/euclidean_resection.cc
@@ -351,9 +351,9 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
}
// Selects 4 virtual control points using mean and PCA.
-void SelectControlPoints(const Mat3X &X_world,
- Mat *X_centered,
- Mat34 *X_control_points) {
+static void SelectControlPoints(const Mat3X &X_world,
+ Mat *X_centered,
+ Mat34 *X_control_points) {
size_t num_points = X_world.cols();
// The first virtual control point, C0, is the centroid.
@@ -377,9 +377,9 @@ void SelectControlPoints(const Mat3X &X_world,
}
// Computes the barycentric coordinates for all real points
-void ComputeBarycentricCoordinates(const Mat3X &X_world_centered,
- const Mat34 &X_control_points,
- Mat4X *alphas) {
+static void ComputeBarycentricCoordinates(const Mat3X &X_world_centered,
+ const Mat34 &X_control_points,
+ Mat4X *alphas) {
size_t num_points = X_world_centered.cols();
Mat3 C2 ;
for (size_t c = 1; c < 4; c++) {
@@ -398,7 +398,7 @@ void ComputeBarycentricCoordinates(const Mat3X &X_world_centered,
}
// Estimates the coordinates of all real points in the camera coordinate frame
-void ComputePointsCoordinatesInCameraFrame(
+static void ComputePointsCoordinatesInCameraFrame(
const Mat4X &alphas,
const Vec4 &betas,
const Eigen::Matrix<double, 12, 12> &U,
@@ -535,7 +535,16 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
vector<Vec3> ts(3);
Vec rmse(3);
- // TODO(julien): Document where the "1e-3" magical constant comes from below.
+ // At one point this threshold was 1e-3, and caused no end of problems in
+ // Blender by causing frames to not resect when they would have worked fine.
+ // When the resect failed, the projective followup is run leading to worse
+ // results, and often the dreaded "flipping" where objects get flipped
+ // between frames. Instead, disable the check for now, always succeeding. The
+ // ultimate check is always reprojection error anyway.
+ //
+ // TODO(keir): Decide if setting this to infinity, effectively disabling the
+ // check, is the right approach. So far this seems the case.
+ double kSuccessThreshold = std::numeric_limits<double>::max();
// Find the first possible solution for R, t corresponding to:
// Betas = [b00 b01 b11 b02 b12 b22 b03 b13 b23 b33]
@@ -548,7 +557,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
Eigen::JacobiSVD<Mat> svd_of_l4(l_6x4,
Eigen::ComputeFullU | Eigen::ComputeFullV);
Vec4 b4 = svd_of_l4.solve(rho);
- if ((l_6x4 * b4).isApprox(rho, 1e-3)) {
+ if ((l_6x4 * b4).isApprox(rho, kSuccessThreshold)) {
if (b4(0) < 0) {
b4 = -b4;
}
@@ -574,7 +583,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
Vec3 b3 = svdOfL3.solve(rho);
VLOG(2) << " rho = " << rho;
VLOG(2) << " l_6x3 * b3 = " << l_6x3 * b3;
- if ((l_6x3 * b3).isApprox(rho, 1e-3)) {
+ if ((l_6x3 * b3).isApprox(rho, kSuccessThreshold)) {
if (b3(0) < 0) {
betas(0) = std::sqrt(-b3(0));
betas(1) = (b3(2) < 0) ? std::sqrt(-b3(2)) : 0;
@@ -605,7 +614,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
Eigen::JacobiSVD<Mat> svdOfL5(l_6x5,
Eigen::ComputeFullU | Eigen::ComputeFullV);
Vec5 b5 = svdOfL5.solve(rho);
- if ((l_6x5 * b5).isApprox(rho, 1e-3)) {
+ if ((l_6x5 * b5).isApprox(rho, kSuccessThreshold)) {
if (b5(0) < 0) {
betas(0) = std::sqrt(-b5(0));
if (b5(2) < 0) {
diff --git a/extern/libmv/libmv/multiview/euclidean_resection.h b/extern/libmv/libmv/multiview/euclidean_resection.h
index 08fa3d90bd3..f20513d3fbe 100644
--- a/extern/libmv/libmv/multiview/euclidean_resection.h
+++ b/extern/libmv/libmv/multiview/euclidean_resection.h
@@ -29,6 +29,9 @@ namespace euclidean_resection {
enum ResectionMethod {
RESECTION_ANSAR_DANIILIDIS,
+
+ // The "EPnP" algorithm by Lepetit et al.
+ // http://cvlab.epfl.ch/~lepetit/papers/lepetit_ijcv08.pdf
RESECTION_EPNP,
};
diff --git a/extern/libmv/libmv/multiview/fundamental.cc b/extern/libmv/libmv/multiview/fundamental.cc
index 7a6b4a08439..80f155e804d 100644
--- a/extern/libmv/libmv/multiview/fundamental.cc
+++ b/extern/libmv/libmv/multiview/fundamental.cc
@@ -28,7 +28,7 @@
namespace libmv {
-void EliminateRow(const Mat34 &P, int row, Mat *X) {
+static void EliminateRow(const Mat34 &P, int row, Mat *X) {
X->resize(2, 4);
int first_row = (row + 1) % 3;
@@ -69,7 +69,7 @@ void FundamentalFromProjections(const Mat34 &P1, const Mat34 &P2, Mat3 *F) {
// HZ 11.1 pag.279 (x1 = x, x2 = x')
// http://www.cs.unc.edu/~marc/tutorial/node54.html
-double EightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F) {
+static double EightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F) {
DCHECK_EQ(x1.rows(), 2);
DCHECK_GE(x1.cols(), 8);
DCHECK_EQ(x1.rows(), x2.rows());
diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc
index 366392f3923..b5c483998d8 100644
--- a/extern/libmv/libmv/multiview/homography.cc
+++ b/extern/libmv/libmv/multiview/homography.cc
@@ -40,7 +40,7 @@ namespace libmv {
* (a-x1*g)*y1 + (b-x1*h)*y2 + c-x1 = |0|
* (-x2*a+x1*d)*y1 + (-x2*b+x1*e)*y2 + -x2*c+x1*f |0|
*/
-bool Homography2DFromCorrespondencesLinearEuc(
+static bool Homography2DFromCorrespondencesLinearEuc(
const Mat &x1,
const Mat &x2,
Mat3 *H,
diff --git a/extern/libmv/libmv/numeric/levenberg_marquardt.h b/extern/libmv/libmv/numeric/levenberg_marquardt.h
index 4473b72f156..a7877e0270b 100644
--- a/extern/libmv/libmv/numeric/levenberg_marquardt.h
+++ b/extern/libmv/libmv/numeric/levenberg_marquardt.h
@@ -124,11 +124,11 @@ class LevenbergMarquardt {
Parameters dx, x_new;
int i;
for (i = 0; results.status == RUNNING && i < params.max_iterations; ++i) {
- VLOG(1) << "iteration: " << i;
- VLOG(1) << "||f(x)||: " << f_(x).norm();
- VLOG(1) << "max(g): " << g.array().abs().maxCoeff();
- VLOG(1) << "u: " << u;
- VLOG(1) << "v: " << v;
+ VLOG(3) << "iteration: " << i;
+ VLOG(3) << "||f(x)||: " << f_(x).norm();
+ VLOG(3) << "max(g): " << g.array().abs().maxCoeff();
+ VLOG(3) << "u: " << u;
+ VLOG(3) << "v: " << v;
AMatrixType A_augmented = A + u*AMatrixType::Identity(J.cols(), J.cols());
Solver solver(A_augmented);
diff --git a/extern/libmv/libmv/simple_pipeline/detect.cc b/extern/libmv/libmv/simple_pipeline/detect.cc
index 8a093dadeca..9e3edf32d71 100644
--- a/extern/libmv/libmv/simple_pipeline/detect.cc
+++ b/extern/libmv/libmv/simple_pipeline/detect.cc
@@ -35,7 +35,7 @@ namespace libmv {
typedef unsigned int uint;
-int featurecmp(const void *a_v, const void *b_v)
+static int featurecmp(const void *a_v, const void *b_v)
{
Feature *a = (Feature*)a_v;
Feature *b = (Feature*)b_v;
diff --git a/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc b/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
index 77fe2a530c4..9c06d1ef4e6 100644
--- a/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
+++ b/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
@@ -24,6 +24,7 @@
#include "libmv/multiview/projection.h"
#include "libmv/numeric/levenberg_marquardt.h"
#include "libmv/numeric/numeric.h"
+#include "libmv/simple_pipeline/initialize_reconstruction.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"
diff --git a/extern/libmv/libmv/simple_pipeline/intersect.cc b/extern/libmv/libmv/simple_pipeline/intersect.cc
index b1518e04651..0c2f744dc1c 100644
--- a/extern/libmv/libmv/simple_pipeline/intersect.cc
+++ b/extern/libmv/libmv/simple_pipeline/intersect.cc
@@ -26,6 +26,7 @@
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
#include "libmv/numeric/levenberg_marquardt.h"
+#include "libmv/simple_pipeline/intersect.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"
diff --git a/extern/libmv/libmv/simple_pipeline/pipeline.cc b/extern/libmv/libmv/simple_pipeline/pipeline.cc
index 2459d059114..4773a70d69b 100644
--- a/extern/libmv/libmv/simple_pipeline/pipeline.cc
+++ b/extern/libmv/libmv/simple_pipeline/pipeline.cc
@@ -242,9 +242,9 @@ void InternalCompleteReconstruction(
(double)tot_resects/(max_image));
if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, true)) {
num_resects++;
- LG << "Ran Resect() for image " << image;
+ LG << "Ran final Resect() for image " << image;
} else {
- LG << "Failed Resect() for image " << image;
+ LG << "Failed final Resect() for image " << image;
}
}
}
diff --git a/extern/libmv/libmv/simple_pipeline/resect.cc b/extern/libmv/libmv/simple_pipeline/resect.cc
index b30d959b512..8737182dd43 100644
--- a/extern/libmv/libmv/simple_pipeline/resect.cc
+++ b/extern/libmv/libmv/simple_pipeline/resect.cc
@@ -27,6 +27,7 @@
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
#include "libmv/numeric/levenberg_marquardt.h"
+#include "libmv/simple_pipeline/resect.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"
@@ -107,6 +108,10 @@ bool EuclideanResect(const vector<Marker> &markers,
// printf("Resection for image %d failed\n", markers[0].image);
LG << "Resection for image " << markers[0].image << " failed;"
<< " trying fallback projective resection.";
+
+ LG << "No fallback; failing resection for " << markers[0].image;
+ return false;
+
if (!final_pass) return false;
// Euclidean resection failed. Fall back to projective resection, which is
// less reliable but better conditioned when there are many points.
diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc
index f52919b2a61..472d58a1547 100644
--- a/extern/libmv/libmv/tracking/track_region.cc
+++ b/extern/libmv/libmv/tracking/track_region.cc
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
-// Author: mierle@google.com (Keir Mierle)
+// Author: mierle@gmail.com (Keir Mierle)
//
// TODO(keir): While this tracking code works rather well, it has some
// outragous inefficiencies. There is probably a 5-10x speedup to be had if a
@@ -41,6 +41,85 @@
#include "libmv/multiview/homography.h"
#include "libmv/numeric/numeric.h"
+// Expand the Jet functionality of Ceres to allow mixed numeric/autodiff.
+//
+// TODO(keir): Push this (or something similar) into upstream Ceres.
+namespace ceres {
+
+// A jet traits class to make it easier to work with mixed auto / numeric diff.
+template<typename T>
+struct JetOps {
+ static bool IsScalar() {
+ return true;
+ }
+ static T GetScalar(const T& t) {
+ return t;
+ }
+ static void SetScalar(const T& scalar, T* t) {
+ *t = scalar;
+ }
+ static void ScaleDerivative(double scale_by, T *value) {
+ // For double, there is no derivative to scale.
+ }
+};
+
+template<typename T, int N>
+struct JetOps<Jet<T, N> > {
+ static bool IsScalar() {
+ return false;
+ }
+ static T GetScalar(const Jet<T, N>& t) {
+ return t.a;
+ }
+ static void SetScalar(const T& scalar, Jet<T, N>* t) {
+ t->a = scalar;
+ }
+ static void ScaleDerivative(double scale_by, Jet<T, N> *value) {
+ value->v *= scale_by;
+ }
+};
+
+template<typename FunctionType, int kNumArgs, typename ArgumentType>
+struct Chain {
+ static ArgumentType Rule(const FunctionType &f,
+ const FunctionType dfdx[kNumArgs],
+ const ArgumentType x[kNumArgs]) {
+ // In the default case of scalars, there's nothing to do since there are no
+ // derivatives to propagate.
+ return f;
+ }
+};
+
+// XXX Add documentation here!
+template<typename FunctionType, int kNumArgs, typename T, int N>
+struct Chain<FunctionType, kNumArgs, Jet<T, N> > {
+ static Jet<T, N> Rule(const FunctionType &f,
+ const FunctionType dfdx[kNumArgs],
+ const Jet<T, N> x[kNumArgs]) {
+ // x is itself a function of another variable ("z"); what this function
+ // needs to return is "f", but with the derivative with respect to z
+ // attached to the jet. So combine the derivative part of x's jets to form
+ // a Jacobian matrix between x and z (i.e. dx/dz).
+ Eigen::Matrix<T, kNumArgs, N> dxdz;
+ for (int i = 0; i < kNumArgs; ++i) {
+ dxdz.row(i) = x[i].v.transpose();
+ }
+
+ // Map the input gradient dfdx into an Eigen row vector.
+ Eigen::Map<const Eigen::Matrix<FunctionType, 1, kNumArgs> >
+ vector_dfdx(dfdx, 1, kNumArgs);
+
+ // Now apply the chain rule to obtain df/dz. Combine the derivative with
+ // the scalar part to obtain f with full derivative information.
+ Jet<T, N> jet_f;
+ jet_f.a = f;
+ jet_f.v = vector_dfdx.template cast<T>() * dxdz; // Also known as dfdz.
+ return jet_f;
+ }
+};
+
+} // namespace ceres
+
namespace libmv {
using ceres::Jet;
@@ -57,6 +136,7 @@ TrackRegionOptions::TrackRegionOptions()
sigma(0.9),
num_extra_points(0),
regularization_coefficient(0.0),
+ minimum_corner_shift_tolerance_pixels(0.005),
image1_mask(NULL) {
}
@@ -108,45 +188,93 @@ static T SampleWithDerivative(const FloatImage &image_and_gradient,
}
template<typename Warp>
-class BoundaryCheckingCallback : public ceres::IterationCallback {
+class TerminationCheckingCallback : public ceres::IterationCallback {
public:
- BoundaryCheckingCallback(const FloatImage& image2,
- const Warp &warp,
- const double *x1, const double *y1)
- : image2_(image2), warp_(warp), x1_(x1), y1_(y1) {}
+ TerminationCheckingCallback(const TrackRegionOptions &options,
+ const FloatImage& image2,
+ const Warp &warp,
+ const double *x1, const double *y1)
+ : options_(options), image2_(image2), warp_(warp), x1_(x1), y1_(y1),
+ have_last_successful_step_(false) {}
virtual ceres::CallbackReturnType operator()(
const ceres::IterationSummary& summary) {
+ // If the step wasn't successful, there's nothing to do.
+ if (!summary.step_is_successful) {
+ return ceres::SOLVER_CONTINUE;
+ }
// Warp the original 4 points with the current warp into image2.
double x2[4];
double y2[4];
for (int i = 0; i < 4; ++i) {
warp_.Forward(warp_.parameters, x1_[i], y1_[i], x2 + i, y2 + i);
}
- // Enusre they are all in bounds.
+ // Ensure the corners are all in bounds.
if (!AllInBounds(image2_, x2, y2)) {
+ LG << "Successful step fell outside of the pattern bounds; aborting.";
return ceres::SOLVER_ABORT;
}
+
+ // Ensure the minimizer is making large enough shifts to bother continuing.
+ // Ideally, this check would happen on the parameters themselves which
+ // Ceres supports directly; however, the mapping from parameter change
+ // magnitude to corner movement in pixels is not a simple norm. Hence, the
+ // need for a stateful callback which tracks the last successful set of
+ // parameters (and the position of the projected patch corners).
+ if (have_last_successful_step_) {
+ // Compute the maximum shift of any corner in pixels since the last
+ // successful iteration.
+ double max_change_pixels = 0;
+ for (int i = 0; i < 4; ++i) {
+ double dx = x2[i] - x2_last_successful_[i];
+ double dy = y2[i] - y2_last_successful_[i];
+ double change_pixels = dx*dx + dy*dy;
+ if (change_pixels > max_change_pixels) {
+ max_change_pixels = change_pixels;
+ }
+ }
+ max_change_pixels = sqrt(max_change_pixels);
+ LG << "Max patch corner shift is " << max_change_pixels;
+
+ // Bail if the shift is too small.
+ if (max_change_pixels < options_.minimum_corner_shift_tolerance_pixels) {
+ LG << "Max patch corner shift is " << max_change_pixels
+ << " from the last iteration; returning success.";
+ return ceres::SOLVER_TERMINATE_SUCCESSFULLY;
+ }
+ }
+
+ // Save the projected corners for checking on the next successful iteration.
+ for (int i = 0; i < 4; ++i) {
+ x2_last_successful_[i] = x2[i];
+ y2_last_successful_[i] = y2[i];
+ }
+ have_last_successful_step_ = true;
return ceres::SOLVER_CONTINUE;
}
private:
+ const TrackRegionOptions &options_;
const FloatImage &image2_;
const Warp &warp_;
const double *x1_;
const double *y1_;
+
+ bool have_last_successful_step_;
+ double x2_last_successful_[4];
+ double y2_last_successful_[4];
};
template<typename Warp>
class PixelDifferenceCostFunctor {
public:
PixelDifferenceCostFunctor(const TrackRegionOptions &options,
- const FloatImage &image_and_gradient1,
- const FloatImage &image_and_gradient2,
- const Mat3 &canonical_to_image1,
- int num_samples_x,
- int num_samples_y,
- const Warp &warp)
+ const FloatImage &image_and_gradient1,
+ const FloatImage &image_and_gradient2,
+ const Mat3 &canonical_to_image1,
+ int num_samples_x,
+ int num_samples_y,
+ const Warp &warp)
: options_(options),
image_and_gradient1_(image_and_gradient1),
image_and_gradient2_(image_and_gradient2),
@@ -1044,6 +1172,9 @@ void CreateBrutePattern(const double *x1, const double *y1,
// correlation. Instead, this is a dumb implementation. Surprisingly, it is
// fast enough in practice.
//
+// Returns true if any alignment was found, and false if the projected pattern
+// is zero sized.
+//
// TODO(keir): The normalization is less effective for the brute force search
// than it is with the Ceres solver. It's unclear if this is a bug or due to
// the original frame being too different from the reprojected reference in the
@@ -1054,7 +1185,7 @@ void CreateBrutePattern(const double *x1, const double *y1,
// totally different warping interface, since access to more than a the source
// and current destination frame is necessary.
template<typename Warp>
-void BruteTranslationOnlyInitialize(const FloatImage &image1,
+bool BruteTranslationOnlyInitialize(const FloatImage &image1,
const FloatImage *image1_mask,
const FloatImage &image2,
const int num_extra_points,
@@ -1100,6 +1231,7 @@ void BruteTranslationOnlyInitialize(const FloatImage &image1,
int best_c = -1;
int w = pattern.cols();
int h = pattern.rows();
+
for (int r = 0; r < (image2.Height() - h); ++r) {
for (int c = 0; c < (image2.Width() - w); ++c) {
// Compute the weighted sum of absolute differences, Eigen style. Note
@@ -1124,8 +1256,12 @@ void BruteTranslationOnlyInitialize(const FloatImage &image1,
}
}
}
- CHECK_NE(best_r, -1);
- CHECK_NE(best_c, -1);
+
+ // This mean the effective pattern area is zero. This check could go earlier,
+ // but this is less code.
+ if (best_r == -1 || best_c == -1) {
+ return false;
+ }
LG << "Brute force translation found a shift. "
<< "best_c: " << best_c << ", best_r: " << best_r << ", "
@@ -1140,6 +1276,7 @@ void BruteTranslationOnlyInitialize(const FloatImage &image1,
x2[i] += best_c - origin_x;
y2[i] += best_r - origin_y;
}
+ return true;
}
} // namespace
@@ -1191,12 +1328,19 @@ void TemplatedTrackRegion(const FloatImage &image1,
if (SearchAreaTooBigForDescent(image2, x2, y2) &&
options.use_brute_initialization) {
LG << "Running brute initialization...";
- BruteTranslationOnlyInitialize<Warp>(image_and_gradient1,
- options.image1_mask,
- image2,
- options.num_extra_points,
- options.use_normalized_intensities,
- x1, y1, x2, y2);
+ bool found_any_alignment = BruteTranslationOnlyInitialize<Warp>(
+ image_and_gradient1,
+ options.image1_mask,
+ image2,
+ options.num_extra_points,
+ options.use_normalized_intensities,
+ x1, y1, x2, y2);
+ if (!found_any_alignment) {
+ LG << "Brute failed to find an alignment; pattern too small. "
+ << "Failing entire track operation.";
+ result->termination = TrackRegionResult::INSUFFICIENT_PATTERN_AREA;
+ return;
+ }
for (int i = 0; i < 4; ++i) {
LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); brute ("
<< x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i])
@@ -1260,14 +1404,15 @@ void TemplatedTrackRegion(const FloatImage &image1,
// Configure the solve.
ceres::Solver::Options solver_options;
- solver_options.linear_solver_type = ceres::DENSE_QR;
+ solver_options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY;
solver_options.max_num_iterations = options.max_iterations;
solver_options.update_state_every_iteration = true;
solver_options.parameter_tolerance = 1e-16;
solver_options.function_tolerance = 1e-16;
- // Prevent the corners from going outside the destination image.
- BoundaryCheckingCallback<Warp> callback(image2, warp, x1, y1);
+ // Prevent the corners from going outside the destination image and
+ // terminate if the optimizer is making tiny moves (converged).
+ TerminationCheckingCallback<Warp> callback(options, image2, warp, x1, y1);
solver_options.callbacks.push_back(&callback);
// Run the solve.
@@ -1290,11 +1435,21 @@ void TemplatedTrackRegion(const FloatImage &image1,
// TODO(keir): Update the result statistics.
// TODO(keir): Add a normalize-cross-correlation variant.
- CHECK_NE(summary.termination_type, ceres::USER_ABORT) << "Libmv bug.";
if (summary.termination_type == ceres::USER_ABORT) {
result->termination = TrackRegionResult::FELL_OUT_OF_BOUNDS;
return;
}
+
+ // This happens when the minimum corner shift tolerance is reached. Due to
+ // how the tolerance is computed this can't be done by Ceres. So return the
+ // same termination enum as Ceres, even though this is slightly different
+ // than Ceres's parameter tolerance, which operates on the raw parameter
+ // values rather than the pixel shifts of the patch corners.
+ if (summary.termination_type == ceres::USER_SUCCESS) {
+ result->termination = TrackRegionResult::PARAMETER_TOLERANCE;
+ return;
+ }
+
#define HANDLE_TERMINATION(termination_enum) \
if (summary.termination_type == ceres::termination_enum) { \
result->termination = TrackRegionResult::termination_enum; \
@@ -1377,11 +1532,11 @@ bool SamplePlanarPatch(const FloatImage &image,
image_position(0),
&(*patch)(r, c, 0));
if (mask) {
- float maskValue = SampleLinear(*mask, image_position(1),
- image_position(0), 0);
+ float mask_value = SampleLinear(*mask, image_position(1),
+ image_position(0), 0);
for (int d = 0; d < image.Depth(); d++)
- (*patch)(r, c, d) *= maskValue;
+ (*patch)(r, c, d) *= mask_value;
}
}
}
diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h
index 22ecfc54a15..cd7ee0aa2ba 100644
--- a/extern/libmv/libmv/tracking/track_region.h
+++ b/extern/libmv/libmv/tracking/track_region.h
@@ -90,6 +90,11 @@ struct TrackRegionOptions {
// If zero, no regularization is used.
double regularization_coefficient;
+ // If the maximum shift of any patch corner between successful iterations of
+ // the solver is less than this amount, then the tracking is declared
+ // successful. The solver termination becomes PARAMETER_TOLERANCE.
+ double minimum_corner_shift_tolerance_pixels;
+
// If non-null, this is used as the pattern mask. It should match the size of
// image1, even though only values inside the image1 quad are examined. The
// values must be in the range 0.0 to 0.1.
@@ -111,6 +116,7 @@ struct TrackRegionResult {
DESTINATION_OUT_OF_BOUNDS,
FELL_OUT_OF_BOUNDS,
INSUFFICIENT_CORRELATION,
+ INSUFFICIENT_PATTERN_AREA,
CONFIGURATION_ERROR,
};
Termination termination;
diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt
index e6a9e430c47..0ce8e273f4a 100644
--- a/extern/libmv/third_party/ceres/CMakeLists.txt
+++ b/extern/libmv/third_party/ceres/CMakeLists.txt
@@ -38,6 +38,7 @@ set(INC_SYS
)
set(SRC
+ internal/ceres/array_utils.cc
internal/ceres/block_evaluate_preparer.cc
internal/ceres/block_jacobian_writer.cc
internal/ceres/block_jacobi_preconditioner.cc
@@ -53,16 +54,19 @@ set(SRC
internal/ceres/conditioned_cost_function.cc
internal/ceres/conjugate_gradients_solver.cc
internal/ceres/corrector.cc
+ internal/ceres/cxsparse.cc
+ internal/ceres/dense_normal_cholesky_solver.cc
internal/ceres/dense_qr_solver.cc
internal/ceres/dense_sparse_matrix.cc
internal/ceres/detect_structure.cc
+ internal/ceres/dogleg_strategy.cc
internal/ceres/evaluator.cc
internal/ceres/file.cc
internal/ceres/generated/schur_eliminator_d_d_d.cc
internal/ceres/gradient_checking_cost_function.cc
internal/ceres/implicit_schur_complement.cc
internal/ceres/iterative_schur_complement_solver.cc
- internal/ceres/levenberg_marquardt.cc
+ internal/ceres/levenberg_marquardt_strategy.cc
internal/ceres/linear_least_squares_problems.cc
internal/ceres/linear_operator.cc
internal/ceres/linear_solver.cc
@@ -70,6 +74,7 @@ set(SRC
internal/ceres/loss_function.cc
internal/ceres/normal_prior.cc
internal/ceres/partitioned_matrix_view.cc
+ internal/ceres/polynomial_solver.cc
internal/ceres/problem.cc
internal/ceres/problem_impl.cc
internal/ceres/program.cc
@@ -88,6 +93,8 @@ set(SRC
internal/ceres/stringprintf.cc
internal/ceres/suitesparse.cc
internal/ceres/triplet_sparse_matrix.cc
+ internal/ceres/trust_region_minimizer.cc
+ internal/ceres/trust_region_strategy.cc
internal/ceres/types.cc
internal/ceres/visibility_based_preconditioner.cc
internal/ceres/visibility.cc
@@ -96,6 +103,8 @@ set(SRC
include/ceres/ceres.h
include/ceres/conditioned_cost_function.h
include/ceres/cost_function.h
+ include/ceres/crs_matrix.h
+ include/ceres/fpclassify.h
include/ceres/internal/autodiff.h
include/ceres/internal/eigen.h
include/ceres/internal/fixed_array.h
@@ -114,6 +123,7 @@ set(SRC
include/ceres/sized_cost_function.h
include/ceres/solver.h
include/ceres/types.h
+ internal/ceres/array_utils.h
internal/ceres/block_evaluate_preparer.h
internal/ceres/block_jacobian_writer.h
internal/ceres/block_jacobi_preconditioner.h
@@ -131,10 +141,13 @@ set(SRC
internal/ceres/compressed_row_sparse_matrix.h
internal/ceres/conjugate_gradients_solver.h
internal/ceres/corrector.h
+ internal/ceres/cxsparse.h
internal/ceres/dense_jacobian_writer.h
+ internal/ceres/dense_normal_cholesky_solver.h
internal/ceres/dense_qr_solver.h
internal/ceres/dense_sparse_matrix.h
internal/ceres/detect_structure.h
+ internal/ceres/dogleg_strategy.h
internal/ceres/evaluator.h
internal/ceres/file.h
internal/ceres/gradient_checking_cost_function.h
@@ -143,7 +156,7 @@ set(SRC
internal/ceres/implicit_schur_complement.h
internal/ceres/integral_types.h
internal/ceres/iterative_schur_complement_solver.h
- internal/ceres/levenberg_marquardt.h
+ internal/ceres/levenberg_marquardt_strategy.h
internal/ceres/linear_least_squares_problems.h
internal/ceres/linear_operator.h
internal/ceres/linear_solver.h
@@ -153,6 +166,7 @@ set(SRC
internal/ceres/mutex.h
internal/ceres/parameter_block.h
internal/ceres/partitioned_matrix_view.h
+ internal/ceres/polynomial_solver.h
internal/ceres/problem_impl.h
internal/ceres/program_evaluator.h
internal/ceres/program.h
@@ -168,10 +182,13 @@ set(SRC
internal/ceres/solver_impl.h
internal/ceres/sparse_matrix.h
internal/ceres/sparse_normal_cholesky_solver.h
+ internal/ceres/split.h
internal/ceres/stl_util.h
internal/ceres/stringprintf.h
internal/ceres/suitesparse.h
internal/ceres/triplet_sparse_matrix.h
+ internal/ceres/trust_region_minimizer.h
+ internal/ceres/trust_region_strategy.h
internal/ceres/visibility_based_preconditioner.h
internal/ceres/visibility.h
)
@@ -203,7 +220,7 @@ if(WIN32)
if(NOT MINGW)
list(APPEND INC
- third_party/msinttypes
+ ../msinttypes
)
endif()
else()
@@ -214,11 +231,30 @@ endif()
add_definitions(
-DCERES_HAVE_PTHREAD
- -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {"
- -D"CERES_HASH_NAMESPACE_END=}}"
-DCERES_NO_SUITESPARSE
- -DCERES_DONT_HAVE_PROTOCOL_BUFFERS
+ -DCERES_NO_CXSPARSE
+ -DCERES_NO_PROTOCOL_BUFFERS
-DCERES_RESTRICT_SCHUR_SPECIALIZATION
)
+if(MSVC10)
+ add_definitions(
+ -D"CERES_HASH_NAMESPACE_START=namespace std {"
+ -D"CERES_HASH_NAMESPACE_END=}"
+ )
+else()
+ add_definitions(
+ -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {"
+ -D"CERES_HASH_NAMESPACE_END=}}"
+ )
+endif()
+
+if(APPLE)
+ if(CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.5")
+ add_definitions(
+ -DCERES_NO_TR1
+ )
+ endif()
+endif()
+
blender_add_lib(extern_ceres "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog
index 6e919658f13..8b84328cf98 100644
--- a/extern/libmv/third_party/ceres/ChangeLog
+++ b/extern/libmv/third_party/ceres/ChangeLog
@@ -1,324 +1,524 @@
-commit ca72152362ae1f4b9928c012e74b4d49d094a4ca
-Merge: d297f8d 0a04199
-Author: Keir Mierle <mierle@gmail.com>
-Date: Wed May 9 13:10:59 2012 -0700
+commit 552f9f85bba89f00ca307bc18fbda1dff23bd0e4
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Fri Aug 31 07:27:22 2012 -0700
- Merge branch 'master' into windows
+ Various minor bug fixes to the solver logic.
+
+ 1. CostFunction returning false is handled better.
+ If only the cost is being evaluated, it is possible to
+ use the false value as an infinite value signal/outside
+ a region of validity. This allows a weak form of constraint
+ handling. Useful for example in handling infinities.
+
+ 2. Changed the way how the slop around zero when model_cost
+ is larger than the current cost. Relative instead of absolute
+ tolerances are used. The same logic is propagated how the
+ corresponding clamping of the model_cost is done.
+
+ 3. Fixed a minor indexing bug in nist.cc.
+
+ 4. Some minor logging fixes to nist.cc to make it more
+ compatible with the rest of ceres.
+
+ Together these changes, take the successful solve count from
+ 41/54 to 46/54 and eliminate all NUMERICAL_FAILURE problems.
+
+ Change-Id: If94170ea4731af5b243805c0200963dd31aa94a7
-commit 0a04199ef279cc9ea97f665fed8e7fae717813c3
-Merge: fdeb577 f2571f1
-Author: Keir Mierle <mierle@gmail.com>
-Date: Wed May 9 12:54:56 2012 -0700
+commit 0b776b5cc9634d3b88d623905b96006f7647ce3e
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Thu Aug 30 15:26:17 2012 -0700
- Merge branch 'master' of https://code.google.com/p/ceres-solver
+ Update docs.
+
+ Change-Id: I69d50bcd37aed3bea2190ca614f023e83172901b
-commit fdeb5772cc5eeebca4d776d220d80cc91b6d0f74
-Author: Keir Mierle <mierle@gmail.com>
-Date: Wed May 9 07:38:07 2012 -0700
+commit 2d7176ad7c8fb7238ca8abd6de73415d95877494
+Author: Petter Strandmark <petter.strandmark@gmail.com>
+Date: Thu Aug 30 19:51:24 2012 -0700
- Support varying numbers of residuals in autodiff.
+ max_consecutive_nonmonotonic_steps should be int
- This commit modifies the only function in autodiff that takes a
- templated number of outputs (i.e. residuals) and makes that
- template parameter a normal parameter. With that change, it
- is a trivial matter to support a dynamic number of residuals.
+ Found via Visual Studio warning.
- The API for dynamic residuals is to pass a fake number of
- residuals as the second template argument to
- AutoDiffCostFunction, and to pass the real number of
- parameters as a second constructor argument.
+ Change-Id: Id2cd7de562dfc8cd35df5d5f5220dd2d7350eb2c
-commit da3e0563cc12e08e7b3e0fbf11d9cc8cfe9658aa
+commit 1a89bcc94e88933f89b20427a45bc40cdd23c056
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed May 9 11:57:47 2012 -0700
+Date: Thu Aug 30 15:26:17 2012 -0700
- Typo corrections in the documentation from Bing
+ Better reporting on the NIST problems.
+
+ Change-Id: I7cf774ec3242c0612dbe52fc233c3fc6cff3f031
-commit aa9526d8e8fb34c23d63e3af5bf9239b0c4ea603
+commit ea11704857a1e4a735e096896e4d775d83981499
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue May 8 21:22:09 2012 -0700
+Date: Wed Aug 29 18:18:48 2012 -0700
- Share search paths across various library searches.
- Fix typos in glog search.
- Split the error messages for include and lib.
- Enable building of tests by default.
- Made building on homebrew installations a bit better.
- Remove temporary variables for glog and gflags.
+ Basic harness for testing NIST problems.
+
+ Change-Id: I5baaa24dbf0506ceedf4a9be4ed17c84974d71a1
-commit f2571f186850ed3dd316236ac4be488979df7d30
+commit 98bf14d2b95386c2c4a6c29154637943dae4c36c
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed May 9 11:57:47 2012 -0700
+Date: Thu Aug 30 10:26:44 2012 -0700
- Typo corrections in the documentation from Bing
+ Miscellaneous fixes.
+
+ Change-Id: I521e11f2d20bf24960bbc6b5dab4ec8bb1503d23
-commit 8f7f11ff7d07737435428a2620c52419cf99f98e
-Merge: e6c17c4 eaccbb3
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed May 9 11:34:15 2012 -0700
+commit 1e3cbd9a4442cdd8fda43a7fb452f19dac8c74af
+Author: Petter Strandmark <strandmark@google.com>
+Date: Wed Aug 29 09:39:56 2012 -0700
- Merge branch 'master' of https://code.google.com/p/ceres-solver
+ Caching the symbolic Cholesky factorization when using CXSparse
+
+ Average factorization times for bundle adjustment test problem:
+ SuiteSparse: 0.2794 s.
+ CXSparse: 0.4039 s.
+ CXSparse cached: 0.2399 s.
+
+ CXSparse will still be slower, though, because it has to compute
+ the transpose and J^T * J.
+
+ Change-Id: If9cdaa3dd520bee84b56e5fd4953b56a93db6bde
-commit e6c17c4c9d9307218f6f739cea39bc2d87733d4d
+commit 8b64140878ccd1e183d3715c38942a81fdecefde
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue May 8 21:22:09 2012 -0700
+Date: Wed Aug 29 05:41:22 2012 -0700
- Share search paths across various library searches.
- Fix typos in glog search.
- Split the error messages for include and lib.
- Enable building of tests by default.
- Made building on homebrew installations a bit better.
- Remove temporary variables for glog and gflags.
+ Documentation update
+
+ Change-Id: I271a0422e7f6f42bcfd1dc6b5dc10c7a18f6a179
-commit eaccbb345614c0d24c5e21fa931f470cfda874df
-Author: Keir Mierle <mierle@gmail.com>
-Date: Wed May 9 05:31:29 2012 -0700
+commit a5353acd85a9fd19370b3d74035d87b0f0bac230
+Author: Petter Strandmark <petter.strandmark@gmail.com>
+Date: Tue Aug 28 18:16:41 2012 -0700
- Remove unused template parameter from VariadicEvaluate.
+ Adding gflags include to test_util.cc
+
+ test_util seems to need gflags.
+
+ Change-Id: I0c4757960f8ac69ad599c138aea58e3c88a4ea28
-commit 82f4b88c34b0b2cf85064e5fc20e374e978b2e3b
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun May 6 21:05:28 2012 -0700
+commit 87ca1b2ba28ec512752bbcf5fc994ce1434eb765
+Author: Petter Strandmark <petter.strandmark@gmail.com>
+Date: Tue Aug 28 18:05:20 2012 -0700
- Extend support writing linear least squares problems to disk.
+ Changing random.h to use cstdlib for Windows compability.
- 1. Make the mechanism for writing problems to disk, generic and
- controllable using an enum DumpType visible in the API.
+ As discussed with Sameer today.
- 2. Instead of single file containing protocol buffers, now matrices can
- be written in a matlab/octave friendly format. This is now the default.
+ Change-Id: If3d0284830c6591c71cc77b8400cafb45c0da61f
+
+commit aeb00a07323808a0a1816e733ad18a87d5109ea3
+Author: Petter Strandmark <strandmark@google.com>
+Date: Mon Aug 27 22:22:57 2012 -0700
+
+ Removing gomp for Visual Studio
- 3. The support for writing problems to disk is moved into
- linear_least_squares_problem.cc/h
+ Linking currently fails in Visual Studio due to a missing library
+ "gomp.lib". This is not needed in Visual Studio. OpenMP works
+ without it.
+
+ Change-Id: I39e204a8dd4f1b7425df7d4b222d86a8bb961432
+
+commit 6f362464ba99b800494d2f15c27768a342ddaa68
+Author: Markus Moll <markus.moll@esat.kuleuven.be>
+Date: Tue Aug 28 01:03:38 2012 +0200
+
+ Add some tests for DoglegStrategy.
- 4. SparseMatrix now has a ToTextFile virtual method which is
- implemented by each of its subclasses to write a (i,j,s) triplets.
+ Not necessarily a complete set.
- 5. Minor changes to simple_bundle_adjuster to enable logging at startup.
+ Change-Id: I14eb3a38c6fe976c8212f3934655411b6d1e0aa4
-commit d297f8d3d3f5025c24752f0f4c1ec2469a769f99
-Merge: 7e74d81 f8bd7fa
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 8 05:39:56 2012 -0700
+commit 122cf836a6dc9726489ce2fbecc6143bddc1caaf
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Fri Aug 24 16:28:27 2012 -0700
- Merge branch 'master' into windows
+ Documentation update.
+
+ Change-Id: I0a3c5ae4bc981a8f5bdd5a8905f923dc5f09a024
-commit f8bd7fa9aa9dbf64b6165606630287cf8cf21194
+commit 69081719f73da8de2935774a42d237837a91952a
Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 8 05:39:32 2012 -0700
+Date: Mon Aug 27 13:28:56 2012 -0700
- Small tweaks to the block jacobi preconditioner.
+ Remove unnecessary overload for hash<>
+
+ The overload for pointers in hash tables was applied in normal
+ usage of schur_ordering.cc. However, the tests did not include the
+ overload since they only included collections_port.h. As a result,
+ the routines in schur_ordering.cc were using a different hash
+ function than that inside the tests.
+
+ The fix is to remove the specialization. If this breaks one of the
+ compiler configurations, we will find a workaround at that time.
+
+ Change-Id: Idbf60415d5e2aec0c865b514ad0c577d21b91405
-commit 7e74d81ad57a159f14110eb5348b3bc7990b8bd4
-Merge: ecd7c8d e2a6cdc
-Author: Keir Mierle <mierle@gmail.com>
-Date: Mon May 7 07:02:49 2012 -0700
+commit 1762420b6ed76b1c4d30b913b2cac1927b666534
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Aug 22 10:01:31 2012 -0700
- Merge branch 'master' into windows
+ Update changelog.
+
+ Change-Id: Idf5af69d5a9dbe35f58e30a8afcbfcd29bb7ebfe
-commit e2a6cdc0816af9d0c77933f5017f137da3d52a35
+commit 976ab7aca908309b8282cb40bc080ca859136854
Author: Keir Mierle <mierle@gmail.com>
-Date: Mon May 7 06:39:56 2012 -0700
+Date: Thu Aug 23 18:21:36 2012 -0700
- Address some of the comments on CGNR patch
+ Remove Google-era vestigial unit test.
- - Rename BlockDiagonalPreconditioner to BlockJacobiPreconditioner
- - Include the diagonal in the block jacobi preconditioner.
- - Better flag help for eta.
- - Enable test for CGNR
- - Rename CONJUGATE_GRADIENTS to CGNR.
- - etc.
+ Change-Id: Ia7a295a5c759a17c1675a3055d287d3e40e9e0fe
-commit 1b95dc580aa5d89be021c0915e26df83f18013bb
-Merge: 211812a 7646039
+commit 6ad6257de0e2152ac5e77dc003758de45187d6ea
Author: Keir Mierle <mierle@gmail.com>
-Date: Mon May 7 04:34:10 2012 -0700
+Date: Wed Aug 22 11:10:31 2012 -0700
- Merge branch 'master' of https://code.google.com/p/ceres-solver
+ Add a workaround for an Android NDK compiler bug.
+
+ On certain NDK build configurations, one of the innermost
+ parts of the Schur eliminator would get compiled
+ incorrectly. The compiler changed a -= to a +=.
+
+ The normal Ceres unit tests caught the problem; however,
+ since it is not possible to build the tests with the NDK
+ (only with the standalone toolchain) this was difficult to
+ track down. Finding the issue involved pasting the schur
+ eliminator unit test inside of solver_impl.cc and other such
+ hacks.
+
+ Change-Id: Ie91bb545d74fe39f0c8cbd1a6eb69ee4d8b25fb2
-commit 211812a57360d2011cbcfd115cd55e0eb73600db
-Author: Keir Mierle <mierle@gmail.com>
-Date: Mon May 7 04:33:50 2012 -0700
+commit aecb2dc92b4aa7f3bf77a1ac918e62953602392b
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Aug 22 10:08:17 2012 -0700
- Better error handling in bundle_adjuster.cc
+ Fix relative path bug in bibtex call.
+
+ Change-Id: I0d31786564320a6831259bcdf4c75a6b665c43ad
-commit 7646039ad9672b267495f5b31925473ad3022ac8
+commit 1e2892009e591804df6286caebd5c960e7e3b099
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun May 6 22:02:19 2012 -0700
+Date: Tue Aug 21 18:00:54 2012 -0700
- Kashif's corrections to the docs
+ Update Summary::FullReport to report dogleg type.
+
+ Change-Id: I0b4be8d7486c1c4b36b299693b3fe8b0d3426537
-commit 0d2d34148d10c5c7e924b3ca82ad2b237573ef64
+commit 295ade1122a86b83e1ea605d5ca394f315874717
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun May 6 21:16:03 2012 -0700
+Date: Wed Aug 22 06:51:22 2012 -0700
- glog minimum version requirements
+ Fix Eigen3 Row/Column Major storage issue.
- Building Ceres requires version 0.3.1 or better of glog.
- Fedora 16 ships with a busted version 0.3.
+ Eigen3 does not allow column vectors to be stored in row-major
+ format. NumericDiffCostFunction by default stores its Jacobian
+ matrices in row-major format. This works fine if the residual
+ contains more than one variable. But if the residual block
+ depends on one variable and has more than one residuals, the
+ resulting Jacobian matrix is a column matrix in row-major format
+ resulting in a compile time error.
- issue 15 contains the gory details.
+ The fix is to check the template parameters and switch to column-major
+ storage as needed.
- Added a note to the build documentation to this effect.
+ Thanks to Lena Gieseke for reporting this.
+
+ Change-Id: Icc51c5b38e1f3609e0e1ecb3c4e4a02aecd72c3b
-commit 39efc5ec4b64b8f5a2c5a3dbacdbc45421221547
-Author: Keir Mierle <mierle@gmail.com>
-Date: Sun May 6 16:09:52 2012 -0700
+commit 9ad27e8e9fb1bbd2054e2f6ae37623e01428f1c0
+Author: Arnaud Gelas <arnaudgelas@gmail.com>
+Date: Tue Aug 21 09:56:30 2012 +0200
- Fix tests broken by the CGNR change.
+ Add one uninstall target to remove all installed files
+
+ Change-Id: Ifcf89a6c27b25f28403d95a50e29c093a525298f
-commit 3faa08b7f7c4ac73661c6a15a6824c12080dfcb1
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun May 6 16:08:22 2012 -0700
+commit 0c3a748ee49e04fe334f8f5a433649d18003d550
+Author: Markus Moll <markus.moll@esat.kuleuven.be>
+Date: Tue Aug 21 14:44:59 2012 +0200
- Formatting fixed based on Keir's comments and extended the tests
+ Allow equal lower and upper bound for diagonal scaling.
+
+ This way, setting the lower and upper bound both to 1.0, one can disable
+ the automatic trust region scaling.
+
+ Change-Id: Ifa317a6911b813a89c1cf7fdfde25af603705319
-commit 4f21c68409bc478c431a9b6aedf9e5cfdf11d2f3
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun May 6 15:33:47 2012 -0700
+commit 3d644b76adefac6475b91dc53c3ae5e01c4f4d66
+Author: Arnaud Gelas <arnaudgelas@gmail.com>
+Date: Thu Aug 16 17:33:21 2012 +0200
- Fix the struct weak ordering used by independent set ordering, tests for it
+ Install headers, libraries and pdf
+
+ Headers are installed in ${CMAKE_INSTALL_PREFIX}/include/ceres
+ Libraries are installed in ${CMAKE_INSTALL_PREFIX}/lib
+ pdf is installed in ${CMAKE_INSTALL_PREFIX}/share/ceres/docs
+
+ Change-Id: Ic175f2c2f5fa86820a1e8c64c2ed171f4a302a68
-commit 887b156b917ccd4c172484452b059d33ea45f4f0
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun May 6 15:14:47 2012 -0700
+commit d2fb5adea4d8c2aeb43c4289c6976798a54d3cf1
+Author: Arnaud Gelas <arnaudgelas@gmail.com>
+Date: Fri Aug 17 10:11:02 2012 +0200
- fix he degree ordering routine
+ Configure gerrit hook at CMake time
+
+ If the source directory is a clone, at CMake time the commit-msg hook gets
+ downloaded and installed in the right location.
+
+ Change-Id: I5fee17d050ca22d8b92a49fdcc2a1cd6659f209b
-commit ecd7c8df2af19404dc394b36bbe96e9db3bce840
-Author: Keir Mierle <mierle@gmail.com>
-Date: Sun May 6 00:09:41 2012 -0700
+commit 73166098fc4b1072adc30321c666188a3909c43c
+Author: Arnaud Gelas <arnaudgelas@gmail.com>
+Date: Mon Aug 20 15:40:41 2012 +0200
- First step towards windows compatibilty
+ Add one CMake option to build the examples.
+
+ Currently the examples are always built. For external projects, it is useful
+ not to compile the examples.
- This adds some small changes to Ceres to make it mostly
- compile on Windows. There are still issues with the
- hash map use in schur_ordering.cc but I will fix those
- shortly.
+ Change-Id: I41d3bde19c7e742818e60f78222d39c43992ca8b
-commit f7898fba1b92f0e996571b5bfa22a37f5e3644de
+commit 86d4f1ba41ef14eb1b6b61a7936af83387b35eb2
Author: Keir Mierle <mierle@gmail.com>
-Date: Sat May 5 20:55:08 2012 -0700
+Date: Mon Aug 20 11:52:04 2012 -0700
- Add a general sparse iterative solver: CGNR
+ Add missing return statement.
- This adds a new LinearOperator which implements symmetric
- products of a matrix, and a new CGNR solver to leverage
- CG to directly solve the normal equations. This also
- includes a block diagonal preconditioner. In experiments
- on problem-16, the non-preconditioned version is about
- 1/5 the speed of SPARSE_SCHUR, and the preconditioned
- version using block cholesky is about 20% slower than
- SPARSE_SCHUR.
+ Change-Id: I5eaf718318e27040e3c97e32ee46cf0a11176a37
-commit 0a359d6198d257776a8831c3eb98f64ee91cf836
+commit 51eb229da34187a4e8ce73ed9cc0e731998bb2be
Author: Keir Mierle <mierle@gmail.com>
-Date: Sat May 5 20:33:46 2012 -0700
+Date: Mon Aug 20 11:46:12 2012 -0700
- Comment formatting.
+ Add Program::ToString() to aid debugging.
+
+ Change-Id: I0ab37ed2fe0947ca87a152919d4e7dc9b56dedc6
-commit db4ec9312bb2f1ca7b2337812f6bad6cdd75b227
+commit bcc7100635e2047dc2b77df19a4ded8a6ab4d4b9
Author: Keir Mierle <mierle@gmail.com>
-Date: Sat May 5 20:33:16 2012 -0700
+Date: Mon Aug 20 11:45:04 2012 -0700
- Comment formatting
+ Ignore minted.sty.
+
+ Change-Id: I2467a6f801812b9007b51bf14b00757f026e4322
-commit f10163aaf3e57f52551bcd60bbdae873890a49dd
+commit 9705a736dd3d6fbead0d8a6ff77102c69bbcdc08
Author: Keir Mierle <mierle@gmail.com>
-Date: Fri May 4 21:33:53 2012 -0700
+Date: Mon Aug 20 11:24:05 2012 -0700
- Warn about disabled schur specializations.
+ Add ParameterBlock::ToString() to aid debugging.
- This commit brought to you from 30,000ft.
+ Change-Id: Id3f5cb27b855c536dd65a986f345bd8eb2799dfa
-commit ad7b2b4aaf3ccc51f2b854febd53a9df54686cfe
-Author: Keir Mierle <mierle@gmail.com>
-Date: Fri May 4 20:15:28 2012 -0700
+commit 0c714a70e6123ceb68e5cfcd3cfbee0d09deb1db
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Aug 20 11:18:16 2012 -0700
+
+ Fix blanks before private in loss_function.h
+
+ Change-Id: I068bed6431bc7c9b7958af391655df61499000b2
+
+commit 51cf7cbe3bac45c6807c2703a2fc3175d76a1b47
+Author: Markus Moll <markus.moll@esat.kuleuven.be>
+Date: Mon Aug 20 20:10:20 2012 +0200
+
+ Add the two-dimensional subspace search to DoglegStrategy
+
+ Change-Id: I5163744c100cdf07dd93343d0734ffe0e80364f3
- Add vim swapfiles to .gitignore
+commit ad1f7b772e559a911ac3a3b078b0aee1836fe785
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Aug 20 11:10:34 2012 -0700
+
+ Add ArcTanLoss, TolerantLoss and ComposedLossFunction.
+
+ Based on work by James Roseborough.
+
+ Change-Id: Idc4e0b099028f67702bfc7fe3e43dbd96b6f9256
-commit 6447219826bf6e47b0c99d9ff0eaf5e2ba573d79
+commit 05292bf8fc5208b86b4a13544615b584f6efa936
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu May 3 21:53:07 2012 -0700
+Date: Mon Aug 20 07:40:45 2012 -0700
+
+ Add a TrustRegionStrategy::Summary object.
+
+ Change-Id: I7caee35a3408ee4a0ec16ba407410d822929340d
- 1. Changes the tutorial to refer to BriefReport.
- 2. Some of the enums have commas at the end.
- 3. Fix a bug in the default value of circle_fit.cc in the examples.
+commit b12b906c4d21c3949f0dce62c4c0d083c8edecf1
+Author: Arnaud Gelas <arnaudgelas@gmail.com>
+Date: Wed Aug 15 16:27:38 2012 +0200
-commit 30c5f93c7f88dec49f76168663372772e06f17f5
+ Add one option to generate the PDF from CMake at build time
+
+ Make sure pygmentize is installed
+
+ Change-Id: I068ba45c33a8e96acc906a464b12d10d58b3e231
+
+commit b9f15a59361c609ffc4a328aea9be3d265b5da81
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu May 3 10:44:43 2012 -0700
+Date: Sat Aug 18 13:06:19 2012 -0700
+
+ Add a dense Cholesky factorization based linear solver.
+
+ For problems with a small number of variables, but a large
+ number of residuals, it is sometimes beneficial to use the
+ Cholesky factorization on the normal equations, instead of
+ the dense QR factorization of the Jacobian, even though it
+ is numerically the better thing to do.
+
+ Change-Id: I3506b006195754018deec964e6e190b7e8c9ac8f
- Rework the glog and gtest path checking to be consistent with the rest of the file and disable the dashboard support enabled by the earlier ctesting related patch.
+commit b3fa009435acf476cd373052e62988f6437970b1
+Author: Arnaud Gelas <arnaudgelas@gmail.com>
+Date: Fri Aug 17 10:31:41 2012 +0200
-commit f10b033eb4aca77919987bc551d16d8a88b10110
-Merge: cc38774 e0a52a9
+ Set CMAKE_*_OUTPUT_DIRECTORY
+
+ Gather
+ * all executables in ${CMAKE_BINARY_DIR}/bin
+ * all libraries (static and dynamic) in ${CMAKE_BINARY_DIR}/lib
+
+ Change-Id: Ibc2fa1adfb6f0aea65d66d570259b79546bf3b07
+
+commit 1b8a4d5d11671ed83cf6077e363dd95333f08ef8
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu May 3 08:45:20 2012 -0700
+Date: Fri Aug 17 16:49:11 2012 -0700
+
+ Fix a minor bug in detect_structure logging.
+
+ Change-Id: I117f7745e4c67595b3ff9244cde82b5b5b34ee4b
- Merge branch 'ctest'
+commit 31c1e784ab2cb9294c6e05414cf06aae2b3766de
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri Aug 17 16:16:32 2012 -0700
+
+ Minor cleanups.
+
+ Change-Id: Ida4866997deeaa1bc2cebd6b69313a05ac82e457
-commit e0a52a993394e73bc7f7db8d520728926feab83e
+commit e83f7879a8b21c6976e116958caf35bcdcf41cb0
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu May 3 08:43:34 2012 -0700
+Date: Fri Aug 17 15:34:42 2012 -0700
- Arnaus Gelas' patch to add better path searching for gflags and glog
+ Fix SuiteSparse3 UFConfig.h detection really.
+
+ Change-Id: Id187102e755b7d778dff4363f22f9a4697ed12dd
-commit a9b8e815e1c026599734510399b10f4cf014c9cd
+commit 96f25dc57658d296ee6b6633818b4f1e51d7d587
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu May 3 08:41:52 2012 -0700
+Date: Fri Aug 17 15:34:42 2012 -0700
+
+ Fix SuiteSparse3 UFConfig.h detection.
+
+ Change-Id: Ia59aefdb0ad7f713f76ed79692f2db4fa2821e5b
+
+commit c497bd6cd9aa944f518aa491d3bc645851ff9594
+Author: Markus Moll <markus.moll@esat.kuleuven.be>
+Date: Fri Aug 17 14:40:13 2012 +0200
- Arnaus Gelas' patch to add .gitignore
+ Add UFconfig and/or SuiteSparse_config test to CMakeLists.txt
+
+ SuiteSparse 4 requires linking to libsuitesparseconfig.a.
+ Both SuiteSparse 3 and SuiteSparse 4 require an additional header
+ (either UFconfig.h or SuiteSparse_config.h) that is not found if it is
+ in a separate path. Therefore, add explicit checks.
+
+ Change-Id: I699902b5db4f1b7f17134b5a54f9aa681445e294
-commit a0cefc3347c32b2065053bbaff4f34d11529d931
+commit 383c04f4236d92801c7c674892814362dedf7ad6
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu May 3 08:38:33 2012 -0700
+Date: Fri Aug 17 10:14:04 2012 -0700
- Arnaus Gelas' patch to move to Ctest
+ Fix QuaternionToAngleAxis to ensure rotations are between -pi and pi.
+
+ Thanks to Guoxuan Zhang for reporting this.
+
+ Change-Id: I2831ca3a04d5dc6467849c290461adbe23faaea3
-commit cc38774d74e287704915282425fbd16818a72ec3
-Author: Keir Mierle <mierle@gmail.com>
-Date: Thu May 3 01:27:50 2012 -0700
+commit dd2b17d7dd9750801ba4720bdece2062e59b7ae3
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Thu Aug 16 19:34:57 2012 -0700
- Clarify ProgramEvaluator comments.
+ CERES_DONT_HAVE_PROTOCOL_BUFFERS -> CERES_NO_PROTOCOL_BUFFERS.
+
+ Change-Id: I6c9f50e4c006faf4e75a8f417455db18357f3187
-commit 017c9530df557863f78212fb5ccd02814baa9fa8
+commit 8b4cb7aa2c74a0da62c638b2023566aa242af995
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed May 2 08:21:59 2012 -0700
+Date: Thu Aug 16 19:26:55 2012 -0700
- Mac OS X build instructions are much simpler, as homebrew takes care of gflags when glog is brought in. Also CMAKE does not need any flags to do the default thing
+ Fix sparse linear algebra library logging in Summary::FullReport.
+
+ Change-Id: Id2c902dc86c00954fde7749c7b4a67dd94215a31
-commit 92d5ab5f8ae6fe355c30b606a5f230415ee0494b
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 1 18:33:08 2012 -0700
+commit 47d26bcd3b38b5ff53b34768c33b499d47b26bd0
+Author: Markus Moll <markus.moll@esat.kuleuven.be>
+Date: Thu Aug 16 00:23:38 2012 +0200
- Link BLAS explicitly on non-Mac platforms
+ Do not implicitly negate the step in the TrustRegionMinimizer.
- Fixes issue #3.
+ In the TrustRegionMinimizer, the step is currently implicitly negated.
+ This is done so that the linearized residual is |r - J*step|^2, which
+ corresponds to J*step = r, so neither J nor r have to be modified.
+ However, it leads to the rather unintuitive situation that the strategy
+ returns a step in positive gradient direction, which you would expect to
+ increase the function value. One way is to rename the "step" parameter in
+ the strategy to "negative_step" and document it.
+ This patch instead moves the negation inside the strategy, just around
+ the linear solver call, so that it is done in a local context and easier
+ to document.
+
+ Change-Id: Idb258149a01f61c64e22128ea221c5a30cd89c89
-commit df3e54eb4a6b001b7f0560a2da73a5bd7f18615e
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 1 18:22:51 2012 -0700
+commit 51da590c8457e6664f76fe9813425a0c71351497
+Author: Markus Moll <markus.moll@esat.kuleuven.be>
+Date: Fri Aug 17 12:56:09 2012 +0200
+
+ Remove tmp file
+
+ Change-Id: I07496fafae7b0c5c12cc26ae336e0db3b5592735
+
+commit 7006a1f2b1701b8d89b8d1525fc0101943802221
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Thu Aug 16 18:04:22 2012 -0700
- Fix link order of CHOLMOD
+ Correct example code in Powell's function example.
+
+ Thanks to Petter Strandmark for pointing this out.
- This was working by accident due to dynamic linking. Fixes issue #2.
+ Change-Id: I967632235dccdb481396e94904bb911c9a1efe1e
-commit f477a3835329e2b48eb20c34c631a480b0f0d5bf
+commit 57a44b27bc6fc95b4e70fdc25c25c9925a2072a0
Author: Keir Mierle <mierle@gmail.com>
-Date: Tue May 1 18:10:48 2012 -0700
+Date: Thu Aug 16 17:04:50 2012 -0700
- Fix Eigen search paths
+ Remove unnecessary flags in NDK build.
- Fixes issue #1 on http://code.google.com/p/ceres-solver.
+ Change-Id: Ib5b4d0b7f2d898671252734978c789b8171d96a8
-commit 17fbc8ebb894c1d22bb3b0b02ea1394b580120f8
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue May 1 00:21:19 2012 -0700
+commit f21bee247251a8b2e836c215a84c4668c31d75cd
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu Aug 16 16:27:10 2012 -0700
- Minor changes to the documentation. Formatting, and typos.
+ Fix for fpclassify.h NDK porting work.
+
+ Change-Id: I69df1b4caf2941ed96a53e35e43ec54073f84f59
-commit 8ebb0730388045570f22b89fe8672c860cd2ad1b
+commit 8ceb02cb75b66602de44a35e413225386cb21c27
Author: Keir Mierle <mierle@gmail.com>
-Date: Mon Apr 30 23:09:08 2012 -0700
+Date: Thu Aug 16 14:23:47 2012 -0700
- Initial commit of Ceres Solver.
+ Add Android NDK build files.
+
+ This adds a Android.mk build that builds a Ceres static library
+ suitable for embetting in larger Android applications. This is
+ useful when needing to build Ceres without GPL'd components, since
+ the standalone toolchain (needed for the CMake Android build) does
+ not work with STLPort.
+
+ Change-Id: I8d857237f6f82658741017d161b2e31d9a20e5a7
diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript
index c629fa00176..6d0d2cd5c40 100644
--- a/extern/libmv/third_party/ceres/SConscript
+++ b/extern/libmv/third_party/ceres/SConscript
@@ -20,9 +20,13 @@ defs.append('CERES_HAVE_PTHREAD')
defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {')
defs.append('CERES_HASH_NAMESPACE_END=}}')
defs.append('CERES_NO_SUITESPARSE')
-defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS')
+defs.append('CERES_NO_CXSPARSE')
+defs.append('CERES_NO_PROTOCOL_BUFFERS')
defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION')
+if 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']:
+ defs.append('CERES_NO_TR1')
+
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags'
# work around broken hashtable in 10.5 SDK
diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh
index 99aaadd8d87..902fce5f398 100755
--- a/extern/libmv/third_party/ceres/bundle.sh
+++ b/extern/libmv/third_party/ceres/bundle.sh
@@ -1,6 +1,5 @@
#!/bin/sh
-if false; then
if [ "x$1" = "x--i-really-know-what-im-doing" ] ; then
echo Proceeding as requested by command line ...
else
@@ -8,16 +7,22 @@ else
exit 1
fi
-repo="https://code.google.com/p/ceres-solver/"
-branch="windows"
+repo="https://ceres-solver.googlesource.com/ceres-solver"
+branch="master"
+tag="1.3.0"
tmp=`mktemp -d`
+checkout="$tmp/ceres"
-GIT="git --git-dir $tmp/ceres/.git --work-tree $tmp/ceres"
+GIT="git --git-dir $tmp/ceres/.git --work-tree $checkout"
-git clone $repo $tmp/ceres
+git clone $repo $checkout
if [ $branch != "master" ]; then
$GIT checkout -t remotes/origin/$branch
+else
+ if [ "x$tag" != "x" ]; then
+ $GIT checkout $tag
+ fi
fi
$GIT log -n 50 > ChangeLog
@@ -37,8 +42,6 @@ done
rm -rf $tmp
-fi
-
sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | grep -v -E 'schur_eliminator_[0-9]_[0-9]_[0-9d].cc' | sort -d`
generated_sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//#\t\t/' | grep -E 'schur_eliminator_[0-9]_[0-9]_[0-9d].cc' | sort -d`
headers=`find ./include ./internal -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d`
@@ -142,7 +145,7 @@ if(WIN32)
if(NOT MINGW)
list(APPEND INC
- third_party/msinttypes
+ ../msinttypes
)
endif()
else()
@@ -153,13 +156,32 @@ endif()
add_definitions(
-DCERES_HAVE_PTHREAD
- -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {"
- -D"CERES_HASH_NAMESPACE_END=}}"
-DCERES_NO_SUITESPARSE
- -DCERES_DONT_HAVE_PROTOCOL_BUFFERS
+ -DCERES_NO_CXSPARSE
+ -DCERES_NO_PROTOCOL_BUFFERS
-DCERES_RESTRICT_SCHUR_SPECIALIZATION
)
+if(MSVC10)
+ add_definitions(
+ -D"CERES_HASH_NAMESPACE_START=namespace std {"
+ -D"CERES_HASH_NAMESPACE_END=}"
+ )
+else()
+ add_definitions(
+ -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {"
+ -D"CERES_HASH_NAMESPACE_END=}}"
+ )
+endif()
+
+if(APPLE)
+ if(CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.5")
+ add_definitions(
+ -DCERES_NO_TR1
+ )
+ endif()
+endif()
+
blender_add_lib(extern_ceres "\${SRC}" "\${INC}" "\${INC_SYS}")
EOF
@@ -186,11 +208,20 @@ defs.append('CERES_HAVE_PTHREAD')
defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {')
defs.append('CERES_HASH_NAMESPACE_END=}}')
defs.append('CERES_NO_SUITESPARSE')
-defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS')
+defs.append('CERES_NO_CXSPARSE')
+defs.append('CERES_NO_PROTOCOL_BUFFERS')
defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION')
+if 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']:
+ defs.append('CERES_NO_TR1')
+
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags'
+# work around broken hashtable in 10.5 SDK
+if env['OURPLATFORM'] == 'darwin' and env['WITH_BF_BOOST']:
+ incs += ' ' + env['BF_BOOST_INC']
+ defs.append('CERES_HASH_BOOST')
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ../msinttypes'
diff --git a/extern/libmv/third_party/ceres/files.txt b/extern/libmv/third_party/ceres/files.txt
index e9d7f585260..55083572977 100644
--- a/extern/libmv/third_party/ceres/files.txt
+++ b/extern/libmv/third_party/ceres/files.txt
@@ -2,6 +2,8 @@ include/ceres/autodiff_cost_function.h
include/ceres/ceres.h
include/ceres/conditioned_cost_function.h
include/ceres/cost_function.h
+include/ceres/crs_matrix.h
+include/ceres/fpclassify.h
include/ceres/internal/autodiff.h
include/ceres/internal/eigen.h
include/ceres/internal/fixed_array.h
@@ -20,6 +22,8 @@ include/ceres/rotation.h
include/ceres/sized_cost_function.h
include/ceres/solver.h
include/ceres/types.h
+internal/ceres/array_utils.cc
+internal/ceres/array_utils.h
internal/ceres/block_evaluate_preparer.cc
internal/ceres/block_evaluate_preparer.h
internal/ceres/block_jacobian_writer.cc
@@ -52,13 +56,19 @@ internal/ceres/conjugate_gradients_solver.cc
internal/ceres/conjugate_gradients_solver.h
internal/ceres/corrector.cc
internal/ceres/corrector.h
+internal/ceres/cxsparse.cc
+internal/ceres/cxsparse.h
internal/ceres/dense_jacobian_writer.h
+internal/ceres/dense_normal_cholesky_solver.cc
+internal/ceres/dense_normal_cholesky_solver.h
internal/ceres/dense_qr_solver.cc
internal/ceres/dense_qr_solver.h
internal/ceres/dense_sparse_matrix.cc
internal/ceres/dense_sparse_matrix.h
internal/ceres/detect_structure.cc
internal/ceres/detect_structure.h
+internal/ceres/dogleg_strategy.cc
+internal/ceres/dogleg_strategy.h
internal/ceres/evaluator.cc
internal/ceres/evaluator.h
internal/ceres/file.cc
@@ -79,6 +89,7 @@ internal/ceres/generated/schur_eliminator_4_4_3.cc
internal/ceres/generated/schur_eliminator_4_4_4.cc
internal/ceres/generated/schur_eliminator_4_4_d.cc
internal/ceres/generated/schur_eliminator_d_d_d.cc
+internal/ceres/generate_eliminator_specialization.py
internal/ceres/gradient_checking_cost_function.cc
internal/ceres/gradient_checking_cost_function.h
internal/ceres/graph_algorithms.h
@@ -88,8 +99,8 @@ internal/ceres/implicit_schur_complement.h
internal/ceres/integral_types.h
internal/ceres/iterative_schur_complement_solver.cc
internal/ceres/iterative_schur_complement_solver.h
-internal/ceres/levenberg_marquardt.cc
-internal/ceres/levenberg_marquardt.h
+internal/ceres/levenberg_marquardt_strategy.cc
+internal/ceres/levenberg_marquardt_strategy.h
internal/ceres/linear_least_squares_problems.cc
internal/ceres/linear_least_squares_problems.h
internal/ceres/linear_operator.cc
@@ -106,6 +117,8 @@ internal/ceres/normal_prior.cc
internal/ceres/parameter_block.h
internal/ceres/partitioned_matrix_view.cc
internal/ceres/partitioned_matrix_view.h
+internal/ceres/polynomial_solver.cc
+internal/ceres/polynomial_solver.h
internal/ceres/problem.cc
internal/ceres/problem_impl.cc
internal/ceres/problem_impl.h
@@ -136,6 +149,7 @@ internal/ceres/sparse_matrix.h
internal/ceres/sparse_normal_cholesky_solver.cc
internal/ceres/sparse_normal_cholesky_solver.h
internal/ceres/split.cc
+internal/ceres/split.h
internal/ceres/stl_util.h
internal/ceres/stringprintf.cc
internal/ceres/stringprintf.h
@@ -143,6 +157,10 @@ internal/ceres/suitesparse.cc
internal/ceres/suitesparse.h
internal/ceres/triplet_sparse_matrix.cc
internal/ceres/triplet_sparse_matrix.h
+internal/ceres/trust_region_minimizer.cc
+internal/ceres/trust_region_minimizer.h
+internal/ceres/trust_region_strategy.cc
+internal/ceres/trust_region_strategy.h
internal/ceres/types.cc
internal/ceres/visibility_based_preconditioner.cc
internal/ceres/visibility_based_preconditioner.h
diff --git a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
index e86d6993864..da9ee2c7993 100644
--- a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
@@ -163,7 +163,7 @@ class AutoDiffCostFunction :
explicit AutoDiffCostFunction(CostFunctor* functor)
: functor_(functor) {
CHECK_NE(M, DYNAMIC) << "Can't run the fixed-size constructor if the "
- << "number of residuals is set to ceres::DYNAMIC.";
+ << "number of residuals is set to ceres::DYNAMIC.";
}
// Takes ownership of functor. Ignores the template-provided number of
@@ -174,7 +174,7 @@ class AutoDiffCostFunction :
AutoDiffCostFunction(CostFunctor* functor, int num_residuals)
: functor_(functor) {
CHECK_EQ(M, DYNAMIC) << "Can't run the dynamic-size constructor if the "
- << "number of residuals is not ceres::DYNAMIC.";
+ << "number of residuals is not ceres::DYNAMIC.";
SizedCostFunction<M, N0, N1, N2, N3, N4, N5>::set_num_residuals(num_residuals);
}
diff --git a/extern/libmv/third_party/ceres/include/ceres/cost_function.h b/extern/libmv/third_party/ceres/include/ceres/cost_function.h
index 84403d90636..9b010f78f9d 100644
--- a/extern/libmv/third_party/ceres/include/ceres/cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/cost_function.h
@@ -119,7 +119,7 @@ class CostFunction {
// number of outputs (residuals).
vector<int16> parameter_block_sizes_;
int num_residuals_;
- DISALLOW_COPY_AND_ASSIGN(CostFunction);
+ CERES_DISALLOW_COPY_AND_ASSIGN(CostFunction);
};
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h b/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h
new file mode 100644
index 00000000000..c9fe8f78b7c
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_PUBLIC_CRS_MATRIX_H_
+#define CERES_PUBLIC_CRS_MATRIX_H_
+
+#include <vector>
+#include "ceres/internal/port.h"
+
+namespace ceres {
+
+// A compressed row sparse matrix used primarily for communicating the
+// Jacobian matrix to the user.
+struct CRSMatrix {
+ CRSMatrix() : num_rows(0), num_cols(0) {}
+
+ int num_rows;
+ int num_cols;
+
+ // A compressed row matrix stores its contents in three arrays.
+ // The non-zero pattern of the i^th row is given by
+ //
+ // rows[cols[i] ... cols[i + 1]]
+ //
+ // and the corresponding values by
+ //
+ // values[cols[i] ... cols[i + 1]]
+ //
+ // Thus, cols is a vector of size num_cols + 1, and rows and values
+ // have as many entries as number of non-zeros in the matrix.
+ vector<int> cols;
+ vector<int> rows;
+ vector<double> values;
+};
+
+} // namespace ceres
+
+#endif // CERES_PUBLIC_CRS_MATRIX_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/fpclassify.h b/extern/libmv/third_party/ceres/include/ceres/fpclassify.h
new file mode 100644
index 00000000000..5a9ea1599d2
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/fpclassify.h
@@ -0,0 +1,88 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keir@google.com (Keir Mierle)
+//
+// Portable floating point classification. The names are picked such that they
+// do not collide with macros. For example, "isnan" in C99 is a macro and hence
+// does not respect namespaces.
+//
+// TODO(keir): Finish porting!
+
+#ifndef CERES_PUBLIC_FPCLASSIFY_H_
+#define CERES_PUBLIC_FPCLASSIFY_H_
+
+#if defined(_MSC_VER)
+#include <float.h>
+#endif
+
+namespace ceres {
+
+#if defined(_MSC_VER)
+inline bool IsFinite (double x) { return _finite(x); }
+inline bool IsInfinite(double x) { return !_finite(x) && !_isnan(x); }
+inline bool IsNaN (double x) { return _isnan(x); }
+inline bool IsNormal (double x) {
+ int classification = _fpclass(x);
+ return classification == _FPCLASS_NN ||
+ classification == _FPCLASS_PN;
+}
+#elif defined(ANDROID)
+
+// On Android when using the GNU STL, the C++ fpclassify functions are not
+// available. Strictly speaking, the std functions are are not standard until
+// C++11. Instead use the C99 macros on Android.
+inline bool IsNaN (double x) { return isnan(x); }
+inline bool IsNormal (double x) { return isnormal(x); }
+
+// On Android NDK r6, when using STLPort, the isinf and isfinite functions are
+// not available, so reimplement them.
+# if defined(_STLPORT_VERSION)
+inline bool IsInfinite(double x) {
+ return x == std::numeric_limits<double>::infinity() ||
+ x == -std::numeric_limits<double>::infinity();
+}
+inline bool IsFinite(double x) {
+ return !isnan(x) && !IsInfinite(x);
+}
+# else
+inline bool IsFinite (double x) { return isfinite(x); }
+inline bool IsInfinite(double x) { return isinf(x); }
+# endif // defined(_STLPORT_VERSION)
+#else
+// These definitions are for the normal Unix suspects.
+// TODO(keir): Test the "else" with more platforms.
+inline bool IsFinite (double x) { return std::isfinite(x); }
+inline bool IsInfinite(double x) { return std::isinf(x); }
+inline bool IsNaN (double x) { return std::isnan(x); }
+inline bool IsNormal (double x) { return std::isnormal(x); }
+#endif
+
+} // namespace ceres
+
+#endif // CERES_PUBLIC_FPCLASSIFY_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
index 84617c4fa06..ce777d22dc7 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
@@ -34,6 +34,8 @@
#include <cstddef>
#include <glog/logging.h>
+#include "Eigen/Core"
+#include "ceres/internal/macros.h"
#include "ceres/internal/manual_constructor.h"
namespace ceres {
@@ -136,7 +138,6 @@ class FixedArray {
// and T must be the same, otherwise callers' assumptions about use
// of this code will be broken.
struct InnerContainer {
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW
T element;
};
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
index 0cfd773bcca..83ec31193e7 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
@@ -43,11 +43,13 @@
//
// For disallowing only assign or copy, write the code directly, but declare
// the intend in a comment, for example:
-// void operator=(const TypeName&); // DISALLOW_ASSIGN
-// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
-// semantically, one should either use disallow both or neither. Try to
-// avoid these in new code.
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+//
+// void operator=(const TypeName&); // _DISALLOW_ASSIGN
+
+// Note, that most uses of CERES_DISALLOW_ASSIGN and CERES_DISALLOW_COPY
+// are broken semantically, one should either use disallow both or
+// neither. Try to avoid these in new code.
+#define CERES_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
@@ -57,9 +59,9 @@
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
-#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+#define CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
- DISALLOW_COPY_AND_ASSIGN(TypeName)
+ CERES_DISALLOW_COPY_AND_ASSIGN(TypeName)
// The arraysize(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
@@ -151,4 +153,19 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
#define MUST_USE_RESULT
#endif
+// Platform independent macros to get aligned memory allocations.
+// For example
+//
+// MyFoo my_foo CERES_ALIGN_ATTRIBUTE(16);
+//
+// Gives us an instance of MyFoo which is aligned at a 16 byte
+// boundary.
+#if defined(_MSC_VER)
+#define CERES_ALIGN_ATTRIBUTE(n) __declspec(align(n))
+#define CERES_ALIGN_OF(T) __alignof(T)
+#elif defined(__GNUC__)
+#define CERES_ALIGN_ATTRIBUTE(n) __attribute__((aligned(n)))
+#define CERES_ALIGN_OF(T) __alignof(T)
+#endif
+
#endif // CERES_PUBLIC_INTERNAL_MACROS_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h
index a1d1f444e36..174d35ee2bd 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h
@@ -45,60 +45,49 @@
namespace ceres {
namespace internal {
-// ------- Define ALIGNED_CHAR_ARRAY --------------------------------
+// ------- Define CERES_ALIGNED_CHAR_ARRAY --------------------------------
-#ifndef ALIGNED_CHAR_ARRAY
+#ifndef CERES_ALIGNED_CHAR_ARRAY
// Because MSVC and older GCCs require that the argument to their alignment
// construct to be a literal constant integer, we use a template instantiated
// at all the possible powers of two.
template<int alignment, int size> struct AlignType { };
template<int size> struct AlignType<0, size> { typedef char result[size]; };
-#if defined(_MSC_VER)
-#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __declspec(align(X))
-#define BASE_PORT_H_ALIGN_OF(T) __alignof(T)
-#elif defined(__GNUC__)
-#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __attribute__((aligned(X)))
-#define BASE_PORT_H_ALIGN_OF(T) __alignof__(T)
-#endif
-#if defined(BASE_PORT_H_ALIGN_ATTRIBUTE)
+#if !defined(CERES_ALIGN_ATTRIBUTE)
+#define CERES_ALIGNED_CHAR_ARRAY you_must_define_CERES_ALIGNED_CHAR_ARRAY_for_your_compiler
+#else // !defined(CERES_ALIGN_ATTRIBUTE)
-#define BASE_PORT_H_ALIGNTYPE_TEMPLATE(X) \
+#define CERES_ALIGN_TYPE_TEMPLATE(X) \
template<int size> struct AlignType<X, size> { \
- typedef BASE_PORT_H_ALIGN_ATTRIBUTE(X) char result[size]; \
- }
-
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(1);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(2);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(4);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(8);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(16);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(32);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(64);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(128);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(256);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(512);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(1024);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(2048);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(4096);
-BASE_PORT_H_ALIGNTYPE_TEMPLATE(8192);
+ typedef CERES_ALIGN_ATTRIBUTE(X) char result[size]; \
+ }
+
+CERES_ALIGN_TYPE_TEMPLATE(1);
+CERES_ALIGN_TYPE_TEMPLATE(2);
+CERES_ALIGN_TYPE_TEMPLATE(4);
+CERES_ALIGN_TYPE_TEMPLATE(8);
+CERES_ALIGN_TYPE_TEMPLATE(16);
+CERES_ALIGN_TYPE_TEMPLATE(32);
+CERES_ALIGN_TYPE_TEMPLATE(64);
+CERES_ALIGN_TYPE_TEMPLATE(128);
+CERES_ALIGN_TYPE_TEMPLATE(256);
+CERES_ALIGN_TYPE_TEMPLATE(512);
+CERES_ALIGN_TYPE_TEMPLATE(1024);
+CERES_ALIGN_TYPE_TEMPLATE(2048);
+CERES_ALIGN_TYPE_TEMPLATE(4096);
+CERES_ALIGN_TYPE_TEMPLATE(8192);
// Any larger and MSVC++ will complain.
-#define ALIGNED_CHAR_ARRAY(T, Size) \
- typename AlignType<BASE_PORT_H_ALIGN_OF(T), sizeof(T) * Size>::result
+#undef CERES_ALIGN_TYPE_TEMPLATE
-#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE
-#undef BASE_PORT_H_ALIGN_ATTRIBUTE
+#define CERES_ALIGNED_CHAR_ARRAY(T, Size) \
+ typename AlignType<CERES_ALIGN_OF(T), sizeof(T) * Size>::result
-#else // defined(BASE_PORT_H_ALIGN_ATTRIBUTE)
-#define ALIGNED_CHAR_ARRAY you_must_define_ALIGNED_CHAR_ARRAY_for_your_compiler
-#endif // defined(BASE_PORT_H_ALIGN_ATTRIBUTE)
+#endif // !defined(CERES_ALIGN_ATTRIBUTE)
-#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE
-#undef BASE_PORT_H_ALIGN_ATTRIBUTE
-
-#endif // ALIGNED_CHAR_ARRAY
+#endif // CERES_ALIGNED_CHAR_ARRAY
template <typename Type>
class ManualConstructor {
@@ -203,10 +192,10 @@ class ManualConstructor {
}
private:
- ALIGNED_CHAR_ARRAY(Type, 1) space_;
+ CERES_ALIGNED_CHAR_ARRAY(Type, 1) space_;
};
-#undef ALIGNED_CHAR_ARRAY
+#undef CERES_ALIGNED_CHAR_ARRAY
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/port.h b/extern/libmv/third_party/ceres/include/ceres/internal/port.h
index 9a3e5cced58..a9fe247cef5 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/port.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/port.h
@@ -31,6 +31,8 @@
#ifndef CERES_PUBLIC_INTERNAL_PORT_H_
#define CERES_PUBLIC_INTERNAL_PORT_H_
+#include <string>
+
namespace ceres {
// It is unfortunate that this import of the entire standard namespace is
@@ -39,6 +41,10 @@ namespace ceres {
// things outside of the Ceres optimization package.
using namespace std;
+// This is necessary to properly handle the case that there is a different
+// "string" implementation in the global namespace.
+using std::string;
+
} // namespace ceres
#endif // CERES_PUBLIC_INTERNAL_PORT_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
index 88da992d0c5..29157d380f2 100644
--- a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
+++ b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
@@ -28,8 +28,9 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
-// When an iteration callback is specified, Ceres calls the callback after each
-// optimizer step and pass it an IterationSummary object, defined below.
+// When an iteration callback is specified, Ceres calls the callback
+// after each minimizer step (if the minimizer has not converged) and
+// passes it an IterationSummary object, defined below.
#ifndef CERES_PUBLIC_ITERATION_CALLBACK_H_
#define CERES_PUBLIC_ITERATION_CALLBACK_H_
@@ -44,7 +45,15 @@ struct IterationSummary {
// Current iteration number.
int32 iteration;
+ // Step was numerically valid, i.e., all values are finite and the
+ // step reduces the value of the linearized model.
+ //
+ // Note: step_is_valid is false when iteration = 0.
+ bool step_is_valid;
+
// Whether or not the algorithm made progress in this iteration.
+ //
+ // Note: step_is_successful is false when iteration = 0.
bool step_is_successful;
// Value of the objective function.
@@ -66,9 +75,10 @@ struct IterationSummary {
// cost and the change in the cost of the linearized approximation.
double relative_decrease;
- // Value of the regularization parameter for Levenberg-Marquardt
- // algorithm at the end of the current iteration.
- double mu;
+ // Size of the trust region at the end of the current iteration. For
+ // the Levenberg-Marquardt algorithm, the regularization parameter
+ // mu = 1.0 / trust_region_radius.
+ double trust_region_radius;
// For the inexact step Levenberg-Marquardt algorithm, this is the
// relative accuracy with which the Newton(LM) step is solved. This
@@ -81,13 +91,15 @@ struct IterationSummary {
// Newton step.
int linear_solver_iterations;
- // TODO(sameeragarwal): Change to use a higher precision timer using
- // clock_gettime.
- // Time (in seconds) spent inside the linear least squares solver.
- int iteration_time_sec;
+ // Time (in seconds) spent inside the minimizer loop in the current
+ // iteration.
+ double iteration_time_in_seconds;
+
+ // Time (in seconds) spent inside the trust region step solver.
+ double step_solver_time_in_seconds;
- // Time (in seconds) spent inside the linear least squares solver.
- int linear_solver_time_sec;
+ // Time (in seconds) since the user called Solve().
+ double cumulative_time_in_seconds;
};
// Interface for specifying callbacks that are executed at the end of
@@ -133,7 +145,7 @@ struct IterationSummary {
// summary.gradient_max_norm,
// summary.step_norm,
// summary.relative_decrease,
-// summary.mu,
+// summary.trust_region_radius,
// summary.eta,
// summary.linear_solver_iterations);
// if (log_to_stdout_) {
diff --git a/extern/libmv/third_party/ceres/include/ceres/jet.h b/extern/libmv/third_party/ceres/include/ceres/jet.h
index a37870210f1..96e2256fd02 100644
--- a/extern/libmv/third_party/ceres/include/ceres/jet.h
+++ b/extern/libmv/third_party/ceres/include/ceres/jet.h
@@ -162,16 +162,7 @@
#include <string>
#include "Eigen/Core"
-
-// Visual Studio 2012 or older version
-#if defined(_MSC_VER) && _MSC_VER <= 1700
-namespace std {
-inline bool isfinite(double x) { return _finite(x); }
-inline bool isinf (double x) { return !_finite(x) && !_isnan(x); }
-inline bool isnan (double x) { return _isnan(x); }
-inline bool isnormal(double x) { return _finite(x) && x != 0.0; }
-} // namespace std
-#endif
+#include "ceres/fpclassify.h"
namespace ceres {
@@ -184,7 +175,9 @@ struct Jet {
// (where T is a Jet<T, N>). This usually only happens in opt mode. Note that
// the C++ standard mandates that e.g. default constructed doubles are
// initialized to 0.0; see sections 8.5 of the C++03 standard.
- Jet() : a() {}
+ Jet() : a() {
+ v.setZero();
+ }
// Constructor from scalar: a + 0.
explicit Jet(const T& value) {
@@ -199,18 +192,6 @@ struct Jet {
v[k] = T(1.0);
}
- /*
-
- // Construct from an array where the first element is the scalar.
- // This is templated to support converting from other data types.
- template<typename D>
- Jet(const D* scalar_and_derivatives) {
- a = T(scalar_and_derivatives[0]);
- v = Eigen::Map<const Eigen::Matrix<D, N, 1> >(
- scalar_and_derivatives + 1, N).cast<T>();
- }
- */
-
// Compound operators
Jet<T, N>& operator+=(const Jet<T, N> &y) {
*this = *this + y;
@@ -232,8 +213,25 @@ struct Jet {
return *this;
}
- T a; // The scalar part.
- Eigen::Matrix<T, N, 1> v; // The infinitesimal part.
+ // The scalar part.
+ T a;
+
+ // The infinitesimal part.
+ //
+ // Note the Eigen::DontAlign bit is needed here because this object
+ // gets allocated on the stack and as part of other arrays and
+ // structs. Forcing the right alignment there is the source of much
+ // pain and suffering. Even if that works, passing Jets around to
+ // functions by value has problems because the C++ ABI does not
+ // guarantee alignment for function arguments.
+ //
+ // Setting the DontAlign bit prevents Eigen from using SSE for the
+ // various operations on Jets. This is a small performance penalty
+ // since the AutoDiff code will still expose much of the code as
+ // statically sized loops to the compiler. But given the subtle
+ // issues that arise due to alignment, especially when dealing with
+ // multiple platforms, it seems to be a trade off worth making.
+ Eigen::Matrix<T, N, 1, Eigen::DontAlign> v;
};
// Unary +
@@ -411,10 +409,6 @@ inline double cos (double x) { return std::cos(x); }
inline double acos (double x) { return std::acos(x); }
inline double sin (double x) { return std::sin(x); }
inline double asin (double x) { return std::asin(x); }
-inline bool isfinite(double x) { return std::isfinite(x); }
-inline bool isinf (double x) { return std::isinf(x); }
-inline bool isnan (double x) { return std::isnan(x); }
-inline bool isnormal(double x) { return std::isnormal(x); }
inline double pow (double x, double y) { return std::pow(x, y); }
inline double atan2(double y, double x) { return std::atan2(y, x); }
@@ -492,22 +486,23 @@ Jet<T, N> asin(const Jet<T, N>& f) {
}
// Jet Classification. It is not clear what the appropriate semantics are for
-// these classifications. This picks that isfinite and isnormal are "all"
-// operations, i.e. all elements of the jet must be finite for the jet itself to
-// be finite (or normal). For isnan and isinf, the answer is less clear. This
-// takes a "any" approach for isnan and isinf such that if any part of a jet is
-// nan or inf, then the entire jet is nan or inf. This leads to strange
-// situations like a jet can be both isinf and isnan, but in practice the "any"
-// semantics are the most useful for e.g. checking that derivatives are sane.
+// these classifications. This picks that IsFinite and isnormal are "all"
+// operations, i.e. all elements of the jet must be finite for the jet itself
+// to be finite (or normal). For IsNaN and IsInfinite, the answer is less
+// clear. This takes a "any" approach for IsNaN and IsInfinite such that if any
+// part of a jet is nan or inf, then the entire jet is nan or inf. This leads
+// to strange situations like a jet can be both IsInfinite and IsNaN, but in
+// practice the "any" semantics are the most useful for e.g. checking that
+// derivatives are sane.
// The jet is finite if all parts of the jet are finite.
template <typename T, int N> inline
-bool isfinite(const Jet<T, N>& f) {
- if (!isfinite(f.a)) {
+bool IsFinite(const Jet<T, N>& f) {
+ if (!IsFinite(f.a)) {
return false;
}
for (int i = 0; i < N; ++i) {
- if (!isfinite(f.v[i])) {
+ if (!IsFinite(f.v[i])) {
return false;
}
}
@@ -516,12 +511,12 @@ bool isfinite(const Jet<T, N>& f) {
// The jet is infinite if any part of the jet is infinite.
template <typename T, int N> inline
-bool isinf(const Jet<T, N>& f) {
- if (isinf(f.a)) {
+bool IsInfinite(const Jet<T, N>& f) {
+ if (IsInfinite(f.a)) {
return true;
}
for (int i = 0; i < N; i++) {
- if (isinf(f.v[i])) {
+ if (IsInfinite(f.v[i])) {
return true;
}
}
@@ -530,12 +525,12 @@ bool isinf(const Jet<T, N>& f) {
// The jet is NaN if any part of the jet is NaN.
template <typename T, int N> inline
-bool isnan(const Jet<T, N>& f) {
- if (isnan(f.a)) {
+bool IsNaN(const Jet<T, N>& f) {
+ if (IsNaN(f.a)) {
return true;
}
for (int i = 0; i < N; ++i) {
- if (isnan(f.v[i])) {
+ if (IsNaN(f.v[i])) {
return true;
}
}
@@ -544,12 +539,12 @@ bool isnan(const Jet<T, N>& f) {
// The jet is normal if all parts of the jet are normal.
template <typename T, int N> inline
-bool isnormal(const Jet<T, N>& f) {
- if (!isnormal(f.a)) {
+bool IsNormal(const Jet<T, N>& f) {
+ if (!IsNormal(f.a)) {
return false;
}
for (int i = 0; i < N; ++i) {
- if (!isnormal(f.v[i])) {
+ if (!IsNormal(f.v[i])) {
return false;
}
}
@@ -650,78 +645,6 @@ inline std::ostream &operator<<(std::ostream &s, const Jet<T, N>& z) {
return s << "[" << z.a << " ; " << z.v.transpose() << "]";
}
-// A jet traits class to make it easier to work with mixed auto / numeric diff.
-template<typename T>
-struct JetOps {
- static bool IsScalar() {
- return true;
- }
- static T GetScalar(const T& t) {
- return t;
- }
- static void SetScalar(const T& scalar, T* t) {
- *t = scalar;
- }
- static void ScaleDerivative(double scale_by, T *value) {
- // For double, there is no derivative to scale.
- }
-};
-
-template<typename T, int N>
-struct JetOps<Jet<T, N> > {
- static bool IsScalar() {
- return false;
- }
- static T GetScalar(const Jet<T, N>& t) {
- return t.a;
- }
- static void SetScalar(const T& scalar, Jet<T, N>* t) {
- t->a = scalar;
- }
- static void ScaleDerivative(double scale_by, Jet<T, N> *value) {
- value->v *= scale_by;
- }
-};
-
-template<typename FunctionType, int kNumArgs, typename ArgumentType>
-struct Chain {
- static ArgumentType Rule(const FunctionType &f,
- const FunctionType dfdx[kNumArgs],
- const ArgumentType x[kNumArgs]) {
- // In the default case of scalars, there's nothing to do since there are no
- // derivatives to propagate.
- return f;
- }
-};
-
-// XXX Add documentation here!
-template<typename FunctionType, int kNumArgs, typename T, int N>
-struct Chain<FunctionType, kNumArgs, Jet<T, N> > {
- static Jet<T, N> Rule(const FunctionType &f,
- const FunctionType dfdx[kNumArgs],
- const Jet<T, N> x[kNumArgs]) {
- // x is itself a function of another variable ("z"); what this function
- // needs to return is "f", but with the derivative with respect to z
- // attached to the jet. So combine the derivative part of x's jets to form
- // a Jacobian matrix between x and z (i.e. dx/dz).
- Eigen::Matrix<T, kNumArgs, N> dxdz;
- for (int i = 0; i < kNumArgs; ++i) {
- dxdz.row(i) = x[i].v.transpose();
- }
-
- // Map the input gradient dfdx into an Eigen row vector.
- Eigen::Map<const Eigen::Matrix<FunctionType, 1, kNumArgs> >
- vector_dfdx(dfdx, 1, kNumArgs);
-
- // Now apply the chain rule to obtain df/dz. Combine the derivative with
- // the scalar part to obtain f with full derivative information.
- Jet<T, N> jet_f;
- jet_f.a = f;
- jet_f.v = vector_dfdx.template cast<T>() * dxdz; // Also known as dfdz.
- return jet_f;
- }
-};
-
} // namespace ceres
namespace Eigen {
diff --git a/extern/libmv/third_party/ceres/include/ceres/loss_function.h b/extern/libmv/third_party/ceres/include/ceres/loss_function.h
index 81add02cdee..0c0ceaaecd0 100644
--- a/extern/libmv/third_party/ceres/include/ceres/loss_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/loss_function.h
@@ -175,6 +175,7 @@ class HuberLoss : public LossFunction {
public:
explicit HuberLoss(double a) : a_(a), b_(a * a) { }
virtual void Evaluate(double, double*) const;
+
private:
const double a_;
// b = a^2.
@@ -190,6 +191,7 @@ class SoftLOneLoss : public LossFunction {
public:
explicit SoftLOneLoss(double a) : b_(a * a), c_(1 / b_) { }
virtual void Evaluate(double, double*) const;
+
private:
// b = a^2.
const double b_;
@@ -206,6 +208,7 @@ class CauchyLoss : public LossFunction {
public:
explicit CauchyLoss(double a) : b_(a * a), c_(1 / b_) { }
virtual void Evaluate(double, double*) const;
+
private:
// b = a^2.
const double b_;
@@ -213,6 +216,78 @@ class CauchyLoss : public LossFunction {
const double c_;
};
+// Loss that is capped beyond a certain level using the arc-tangent function.
+// The scaling parameter 'a' determines the level where falloff occurs.
+// For costs much smaller than 'a', the loss function is linear and behaves like
+// TrivialLoss, and for values much larger than 'a' the value asymptotically
+// approaches the constant value of a * PI / 2.
+//
+// rho(s) = a atan(s / a).
+//
+// At s = 0: rho = [0, 1, 0].
+class ArctanLoss : public LossFunction {
+ public:
+ explicit ArctanLoss(double a) : a_(a), b_(1 / (a * a)) { }
+ virtual void Evaluate(double, double*) const;
+
+ private:
+ const double a_;
+ // b = 1 / a^2.
+ const double b_;
+};
+
+// Loss function that maps to approximately zero cost in a range around the
+// origin, and reverts to linear in error (quadratic in cost) beyond this range.
+// The tolerance parameter 'a' sets the nominal point at which the
+// transition occurs, and the transition size parameter 'b' sets the nominal
+// distance over which most of the transition occurs. Both a and b must be
+// greater than zero, and typically b will be set to a fraction of a.
+// The slope rho'[s] varies smoothly from about 0 at s <= a - b to
+// about 1 at s >= a + b.
+//
+// The term is computed as:
+//
+// rho(s) = b log(1 + exp((s - a) / b)) - c0.
+//
+// where c0 is chosen so that rho(0) == 0
+//
+// c0 = b log(1 + exp(-a / b)
+//
+// This has the following useful properties:
+//
+// rho(s) == 0 for s = 0
+// rho'(s) ~= 0 for s << a - b
+// rho'(s) ~= 1 for s >> a + b
+// rho''(s) > 0 for all s
+//
+// In addition, all derivatives are continuous, and the curvature is
+// concentrated in the range a - b to a + b.
+//
+// At s = 0: rho = [0, ~0, ~0].
+class TolerantLoss : public LossFunction {
+ public:
+ explicit TolerantLoss(double a, double b);
+ virtual void Evaluate(double, double*) const;
+
+ private:
+ const double a_, b_, c_;
+};
+
+// Composition of two loss functions. The error is the result of first
+// evaluating g followed by f to yield the composition f(g(s)).
+// The loss functions must not be NULL.
+class ComposedLoss : public LossFunction {
+ public:
+ explicit ComposedLoss(const LossFunction* f, Ownership ownership_f,
+ const LossFunction* g, Ownership ownership_g);
+ virtual ~ComposedLoss();
+ virtual void Evaluate(double, double*) const;
+
+ private:
+ internal::scoped_ptr<const LossFunction> f_, g_;
+ const Ownership ownership_f_, ownership_g_;
+};
+
// The discussion above has to do with length scaling: it affects the space
// in which s is measured. Sometimes you want to simply scale the output
// value of the robustifier. For example, you might want to weight
@@ -249,7 +324,7 @@ class ScaledLoss : public LossFunction {
internal::scoped_ptr<const LossFunction> rho_;
const double a_;
const Ownership ownership_;
- DISALLOW_COPY_AND_ASSIGN(ScaledLoss);
+ CERES_DISALLOW_COPY_AND_ASSIGN(ScaledLoss);
};
// Sometimes after the optimization problem has been constructed, we
@@ -314,7 +389,7 @@ class LossFunctionWrapper : public LossFunction {
private:
internal::scoped_ptr<const LossFunction> rho_;
Ownership ownership_;
- DISALLOW_COPY_AND_ASSIGN(LossFunctionWrapper);
+ CERES_DISALLOW_COPY_AND_ASSIGN(LossFunctionWrapper);
};
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
index bbaefca5b6c..8544e44d0bc 100644
--- a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
@@ -93,11 +93,13 @@ struct Differencer {
using Eigen::Map;
using Eigen::Matrix;
using Eigen::RowMajor;
+ using Eigen::ColMajor;
typedef Matrix<double, num_residuals, 1> ResidualVector;
typedef Matrix<double, parameter_block_size, 1> ParameterVector;
- typedef Matrix<double, num_residuals, parameter_block_size, RowMajor>
- JacobianMatrix;
+ typedef Matrix<double, num_residuals, parameter_block_size,
+ (parameter_block_size == 1 &&
+ num_residuals > 1) ? ColMajor : RowMajor> JacobianMatrix;
Map<JacobianMatrix> parameter_jacobian(jacobians[parameter_block],
num_residuals,
diff --git a/extern/libmv/third_party/ceres/include/ceres/problem.h b/extern/libmv/third_party/ceres/include/ceres/problem.h
index 0ca61006bdb..2b08c6723e8 100644
--- a/extern/libmv/third_party/ceres/include/ceres/problem.h
+++ b/extern/libmv/third_party/ceres/include/ceres/problem.h
@@ -50,13 +50,13 @@ namespace ceres {
class CostFunction;
class LossFunction;
class LocalParameterization;
+class Solver;
namespace internal {
class Preprocessor;
class ProblemImpl;
class ParameterBlock;
class ResidualBlock;
-class SolverImpl;
} // namespace internal
// A ResidualBlockId is a handle clients can use to delete residual
@@ -255,9 +255,9 @@ class Problem {
int NumResiduals() const;
private:
- friend class internal::SolverImpl;
+ friend class Solver;
internal::scoped_ptr<internal::ProblemImpl> problem_impl_;
- DISALLOW_COPY_AND_ASSIGN(Problem);
+ CERES_DISALLOW_COPY_AND_ASSIGN(Problem);
};
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/include/ceres/rotation.h b/extern/libmv/third_party/ceres/include/ceres/rotation.h
index e4227e78b9a..0d8a390d5d1 100644
--- a/extern/libmv/third_party/ceres/include/ceres/rotation.h
+++ b/extern/libmv/third_party/ceres/include/ceres/rotation.h
@@ -47,6 +47,7 @@
#include <algorithm>
#include <cmath>
+#include "glog/logging.h"
namespace ceres {
@@ -145,18 +146,11 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]);
// --- IMPLEMENTATION
-// Duplicate rather than decorate every use of cmath with _USE_MATH_CONSTANTS.
-// Necessitated by Windows.
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#define CERES_NEED_M_PI_UNDEF
-#endif
-
template<typename T>
inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) {
- const T &a0 = angle_axis[0];
- const T &a1 = angle_axis[1];
- const T &a2 = angle_axis[2];
+ const T& a0 = angle_axis[0];
+ const T& a1 = angle_axis[1];
+ const T& a2 = angle_axis[2];
const T theta_squared = a0 * a0 + a1 * a1 + a2 * a2;
// For points not at the origin, the full conversion is numerically stable.
@@ -183,16 +177,35 @@ inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) {
template<typename T>
inline void QuaternionToAngleAxis(const T* quaternion, T* angle_axis) {
- const T &q1 = quaternion[1];
- const T &q2 = quaternion[2];
- const T &q3 = quaternion[3];
- const T sin_squared = q1 * q1 + q2 * q2 + q3 * q3;
+ const T& q1 = quaternion[1];
+ const T& q2 = quaternion[2];
+ const T& q3 = quaternion[3];
+ const T sin_squared_theta = q1 * q1 + q2 * q2 + q3 * q3;
// For quaternions representing non-zero rotation, the conversion
// is numerically stable.
- if (sin_squared > T(0.0)) {
- const T sin_theta = sqrt(sin_squared);
- const T k = T(2.0) * atan2(sin_theta, quaternion[0]) / sin_theta;
+ if (sin_squared_theta > T(0.0)) {
+ const T sin_theta = sqrt(sin_squared_theta);
+ const T& cos_theta = quaternion[0];
+
+ // If cos_theta is negative, theta is greater than pi/2, which
+ // means that angle for the angle_axis vector which is 2 * theta
+ // would be greater than pi.
+ //
+ // While this will result in the correct rotation, it does not
+ // result in a normalized angle-axis vector.
+ //
+ // In that case we observe that 2 * theta ~ 2 * theta - 2 * pi,
+ // which is equivalent saying
+ //
+ // theta - pi = atan(sin(theta - pi), cos(theta - pi))
+ // = atan(-sin(theta), -cos(theta))
+ //
+ const T two_theta =
+ T(2.0) * ((cos_theta < 0.0)
+ ? atan2(-sin_theta, -cos_theta)
+ : atan2(sin_theta, cos_theta));
+ const T k = two_theta / sin_theta;
angle_axis[0] = q1 * k;
angle_axis[1] = q2 * k;
angle_axis[2] = q3 * k;
@@ -259,7 +272,7 @@ inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) {
// Case 2: theta ~ 0, means sin(theta) ~ theta to a good
// approximation.
- if (costheta > 0) {
+ if (costheta > 0.0) {
const T kHalf = T(0.5);
for (int i = 0; i < 3; ++i) {
angle_axis[i] *= kHalf;
@@ -284,8 +297,8 @@ inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) {
// angle_axis[i] should be positive, otherwise negative.
for (int i = 0; i < 3; ++i) {
angle_axis[i] = theta * sqrt((R[i*4] - costheta) * inv_one_minus_costheta);
- if (((sintheta < 0) && (angle_axis[i] > 0)) ||
- ((sintheta > 0) && (angle_axis[i] < 0))) {
+ if (((sintheta < 0.0) && (angle_axis[i] > 0.0)) ||
+ ((sintheta > 0.0) && (angle_axis[i] < 0.0))) {
angle_axis[i] = -angle_axis[i];
}
}
@@ -334,7 +347,8 @@ template <typename T>
inline void EulerAnglesToRotationMatrix(const T* euler,
const int row_stride,
T* R) {
- const T degrees_to_radians(M_PI / 180.0);
+ const double kPi = 3.14159265358979323846;
+ const T degrees_to_radians(kPi / 180.0);
const T pitch(euler[0] * degrees_to_radians);
const T roll(euler[1] * degrees_to_radians);
@@ -517,10 +531,4 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
} // namespace ceres
-// Clean define pollution.
-#ifdef CERES_NEED_M_PI_UNDEF
-#undef CERES_NEED_M_PI_UNDEF
-#undef M_PI
-#endif
-
#endif // CERES_PUBLIC_ROTATION_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h
index bd669272023..31d5e8d7987 100644
--- a/extern/libmv/third_party/ceres/include/ceres/solver.h
+++ b/extern/libmv/third_party/ceres/include/ceres/solver.h
@@ -34,10 +34,10 @@
#include <cmath>
#include <string>
#include <vector>
-
-#include "ceres/iteration_callback.h"
+#include "ceres/crs_matrix.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
+#include "ceres/iteration_callback.h"
#include "ceres/types.h"
namespace ceres {
@@ -57,24 +57,47 @@ class Solver {
struct Options {
// Default constructor that sets up a generic sparse problem.
Options() {
- minimizer_type = LEVENBERG_MARQUARDT;
+ trust_region_strategy_type = LEVENBERG_MARQUARDT;
+ dogleg_type = TRADITIONAL_DOGLEG;
+ use_nonmonotonic_steps = false;
+ max_consecutive_nonmonotonic_steps = 5;
max_num_iterations = 50;
- max_solver_time_sec = 1.0e9;
+ max_solver_time_in_seconds = 1e9;
num_threads = 1;
- tau = 1e-4;
+ initial_trust_region_radius = 1e4;
+ max_trust_region_radius = 1e16;
+ min_trust_region_radius = 1e-32;
min_relative_decrease = 1e-3;
+ lm_min_diagonal = 1e-6;
+ lm_max_diagonal = 1e32;
+ max_num_consecutive_invalid_steps = 5;
function_tolerance = 1e-6;
gradient_tolerance = 1e-10;
parameter_tolerance = 1e-8;
-#ifndef CERES_NO_SUITESPARSE
- linear_solver_type = SPARSE_NORMAL_CHOLESKY;
-#else
+
+#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
linear_solver_type = DENSE_QR;
-#endif // CERES_NO_SUITESPARSE
+#else
+ linear_solver_type = SPARSE_NORMAL_CHOLESKY;
+#endif
+
preconditioner_type = JACOBI;
+
+ sparse_linear_algebra_library = SUITE_SPARSE;
+#if defined(CERES_NO_SUITESPARSE) && !defined(CERES_NO_CXSPARSE)
+ sparse_linear_algebra_library = CX_SPARSE;
+#endif
+
num_linear_solver_threads = 1;
num_eliminate_blocks = 0;
ordering_type = NATURAL;
+
+#if defined(CERES_NO_SUITESPARSE)
+ use_block_amd = false;
+#else
+ use_block_amd = true;
+#endif
+
linear_solver_min_num_iterations = 1;
linear_solver_max_num_iterations = 500;
eta = 1e-1;
@@ -82,10 +105,13 @@ class Solver {
logging_type = PER_MINIMIZER_ITERATION;
minimizer_progress_to_stdout = false;
return_initial_residuals = false;
+ return_initial_gradient = false;
+ return_initial_jacobian = false;
return_final_residuals = false;
+ return_final_gradient = false;
+ return_final_jacobian = false;
lsqp_dump_directory = "/tmp";
lsqp_dump_format_type = TEXTFILE;
- crash_and_dump_lsqp_on_failure = false;
check_gradients = false;
gradient_check_relative_precision = 1e-8;
numeric_derivative_relative_step_size = 1e-6;
@@ -94,27 +120,78 @@ class Solver {
// Minimizer options ----------------------------------------
- MinimizerType minimizer_type;
+ TrustRegionStrategyType trust_region_strategy_type;
+
+ // Type of dogleg strategy to use.
+ DoglegType dogleg_type;
+
+ // The classical trust region methods are descent methods, in that
+ // they only accept a point if it strictly reduces the value of
+ // the objective function.
+ //
+ // Relaxing this requirement allows the algorithm to be more
+ // efficient in the long term at the cost of some local increase
+ // in the value of the objective function.
+ //
+ // This is because allowing for non-decreasing objective function
+ // values in a princpled manner allows the algorithm to "jump over
+ // boulders" as the method is not restricted to move into narrow
+ // valleys while preserving its convergence properties.
+ //
+ // Setting use_nonmonotonic_steps to true enables the
+ // non-monotonic trust region algorithm as described by Conn,
+ // Gould & Toint in "Trust Region Methods", Section 10.1.
+ //
+ // The parameter max_consecutive_nonmonotonic_steps controls the
+ // window size used by the step selection algorithm to accept
+ // non-monotonic steps.
+ //
+ // Even though the value of the objective function may be larger
+ // than the minimum value encountered over the course of the
+ // optimization, the final parameters returned to the user are the
+ // ones corresponding to the minimum cost over all iterations.
+ bool use_nonmonotonic_steps;
+ int max_consecutive_nonmonotonic_steps;
// Maximum number of iterations for the minimizer to run for.
int max_num_iterations;
// Maximum time for which the minimizer should run for.
- double max_solver_time_sec;
+ double max_solver_time_in_seconds;
// Number of threads used by Ceres for evaluating the cost and
// jacobians.
int num_threads;
- // For Levenberg-Marquardt, the initial value for the
- // regularizer. This is the inversely related to the size of the
- // initial trust region.
- double tau;
+ // Trust region minimizer settings.
+ double initial_trust_region_radius;
+ double max_trust_region_radius;
+
+ // Minimizer terminates when the trust region radius becomes
+ // smaller than this value.
+ double min_trust_region_radius;
- // For trust region methods, this is lower threshold for the
- // relative decrease before a step is accepted.
+ // Lower bound for the relative decrease before a step is
+ // accepted.
double min_relative_decrease;
+ // For the Levenberg-Marquadt algorithm, the scaled diagonal of
+ // the normal equations J'J is used to control the size of the
+ // trust region. Extremely small and large values along the
+ // diagonal can make this regularization scheme
+ // fail. lm_max_diagonal and lm_min_diagonal, clamp the values of
+ // diag(J'J) from above and below. In the normal course of
+ // operation, the user should not have to modify these parameters.
+ double lm_min_diagonal;
+ double lm_max_diagonal;
+
+ // Sometimes due to numerical conditioning problems or linear
+ // solver flakiness, the trust region strategy may return a
+ // numerically invalid step that can be fixed by reducing the
+ // trust region size. So the TrustRegionMinimizer allows for a few
+ // successive invalid steps before it declares NUMERICAL_FAILURE.
+ int max_num_consecutive_invalid_steps;
+
// Minimizer terminates when
//
// (new_cost - old_cost) < function_tolerance * old_cost;
@@ -141,6 +218,12 @@ class Solver {
// Type of preconditioner to use with the iterative linear solvers.
PreconditionerType preconditioner_type;
+ // Ceres supports using multiple sparse linear algebra libraries
+ // for sparse matrix ordering and factorizations. Currently,
+ // SUITE_SPARSE and CX_SPARSE are the valid choices, depending on
+ // whether they are linked into Ceres at build time.
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library;
+
// Number of threads used by Ceres to solve the Newton
// step. Currently only the SPARSE_SCHUR solver is capable of
// using this setting.
@@ -170,6 +253,19 @@ class Solver {
// non-empty.
vector<double*> ordering;
+ // By virtue of the modeling layer in Ceres being block oriented,
+ // all the matrices used by Ceres are also block oriented. When
+ // doing sparse direct factorization of these matrices (for
+ // SPARSE_NORMAL_CHOLESKY, SPARSE_SCHUR and ITERATIVE in
+ // conjunction with CLUSTER_TRIDIAGONAL AND CLUSTER_JACOBI
+ // preconditioners), the fill-reducing ordering algorithms can
+ // either be run on the block or the scalar form of these matrices.
+ // Running it on the block form exposes more of the super-nodal
+ // structure of the matrix to the factorization routines. Setting
+ // this parameter to true runs the ordering algorithms in block
+ // form. Currently this option only makes sense with
+ // sparse_linear_algebra_library = SUITE_SPARSE.
+ bool use_block_amd;
// Minimum number of iterations for which the linear solver should
// run, even if the convergence criterion is satisfied.
@@ -206,7 +302,12 @@ class Solver {
bool minimizer_progress_to_stdout;
bool return_initial_residuals;
+ bool return_initial_gradient;
+ bool return_initial_jacobian;
+
bool return_final_residuals;
+ bool return_final_gradient;
+ bool return_final_jacobian;
// List of iterations at which the optimizer should dump the
// linear least squares problem to disk. Useful for testing and
@@ -217,15 +318,6 @@ class Solver {
string lsqp_dump_directory;
DumpFormatType lsqp_dump_format_type;
- // Dump the linear least squares problem to disk if the minimizer
- // fails due to NUMERICAL_FAILURE and crash the process. This flag
- // is useful for generating debugging information. The problem is
- // dumped in a file whose name is determined by
- // Solver::Options::lsqp_dump_format.
- //
- // Note: This requires a version of Ceres built with protocol buffers.
- bool crash_and_dump_lsqp_on_failure;
-
// Finite differences options ----------------------------------------------
// Check all jacobians computed by each residual block with finite
@@ -273,16 +365,25 @@ class Solver {
bool update_state_every_iteration;
// Callbacks that are executed at the end of each iteration of the
- // Minimizer. They are executed in the order that they are
- // specified in this vector. By default, parameter blocks are
- // updated only at the end of the optimization, i.e when the
- // Minimizer terminates. This behaviour is controlled by
+ // Minimizer. An iteration may terminate midway, either due to
+ // numerical failures or because one of the convergence tests has
+ // been satisfied. In this case none of the callbacks are
+ // executed.
+
+ // Callbacks are executed in the order that they are specified in
+ // this vector. By default, parameter blocks are updated only at
+ // the end of the optimization, i.e when the Minimizer
+ // terminates. This behaviour is controlled by
// update_state_every_variable. If the user wishes to have access
// to the update parameter blocks when his/her callbacks are
// executed, then set update_state_every_iteration to true.
//
// The solver does NOT take ownership of these pointers.
vector<IterationCallback*> callbacks;
+
+ // If non-empty, a summary of the execution of the solver is
+ // recorded to this file.
+ string solver_log;
};
struct Summary {
@@ -313,20 +414,74 @@ class Solver {
// blocks that they depend on were fixed.
double fixed_cost;
- // Residuals before and after the optimization. Each vector
- // contains problem.NumResiduals() elements. Residuals are in the
- // same order in which they were added to the problem object when
- // constructing this problem.
+ // Vectors of residuals before and after the optimization. The
+ // entries of these vectors are in the order in which
+ // ResidualBlocks were added to the Problem object.
+ //
+ // Whether the residual vectors are populated with values is
+ // controlled by Solver::Options::return_initial_residuals and
+ // Solver::Options::return_final_residuals respectively.
vector<double> initial_residuals;
vector<double> final_residuals;
+ // Gradient vectors, before and after the optimization. The rows
+ // are in the same order in which the ParameterBlocks were added
+ // to the Problem object.
+ //
+ // NOTE: Since AddResidualBlock adds ParameterBlocks to the
+ // Problem automatically if they do not already exist, if you wish
+ // to have explicit control over the ordering of the vectors, then
+ // use Problem::AddParameterBlock to explicitly add the
+ // ParameterBlocks in the order desired.
+ //
+ // Whether the vectors are populated with values is controlled by
+ // Solver::Options::return_initial_gradient and
+ // Solver::Options::return_final_gradient respectively.
+ vector<double> initial_gradient;
+ vector<double> final_gradient;
+
+ // Jacobian matrices before and after the optimization. The rows
+ // of these matrices are in the same order in which the
+ // ResidualBlocks were added to the Problem object. The columns
+ // are in the same order in which the ParameterBlocks were added
+ // to the Problem object.
+ //
+ // NOTE: Since AddResidualBlock adds ParameterBlocks to the
+ // Problem automatically if they do not already exist, if you wish
+ // to have explicit control over the column ordering of the
+ // matrix, then use Problem::AddParameterBlock to explicitly add
+ // the ParameterBlocks in the order desired.
+ //
+ // The Jacobian matrices are stored as compressed row sparse
+ // matrices. Please see ceres/crs_matrix.h for more details of the
+ // format.
+ //
+ // Whether the Jacboan matrices are populated with values is
+ // controlled by Solver::Options::return_initial_jacobian and
+ // Solver::Options::return_final_jacobian respectively.
+ CRSMatrix initial_jacobian;
+ CRSMatrix final_jacobian;
+
vector<IterationSummary> iterations;
int num_successful_steps;
int num_unsuccessful_steps;
+ // When the user calls Solve, before the actual optimization
+ // occurs, Ceres performs a number of preprocessing steps. These
+ // include error checks, memory allocations, and reorderings. This
+ // time is accounted for as preprocessing time.
double preprocessor_time_in_seconds;
+
+ // Time spent in the TrustRegionMinimizer.
double minimizer_time_in_seconds;
+
+ // After the Minimizer is finished, some time is spent in
+ // re-evaluating residuals etc. This time is accounted for in the
+ // postprocessor time.
+ double postprocessor_time_in_seconds;
+
+ // Some total of all time spent inside Ceres when Solve is called.
double total_time_in_seconds;
// Preprocessor summary.
@@ -354,6 +509,10 @@ class Solver {
PreconditionerType preconditioner_type;
OrderingType ordering_type;
+
+ TrustRegionStrategyType trust_region_strategy_type;
+ DoglegType dogleg_type;
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library;
};
// Once a least squares problem has been built, this function takes
diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h
index a30c79029ac..3980885b53c 100644
--- a/extern/libmv/third_party/ceres/include/ceres/types.h
+++ b/extern/libmv/third_party/ceres/include/ceres/types.h
@@ -59,14 +59,18 @@ enum LinearSolverType {
// normal equations A'A x = A'b. They are direct solvers and do not
// assume any special problem structure.
- // Solve the normal equations using a sparse cholesky solver; based
- // on CHOLMOD.
- SPARSE_NORMAL_CHOLESKY,
+ // Solve the normal equations using a dense Cholesky solver; based
+ // on Eigen.
+ DENSE_NORMAL_CHOLESKY,
// Solve the normal equations using a dense QR solver; based on
// Eigen.
DENSE_QR,
+ // Solve the normal equations using a sparse cholesky solver; requires
+ // SuiteSparse or CXSparse.
+ SPARSE_NORMAL_CHOLESKY,
+
// Specialized solvers, specific to problems with a generalized
// bi-partitite structure.
@@ -110,6 +114,15 @@ enum PreconditionerType {
CLUSTER_TRIDIAGONAL
};
+enum SparseLinearAlgebraLibraryType {
+ // High performance sparse Cholesky factorization and approximate
+ // minimum degree ordering.
+ SUITE_SPARSE,
+
+ // A lightweight replacment for SuiteSparse.
+ CX_SPARSE
+};
+
enum LinearSolverTerminationType {
// Termination criterion was met. For factorization based solvers
// the tolerance is assumed to be zero. Any user provided values are
@@ -149,8 +162,47 @@ enum LoggingType {
PER_MINIMIZER_ITERATION
};
-enum MinimizerType {
- LEVENBERG_MARQUARDT
+// Ceres supports different strategies for computing the trust region
+// step.
+enum TrustRegionStrategyType {
+ // The default trust region strategy is to use the step computation
+ // used in the Levenberg-Marquardt algorithm. For more details see
+ // levenberg_marquardt_strategy.h
+ LEVENBERG_MARQUARDT,
+
+ // Powell's dogleg algorithm interpolates between the Cauchy point
+ // and the Gauss-Newton step. It is particularly useful if the
+ // LEVENBERG_MARQUARDT algorithm is making a large number of
+ // unsuccessful steps. For more details see dogleg_strategy.h.
+ //
+ // NOTES:
+ //
+ // 1. This strategy has not been experimented with or tested as
+ // extensively as LEVENBERG_MARQUARDT, and therefore it should be
+ // considered EXPERIMENTAL for now.
+ //
+ // 2. For now this strategy should only be used with exact
+ // factorization based linear solvers, i.e., SPARSE_SCHUR,
+ // DENSE_SCHUR, DENSE_QR and SPARSE_NORMAL_CHOLESKY.
+ DOGLEG
+};
+
+// Ceres supports two different dogleg strategies.
+// The "traditional" dogleg method by Powell and the
+// "subspace" method described in
+// R. H. Byrd, R. B. Schnabel, and G. A. Shultz,
+// "Approximate solution of the trust region problem by minimization
+// over two-dimensional subspaces", Mathematical Programming,
+// 40 (1988), pp. 247--263
+enum DoglegType {
+ // The traditional approach constructs a dogleg path
+ // consisting of two line segments and finds the furthest
+ // point on that path that is still inside the trust region.
+ TRADITIONAL_DOGLEG,
+
+ // The subspace approach finds the exact minimum of the model
+ // constrained to the subspace spanned by the dogleg path.
+ SUBSPACE_DOGLEG
};
enum SolverTerminationType {
@@ -246,11 +298,15 @@ enum DimensionType {
const char* LinearSolverTypeToString(LinearSolverType type);
const char* PreconditionerTypeToString(PreconditionerType type);
+const char* SparseLinearAlgebraLibraryTypeToString(
+ SparseLinearAlgebraLibraryType type);
const char* LinearSolverTerminationTypeToString(
LinearSolverTerminationType type);
const char* OrderingTypeToString(OrderingType type);
const char* SolverTerminationTypeToString(SolverTerminationType type);
-
+const char* SparseLinearAlgebraLibraryTypeToString(
+ SparseLinearAlgebraLibraryType type);
+const char* TrustRegionStrategyTypeToString( TrustRegionStrategyType type);
bool IsSchurType(LinearSolverType type);
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h b/extern/libmv/third_party/ceres/internal/ceres/array_utils.cc
index d00bb9095be..673baa4f70f 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/array_utils.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -27,39 +27,41 @@
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-//
-// Implmentation of Levenberg Marquardt algorithm based on "Methods for
-// Nonlinear Least Squares" by K. Madsen, H.B. Nielsen and
-// O. Tingleff. Available to download from
-//
-// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
-//
-#ifndef CERES_INTERNAL_LEVENBERG_MARQUARDT_H_
-#define CERES_INTERNAL_LEVENBERG_MARQUARDT_H_
+#include "ceres/array_utils.h"
-#include "ceres/minimizer.h"
-#include "ceres/solver.h"
+#include <cmath>
+#include <cstddef>
+#include "ceres/fpclassify.h"
namespace ceres {
namespace internal {
-class Evaluator;
-class LinearSolver;
+// It is a near impossibility that user code generates this exact
+// value in normal operation, thus we will use it to fill arrays
+// before passing them to user code. If on return an element of the
+// array still contains this value, we will assume that the user code
+// did not write to that memory location.
+const double kImpossibleValue = 1e302;
-class LevenbergMarquardt : public Minimizer {
- public:
- virtual ~LevenbergMarquardt();
+bool IsArrayValid(const int size, const double* x) {
+ if (x != NULL) {
+ for (int i = 0; i < size; ++i) {
+ if (!IsFinite(x[i]) || (x[i] == kImpossibleValue)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
- virtual void Minimize(const Minimizer::Options& options,
- Evaluator* evaluator,
- LinearSolver* linear_solver,
- const double* initial_parameters,
- double* final_parameters,
- Solver::Summary* summary);
-};
+void InvalidateArray(const int size, double* x) {
+ if (x != NULL) {
+ for (int i = 0; i < size; ++i) {
+ x[i] = kImpossibleValue;
+ }
+ }
+}
} // namespace internal
} // namespace ceres
-
-#endif // CERES_INTERNAL_LEVENBERG_MARQUARDT_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/array_utils.h b/extern/libmv/third_party/ceres/internal/ceres/array_utils.h
new file mode 100644
index 00000000000..99cc8d8ebbf
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/array_utils.h
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Utility routines for validating arrays.
+//
+// These are useful for detecting two common class of errors.
+//
+// 1. Uninitialized memory - where the user for some reason did not
+// compute part of an array, but the code expects it.
+//
+// 2. Numerical failure while computing the cost/residual/jacobian,
+// e.g. NaN, infinities etc. This is particularly useful since the
+// automatic differentiation code does computations that are not
+// evident to the user and can silently generate hard to debug errors.
+
+#ifndef CERES_INTERNAL_ARRAY_UTILS_H_
+#define CERES_INTERNAL_ARRAY_UTILS_H_
+
+#include "ceres/internal/port.h"
+
+namespace ceres {
+namespace internal {
+
+// Fill the array x with an impossible value that the user code is
+// never expected to compute.
+void InvalidateArray(int size, double* x);
+
+// Check if all the entries of the array x are valid, i.e. all the
+// values in the array should be finite and none of them should be
+// equal to the "impossible" value used by InvalidateArray.
+bool IsArrayValid(int size, const double* x);
+
+extern const double kImpossibleValue;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_ARRAY_UTILS_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc
index 05e63eb560b..9edc4fa23bd 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc
@@ -40,16 +40,26 @@
namespace ceres {
namespace internal {
-void BlockEvaluatePreparer::Init(int** jacobian_layout) {
+void BlockEvaluatePreparer::Init(int const* const* jacobian_layout,
+ int max_derivatives_per_residual_block) {
jacobian_layout_ = jacobian_layout;
+ scratch_evaluate_preparer_.Init(max_derivatives_per_residual_block);
}
// Point the jacobian blocks directly into the block sparse matrix.
void BlockEvaluatePreparer::Prepare(const ResidualBlock* residual_block,
int residual_block_index,
SparseMatrix* jacobian,
- double** jacobians) const {
- CHECK(jacobian != NULL);
+ double** jacobians) {
+ // If the overall jacobian is not available, use the scratch space.
+ if (jacobian == NULL) {
+ scratch_evaluate_preparer_.Prepare(residual_block,
+ residual_block_index,
+ jacobian,
+ jacobians);
+ return;
+ }
+
double* jacobian_values =
down_cast<BlockSparseMatrix*>(jacobian)->mutable_values();
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h
index a7869311e6e..354acc031f4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h
@@ -36,6 +36,8 @@
#ifndef CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_
#define CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_
+#include "ceres/scratch_evaluate_preparer.h"
+
namespace ceres {
namespace internal {
@@ -47,18 +49,26 @@ class BlockEvaluatePreparer {
// Using Init() instead of a constructor allows for allocating this structure
// with new[]. This is because C++ doesn't allow passing arguments to objects
// constructed with new[] (as opposed to plain 'new').
- void Init(int** jacobian_layout);
+ void Init(int const* const* jacobian_layout,
+ int max_derivatives_per_residual_block);
// EvaluatePreparer interface
- // Point the jacobian blocks directly into the block sparse matrix.
+ // Point the jacobian blocks directly into the block sparse matrix, if
+ // jacobian is non-null. Otherwise, uses an internal per-thread buffer to
+ // store the jacobians temporarily.
void Prepare(const ResidualBlock* residual_block,
int residual_block_index,
SparseMatrix* jacobian,
- double** jacobians) const;
+ double** jacobians);
private:
int const* const* jacobian_layout_;
+
+ // For the case that the overall jacobian is not available, but the
+ // individual jacobians are requested, use a pass-through scratch evaluate
+ // preparer.
+ ScratchEvaluatePreparer scratch_evaluate_preparer_;
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc
index 1a5001f9c71..474c37f7ca4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc
@@ -40,11 +40,10 @@
namespace ceres {
namespace internal {
-BlockJacobiPreconditioner::BlockJacobiPreconditioner(
- const LinearOperator& A)
- : block_structure_(
- *(down_cast<const BlockSparseMatrix*>(&A)->block_structure())),
- num_rows_(A.num_rows()) {
+BlockJacobiPreconditioner::BlockJacobiPreconditioner(const LinearOperator& A)
+ : num_rows_(A.num_rows()),
+ block_structure_(
+ *(down_cast<const BlockSparseMatrix*>(&A)->block_structure())) {
// Calculate the amount of storage needed.
int storage_needed = 0;
for (int c = 0; c < block_structure_.cols.size(); ++c) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc
index 52a58bb43a6..f90c350cc80 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc
@@ -136,9 +136,12 @@ BlockJacobianWriter::BlockJacobianWriter(const Evaluator::Options& options,
// makes the final Write() a nop.
BlockEvaluatePreparer* BlockJacobianWriter::CreateEvaluatePreparers(
int num_threads) {
+ int max_derivatives_per_residual_block =
+ program_->MaxDerivativesPerResidualBlock();
+
BlockEvaluatePreparer* preparers = new BlockEvaluatePreparer[num_threads];
for (int i = 0; i < num_threads; i++) {
- preparers[i].Init(&jacobian_layout_[0]);
+ preparers[i].Init(&jacobian_layout_[0], max_derivatives_per_residual_block);
}
return preparers;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc
index 2afaf5e2ea2..0f95e8932b8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc
@@ -28,10 +28,10 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
+#include "glog/logging.h"
#include "ceres/block_random_access_dense_matrix.h"
#include <vector>
-#include <glog/logging.h>
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h
index 3a0096209f7..9f27a4c30f3 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h
@@ -89,7 +89,7 @@ class BlockRandomAccessDenseMatrix : public BlockRandomAccessMatrix {
vector<int> block_layout_;
scoped_array<double> values_;
- DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDenseMatrix);
+ CERES_DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDenseMatrix);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h
index f398af3be87..b76cb78b160 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h
@@ -77,7 +77,7 @@ namespace internal {
//
// if (cell != NULL) {
// MatrixRef m(cell->values, row_stride, col_stride);
-// MutexLock l(&cell->m);
+// CeresMutexLock l(&cell->m);
// m.block(row, col, row_block_size, col_block_size) = ...
// }
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc
index c496fcd13de..9ed62ce948b 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc
@@ -28,17 +28,17 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
+#include "glog/logging.h"
#include "ceres/block_random_access_sparse_matrix.h"
#include <algorithm>
#include <set>
#include <utility>
#include <vector>
-#include <glog/logging.h>
-#include "ceres/mutex.h"
-#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/mutex.h"
+#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h
index 12613c3daa0..48a00437cf6 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h
@@ -38,6 +38,7 @@
#include "ceres/block_random_access_matrix.h"
#include "ceres/collections_port.h"
#include "ceres/triplet_sparse_matrix.h"
+#include "ceres/integral_types.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
@@ -84,11 +85,11 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix {
TripletSparseMatrix* mutable_matrix() { return tsm_.get(); }
private:
- long int IntPairToLong(int a, int b) {
+ int64 IntPairToLong(int a, int b) {
return a * kMaxRowBlocks + b;
}
- const int kMaxRowBlocks;
+ const int64 kMaxRowBlocks;
// row/column block sizes.
const vector<int> blocks_;
@@ -100,7 +101,8 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix {
// The underlying matrix object which actually stores the cells.
scoped_ptr<TripletSparseMatrix> tsm_;
- DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessSparseMatrix);
+ friend class BlockRandomAccessSparseMatrixTest;
+ CERES_DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessSparseMatrix);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc
index 7dd395e2975..dbe5ec93ef0 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc
@@ -33,11 +33,11 @@
#include <cstddef>
#include <algorithm>
#include <vector>
-#include <glog/logging.h>
#include "ceres/block_structure.h"
+#include "ceres/internal/eigen.h"
#include "ceres/matrix_proto.h"
#include "ceres/triplet_sparse_matrix.h"
-#include "ceres/internal/eigen.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -81,7 +81,7 @@ BlockSparseMatrix::BlockSparseMatrix(
CHECK_NOTNULL(values_.get());
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
BlockSparseMatrix::BlockSparseMatrix(const SparseMatrixProto& outer_proto) {
CHECK(outer_proto.has_block_matrix());
@@ -244,7 +244,7 @@ const CompressedRowBlockStructure* BlockSparseMatrix::block_structure()
return block_structure_.get();
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
void BlockSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
outer_proto->Clear();
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h
index f71446e8f58..513d398c54d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h
@@ -74,7 +74,7 @@ class BlockSparseMatrixBase : public SparseMatrix {
virtual const double* RowBlockValues(int row_block_index) const = 0;
private:
- DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrixBase);
+ CERES_DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrixBase);
};
// This class implements the SparseMatrix interface for storing and
@@ -96,7 +96,7 @@ class BlockSparseMatrix : public BlockSparseMatrixBase {
explicit BlockSparseMatrix(CompressedRowBlockStructure* block_structure);
// Construct a block sparse matrix from a protocol buffer.
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
explicit BlockSparseMatrix(const SparseMatrixProto& proto);
#endif
@@ -110,7 +110,7 @@ class BlockSparseMatrix : public BlockSparseMatrixBase {
virtual void SquaredColumnNorm(double* x) const;
virtual void ScaleColumns(const double* scale);
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
virtual void ToProto(SparseMatrixProto* proto) const;
#endif
virtual void ToTextFile(FILE* file) const;
@@ -135,7 +135,7 @@ class BlockSparseMatrix : public BlockSparseMatrixBase {
int num_nonzeros_;
scoped_array<double> values_;
scoped_ptr<CompressedRowBlockStructure> block_structure_;
- DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrix);
+ CERES_DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrix);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc b/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc
index 5add4f3b94d..e61131192af 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc
@@ -38,7 +38,7 @@ bool CellLessThan(const Cell& lhs, const Cell& rhs) {
return (lhs.block_id < rhs.block_id);
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
void ProtoToBlockStructure(const BlockStructureProto &proto,
CompressedRowBlockStructure *block_structure) {
// Decode the column blocks.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
index 53190ada6fc..d0dc1e670c2 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
@@ -31,11 +31,11 @@
#include "ceres/canonical_views_clustering.h"
-#include <glog/logging.h>
-#include "ceres/graph.h"
#include "ceres/collections_port.h"
-#include "ceres/map_util.h"
+#include "ceres/graph.h"
#include "ceres/internal/macros.h"
+#include "ceres/map_util.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -75,7 +75,7 @@ class CanonicalViewsClustering {
IntMap view_to_canonical_view_;
// Maps a view to its similarity to its current cluster center.
HashMap<int, double> view_to_canonical_view_similarity_;
- DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering);
+ CERES_DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering);
};
void ComputeCanonicalViewsClustering(
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h
index dd36f99006b..877b4c4ceea 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h
@@ -57,7 +57,7 @@ class CgnrSolver : public LinearSolver {
private:
const LinearSolver::Options options_;
scoped_ptr<BlockJacobiPreconditioner> jacobi_preconditioner_;
- DISALLOW_COPY_AND_ASSIGN(CgnrSolver);
+ CERES_DISALLOW_COPY_AND_ASSIGN(CgnrSolver);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
index 9dff0efe245..c2fce9033cd 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
@@ -33,31 +33,49 @@
#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_
#define CERES_INTERNAL_COLLECTIONS_PORT_H_
-#ifdef CERES_HASH_BOOST
-#include <boost/tr1/unordered_map.hpp>
-#include <boost/tr1/unordered_set.hpp>
+#if defined(CERES_NO_TR1)
+# include <map>
+# include <set>
#else
-#if defined(_MSC_VER) && _MSC_VER <= 1700
-#include <unordered_map>
-#include <unordered_set>
-#else
-#include <tr1/unordered_map>
-#include <tr1/unordered_set>
-#endif
+# if defined(_MSC_VER) && _MSC_VER <= 1600
+# include <unordered_map>
+# include <unordered_set>
+# else
+# include <tr1/unordered_map>
+# include <tr1/unordered_set>
+# endif
#endif
-
#include <utility>
#include "ceres/integral_types.h"
#include "ceres/internal/port.h"
+// Some systems don't have access to TR1. In that case, substitute the hash
+// map/set with normal map/set. The price to pay is slightly slower speed for
+// some operations.
+#if defined(CERES_NO_TR1)
+
namespace ceres {
namespace internal {
template<typename K, typename V>
-struct HashMap : tr1::unordered_map<K, V> {};
+struct HashMap : map<K, V> {};
template<typename K>
-struct HashSet : tr1::unordered_set<K> {};
+struct HashSet : set<K> {};
+
+} // namespace internal
+} // namespace ceres
+
+#else
+
+namespace ceres {
+namespace internal {
+
+template<typename K, typename V>
+struct HashMap : std::tr1::unordered_map<K, V> {};
+
+template<typename K>
+struct HashSet : std::tr1::unordered_set<K> {};
#if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__)
#define GG_LONGLONG(x) x##I64
@@ -124,11 +142,7 @@ CERES_HASH_NAMESPACE_START
// Hasher for STL pairs. Requires hashers for both members to be defined.
template<typename T>
-#ifdef CERES_HASH_BOOST
-struct hash {
-#else
struct hash<pair<T, T> > {
-#endif
size_t operator()(const pair<T, T>& p) const {
size_t h1 = hash<T>()(p.first);
size_t h2 = hash<T>()(p.second);
@@ -148,4 +162,6 @@ struct hash<pair<T, T> > {
CERES_HASH_NAMESPACE_END
+#endif // CERES_NO_TR1
+
#endif // CERES_INTERNAL_COLLECTIONS_PORT_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc
index aa883b7d353..912c4845441 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc
@@ -130,8 +130,24 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const {
}
row_pos += num_residuals;
}
-
CHECK_EQ(num_jacobian_nonzeros, rows[total_num_residuals]);
+
+ // Populate the row and column block vectors for use by block
+ // oriented ordering algorithms. This is useful when
+ // Solver::Options::use_block_amd = true.
+ const vector<ParameterBlock*>& parameter_blocks = program_->parameter_blocks();
+ vector<int>& col_blocks = *(jacobian->mutable_col_blocks());
+ col_blocks.resize(parameter_blocks.size());
+ for (int i = 0; i < parameter_blocks.size(); ++i) {
+ col_blocks[i] = parameter_blocks[i]->LocalSize();
+ }
+
+ vector<int>& row_blocks = *(jacobian->mutable_row_blocks());
+ row_blocks.resize(residual_blocks.size());
+ for (int i = 0; i < residual_blocks.size(); ++i) {
+ row_blocks[i] = residual_blocks[i]->NumResiduals();
+ }
+
return jacobian;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc
index 95edf5396af..1b61468aaae 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc
@@ -32,15 +32,22 @@
#include <algorithm>
#include <vector>
-#include "ceres/matrix_proto.h"
+#include "ceres/crs_matrix.h"
#include "ceres/internal/port.h"
+#include "ceres/matrix_proto.h"
namespace ceres {
namespace internal {
namespace {
// Helper functor used by the constructor for reordering the contents
-// of a TripletSparseMatrix.
+// of a TripletSparseMatrix. This comparator assumes thay there are no
+// duplicates in the pair of arrays rows and cols, i.e., there is no
+// indices i and j (not equal to each other) s.t.
+//
+// rows[i] == rows[j] && cols[i] == cols[j]
+//
+// If this is the case, this functor will not be a StrictWeakOrdering.
struct RowColLessThan {
RowColLessThan(const int* rows, const int* cols)
: rows(rows), cols(cols) {
@@ -128,7 +135,7 @@ CompressedRowSparseMatrix::CompressedRowSparseMatrix(
CHECK_EQ(num_nonzeros(), m.num_nonzeros());
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
CompressedRowSparseMatrix::CompressedRowSparseMatrix(
const SparseMatrixProto& outer_proto) {
CHECK(outer_proto.has_compressed_row_matrix());
@@ -241,7 +248,7 @@ void CompressedRowSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
}
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
void CompressedRowSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
CHECK_NOTNULL(outer_proto);
@@ -330,5 +337,18 @@ void CompressedRowSparseMatrix::ToTextFile(FILE* file) const {
}
}
+void CompressedRowSparseMatrix::ToCRSMatrix(CRSMatrix* matrix) const {
+ matrix->num_rows = num_rows();
+ matrix->num_cols = num_cols();
+
+ matrix->rows.resize(matrix->num_rows + 1);
+ matrix->cols.resize(num_nonzeros());
+ matrix->values.resize(num_nonzeros());
+
+ copy(rows_.get(), rows_.get() + matrix->num_rows + 1, matrix->rows.begin());
+ copy(cols_.get(), cols_.get() + num_nonzeros(), matrix->cols.begin());
+ copy(values_.get(), values_.get() + num_nonzeros(), matrix->values.begin());
+}
+
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h
index 9a39d28e111..6a9d82842e5 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h
@@ -31,14 +31,19 @@
#ifndef CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_
#define CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_
+#include <vector>
#include <glog/logging.h>
#include "ceres/sparse_matrix.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/macros.h"
+#include "ceres/internal/port.h"
#include "ceres/types.h"
namespace ceres {
+
+class CRSMatrix;
+
namespace internal {
class SparseMatrixProto;
@@ -52,7 +57,7 @@ class CompressedRowSparseMatrix : public SparseMatrix {
//
// We assume that m does not have any repeated entries.
explicit CompressedRowSparseMatrix(const TripletSparseMatrix& m);
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
explicit CompressedRowSparseMatrix(const SparseMatrixProto& proto);
#endif
@@ -85,7 +90,7 @@ class CompressedRowSparseMatrix : public SparseMatrix {
virtual void ScaleColumns(const double* scale);
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
virtual void ToProto(SparseMatrixProto* proto) const;
#endif
virtual void ToTextFile(FILE* file) const;
@@ -103,6 +108,8 @@ class CompressedRowSparseMatrix : public SparseMatrix {
// have the same number of columns as this matrix.
void AppendRows(const CompressedRowSparseMatrix& m);
+ void ToCRSMatrix(CRSMatrix* matrix) const;
+
// Low level access methods that expose the structure of the matrix.
const int* cols() const { return cols_.get(); }
int* mutable_cols() { return cols_.get(); }
@@ -110,6 +117,12 @@ class CompressedRowSparseMatrix : public SparseMatrix {
const int* rows() const { return rows_.get(); }
int* mutable_rows() { return rows_.get(); }
+ const vector<int>& row_blocks() const { return row_blocks_; }
+ vector<int>* mutable_row_blocks() { return &row_blocks_; }
+
+ const vector<int>& col_blocks() const { return col_blocks_; }
+ vector<int>* mutable_col_blocks() { return &col_blocks_; }
+
private:
scoped_array<int> cols_;
scoped_array<int> rows_;
@@ -117,10 +130,17 @@ class CompressedRowSparseMatrix : public SparseMatrix {
int num_rows_;
int num_cols_;
-
int max_num_nonzeros_;
- DISALLOW_COPY_AND_ASSIGN(CompressedRowSparseMatrix);
+ // If the matrix has an underlying block structure, then it can also
+ // carry with it row and column block sizes. This is auxilliary and
+ // optional information for use by algorithms operating on the
+ // matrix. The class itself does not make use of this information in
+ // any way.
+ vector<int> row_blocks_;
+ vector<int> col_blocks_;
+
+ CERES_DISALLOW_COPY_AND_ASSIGN(CompressedRowSparseMatrix);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc
index ca80bfb9c9d..7322790f717 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc
@@ -34,10 +34,10 @@
#include <cstddef>
-#include <glog/logging.h>
-#include "ceres/stl_util.h"
#include "ceres/internal/eigen.h"
+#include "ceres/stl_util.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc
index 75f9e043fa5..ae8e8774709 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc
@@ -41,18 +41,18 @@
#include <cmath>
#include <cstddef>
-#include <glog/logging.h>
-#include "ceres/linear_operator.h"
+#include "ceres/fpclassify.h"
#include "ceres/internal/eigen.h"
+#include "ceres/linear_operator.h"
#include "ceres/types.h"
-#include "ceres/jet.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
namespace {
bool IsZeroOrInfinity(double x) {
- return ((x == 0.0) || (isinf(x)));
+ return ((x == 0.0) || (IsInfinite(x)));
}
// Constant used in the MATLAB implementation ~ 2 * eps.
@@ -115,7 +115,7 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
for (summary.num_iterations = 1;
summary.num_iterations < options_.max_num_iterations;
++summary.num_iterations) {
- VLOG(2) << "cg iteration " << summary.num_iterations;
+ VLOG(3) << "cg iteration " << summary.num_iterations;
// Apply preconditioner
if (per_solve_options.preconditioner != NULL) {
@@ -151,14 +151,14 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
A->RightMultiply(p.data(), q.data());
double pq = p.dot(q);
- if ((pq <= 0) || isinf(pq)) {
+ if ((pq <= 0) || IsInfinite(pq)) {
LOG(ERROR) << "Numerical failure. pq = " << pq;
summary.termination_type = FAILURE;
break;
}
double alpha = rho / pq;
- if (isinf(alpha)) {
+ if (IsInfinite(alpha)) {
LOG(ERROR) << "Numerical failure. alpha " << alpha;
summary.termination_type = FAILURE;
break;
@@ -202,13 +202,13 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
// 1. Stephen G. Nash & Ariela Sofer, Assessing A Search
// Direction Within A Truncated Newton Method, Operation
// Research Letters 9(1990) 219-221.
- //
+ //
// 2. Stephen G. Nash, A Survey of Truncated Newton Methods,
// Journal of Computational and Applied Mathematics,
// 124(1-2), 45-59, 2000.
//
double zeta = summary.num_iterations * (Q1 - Q0) / Q1;
- VLOG(2) << "Q termination: zeta " << zeta
+ VLOG(3) << "Q termination: zeta " << zeta
<< " " << per_solve_options.q_tolerance;
if (zeta < per_solve_options.q_tolerance) {
summary.termination_type = TOLERANCE;
@@ -218,7 +218,7 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
// Residual based termination.
norm_r = r. norm();
- VLOG(2) << "R termination: norm_r " << norm_r
+ VLOG(3) << "R termination: norm_r " << norm_r
<< " " << tol_r;
if (norm_r <= tol_r) {
summary.termination_type = TOLERANCE;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h
index 57f99e31db7..b8dfa56b526 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h
@@ -65,7 +65,7 @@ class ConjugateGradientsSolver : public LinearSolver {
private:
const LinearSolver::Options options_;
- DISALLOW_COPY_AND_ASSIGN(ConjugateGradientsSolver);
+ CERES_DISALLOW_COPY_AND_ASSIGN(ConjugateGradientsSolver);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
index 4ca2c6f6c86..eff4dff8566 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
@@ -32,8 +32,8 @@
#include <cstddef>
#include <cmath>
-#include <glog/logging.h>
#include "ceres/internal/eigen.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc
new file mode 100644
index 00000000000..ca36ce07614
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc
@@ -0,0 +1,130 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: strandmark@google.com (Petter Strandmark)
+
+#ifndef CERES_NO_CXSPARSE
+
+#include "ceres/cxsparse.h"
+
+#include "ceres/compressed_row_sparse_matrix.h"
+#include "ceres/triplet_sparse_matrix.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+CXSparse::CXSparse() : scratch_size_(0), scratch_(NULL) {
+}
+
+CXSparse::~CXSparse() {
+ if (scratch_size_ > 0) {
+ cs_free(scratch_);
+ }
+}
+
+bool CXSparse::SolveCholesky(cs_di* A,
+ cs_dis* symbolic_factorization,
+ double* b) {
+ // Make sure we have enough scratch space available.
+ if (scratch_size_ < A->n) {
+ if (scratch_size_ > 0) {
+ cs_free(scratch_);
+ }
+ scratch_ = reinterpret_cast<CS_ENTRY*>(cs_malloc(A->n, sizeof(CS_ENTRY)));
+ }
+
+ // Solve using Cholesky factorization
+ csn* numeric_factorization = cs_chol(A, symbolic_factorization);
+ if (numeric_factorization == NULL) {
+ LOG(WARNING) << "Cholesky factorization failed.";
+ return false;
+ }
+
+ // When the Cholesky factorization succeeded, these methods are guaranteed to
+ // succeeded as well. In the comments below, "x" refers to the scratch space.
+ //
+ // Set x = P * b.
+ cs_ipvec(symbolic_factorization->pinv, b, scratch_, A->n);
+
+ // Set x = L \ x.
+ cs_lsolve(numeric_factorization->L, scratch_);
+
+ // Set x = L' \ x.
+ cs_ltsolve(numeric_factorization->L, scratch_);
+
+ // Set b = P' * x.
+ cs_pvec(symbolic_factorization->pinv, scratch_, b, A->n);
+
+ // Free Cholesky factorization.
+ cs_nfree(numeric_factorization);
+ return true;
+}
+
+cs_dis* CXSparse::AnalyzeCholesky(cs_di* A) {
+ // order = 1 for Cholesky factorization.
+ return cs_schol(1, A);
+}
+
+cs_di CXSparse::CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A) {
+ cs_di At;
+ At.m = A->num_cols();
+ At.n = A->num_rows();
+ At.nz = -1;
+ At.nzmax = A->num_nonzeros();
+ At.p = A->mutable_rows();
+ At.i = A->mutable_cols();
+ At.x = A->mutable_values();
+ return At;
+}
+
+cs_di* CXSparse::CreateSparseMatrix(TripletSparseMatrix* tsm) {
+ cs_di_sparse tsm_wrapper;
+ tsm_wrapper.nzmax = tsm->num_nonzeros();;
+ tsm_wrapper.nz = tsm->num_nonzeros();;
+ tsm_wrapper.m = tsm->num_rows();
+ tsm_wrapper.n = tsm->num_cols();
+ tsm_wrapper.p = tsm->mutable_cols();
+ tsm_wrapper.i = tsm->mutable_rows();
+ tsm_wrapper.x = tsm->mutable_values();
+
+ return cs_compress(&tsm_wrapper);
+}
+
+void CXSparse::Free(cs_di* factor) {
+ cs_free(factor);
+}
+
+void CXSparse::Free(cs_dis* factor) {
+ cs_sfree(factor);
+}
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_CXSPARSE
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h
new file mode 100644
index 00000000000..d3b64fcd1a5
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h
@@ -0,0 +1,90 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: strandmark@google.com (Petter Strandmark)
+
+#ifndef CERES_INTERNAL_CXSPARSE_H_
+#define CERES_INTERNAL_CXSPARSE_H_
+
+#ifndef CERES_NO_CXSPARSE
+
+#include "cs.h"
+
+namespace ceres {
+namespace internal {
+
+class CompressedRowSparseMatrix;
+class TripletSparseMatrix;
+
+// This object provides access to solving linear systems using Cholesky
+// factorization with a known symbolic factorization. This features does not
+// explicity exist in CXSparse. The methods in the class are nonstatic because
+// the class manages internal scratch space.
+class CXSparse {
+ public:
+ CXSparse();
+ ~CXSparse();
+
+ // Solves a symmetric linear system A * x = b using Cholesky factorization.
+ // A - The system matrix.
+ // symbolic_factorization - The symbolic factorization of A. This is obtained
+ // from AnalyzeCholesky.
+ // b - The right hand size of the linear equation. This
+ // array will also recieve the solution.
+ // Returns false if Cholesky factorization of A fails.
+ bool SolveCholesky(cs_di* A, cs_dis* symbolic_factorization, double* b);
+
+ // Creates a sparse matrix from a compressed-column form. No memory is
+ // allocated or copied; the structure A is filled out with info from the
+ // argument.
+ cs_di CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A);
+
+ // Creates a new matrix from a triplet form. Deallocate the returned matrix
+ // with Free. May return NULL if the compression or allocation fails.
+ cs_di* CreateSparseMatrix(TripletSparseMatrix* A);
+
+ // Computes a symbolic factorization of A that can be used in SolveCholesky.
+ // The returned matrix should be deallocated with Free when not used anymore.
+ cs_dis* AnalyzeCholesky(cs_di* A);
+
+ // Deallocates the memory of a matrix obtained from AnalyzeCholesky.
+ void Free(cs_di* factor);
+ void Free(cs_dis* factor);
+
+ private:
+ // Cached scratch space
+ CS_ENTRY* scratch_;
+ int scratch_size_;
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_CXSPARSE
+
+#endif // CERES_INTERNAL_CXSPARSE_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc
new file mode 100644
index 00000000000..f6bb99abf63
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc
@@ -0,0 +1,86 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/dense_normal_cholesky_solver.h"
+
+#include <cstddef>
+
+#include "Eigen/Dense"
+#include "ceres/dense_sparse_matrix.h"
+#include "ceres/linear_solver.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/types.h"
+
+namespace ceres {
+namespace internal {
+
+DenseNormalCholeskySolver::DenseNormalCholeskySolver(
+ const LinearSolver::Options& options)
+ : options_(options) {}
+
+LinearSolver::Summary DenseNormalCholeskySolver::SolveImpl(
+ DenseSparseMatrix* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double* x) {
+ const int num_rows = A->num_rows();
+ const int num_cols = A->num_cols();
+
+ ConstAlignedMatrixRef Aref = A->matrix();
+ Matrix lhs(num_cols, num_cols);
+ lhs.setZero();
+
+ // lhs += A'A
+ //
+ // Using rankUpdate instead of GEMM, exposes the fact that its the
+ // same matrix being multiplied with itself and that the product is
+ // symmetric.
+ lhs.selfadjointView<Eigen::Upper>().rankUpdate(Aref.transpose());
+
+ // rhs = A'b
+ Vector rhs = Aref.transpose() * ConstVectorRef(b, num_rows);
+
+ if (per_solve_options.D != NULL) {
+ ConstVectorRef D(per_solve_options.D, num_cols);
+ lhs += D.array().square().matrix().asDiagonal();
+ }
+
+ VectorRef(x, num_cols) =
+ lhs.selfadjointView<Eigen::Upper>().ldlt().solve(rhs);
+
+ LinearSolver::Summary summary;
+ summary.num_iterations = 1;
+ summary.termination_type = TOLERANCE;
+ return summary;
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.h b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.h
new file mode 100644
index 00000000000..de47740583d
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.h
@@ -0,0 +1,95 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Solve dense rectangular systems Ax = b by forming the normal
+// equations and solving them using the Cholesky factorization.
+
+#ifndef CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_
+#define CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_
+
+#include "ceres/linear_solver.h"
+#include "ceres/internal/macros.h"
+
+namespace ceres {
+namespace internal {
+
+class DenseSparseMatrix;
+
+// This class implements the LinearSolver interface for solving
+// rectangular/unsymmetric (well constrained) linear systems of the
+// form
+//
+// Ax = b
+//
+// Since there does not usually exist a solution that satisfies these
+// equations, the solver instead solves the linear least squares
+// problem
+//
+// min_x |Ax - b|^2
+//
+// Setting the gradient of the above optimization problem to zero
+// gives us the normal equations
+//
+// A'Ax = A'b
+//
+// A'A is a positive definite matrix (hopefully), and the resulting
+// linear system can be solved using Cholesky factorization.
+//
+// If the PerSolveOptions struct has a non-null array D, then the
+// augmented/regularized linear system
+//
+// [ A ]x = [b]
+// [ diag(D) ] [0]
+//
+// is solved.
+//
+// This class uses the LDLT factorization routines from the Eigen
+// library. This solver always returns a solution, it is the user's
+// responsibility to judge if the solution is good enough for their
+// purposes.
+class DenseNormalCholeskySolver: public DenseSparseMatrixSolver {
+ public:
+ explicit DenseNormalCholeskySolver(const LinearSolver::Options& options);
+
+ private:
+ virtual LinearSolver::Summary SolveImpl(
+ DenseSparseMatrix* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double* x);
+
+ const LinearSolver::Options options_;
+ CERES_DISALLOW_COPY_AND_ASSIGN(DenseNormalCholeskySolver);
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
index 328505404d7..2b329ee0e9c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
@@ -33,8 +33,8 @@
#include <cstddef>
#include "Eigen/Dense"
+#include "ceres/dense_sparse_matrix.h"
#include "ceres/linear_solver.h"
-#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
@@ -62,7 +62,7 @@ LinearSolver::Summary DenseQRSolver::SolveImpl(
}
// rhs = [b;0] to account for the additional rows in the lhs.
- Vector rhs(num_rows + ((per_solve_options.D !=NULL) ? num_cols : 0));
+ Vector rhs(num_rows + ((per_solve_options.D != NULL) ? num_cols : 0));
rhs.setZero();
rhs.head(num_rows) = ConstVectorRef(b, num_rows);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h
index 990c8d445eb..dd683a8c4ea 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h
@@ -28,7 +28,7 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
-// Solve dense rectangular systems Ax = b using the QR factoriztion.
+// Solve dense rectangular systems Ax = b using the QR factorization.
#ifndef CERES_INTERNAL_DENSE_QR_SOLVER_H_
#define CERES_INTERNAL_DENSE_QR_SOLVER_H_
@@ -90,7 +90,7 @@ class DenseQRSolver: public DenseSparseMatrixSolver {
double* x);
const LinearSolver::Options options_;
- DISALLOW_COPY_AND_ASSIGN(DenseQRSolver);
+ CERES_DISALLOW_COPY_AND_ASSIGN(DenseQRSolver);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc
index 5d392ba6c3b..86730cc101b 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc
@@ -67,7 +67,7 @@ DenseSparseMatrix::DenseSparseMatrix(const Matrix& m)
has_diagonal_reserved_(false) {
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
DenseSparseMatrix::DenseSparseMatrix(const SparseMatrixProto& outer_proto)
: m_(Eigen::MatrixXd::Zero(
outer_proto.dense_matrix().num_rows(),
@@ -108,7 +108,7 @@ void DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
*dense_matrix = m_;
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
void DenseSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
CHECK(!has_diagonal_appended_) << "Not supported.";
outer_proto->Clear();
@@ -183,7 +183,7 @@ void DenseSparseMatrix::ToTextFile(FILE* file) const {
CHECK_NOTNULL(file);
const int active_rows =
(has_diagonal_reserved_ && !has_diagonal_appended_)
- ? (m_.rows() - m_.cols())
+ ? (m_.rows() - m_.cols())
: m_.rows();
for (int r = 0; r < active_rows; ++r) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h
index 416c2143c2c..e7ad14d0ee6 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h
@@ -52,7 +52,7 @@ class DenseSparseMatrix : public SparseMatrix {
// m. This assumes that m does not have any repeated entries.
explicit DenseSparseMatrix(const TripletSparseMatrix& m);
explicit DenseSparseMatrix(const Matrix& m);
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
explicit DenseSparseMatrix(const SparseMatrixProto& proto);
#endif
@@ -67,7 +67,7 @@ class DenseSparseMatrix : public SparseMatrix {
virtual void SquaredColumnNorm(double* x) const;
virtual void ScaleColumns(const double* scale);
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
virtual void ToProto(SparseMatrixProto* proto) const;
#endif
virtual void ToTextFile(FILE* file) const;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc
index e9755043bab..ea5bf2e9690 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc
@@ -28,9 +28,9 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-#include <glog/logging.h>
#include "ceres/detect_structure.h"
#include "ceres/internal/eigen.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -60,10 +60,10 @@ void DetectStructure(const CompressedRowBlockStructure& bs,
*row_block_size = row.block.size;
} else if (*row_block_size != Eigen::Dynamic &&
*row_block_size != row.block.size) {
- *row_block_size = Eigen::Dynamic;
VLOG(2) << "Dynamic row block size because the block size changed from "
<< *row_block_size << " to "
<< row.block.size;
+ *row_block_size = Eigen::Dynamic;
}
@@ -71,10 +71,10 @@ void DetectStructure(const CompressedRowBlockStructure& bs,
*e_block_size = bs.cols[e_block_id].size;
} else if (*e_block_size != Eigen::Dynamic &&
*e_block_size != bs.cols[e_block_id].size) {
- *e_block_size = Eigen::Dynamic;
VLOG(2) << "Dynamic e block size because the block size changed from "
<< *e_block_size << " to "
<< bs.cols[e_block_id].size;
+ *e_block_size = Eigen::Dynamic;
}
if (*f_block_size == 0) {
@@ -85,11 +85,11 @@ void DetectStructure(const CompressedRowBlockStructure& bs,
} else if (*f_block_size != Eigen::Dynamic) {
for (int c = 1; c < row.cells.size(); ++c) {
if (*f_block_size != bs.cols[row.cells[c].block_id].size) {
- *f_block_size = Eigen::Dynamic;
VLOG(2) << "Dynamic f block size because the block size "
- << "changed from " << *f_block_size << " to "
- << bs.cols[row.cells[c].block_id].size;
- break;
+ << "changed from " << *f_block_size << " to "
+ << bs.cols[row.cells[c].block_id].size;
+ *f_block_size = Eigen::Dynamic;
+ break;
}
}
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h
index 8af4f236690..5f8e1b4ff46 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h
@@ -49,7 +49,7 @@ namespace internal {
// is known as compile time.
//
// For more details about e_blocks and f_blocks, see
-// schur_complement.h. This information is used to initialized an
+// schur_eliminator.h. This information is used to initialized an
// appropriate template specialization of SchurEliminator.
void DetectStructure(const CompressedRowBlockStructure& bs,
const int num_eliminate_blocks,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc
new file mode 100644
index 00000000000..668fa54b8b8
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc
@@ -0,0 +1,691 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/dogleg_strategy.h"
+
+#include <cmath>
+#include "Eigen/Dense"
+#include "ceres/array_utils.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/linear_solver.h"
+#include "ceres/polynomial_solver.h"
+#include "ceres/sparse_matrix.h"
+#include "ceres/trust_region_strategy.h"
+#include "ceres/types.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+namespace {
+const double kMaxMu = 1.0;
+const double kMinMu = 1e-8;
+}
+
+DoglegStrategy::DoglegStrategy(const TrustRegionStrategy::Options& options)
+ : linear_solver_(options.linear_solver),
+ radius_(options.initial_radius),
+ max_radius_(options.max_radius),
+ min_diagonal_(options.lm_min_diagonal),
+ max_diagonal_(options.lm_max_diagonal),
+ mu_(kMinMu),
+ min_mu_(kMinMu),
+ max_mu_(kMaxMu),
+ mu_increase_factor_(10.0),
+ increase_threshold_(0.75),
+ decrease_threshold_(0.25),
+ dogleg_step_norm_(0.0),
+ reuse_(false),
+ dogleg_type_(options.dogleg_type) {
+ CHECK_NOTNULL(linear_solver_);
+ CHECK_GT(min_diagonal_, 0.0);
+ CHECK_LE(min_diagonal_, max_diagonal_);
+ CHECK_GT(max_radius_, 0.0);
+}
+
+// If the reuse_ flag is not set, then the Cauchy point (scaled
+// gradient) and the new Gauss-Newton step are computed from
+// scratch. The Dogleg step is then computed as interpolation of these
+// two vectors.
+TrustRegionStrategy::Summary DoglegStrategy::ComputeStep(
+ const TrustRegionStrategy::PerSolveOptions& per_solve_options,
+ SparseMatrix* jacobian,
+ const double* residuals,
+ double* step) {
+ CHECK_NOTNULL(jacobian);
+ CHECK_NOTNULL(residuals);
+ CHECK_NOTNULL(step);
+
+ const int n = jacobian->num_cols();
+ if (reuse_) {
+ // Gauss-Newton and gradient vectors are always available, only a
+ // new interpolant need to be computed. For the subspace case,
+ // the subspace and the two-dimensional model are also still valid.
+ switch(dogleg_type_) {
+ case TRADITIONAL_DOGLEG:
+ ComputeTraditionalDoglegStep(step);
+ break;
+
+ case SUBSPACE_DOGLEG:
+ ComputeSubspaceDoglegStep(step);
+ break;
+ }
+ TrustRegionStrategy::Summary summary;
+ summary.num_iterations = 0;
+ summary.termination_type = TOLERANCE;
+ return summary;
+ }
+
+ reuse_ = true;
+ // Check that we have the storage needed to hold the various
+ // temporary vectors.
+ if (diagonal_.rows() != n) {
+ diagonal_.resize(n, 1);
+ gradient_.resize(n, 1);
+ gauss_newton_step_.resize(n, 1);
+ }
+
+ // Vector used to form the diagonal matrix that is used to
+ // regularize the Gauss-Newton solve and that defines the
+ // elliptical trust region
+ //
+ // || D * step || <= radius_ .
+ //
+ jacobian->SquaredColumnNorm(diagonal_.data());
+ for (int i = 0; i < n; ++i) {
+ diagonal_[i] = min(max(diagonal_[i], min_diagonal_), max_diagonal_);
+ }
+ diagonal_ = diagonal_.array().sqrt();
+
+ ComputeGradient(jacobian, residuals);
+ ComputeCauchyPoint(jacobian);
+
+ LinearSolver::Summary linear_solver_summary =
+ ComputeGaussNewtonStep(jacobian, residuals);
+
+ TrustRegionStrategy::Summary summary;
+ summary.residual_norm = linear_solver_summary.residual_norm;
+ summary.num_iterations = linear_solver_summary.num_iterations;
+ summary.termination_type = linear_solver_summary.termination_type;
+
+ if (linear_solver_summary.termination_type != FAILURE) {
+ switch(dogleg_type_) {
+ // Interpolate the Cauchy point and the Gauss-Newton step.
+ case TRADITIONAL_DOGLEG:
+ ComputeTraditionalDoglegStep(step);
+ break;
+
+ // Find the minimum in the subspace defined by the
+ // Cauchy point and the (Gauss-)Newton step.
+ case SUBSPACE_DOGLEG:
+ if (!ComputeSubspaceModel(jacobian)) {
+ summary.termination_type = FAILURE;
+ break;
+ }
+ ComputeSubspaceDoglegStep(step);
+ break;
+ }
+ }
+
+ return summary;
+}
+
+// The trust region is assumed to be elliptical with the
+// diagonal scaling matrix D defined by sqrt(diagonal_).
+// It is implemented by substituting step' = D * step.
+// The trust region for step' is spherical.
+// The gradient, the Gauss-Newton step, the Cauchy point,
+// and all calculations involving the Jacobian have to
+// be adjusted accordingly.
+void DoglegStrategy::ComputeGradient(
+ SparseMatrix* jacobian,
+ const double* residuals) {
+ gradient_.setZero();
+ jacobian->LeftMultiply(residuals, gradient_.data());
+ gradient_.array() /= diagonal_.array();
+}
+
+// The Cauchy point is the global minimizer of the quadratic model
+// along the one-dimensional subspace spanned by the gradient.
+void DoglegStrategy::ComputeCauchyPoint(SparseMatrix* jacobian) {
+ // alpha * -gradient is the Cauchy point.
+ Vector Jg(jacobian->num_rows());
+ Jg.setZero();
+ // The Jacobian is scaled implicitly by computing J * (D^-1 * (D^-1 * g))
+ // instead of (J * D^-1) * (D^-1 * g).
+ Vector scaled_gradient =
+ (gradient_.array() / diagonal_.array()).matrix();
+ jacobian->RightMultiply(scaled_gradient.data(), Jg.data());
+ alpha_ = gradient_.squaredNorm() / Jg.squaredNorm();
+}
+
+// The dogleg step is defined as the intersection of the trust region
+// boundary with the piecewise linear path from the origin to the Cauchy
+// point and then from there to the Gauss-Newton point (global minimizer
+// of the model function). The Gauss-Newton point is taken if it lies
+// within the trust region.
+void DoglegStrategy::ComputeTraditionalDoglegStep(double* dogleg) {
+ VectorRef dogleg_step(dogleg, gradient_.rows());
+
+ // Case 1. The Gauss-Newton step lies inside the trust region, and
+ // is therefore the optimal solution to the trust-region problem.
+ const double gradient_norm = gradient_.norm();
+ const double gauss_newton_norm = gauss_newton_step_.norm();
+ if (gauss_newton_norm <= radius_) {
+ dogleg_step = gauss_newton_step_;
+ dogleg_step_norm_ = gauss_newton_norm;
+ dogleg_step.array() /= diagonal_.array();
+ VLOG(3) << "GaussNewton step size: " << dogleg_step_norm_
+ << " radius: " << radius_;
+ return;
+ }
+
+ // Case 2. The Cauchy point and the Gauss-Newton steps lie outside
+ // the trust region. Rescale the Cauchy point to the trust region
+ // and return.
+ if (gradient_norm * alpha_ >= radius_) {
+ dogleg_step = -(radius_ / gradient_norm) * gradient_;
+ dogleg_step_norm_ = radius_;
+ dogleg_step.array() /= diagonal_.array();
+ VLOG(3) << "Cauchy step size: " << dogleg_step_norm_
+ << " radius: " << radius_;
+ return;
+ }
+
+ // Case 3. The Cauchy point is inside the trust region and the
+ // Gauss-Newton step is outside. Compute the line joining the two
+ // points and the point on it which intersects the trust region
+ // boundary.
+
+ // a = alpha * -gradient
+ // b = gauss_newton_step
+ const double b_dot_a = -alpha_ * gradient_.dot(gauss_newton_step_);
+ const double a_squared_norm = pow(alpha_ * gradient_norm, 2.0);
+ const double b_minus_a_squared_norm =
+ a_squared_norm - 2 * b_dot_a + pow(gauss_newton_norm, 2);
+
+ // c = a' (b - a)
+ // = alpha * -gradient' gauss_newton_step - alpha^2 |gradient|^2
+ const double c = b_dot_a - a_squared_norm;
+ const double d = sqrt(c * c + b_minus_a_squared_norm *
+ (pow(radius_, 2.0) - a_squared_norm));
+
+ double beta =
+ (c <= 0)
+ ? (d - c) / b_minus_a_squared_norm
+ : (radius_ * radius_ - a_squared_norm) / (d + c);
+ dogleg_step = (-alpha_ * (1.0 - beta)) * gradient_
+ + beta * gauss_newton_step_;
+ dogleg_step_norm_ = dogleg_step.norm();
+ dogleg_step.array() /= diagonal_.array();
+ VLOG(3) << "Dogleg step size: " << dogleg_step_norm_
+ << " radius: " << radius_;
+}
+
+// The subspace method finds the minimum of the two-dimensional problem
+//
+// min. 1/2 x' B' H B x + g' B x
+// s.t. || B x ||^2 <= r^2
+//
+// where r is the trust region radius and B is the matrix with unit columns
+// spanning the subspace defined by the steepest descent and Newton direction.
+// This subspace by definition includes the Gauss-Newton point, which is
+// therefore taken if it lies within the trust region.
+void DoglegStrategy::ComputeSubspaceDoglegStep(double* dogleg) {
+ VectorRef dogleg_step(dogleg, gradient_.rows());
+
+ // The Gauss-Newton point is inside the trust region if |GN| <= radius_.
+ // This test is valid even though radius_ is a length in the two-dimensional
+ // subspace while gauss_newton_step_ is expressed in the (scaled)
+ // higher dimensional original space. This is because
+ //
+ // 1. gauss_newton_step_ by definition lies in the subspace, and
+ // 2. the subspace basis is orthonormal.
+ //
+ // As a consequence, the norm of the gauss_newton_step_ in the subspace is
+ // the same as its norm in the original space.
+ const double gauss_newton_norm = gauss_newton_step_.norm();
+ if (gauss_newton_norm <= radius_) {
+ dogleg_step = gauss_newton_step_;
+ dogleg_step_norm_ = gauss_newton_norm;
+ dogleg_step.array() /= diagonal_.array();
+ VLOG(3) << "GaussNewton step size: " << dogleg_step_norm_
+ << " radius: " << radius_;
+ return;
+ }
+
+ // The optimum lies on the boundary of the trust region. The above problem
+ // therefore becomes
+ //
+ // min. 1/2 x^T B^T H B x + g^T B x
+ // s.t. || B x ||^2 = r^2
+ //
+ // Notice the equality in the constraint.
+ //
+ // This can be solved by forming the Lagrangian, solving for x(y), where
+ // y is the Lagrange multiplier, using the gradient of the objective, and
+ // putting x(y) back into the constraint. This results in a fourth order
+ // polynomial in y, which can be solved using e.g. the companion matrix.
+ // See the description of MakePolynomialForBoundaryConstrainedProblem for
+ // details. The result is up to four real roots y*, not all of which
+ // correspond to feasible points. The feasible points x(y*) have to be
+ // tested for optimality.
+
+ if (subspace_is_one_dimensional_) {
+ // The subspace is one-dimensional, so both the gradient and
+ // the Gauss-Newton step point towards the same direction.
+ // In this case, we move along the gradient until we reach the trust
+ // region boundary.
+ dogleg_step = -(radius_ / gradient_.norm()) * gradient_;
+ dogleg_step_norm_ = radius_;
+ dogleg_step.array() /= diagonal_.array();
+ VLOG(3) << "Dogleg subspace step size (1D): " << dogleg_step_norm_
+ << " radius: " << radius_;
+ return;
+ }
+
+ Vector2d minimum(0.0, 0.0);
+ if (!FindMinimumOnTrustRegionBoundary(&minimum)) {
+ // For the positive semi-definite case, a traditional dogleg step
+ // is taken in this case.
+ LOG(WARNING) << "Failed to compute polynomial roots. "
+ << "Taking traditional dogleg step instead.";
+ ComputeTraditionalDoglegStep(dogleg);
+ return;
+ }
+
+ // Test first order optimality at the minimum.
+ // The first order KKT conditions state that the minimum x*
+ // has to satisfy either || x* ||^2 < r^2 (i.e. has to lie within
+ // the trust region), or
+ //
+ // (B x* + g) + y x* = 0
+ //
+ // for some positive scalar y.
+ // Here, as it is already known that the minimum lies on the boundary, the
+ // latter condition is tested. To allow for small imprecisions, we test if
+ // the angle between (B x* + g) and -x* is smaller than acos(0.99).
+ // The exact value of the cosine is arbitrary but should be close to 1.
+ //
+ // This condition should not be violated. If it is, the minimum was not
+ // correctly determined.
+ const double kCosineThreshold = 0.99;
+ const Vector2d grad_minimum = subspace_B_ * minimum + subspace_g_;
+ const double cosine_angle = -minimum.dot(grad_minimum) /
+ (minimum.norm() * grad_minimum.norm());
+ if (cosine_angle < kCosineThreshold) {
+ LOG(WARNING) << "First order optimality seems to be violated "
+ << "in the subspace method!\n"
+ << "Cosine of angle between x and B x + g is "
+ << cosine_angle << ".\n"
+ << "Taking a regular dogleg step instead.\n"
+ << "Please consider filing a bug report if this "
+ << "happens frequently or consistently.\n";
+ ComputeTraditionalDoglegStep(dogleg);
+ return;
+ }
+
+ // Create the full step from the optimal 2d solution.
+ dogleg_step = subspace_basis_ * minimum;
+ dogleg_step_norm_ = radius_;
+ dogleg_step.array() /= diagonal_.array();
+ VLOG(3) << "Dogleg subspace step size: " << dogleg_step_norm_
+ << " radius: " << radius_;
+}
+
+// Build the polynomial that defines the optimal Lagrange multipliers.
+// Let the Lagrangian be
+//
+// L(x, y) = 0.5 x^T B x + x^T g + y (0.5 x^T x - 0.5 r^2). (1)
+//
+// Stationary points of the Lagrangian are given by
+//
+// 0 = d L(x, y) / dx = Bx + g + y x (2)
+// 0 = d L(x, y) / dy = 0.5 x^T x - 0.5 r^2 (3)
+//
+// For any given y, we can solve (2) for x as
+//
+// x(y) = -(B + y I)^-1 g . (4)
+//
+// As B + y I is 2x2, we form the inverse explicitly:
+//
+// (B + y I)^-1 = (1 / det(B + y I)) adj(B + y I) (5)
+//
+// where adj() denotes adjugation. This should be safe, as B is positive
+// semi-definite and y is necessarily positive, so (B + y I) is indeed
+// invertible.
+// Plugging (5) into (4) and the result into (3), then dividing by 0.5 we
+// obtain
+//
+// 0 = (1 / det(B + y I))^2 g^T adj(B + y I)^T adj(B + y I) g - r^2
+// (6)
+//
+// or
+//
+// det(B + y I)^2 r^2 = g^T adj(B + y I)^T adj(B + y I) g (7a)
+// = g^T adj(B)^T adj(B) g
+// + 2 y g^T adj(B)^T g + y^2 g^T g (7b)
+//
+// as
+//
+// adj(B + y I) = adj(B) + y I = adj(B)^T + y I . (8)
+//
+// The left hand side can be expressed explicitly using
+//
+// det(B + y I) = det(B) + y tr(B) + y^2 . (9)
+//
+// So (7) is a polynomial in y of degree four.
+// Bringing everything back to the left hand side, the coefficients can
+// be read off as
+//
+// y^4 r^2
+// + y^3 2 r^2 tr(B)
+// + y^2 (r^2 tr(B)^2 + 2 r^2 det(B) - g^T g)
+// + y^1 (2 r^2 det(B) tr(B) - 2 g^T adj(B)^T g)
+// + y^0 (r^2 det(B)^2 - g^T adj(B)^T adj(B) g)
+//
+Vector DoglegStrategy::MakePolynomialForBoundaryConstrainedProblem() const {
+ const double detB = subspace_B_.determinant();
+ const double trB = subspace_B_.trace();
+ const double r2 = radius_ * radius_;
+ Matrix2d B_adj;
+ B_adj << subspace_B_(1,1) , -subspace_B_(0,1),
+ -subspace_B_(1,0) , subspace_B_(0,0);
+
+ Vector polynomial(5);
+ polynomial(0) = r2;
+ polynomial(1) = 2.0 * r2 * trB;
+ polynomial(2) = r2 * ( trB * trB + 2.0 * detB ) - subspace_g_.squaredNorm();
+ polynomial(3) = -2.0 * ( subspace_g_.transpose() * B_adj * subspace_g_
+ - r2 * detB * trB );
+ polynomial(4) = r2 * detB * detB - (B_adj * subspace_g_).squaredNorm();
+
+ return polynomial;
+}
+
+// Given a Lagrange multiplier y that corresponds to a stationary point
+// of the Lagrangian L(x, y), compute the corresponding x from the
+// equation
+//
+// 0 = d L(x, y) / dx
+// = B * x + g + y * x
+// = (B + y * I) * x + g
+//
+DoglegStrategy::Vector2d DoglegStrategy::ComputeSubspaceStepFromRoot(
+ double y) const {
+ const Matrix2d B_i = subspace_B_ + y * Matrix2d::Identity();
+ return -B_i.partialPivLu().solve(subspace_g_);
+}
+
+// This function evaluates the quadratic model at a point x in the
+// subspace spanned by subspace_basis_.
+double DoglegStrategy::EvaluateSubspaceModel(const Vector2d& x) const {
+ return 0.5 * x.dot(subspace_B_ * x) + subspace_g_.dot(x);
+}
+
+// This function attempts to solve the boundary-constrained subspace problem
+//
+// min. 1/2 x^T B^T H B x + g^T B x
+// s.t. || B x ||^2 = r^2
+//
+// where B is an orthonormal subspace basis and r is the trust-region radius.
+//
+// This is done by finding the roots of a fourth degree polynomial. If the
+// root finding fails, the function returns false and minimum will be set
+// to (0, 0). If it succeeds, true is returned.
+//
+// In the failure case, another step should be taken, such as the traditional
+// dogleg step.
+bool DoglegStrategy::FindMinimumOnTrustRegionBoundary(Vector2d* minimum) const {
+ CHECK_NOTNULL(minimum);
+
+ // Return (0, 0) in all error cases.
+ minimum->setZero();
+
+ // Create the fourth-degree polynomial that is a necessary condition for
+ // optimality.
+ const Vector polynomial = MakePolynomialForBoundaryConstrainedProblem();
+
+ // Find the real parts y_i of its roots (not only the real roots).
+ Vector roots_real;
+ if (!FindPolynomialRoots(polynomial, &roots_real, NULL)) {
+ // Failed to find the roots of the polynomial, i.e. the candidate
+ // solutions of the constrained problem. Report this back to the caller.
+ return false;
+ }
+
+ // For each root y, compute B x(y) and check for feasibility.
+ // Notice that there should always be four roots, as the leading term of
+ // the polynomial is r^2 and therefore non-zero. However, as some roots
+ // may be complex, the real parts are not necessarily unique.
+ double minimum_value = std::numeric_limits<double>::max();
+ bool valid_root_found = false;
+ for (int i = 0; i < roots_real.size(); ++i) {
+ const Vector2d x_i = ComputeSubspaceStepFromRoot(roots_real(i));
+
+ // Not all roots correspond to points on the trust region boundary.
+ // There are at most four candidate solutions. As we are interested
+ // in the minimum, it is safe to consider all of them after projecting
+ // them onto the trust region boundary.
+ if (x_i.norm() > 0) {
+ const double f_i = EvaluateSubspaceModel((radius_ / x_i.norm()) * x_i);
+ valid_root_found = true;
+ if (f_i < minimum_value) {
+ minimum_value = f_i;
+ *minimum = x_i;
+ }
+ }
+ }
+
+ return valid_root_found;
+}
+
+LinearSolver::Summary DoglegStrategy::ComputeGaussNewtonStep(
+ SparseMatrix* jacobian,
+ const double* residuals) {
+ const int n = jacobian->num_cols();
+ LinearSolver::Summary linear_solver_summary;
+ linear_solver_summary.termination_type = FAILURE;
+
+ // The Jacobian matrix is often quite poorly conditioned. Thus it is
+ // necessary to add a diagonal matrix at the bottom to prevent the
+ // linear solver from failing.
+ //
+ // We do this by computing the same diagonal matrix as the one used
+ // by Levenberg-Marquardt (other choices are possible), and scaling
+ // it by a small constant (independent of the trust region radius).
+ //
+ // If the solve fails, the multiplier to the diagonal is increased
+ // up to max_mu_ by a factor of mu_increase_factor_ every time. If
+ // the linear solver is still not successful, the strategy returns
+ // with FAILURE.
+ //
+ // Next time when a new Gauss-Newton step is requested, the
+ // multiplier starts out from the last successful solve.
+ //
+ // When a step is declared successful, the multiplier is decreased
+ // by half of mu_increase_factor_.
+
+ while (mu_ < max_mu_) {
+ // Dogleg, as far as I (sameeragarwal) understand it, requires a
+ // reasonably good estimate of the Gauss-Newton step. This means
+ // that we need to solve the normal equations more or less
+ // exactly. This is reflected in the values of the tolerances set
+ // below.
+ //
+ // For now, this strategy should only be used with exact
+ // factorization based solvers, for which these tolerances are
+ // automatically satisfied.
+ //
+ // The right way to combine inexact solves with trust region
+ // methods is to use Stiehaug's method.
+ LinearSolver::PerSolveOptions solve_options;
+ solve_options.q_tolerance = 0.0;
+ solve_options.r_tolerance = 0.0;
+
+ lm_diagonal_ = diagonal_ * std::sqrt(mu_);
+ solve_options.D = lm_diagonal_.data();
+
+ // As in the LevenbergMarquardtStrategy, solve Jy = r instead
+ // of Jx = -r and later set x = -y to avoid having to modify
+ // either jacobian or residuals.
+ InvalidateArray(n, gauss_newton_step_.data());
+ linear_solver_summary = linear_solver_->Solve(jacobian,
+ residuals,
+ solve_options,
+ gauss_newton_step_.data());
+
+ if (linear_solver_summary.termination_type == FAILURE ||
+ !IsArrayValid(n, gauss_newton_step_.data())) {
+ mu_ *= mu_increase_factor_;
+ VLOG(2) << "Increasing mu " << mu_;
+ linear_solver_summary.termination_type = FAILURE;
+ continue;
+ }
+ break;
+ }
+
+ if (linear_solver_summary.termination_type != FAILURE) {
+ // The scaled Gauss-Newton step is D * GN:
+ //
+ // - (D^-1 J^T J D^-1)^-1 (D^-1 g)
+ // = - D (J^T J)^-1 D D^-1 g
+ // = D -(J^T J)^-1 g
+ //
+ gauss_newton_step_.array() *= -diagonal_.array();
+ }
+
+ return linear_solver_summary;
+}
+
+void DoglegStrategy::StepAccepted(double step_quality) {
+ CHECK_GT(step_quality, 0.0);
+
+ if (step_quality < decrease_threshold_) {
+ radius_ *= 0.5;
+ }
+
+ if (step_quality > increase_threshold_) {
+ radius_ = max(radius_, 3.0 * dogleg_step_norm_);
+ }
+
+ // Reduce the regularization multiplier, in the hope that whatever
+ // was causing the rank deficiency has gone away and we can return
+ // to doing a pure Gauss-Newton solve.
+ mu_ = max(min_mu_, 2.0 * mu_ / mu_increase_factor_ );
+ reuse_ = false;
+}
+
+void DoglegStrategy::StepRejected(double step_quality) {
+ radius_ *= 0.5;
+ reuse_ = true;
+}
+
+void DoglegStrategy::StepIsInvalid() {
+ mu_ *= mu_increase_factor_;
+ reuse_ = false;
+}
+
+double DoglegStrategy::Radius() const {
+ return radius_;
+}
+
+bool DoglegStrategy::ComputeSubspaceModel(SparseMatrix* jacobian) {
+ // Compute an orthogonal basis for the subspace using QR decomposition.
+ Matrix basis_vectors(jacobian->num_cols(), 2);
+ basis_vectors.col(0) = gradient_;
+ basis_vectors.col(1) = gauss_newton_step_;
+ Eigen::ColPivHouseholderQR<Matrix> basis_qr(basis_vectors);
+
+ switch (basis_qr.rank()) {
+ case 0:
+ // This should never happen, as it implies that both the gradient
+ // and the Gauss-Newton step are zero. In this case, the minimizer should
+ // have stopped due to the gradient being too small.
+ LOG(ERROR) << "Rank of subspace basis is 0. "
+ << "This means that the gradient at the current iterate is "
+ << "zero but the optimization has not been terminated. "
+ << "You may have found a bug in Ceres.";
+ return false;
+
+ case 1:
+ // Gradient and Gauss-Newton step coincide, so we lie on one of the
+ // major axes of the quadratic problem. In this case, we simply move
+ // along the gradient until we reach the trust region boundary.
+ subspace_is_one_dimensional_ = true;
+ return true;
+
+ case 2:
+ subspace_is_one_dimensional_ = false;
+ break;
+
+ default:
+ LOG(ERROR) << "Rank of the subspace basis matrix is reported to be "
+ << "greater than 2. As the matrix contains only two "
+ << "columns this cannot be true and is indicative of "
+ << "a bug.";
+ return false;
+ }
+
+ // The subspace is two-dimensional, so compute the subspace model.
+ // Given the basis U, this is
+ //
+ // subspace_g_ = g_scaled^T U
+ //
+ // and
+ //
+ // subspace_B_ = U^T (J_scaled^T J_scaled) U
+ //
+ // As J_scaled = J * D^-1, the latter becomes
+ //
+ // subspace_B_ = ((U^T D^-1) J^T) (J (D^-1 U))
+ // = (J (D^-1 U))^T (J (D^-1 U))
+
+ subspace_basis_ =
+ basis_qr.householderQ() * Matrix::Identity(jacobian->num_cols(), 2);
+
+ subspace_g_ = subspace_basis_.transpose() * gradient_;
+
+ Eigen::Matrix<double, 2, Eigen::Dynamic, Eigen::RowMajor>
+ Jb(2, jacobian->num_rows());
+ Jb.setZero();
+
+ Vector tmp;
+ tmp = (subspace_basis_.col(0).array() / diagonal_.array()).matrix();
+ jacobian->RightMultiply(tmp.data(), Jb.row(0).data());
+ tmp = (subspace_basis_.col(1).array() / diagonal_.array()).matrix();
+ jacobian->RightMultiply(tmp.data(), Jb.row(1).data());
+
+ subspace_B_ = Jb * Jb.transpose();
+
+ return true;
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h
new file mode 100644
index 00000000000..bff1689aa4a
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h
@@ -0,0 +1,163 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_DOGLEG_STRATEGY_H_
+#define CERES_INTERNAL_DOGLEG_STRATEGY_H_
+
+#include "ceres/linear_solver.h"
+#include "ceres/trust_region_strategy.h"
+
+namespace ceres {
+namespace internal {
+
+// Dogleg step computation and trust region sizing strategy based on
+// on "Methods for Nonlinear Least Squares" by K. Madsen, H.B. Nielsen
+// and O. Tingleff. Available to download from
+//
+// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
+//
+// One minor modification is that instead of computing the pure
+// Gauss-Newton step, we compute a regularized version of it. This is
+// because the Jacobian is often rank-deficient and in such cases
+// using a direct solver leads to numerical failure.
+//
+// If SUBSPACE is passed as the type argument to the constructor, the
+// DoglegStrategy follows the approach by Shultz, Schnabel, Byrd.
+// This finds the exact optimum over the two-dimensional subspace
+// spanned by the two Dogleg vectors.
+class DoglegStrategy : public TrustRegionStrategy {
+public:
+ DoglegStrategy(const TrustRegionStrategy::Options& options);
+ virtual ~DoglegStrategy() {}
+
+ // TrustRegionStrategy interface
+ virtual Summary ComputeStep(const PerSolveOptions& per_solve_options,
+ SparseMatrix* jacobian,
+ const double* residuals,
+ double* step);
+ virtual void StepAccepted(double step_quality);
+ virtual void StepRejected(double step_quality);
+ virtual void StepIsInvalid();
+
+ virtual double Radius() const;
+
+ // These functions are predominantly for testing.
+ Vector gradient() const { return gradient_; }
+ Vector gauss_newton_step() const { return gauss_newton_step_; }
+ Matrix subspace_basis() const { return subspace_basis_; }
+ Vector subspace_g() const { return subspace_g_; }
+ Matrix subspace_B() const { return subspace_B_; }
+
+ private:
+ typedef Eigen::Matrix<double, 2, 1, Eigen::DontAlign> Vector2d;
+ typedef Eigen::Matrix<double, 2, 2, Eigen::DontAlign> Matrix2d;
+
+ LinearSolver::Summary ComputeGaussNewtonStep(SparseMatrix* jacobian,
+ const double* residuals);
+ void ComputeCauchyPoint(SparseMatrix* jacobian);
+ void ComputeGradient(SparseMatrix* jacobian, const double* residuals);
+ void ComputeTraditionalDoglegStep(double* step);
+ bool ComputeSubspaceModel(SparseMatrix* jacobian);
+ void ComputeSubspaceDoglegStep(double* step);
+
+ bool FindMinimumOnTrustRegionBoundary(Vector2d* minimum) const;
+ Vector MakePolynomialForBoundaryConstrainedProblem() const;
+ Vector2d ComputeSubspaceStepFromRoot(double lambda) const;
+ double EvaluateSubspaceModel(const Vector2d& x) const;
+
+ LinearSolver* linear_solver_;
+ double radius_;
+ const double max_radius_;
+
+ const double min_diagonal_;
+ const double max_diagonal_;
+
+ // mu is used to scale the diagonal matrix used to make the
+ // Gauss-Newton solve full rank. In each solve, the strategy starts
+ // out with mu = min_mu, and tries values upto max_mu. If the user
+ // reports an invalid step, the value of mu_ is increased so that
+ // the next solve starts with a stronger regularization.
+ //
+ // If a successful step is reported, then the value of mu_ is
+ // decreased with a lower bound of min_mu_.
+ double mu_;
+ const double min_mu_;
+ const double max_mu_;
+ const double mu_increase_factor_;
+ const double increase_threshold_;
+ const double decrease_threshold_;
+
+ Vector diagonal_; // sqrt(diag(J^T J))
+ Vector lm_diagonal_;
+
+ Vector gradient_;
+ Vector gauss_newton_step_;
+
+ // cauchy_step = alpha * gradient
+ double alpha_;
+ double dogleg_step_norm_;
+
+ // When, ComputeStep is called, reuse_ indicates whether the
+ // Gauss-Newton and Cauchy steps from the last call to ComputeStep
+ // can be reused or not.
+ //
+ // If the user called StepAccepted, then it is expected that the
+ // user has recomputed the Jacobian matrix and new Gauss-Newton
+ // solve is needed and reuse is set to false.
+ //
+ // If the user called StepRejected, then it is expected that the
+ // user wants to solve the trust region problem with the same matrix
+ // but a different trust region radius and the Gauss-Newton and
+ // Cauchy steps can be reused to compute the Dogleg, thus reuse is
+ // set to true.
+ //
+ // If the user called StepIsInvalid, then there was a numerical
+ // problem with the step computed in the last call to ComputeStep,
+ // and the regularization used to do the Gauss-Newton solve is
+ // increased and a new solve should be done when ComputeStep is
+ // called again, thus reuse is set to false.
+ bool reuse_;
+
+ // The dogleg type determines how the minimum of the local
+ // quadratic model is found.
+ DoglegType dogleg_type_;
+
+ // If the type is SUBSPACE_DOGLEG, the two-dimensional
+ // model 1/2 x^T B x + g^T x has to be computed and stored.
+ bool subspace_is_one_dimensional_;
+ Matrix subspace_basis_;
+ Vector2d subspace_g_;
+ Matrix2d subspace_B_;
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_DOGLEG_STRATEGY_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc
index ea05aefec8c..a3ce6f04bd4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc
@@ -28,14 +28,18 @@
//
// Author: keir@google.com (Keir Mierle)
-#include <glog/logging.h>
-#include "ceres/evaluator.h"
+#include <vector>
#include "ceres/block_evaluate_preparer.h"
#include "ceres/block_jacobian_writer.h"
#include "ceres/compressed_row_jacobian_writer.h"
-#include "ceres/scratch_evaluate_preparer.h"
+#include "ceres/compressed_row_sparse_matrix.h"
+#include "ceres/crs_matrix.h"
#include "ceres/dense_jacobian_writer.h"
+#include "ceres/evaluator.h"
+#include "ceres/internal/port.h"
#include "ceres/program_evaluator.h"
+#include "ceres/scratch_evaluate_preparer.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -47,6 +51,7 @@ Evaluator* Evaluator::Create(const Evaluator::Options& options,
string* error) {
switch (options.linear_solver_type) {
case DENSE_QR:
+ case DENSE_NORMAL_CHOLESKY:
return new ProgramEvaluator<ScratchEvaluatePreparer,
DenseJacobianWriter>(options,
program);
@@ -67,5 +72,76 @@ Evaluator* Evaluator::Create(const Evaluator::Options& options,
}
}
+bool Evaluator::Evaluate(Program* program,
+ int num_threads,
+ double* cost,
+ vector<double>* residuals,
+ vector<double>* gradient,
+ CRSMatrix* output_jacobian) {
+ CHECK_GE(num_threads, 1)
+ << "This is a Ceres bug; please contact the developers!";
+ CHECK_NOTNULL(cost);
+
+ // Setup the Parameter indices and offsets before an evaluator can
+ // be constructed and used.
+ program->SetParameterOffsetsAndIndex();
+
+ Evaluator::Options evaluator_options;
+ evaluator_options.linear_solver_type = SPARSE_NORMAL_CHOLESKY;
+ evaluator_options.num_threads = num_threads;
+
+ string error;
+ scoped_ptr<Evaluator> evaluator(
+ Evaluator::Create(evaluator_options, program, &error));
+ if (evaluator.get() == NULL) {
+ LOG(ERROR) << "Unable to create an Evaluator object. "
+ << "Error: " << error
+ << "This is a Ceres bug; please contact the developers!";
+ return false;
+ }
+
+ if (residuals !=NULL) {
+ residuals->resize(evaluator->NumResiduals());
+ }
+
+ if (gradient != NULL) {
+ gradient->resize(evaluator->NumEffectiveParameters());
+ }
+
+ scoped_ptr<CompressedRowSparseMatrix> jacobian;
+ if (output_jacobian != NULL) {
+ jacobian.reset(
+ down_cast<CompressedRowSparseMatrix*>(evaluator->CreateJacobian()));
+ }
+
+ // Point the state pointers to the user state pointers. This is
+ // needed so that we can extract a parameter vector which is then
+ // passed to Evaluator::Evaluate.
+ program->SetParameterBlockStatePtrsToUserStatePtrs();
+
+ // Copy the value of the parameter blocks into a vector, since the
+ // Evaluate::Evaluate method needs its input as such. The previous
+ // call to SetParameterBlockStatePtrsToUserStatePtrs ensures that
+ // these values are the ones corresponding to the actual state of
+ // the parameter blocks, rather than the temporary state pointer
+ // used for evaluation.
+ Vector parameters(program->NumParameters());
+ program->ParameterBlocksToStateVector(parameters.data());
+
+ if (!evaluator->Evaluate(parameters.data(),
+ cost,
+ residuals != NULL ? &(*residuals)[0] : NULL,
+ gradient != NULL ? &(*gradient)[0] : NULL,
+ jacobian.get())) {
+ return false;
+ }
+
+ if (output_jacobian != NULL) {
+ jacobian->ToCRSMatrix(output_jacobian);
+ }
+
+ return true;
+}
+
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h
index adefdd26660..6aa30d7b739 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/evaluator.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h
@@ -33,10 +33,14 @@
#define CERES_INTERNAL_EVALUATOR_H_
#include <string>
+#include <vector>
#include "ceres/internal/port.h"
#include "ceres/types.h"
namespace ceres {
+
+class CRSMatrix;
+
namespace internal {
class Program;
@@ -65,6 +69,32 @@ class Evaluator {
Program* program,
string* error);
+
+ // This is used for computing the cost, residual and Jacobian for
+ // returning to the user. For actually solving the optimization
+ // problem, the optimization algorithm uses the ProgramEvaluator
+ // objects directly.
+ //
+ // The residual, gradients and jacobian pointers can be NULL, in
+ // which case they will not be evaluated. cost cannot be NULL.
+ //
+ // The parallelism of the evaluator is controlled by num_threads; it
+ // should be at least 1.
+ //
+ // Note: That this function does not take a parameter vector as
+ // input. The parameter blocks are evaluated on the values contained
+ // in the arrays pointed to by their user_state pointers.
+ //
+ // Also worth noting is that this function mutates program by
+ // calling Program::SetParameterOffsetsAndIndex() on it so that an
+ // evaluator object can be constructed.
+ static bool Evaluate(Program* program,
+ int num_threads,
+ double* cost,
+ vector<double>* residuals,
+ vector<double>* gradient,
+ CRSMatrix* jacobian);
+
// Build and return a sparse matrix for storing and working with the Jacobian
// of the objective function. The jacobian has dimensions
// NumEffectiveParameters() by NumParameters(), and is typically extremely
@@ -95,6 +125,7 @@ class Evaluator {
virtual bool Evaluate(const double* state,
double* cost,
double* residuals,
+ double* gradient,
SparseMatrix* jacobian) = 0;
// Make a change delta (of size NumEffectiveParameters()) to state (of size
diff --git a/extern/libmv/third_party/ceres/internal/ceres/file.cc b/extern/libmv/third_party/ceres/internal/ceres/file.cc
index 5fc9d220861..6fe7557246d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/file.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/file.cc
@@ -31,7 +31,8 @@
// Really simple file IO.
#include <cstdio>
-#include <glog/logging.h>
+#include "file.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -48,7 +49,7 @@ void WriteStringToFileOrDie(const string &data, const string &filename) {
}
void ReadFileToStringOrDie(const string &filename, string *data) {
- FILE* file_descriptor = file_descriptor = fopen(filename.c_str(), "r");
+ FILE* file_descriptor = fopen(filename.c_str(), "r");
if (!file_descriptor) {
LOG(FATAL) << "Couldn't read file: " << filename;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py b/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py
new file mode 100644
index 00000000000..af9873f94c0
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py
@@ -0,0 +1,186 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#
+# Copyright 2011 Google Inc. All Rights Reserved.
+# Author: sameeragarwal@google.com (Sameer Agarwal)
+#
+# Script for explicitly generating template specialization of the
+# SchurEliminator class. It is a rather large class
+# and the number of explicit instantiations is also large. Explicitly
+# generating these instantiations in separate .cc files breaks the
+# compilation into separate compilation unit rather than one large cc
+# file which takes 2+GB of RAM to compile.
+#
+# This script creates two sets of files.
+#
+# 1. schur_eliminator_x_x_x.cc
+# where, the x indicates the template parameters and
+#
+# 2. schur_eliminator.cc
+#
+# that contains a factory function for instantiating these classes
+# based on runtime parameters.
+#
+# The list of tuples, specializations indicates the set of
+# specializations that is generated.
+
+# Set of template specializations to generate
+SPECIALIZATIONS = [(2, 2, 2),
+ (2, 2, 3),
+ (2, 2, 4),
+ (2, 2, "Dynamic"),
+ (2, 3, 3),
+ (2, 3, 4),
+ (2, 3, 9),
+ (2, 3, "Dynamic"),
+ (2, 4, 3),
+ (2, 4, 4),
+ (2, 4, "Dynamic"),
+ (4, 4, 2),
+ (4, 4, 3),
+ (4, 4, 4),
+ (4, 4, "Dynamic"),
+ ("Dynamic", "Dynamic", "Dynamic")]
+
+SPECIALIZATION_FILE = """// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of SchurEliminator.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specializations.py.
+// Editing it manually is not recommended.
+
+#include "ceres/schur_eliminator_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class SchurEliminator<%s, %s, %s>;
+
+} // namespace internal
+} // namespace ceres
+
+"""
+
+FACTORY_FILE_HEADER = """// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_template_specializations.py.
+// Editing it manually is not recommended.
+
+#include "ceres/linear_solver.h"
+#include "ceres/schur_eliminator.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+SchurEliminatorBase*
+SchurEliminatorBase::Create(const LinearSolver::Options& options) {
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+"""
+
+FACTORY_CONDITIONAL = """ if ((options.row_block_size == %s) &&
+ (options.e_block_size == %s) &&
+ (options.f_block_size == %s)) {
+ return new SchurEliminator<%s, %s, %s>(options);
+ }
+"""
+
+FACTORY_FOOTER = """
+#endif
+ VLOG(1) << "Template specializations not found for <"
+ << options.row_block_size << ","
+ << options.e_block_size << ","
+ << options.f_block_size << ">";
+ return new SchurEliminator<Dynamic, Dynamic, Dynamic>(options);
+}
+
+} // namespace internal
+} // namespace ceres
+"""
+
+
+def SuffixForSize(size):
+ if size == "Dynamic":
+ return "d"
+ return str(size)
+
+
+def SpecializationFilename(prefix, row_block_size, e_block_size, f_block_size):
+ return "_".join([prefix] + map(SuffixForSize, (row_block_size,
+ e_block_size,
+ f_block_size)))
+
+
+def Specialize():
+ """
+ Generate specialization code and the conditionals to instantiate it.
+ """
+ f = open("schur_eliminator.cc", "w")
+ f.write(FACTORY_FILE_HEADER)
+
+ for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS:
+ output = SpecializationFilename("generated/schur_eliminator",
+ row_block_size,
+ e_block_size,
+ f_block_size) + ".cc"
+ fptr = open(output, "w")
+ fptr.write(SPECIALIZATION_FILE % (row_block_size,
+ e_block_size,
+ f_block_size))
+ fptr.close()
+
+ f.write(FACTORY_CONDITIONAL % (row_block_size,
+ e_block_size,
+ f_block_size,
+ row_block_size,
+ e_block_size,
+ f_block_size))
+ f.write(FACTORY_FOOTER)
+ f.close()
+
+
+if __name__ == "__main__":
+ Specialize()
diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
index abba40824ef..7fb3ed7b3a8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
@@ -36,18 +36,18 @@
#include <string>
#include <vector>
-#include <glog/logging.h>
+#include "ceres/cost_function.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/scoped_ptr.h"
#include "ceres/parameter_block.h"
+#include "ceres/problem.h"
#include "ceres/problem_impl.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
#include "ceres/runtime_numeric_diff_cost_function.h"
#include "ceres/stringprintf.h"
-#include "ceres/cost_function.h"
-#include "ceres/internal/eigen.h"
-#include "ceres/internal/scoped_ptr.h"
-#include "ceres/problem.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph.h b/extern/libmv/third_party/ceres/internal/ceres/graph.h
index fd7a224f0aa..2c0f6d28e54 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/graph.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/graph.h
@@ -129,7 +129,7 @@ class Graph {
HashMap<Vertex, HashSet<Vertex> > edges_;
HashMap<pair<Vertex, Vertex>, double> edge_weights_;
- DISALLOW_COPY_AND_ASSIGN(Graph);
+ CERES_DISALLOW_COPY_AND_ASSIGN(Graph);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc
index bd908846362..4af030a8535 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc
@@ -30,22 +30,20 @@
#include "ceres/implicit_schur_complement.h"
-#include <glog/logging.h>
#include "Eigen/Dense"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
ImplicitSchurComplement::ImplicitSchurComplement(int num_eliminate_blocks,
- bool constant_sparsity,
bool preconditioner)
: num_eliminate_blocks_(num_eliminate_blocks),
- constant_sparsity_(constant_sparsity),
preconditioner_(preconditioner),
A_(NULL),
D_(NULL),
@@ -62,7 +60,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrixBase& A,
const double* b) {
// Since initialization is reasonably heavy, perhaps we can save on
// constructing a new object everytime.
- if ((A_ == NULL) || !constant_sparsity_) {
+ if (A_ == NULL) {
A_.reset(new PartitionedMatrixView(A, num_eliminate_blocks_));
}
@@ -71,7 +69,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrixBase& A,
// Initialize temporary storage and compute the block diagonals of
// E'E and F'E.
- if ((!constant_sparsity_) || (block_diagonal_EtE_inverse_ == NULL)) {
+ if (block_diagonal_EtE_inverse_ == NULL) {
block_diagonal_EtE_inverse_.reset(A_->CreateBlockDiagonalEtE());
if (preconditioner_) {
block_diagonal_FtF_inverse_.reset(A_->CreateBlockDiagonalFtF());
@@ -92,17 +90,10 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrixBase& A,
// The block diagonals of the augmented linear system contain
// contributions from the diagonal D if it is non-null. Add that to
// the block diagonals and invert them.
- if (D_ != NULL) {
- AddDiagonalAndInvert(D_, block_diagonal_EtE_inverse_.get());
- if (preconditioner_) {
- AddDiagonalAndInvert(D_ + A_->num_cols_e(),
- block_diagonal_FtF_inverse_.get());
- }
- } else {
- AddDiagonalAndInvert(NULL, block_diagonal_EtE_inverse_.get());
- if (preconditioner_) {
- AddDiagonalAndInvert(NULL, block_diagonal_FtF_inverse_.get());
- }
+ AddDiagonalAndInvert(D_, block_diagonal_EtE_inverse_.get());
+ if (preconditioner_) {
+ AddDiagonalAndInvert((D_ == NULL) ? NULL : D_ + A_->num_cols_e(),
+ block_diagonal_FtF_inverse_.get());
}
// Compute the RHS of the Schur complement system.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h
index 37a319f9c57..b9ebaa4628e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h
@@ -91,20 +91,13 @@ class ImplicitSchurComplement : public LinearOperator {
// num_eliminate_blocks is the number of E blocks in the matrix
// A.
//
- // constant_sparsity indicates if across calls to Init, the sparsity
- // structure of the matrix A remains constant or not. This makes for
- // significant savings across multiple matrices A, e.g. when used in
- // conjunction with an optimization algorithm.
- //
// preconditioner indicates whether the inverse of the matrix F'F
// should be computed or not as a preconditioner for the Schur
// Complement.
//
// TODO(sameeragarwal): Get rid of the two bools below and replace
// them with enums.
- ImplicitSchurComplement(int num_eliminate_blocks,
- bool constant_sparsity,
- bool preconditioner);
+ ImplicitSchurComplement(int num_eliminate_blocks, bool preconditioner);
virtual ~ImplicitSchurComplement();
// Initialize the Schur complement for a linear least squares
@@ -151,7 +144,6 @@ class ImplicitSchurComplement : public LinearOperator {
void UpdateRhs();
int num_eliminate_blocks_;
- bool constant_sparsity_;
bool preconditioner_;
scoped_ptr<PartitionedMatrixView> A_;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
index 51303195317..679c41f2431 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
@@ -33,22 +33,18 @@
#include <algorithm>
#include <cstring>
#include <vector>
-
-#include <glog/logging.h>
#include "Eigen/Dense"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
#include "ceres/conjugate_gradients_solver.h"
#include "ceres/implicit_schur_complement.h"
-#include "ceres/linear_solver.h"
-#include "ceres/triplet_sparse_matrix.h"
-#include "ceres/visibility_based_preconditioner.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_solver.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
#include "ceres/visibility_based_preconditioner.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -69,10 +65,9 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
CHECK_NOTNULL(A->block_structure());
// Initialize a ImplicitSchurComplement object.
- if ((schur_complement_ == NULL) || (!options_.constant_sparsity)) {
+ if (schur_complement_ == NULL) {
schur_complement_.reset(
new ImplicitSchurComplement(options_.num_eliminate_blocks,
- options_.constant_sparsity,
options_.preconditioner_type == JACOBI));
}
schur_complement_->Init(*A, per_solve_options.D, b);
@@ -119,7 +114,7 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
new VisibilityBasedPreconditioner(*A->block_structure(), options_));
}
is_preconditioner_good =
- visibility_based_preconditioner_->Compute(*A, per_solve_options.D);
+ visibility_based_preconditioner_->Update(*A, per_solve_options.D);
cg_per_solve_options.preconditioner =
visibility_based_preconditioner_.get();
break;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc
deleted file mode 100644
index b40a5162adc..00000000000
--- a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc
+++ /dev/null
@@ -1,574 +0,0 @@
-// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
-// http://code.google.com/p/ceres-solver/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: sameeragarwal@google.com (Sameer Agarwal)
-//
-// Implementation of a simple LM algorithm which uses the step sizing
-// rule of "Methods for Nonlinear Least Squares" by K. Madsen,
-// H.B. Nielsen and O. Tingleff. Available to download from
-//
-// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
-//
-// The basic algorithm described in this note is an exact step
-// algorithm that depends on the Newton(LM) step being solved exactly
-// in each iteration. When a suitable iterative solver is available to
-// solve the Newton(LM) step, the algorithm will automatically switch
-// to an inexact step solution method. This trades some slowdown in
-// convergence for significant savings in solve time and memory
-// usage. Our implementation of the Truncated Newton algorithm follows
-// the discussion and recommendataions in "Stephen G. Nash, A Survey
-// of Truncated Newton Methods, Journal of Computational and Applied
-// Mathematics, 124(1-2), 45-59, 2000.
-
-#include "ceres/levenberg_marquardt.h"
-
-#include <algorithm>
-#include <cstdlib>
-#include <cmath>
-#include <cstring>
-#include <string>
-#include <vector>
-
-#include <glog/logging.h>
-#include "Eigen/Core"
-#include "ceres/evaluator.h"
-#include "ceres/file.h"
-#include "ceres/linear_least_squares_problems.h"
-#include "ceres/linear_solver.h"
-#include "ceres/matrix_proto.h"
-#include "ceres/sparse_matrix.h"
-#include "ceres/stringprintf.h"
-#include "ceres/internal/eigen.h"
-#include "ceres/internal/scoped_ptr.h"
-#include "ceres/types.h"
-
-namespace ceres {
-namespace internal {
-namespace {
-
-// Numbers for clamping the size of the LM diagonal. The size of these
-// numbers is heuristic. We will probably be adjusting them in the
-// future based on more numerical experience. With jacobi scaling
-// enabled, these numbers should be all but redundant.
-const double kMinLevenbergMarquardtDiagonal = 1e-6;
-const double kMaxLevenbergMarquardtDiagonal = 1e32;
-
-// Small constant for various floating point issues.
-const double kEpsilon = 1e-12;
-
-// Number of times the linear solver should be retried in case of
-// numerical failure. The retries are done by exponentially scaling up
-// mu at each retry. This leads to stronger and stronger
-// regularization making the linear least squares problem better
-// conditioned at each retry.
-const int kMaxLinearSolverRetries = 5;
-
-// D = 1/sqrt(diag(J^T * J))
-void EstimateScale(const SparseMatrix& jacobian, double* D) {
- CHECK_NOTNULL(D);
- jacobian.SquaredColumnNorm(D);
- for (int i = 0; i < jacobian.num_cols(); ++i) {
- D[i] = 1.0 / (kEpsilon + sqrt(D[i]));
- }
-}
-
-// D = diag(J^T * J)
-void LevenbergMarquardtDiagonal(const SparseMatrix& jacobian,
- double* D) {
- CHECK_NOTNULL(D);
- jacobian.SquaredColumnNorm(D);
- for (int i = 0; i < jacobian.num_cols(); ++i) {
- D[i] = min(max(D[i], kMinLevenbergMarquardtDiagonal),
- kMaxLevenbergMarquardtDiagonal);
- }
-}
-
-bool RunCallback(IterationCallback* callback,
- const IterationSummary& iteration_summary,
- Solver::Summary* summary) {
- const CallbackReturnType status = (*callback)(iteration_summary);
- switch (status) {
- case SOLVER_TERMINATE_SUCCESSFULLY:
- summary->termination_type = USER_SUCCESS;
- VLOG(1) << "Terminating on USER_SUCCESS.";
- return false;
- case SOLVER_ABORT:
- summary->termination_type = USER_ABORT;
- VLOG(1) << "Terminating on USER_ABORT.";
- return false;
- case SOLVER_CONTINUE:
- return true;
- default:
- LOG(FATAL) << "Unknown status returned by callback: "
- << status;
- return NULL;
- }
-}
-
-} // namespace
-
-LevenbergMarquardt::~LevenbergMarquardt() {}
-
-void LevenbergMarquardt::Minimize(const Minimizer::Options& options,
- Evaluator* evaluator,
- LinearSolver* linear_solver,
- const double* initial_parameters,
- double* final_parameters,
- Solver::Summary* summary) {
- time_t start_time = time(NULL);
- const int num_parameters = evaluator->NumParameters();
- const int num_effective_parameters = evaluator->NumEffectiveParameters();
- const int num_residuals = evaluator->NumResiduals();
-
- summary->termination_type = NO_CONVERGENCE;
- summary->num_successful_steps = 0;
- summary->num_unsuccessful_steps = 0;
-
- // Allocate the various vectors needed by the algorithm.
- memcpy(final_parameters, initial_parameters,
- num_parameters * sizeof(*initial_parameters));
-
- VectorRef x(final_parameters, num_parameters);
- Vector x_new(num_parameters);
-
- Vector lm_step(num_effective_parameters);
- Vector gradient(num_effective_parameters);
- Vector scaled_gradient(num_effective_parameters);
- // Jacobi scaling vector
- Vector scale(num_effective_parameters);
-
- Vector f_model(num_residuals);
- Vector f(num_residuals);
- Vector f_new(num_residuals);
- Vector D(num_parameters);
- Vector muD(num_parameters);
-
- // Ask the Evaluator to create the jacobian matrix. The sparsity
- // pattern of this matrix is going to remain constant, so we only do
- // this once and then re-use this matrix for all subsequent Jacobian
- // computations.
- scoped_ptr<SparseMatrix> jacobian(evaluator->CreateJacobian());
-
- double x_norm = x.norm();
-
- double cost = 0.0;
- D.setOnes();
- f.setZero();
-
- // Do initial cost and Jacobian evaluation.
- if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) {
- LOG(WARNING) << "Failed to compute residuals and Jacobian. "
- << "Terminating.";
- summary->termination_type = NUMERICAL_FAILURE;
- return;
- }
-
- if (options.jacobi_scaling) {
- EstimateScale(*jacobian, scale.data());
- jacobian->ScaleColumns(scale.data());
- } else {
- scale.setOnes();
- }
-
- // This is a poor way to do this computation. Even if fixed_cost is
- // zero, because we are subtracting two possibly large numbers, we
- // are depending on exact cancellation to give us a zero here. But
- // initial_cost and cost have been computed by two different
- // evaluators. One which runs on the whole problem (in
- // solver_impl.cc) in single threaded mode and another which runs
- // here on the reduced problem, so fixed_cost can (and does) contain
- // some numerical garbage with a relative magnitude of 1e-14.
- //
- // The right way to do this, would be to compute the fixed cost on
- // just the set of residual blocks which are held constant and were
- // removed from the original problem when the reduced problem was
- // constructed.
- summary->fixed_cost = summary->initial_cost - cost;
-
- double model_cost = f.squaredNorm() / 2.0;
- double total_cost = summary->fixed_cost + cost;
-
- scaled_gradient.setZero();
- jacobian->LeftMultiply(f.data(), scaled_gradient.data());
- gradient = scaled_gradient.array() / scale.array();
-
- double gradient_max_norm = gradient.lpNorm<Eigen::Infinity>();
- // We need the max here to guard againt the gradient being zero.
- const double gradient_max_norm_0 = max(gradient_max_norm, kEpsilon);
- double gradient_tolerance = options.gradient_tolerance * gradient_max_norm_0;
-
- double mu = options.tau;
- double nu = 2.0;
- int iteration = 0;
- double actual_cost_change = 0.0;
- double step_norm = 0.0;
- double relative_decrease = 0.0;
-
- // Insane steps are steps which are not sane, i.e. there is some
- // numerical kookiness going on with them. There are various reasons
- // for this kookiness, some easier to diagnose then others. From the
- // point of view of the non-linear solver, they are steps which
- // cannot be used. We return with NUMERICAL_FAILURE after
- // kMaxLinearSolverRetries consecutive insane steps.
- bool step_is_sane = false;
- int num_consecutive_insane_steps = 0;
-
- // Whether the step resulted in a sufficient decrease in the
- // objective function when compared to the decrease in the value of
- // the lineariztion.
- bool step_is_successful = false;
-
- // Parse the iterations for which to dump the linear problem.
- vector<int> iterations_to_dump = options.lsqp_iterations_to_dump;
- sort(iterations_to_dump.begin(), iterations_to_dump.end());
-
- IterationSummary iteration_summary;
- iteration_summary.iteration = iteration;
- iteration_summary.step_is_successful = false;
- iteration_summary.cost = total_cost;
- iteration_summary.cost_change = actual_cost_change;
- iteration_summary.gradient_max_norm = gradient_max_norm;
- iteration_summary.step_norm = step_norm;
- iteration_summary.relative_decrease = relative_decrease;
- iteration_summary.mu = mu;
- iteration_summary.eta = options.eta;
- iteration_summary.linear_solver_iterations = 0;
- iteration_summary.linear_solver_time_sec = 0.0;
- iteration_summary.iteration_time_sec = (time(NULL) - start_time);
- if (options.logging_type >= PER_MINIMIZER_ITERATION) {
- summary->iterations.push_back(iteration_summary);
- }
-
- // Check if the starting point is an optimum.
- VLOG(2) << "Gradient max norm: " << gradient_max_norm
- << " tolerance: " << gradient_tolerance
- << " ratio: " << gradient_max_norm / gradient_max_norm_0
- << " tolerance: " << options.gradient_tolerance;
- if (gradient_max_norm <= gradient_tolerance) {
- summary->termination_type = GRADIENT_TOLERANCE;
- VLOG(1) << "Terminating on GRADIENT_TOLERANCE. "
- << "Relative gradient max norm: "
- << gradient_max_norm / gradient_max_norm_0
- << " <= " << options.gradient_tolerance;
- return;
- }
-
- // Call the various callbacks.
- for (int i = 0; i < options.callbacks.size(); ++i) {
- if (!RunCallback(options.callbacks[i], iteration_summary, summary)) {
- return;
- }
- }
-
- // We only need the LM diagonal if we are actually going to do at
- // least one iteration of the optimization. So we wait to do it
- // until now.
- LevenbergMarquardtDiagonal(*jacobian, D.data());
-
- while ((iteration < options.max_num_iterations) &&
- (time(NULL) - start_time) <= options.max_solver_time_sec) {
- time_t iteration_start_time = time(NULL);
- step_is_sane = false;
- step_is_successful = false;
-
- IterationSummary iteration_summary;
- // The while loop here is just to provide an easily breakable
- // control structure. We are guaranteed to always exit this loop
- // at the end of one iteration or before.
- while (1) {
- muD = (mu * D).array().sqrt();
- LinearSolver::PerSolveOptions solve_options;
- solve_options.D = muD.data();
- solve_options.q_tolerance = options.eta;
- // Disable r_tolerance checking. Since we only care about
- // termination via the q_tolerance. As Nash and Sofer show,
- // r_tolerance based termination is essentially useless in
- // Truncated Newton methods.
- solve_options.r_tolerance = -1.0;
-
- const time_t linear_solver_start_time = time(NULL);
- LinearSolver::Summary linear_solver_summary =
- linear_solver->Solve(jacobian.get(),
- f.data(),
- solve_options,
- lm_step.data());
- iteration_summary.linear_solver_time_sec =
- (time(NULL) - linear_solver_start_time);
- iteration_summary.linear_solver_iterations =
- linear_solver_summary.num_iterations;
-
- if (binary_search(iterations_to_dump.begin(),
- iterations_to_dump.end(),
- iteration)) {
- CHECK(DumpLinearLeastSquaresProblem(options.lsqp_dump_directory,
- iteration,
- options.lsqp_dump_format_type,
- jacobian.get(),
- muD.data(),
- f.data(),
- lm_step.data(),
- options.num_eliminate_blocks))
- << "Tried writing linear least squares problem: "
- << options.lsqp_dump_directory
- << " but failed.";
- }
-
- // We ignore the case where the linear solver did not converge,
- // since the partial solution computed by it still maybe of use,
- // and there is no reason to ignore it, especially since we
- // spent so much time computing it.
- if ((linear_solver_summary.termination_type != TOLERANCE) &&
- (linear_solver_summary.termination_type != MAX_ITERATIONS)) {
- VLOG(1) << "Linear solver failure: retrying with a higher mu";
- break;
- }
-
- step_norm = (lm_step.array() * scale.array()).matrix().norm();
-
- // Check step length based convergence. If the step length is
- // too small, then we are done.
- const double step_size_tolerance = options.parameter_tolerance *
- (x_norm + options.parameter_tolerance);
-
- VLOG(2) << "Step size: " << step_norm
- << " tolerance: " << step_size_tolerance
- << " ratio: " << step_norm / step_size_tolerance
- << " tolerance: " << options.parameter_tolerance;
- if (step_norm <= options.parameter_tolerance *
- (x_norm + options.parameter_tolerance)) {
- summary->termination_type = PARAMETER_TOLERANCE;
- VLOG(1) << "Terminating on PARAMETER_TOLERANCE."
- << "Relative step size: " << step_norm / step_size_tolerance
- << " <= " << options.parameter_tolerance;
- return;
- }
-
- Vector delta = -(lm_step.array() * scale.array()).matrix();
- if (!evaluator->Plus(x.data(), delta.data(), x_new.data())) {
- LOG(WARNING) << "Failed to compute Plus(x, delta, x_plus_delta). "
- << "Terminating.";
- summary->termination_type = NUMERICAL_FAILURE;
- return;
- }
-
- double cost_new = 0.0;
- if (!evaluator->Evaluate(x_new.data(), &cost_new, NULL, NULL)) {
- LOG(WARNING) << "Failed to compute the value of the objective "
- << "function. Terminating.";
- summary->termination_type = NUMERICAL_FAILURE;
- return;
- }
-
- f_model.setZero();
- jacobian->RightMultiply(lm_step.data(), f_model.data());
- const double model_cost_new =
- (f.segment(0, num_residuals) - f_model).squaredNorm() / 2;
-
- actual_cost_change = cost - cost_new;
- double model_cost_change = model_cost - model_cost_new;
-
- VLOG(2) << "[Model cost] current: " << model_cost
- << " new : " << model_cost_new
- << " change: " << model_cost_change;
-
- VLOG(2) << "[Nonlinear cost] current: " << cost
- << " new : " << cost_new
- << " change: " << actual_cost_change
- << " relative change: " << fabs(actual_cost_change) / cost
- << " tolerance: " << options.function_tolerance;
-
- // In exact arithmetic model_cost_change should never be
- // negative. But due to numerical precision issues, we may end up
- // with a small negative number. model_cost_change which are
- // negative and large in absolute value are indicative of a
- // numerical failure in the solver.
- if (model_cost_change < -kEpsilon) {
- VLOG(1) << "Model cost change is negative.\n"
- << "Current : " << model_cost
- << " new : " << model_cost_new
- << " change: " << model_cost_change << "\n";
- break;
- }
-
- // If we have reached this far, then we are willing to trust the
- // numerical quality of the step.
- step_is_sane = true;
- num_consecutive_insane_steps = 0;
-
- // Check function value based convergence.
- if (fabs(actual_cost_change) < options.function_tolerance * cost) {
- VLOG(1) << "Termination on FUNCTION_TOLERANCE."
- << " Relative cost change: " << fabs(actual_cost_change) / cost
- << " tolerance: " << options.function_tolerance;
- summary->termination_type = FUNCTION_TOLERANCE;
- return;
- }
-
- // Clamp model_cost_change at kEpsilon from below.
- if (model_cost_change < kEpsilon) {
- VLOG(1) << "Clamping model cost change " << model_cost_change
- << " to " << kEpsilon;
- model_cost_change = kEpsilon;
- }
-
- relative_decrease = actual_cost_change / model_cost_change;
- VLOG(2) << "actual_cost_change / model_cost_change = "
- << relative_decrease;
-
- if (relative_decrease < options.min_relative_decrease) {
- VLOG(2) << "Unsuccessful step.";
- break;
- }
-
- VLOG(2) << "Successful step.";
-
- ++summary->num_successful_steps;
- x = x_new;
- x_norm = x.norm();
-
- if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) {
- LOG(WARNING) << "Failed to compute residuals and jacobian. "
- << "Terminating.";
- summary->termination_type = NUMERICAL_FAILURE;
- return;
- }
-
- if (options.jacobi_scaling) {
- jacobian->ScaleColumns(scale.data());
- }
-
- model_cost = f.squaredNorm() / 2.0;
- LevenbergMarquardtDiagonal(*jacobian, D.data());
- scaled_gradient.setZero();
- jacobian->LeftMultiply(f.data(), scaled_gradient.data());
- gradient = scaled_gradient.array() / scale.array();
- gradient_max_norm = gradient.lpNorm<Eigen::Infinity>();
-
- // Check gradient based convergence.
- VLOG(2) << "Gradient max norm: " << gradient_max_norm
- << " tolerance: " << gradient_tolerance
- << " ratio: " << gradient_max_norm / gradient_max_norm_0
- << " tolerance: " << options.gradient_tolerance;
- if (gradient_max_norm <= gradient_tolerance) {
- summary->termination_type = GRADIENT_TOLERANCE;
- VLOG(1) << "Terminating on GRADIENT_TOLERANCE. "
- << "Relative gradient max norm: "
- << gradient_max_norm / gradient_max_norm_0
- << " <= " << options.gradient_tolerance
- << " (tolerance).";
- return;
- }
-
- mu = mu * max(1.0 / 3.0, 1 - pow(2 * relative_decrease - 1, 3));
- nu = 2.0;
- step_is_successful = true;
- break;
- }
-
- if (!step_is_sane) {
- ++num_consecutive_insane_steps;
- }
-
- if (num_consecutive_insane_steps == kMaxLinearSolverRetries) {
- summary->termination_type = NUMERICAL_FAILURE;
- VLOG(1) << "Too many consecutive retries; ending with numerical fail.";
-
- if (!options.crash_and_dump_lsqp_on_failure) {
- return;
- }
-
- // Dump debugging information to disk.
- CHECK(options.lsqp_dump_format_type == TEXTFILE ||
- options.lsqp_dump_format_type == PROTOBUF)
- << "Dumping the linear least squares problem on crash "
- << "requires Solver::Options::lsqp_dump_format_type to be "
- << "PROTOBUF or TEXTFILE.";
-
- if (DumpLinearLeastSquaresProblem(options.lsqp_dump_directory,
- iteration,
- options.lsqp_dump_format_type,
- jacobian.get(),
- muD.data(),
- f.data(),
- lm_step.data(),
- options.num_eliminate_blocks)) {
- LOG(FATAL) << "Linear least squares problem saved to: "
- << options.lsqp_dump_directory
- << ". Please provide this to the Ceres developers for "
- << " debugging along with the v=2 log.";
- } else {
- LOG(FATAL) << "Tried writing linear least squares problem: "
- << options.lsqp_dump_directory
- << " but failed.";
- }
- }
-
- if (!step_is_successful) {
- // Either the step did not lead to a decrease in cost or there
- // was numerical failure. In either case we will scale mu up and
- // retry. If it was a numerical failure, we hope that the
- // stronger regularization will make the linear system better
- // conditioned. If it was numerically sane, but there was no
- // decrease in cost, then increasing mu reduces the size of the
- // trust region and we look for a decrease closer to the
- // linearization point.
- ++summary->num_unsuccessful_steps;
- mu = mu * nu;
- nu = 2 * nu;
- }
-
- ++iteration;
-
- total_cost = summary->fixed_cost + cost;
-
- iteration_summary.iteration = iteration;
- iteration_summary.step_is_successful = step_is_successful;
- iteration_summary.cost = total_cost;
- iteration_summary.cost_change = actual_cost_change;
- iteration_summary.gradient_max_norm = gradient_max_norm;
- iteration_summary.step_norm = step_norm;
- iteration_summary.relative_decrease = relative_decrease;
- iteration_summary.mu = mu;
- iteration_summary.eta = options.eta;
- iteration_summary.iteration_time_sec = (time(NULL) - iteration_start_time);
-
- if (options.logging_type >= PER_MINIMIZER_ITERATION) {
- summary->iterations.push_back(iteration_summary);
- }
-
- // Call the various callbacks.
- for (int i = 0; i < options.callbacks.size(); ++i) {
- if (!RunCallback(options.callbacks[i], iteration_summary, summary)) {
- return;
- }
- }
- }
-}
-
-} // namespace internal
-} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc
new file mode 100644
index 00000000000..9e6a59e3813
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc
@@ -0,0 +1,144 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/levenberg_marquardt_strategy.h"
+
+#include <cmath>
+#include "Eigen/Core"
+#include "ceres/array_utils.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/linear_solver.h"
+#include "ceres/sparse_matrix.h"
+#include "ceres/trust_region_strategy.h"
+#include "ceres/types.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+LevenbergMarquardtStrategy::LevenbergMarquardtStrategy(
+ const TrustRegionStrategy::Options& options)
+ : linear_solver_(options.linear_solver),
+ radius_(options.initial_radius),
+ max_radius_(options.max_radius),
+ min_diagonal_(options.lm_min_diagonal),
+ max_diagonal_(options.lm_max_diagonal),
+ decrease_factor_(2.0),
+ reuse_diagonal_(false) {
+ CHECK_NOTNULL(linear_solver_);
+ CHECK_GT(min_diagonal_, 0.0);
+ CHECK_LE(min_diagonal_, max_diagonal_);
+ CHECK_GT(max_radius_, 0.0);
+}
+
+LevenbergMarquardtStrategy::~LevenbergMarquardtStrategy() {
+}
+
+TrustRegionStrategy::Summary LevenbergMarquardtStrategy::ComputeStep(
+ const TrustRegionStrategy::PerSolveOptions& per_solve_options,
+ SparseMatrix* jacobian,
+ const double* residuals,
+ double* step) {
+ CHECK_NOTNULL(jacobian);
+ CHECK_NOTNULL(residuals);
+ CHECK_NOTNULL(step);
+
+ const int num_parameters = jacobian->num_cols();
+ if (!reuse_diagonal_) {
+ if (diagonal_.rows() != num_parameters) {
+ diagonal_.resize(num_parameters, 1);
+ }
+
+ jacobian->SquaredColumnNorm(diagonal_.data());
+ for (int i = 0; i < num_parameters; ++i) {
+ diagonal_[i] = min(max(diagonal_[i], min_diagonal_), max_diagonal_);
+ }
+ }
+
+ lm_diagonal_ = (diagonal_ / radius_).array().sqrt();
+
+ LinearSolver::PerSolveOptions solve_options;
+ solve_options.D = lm_diagonal_.data();
+ solve_options.q_tolerance = per_solve_options.eta;
+ // Disable r_tolerance checking. Since we only care about
+ // termination via the q_tolerance. As Nash and Sofer show,
+ // r_tolerance based termination is essentially useless in
+ // Truncated Newton methods.
+ solve_options.r_tolerance = -1.0;
+
+ // Invalidate the output array lm_step, so that we can detect if
+ // the linear solver generated numerical garbage. This is known
+ // to happen for the DENSE_QR and then DENSE_SCHUR solver when
+ // the Jacobin is severly rank deficient and mu is too small.
+ InvalidateArray(num_parameters, step);
+
+ // Instead of solving Jx = -r, solve Jy = r.
+ // Then x can be found as x = -y, but the inputs jacobian and residuals
+ // do not need to be modified.
+ LinearSolver::Summary linear_solver_summary =
+ linear_solver_->Solve(jacobian, residuals, solve_options, step);
+ if (linear_solver_summary.termination_type == FAILURE ||
+ !IsArrayValid(num_parameters, step)) {
+ LOG(WARNING) << "Linear solver failure. Failed to compute a finite step.";
+ linear_solver_summary.termination_type = FAILURE;
+ } else {
+ VectorRef(step, num_parameters) *= -1.0;
+ }
+
+ reuse_diagonal_ = true;
+
+ TrustRegionStrategy::Summary summary;
+ summary.residual_norm = linear_solver_summary.residual_norm;
+ summary.num_iterations = linear_solver_summary.num_iterations;
+ summary.termination_type = linear_solver_summary.termination_type;
+ return summary;
+}
+
+void LevenbergMarquardtStrategy::StepAccepted(double step_quality) {
+ CHECK_GT(step_quality, 0.0);
+ radius_ = radius_ / std::max(1.0 / 3.0,
+ 1.0 - pow(2.0 * step_quality - 1.0, 3));
+ radius_ = std::min(max_radius_, radius_);
+ decrease_factor_ = 2.0;
+ reuse_diagonal_ = false;
+}
+
+void LevenbergMarquardtStrategy::StepRejected(double step_quality) {
+ radius_ = radius_ / decrease_factor_;
+ decrease_factor_ *= 2.0;
+ reuse_diagonal_ = true;
+}
+
+double LevenbergMarquardtStrategy::Radius() const {
+ return radius_;
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h
new file mode 100644
index 00000000000..90c21789797
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h
@@ -0,0 +1,86 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_
+#define CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_
+
+#include "ceres/internal/eigen.h"
+#include "ceres/trust_region_strategy.h"
+
+namespace ceres {
+namespace internal {
+
+// Levenberg-Marquardt step computation and trust region sizing
+// strategy based on on "Methods for Nonlinear Least Squares" by
+// K. Madsen, H.B. Nielsen and O. Tingleff. Available to download from
+//
+// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
+class LevenbergMarquardtStrategy : public TrustRegionStrategy {
+public:
+ LevenbergMarquardtStrategy(const TrustRegionStrategy::Options& options);
+ virtual ~LevenbergMarquardtStrategy();
+
+ // TrustRegionStrategy interface
+ virtual TrustRegionStrategy::Summary ComputeStep(
+ const TrustRegionStrategy::PerSolveOptions& per_solve_options,
+ SparseMatrix* jacobian,
+ const double* residuals,
+ double* step);
+ virtual void StepAccepted(double step_quality);
+ virtual void StepRejected(double step_quality);
+ virtual void StepIsInvalid() {
+ // Treat the current step as a rejected step with no increase in
+ // solution quality. Since rejected steps lead to decrease in the
+ // size of the trust region, the next time ComputeStep is called,
+ // this will lead to a better conditioned system.
+ StepRejected(0.0);
+ }
+
+ virtual double Radius() const;
+
+ private:
+ LinearSolver* linear_solver_;
+ double radius_;
+ double max_radius_;
+ const double min_diagonal_;
+ const double max_diagonal_;
+ double decrease_factor_;
+ bool reuse_diagonal_;
+ Vector diagonal_; // diagonal_ = diag(J'J)
+ // Scaled copy of diagonal_. Stored here as optimization to prevent
+ // allocations in every iteration and reuse when a step fails and
+ // ComputeStep is called again.
+ Vector lm_diagonal_; // lm_diagonal_ = diagonal_ / radius_;
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc
index cca9f442fe7..a91e254a663 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc
@@ -33,17 +33,17 @@
#include <cstdio>
#include <string>
#include <vector>
-#include <glog/logging.h>
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
#include "ceres/casts.h"
#include "ceres/compressed_row_sparse_matrix.h"
#include "ceres/file.h"
+#include "ceres/internal/scoped_ptr.h"
#include "ceres/matrix_proto.h"
-#include "ceres/triplet_sparse_matrix.h"
#include "ceres/stringprintf.h"
-#include "ceres/internal/scoped_ptr.h"
+#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -64,7 +64,7 @@ LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id) {
return NULL;
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile(
const string& filename) {
LinearLeastSquaresProblemProto problem_proto;
@@ -130,7 +130,7 @@ LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile(
<< "Ceres to be built with Protocol Buffers support.";
return NULL;
}
-#endif // CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#endif // CERES_NO_PROTOCOL_BUFFERS
/*
A = [1 2]
@@ -573,13 +573,13 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() {
return problem;
}
-bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
- int iteration,
- const SparseMatrix* A,
- const double* D,
- const double* b,
- const double* x,
- int num_eliminate_blocks) {
+static bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
+ int iteration,
+ const SparseMatrix* A,
+ const double* D,
+ const double* b,
+ const double* x,
+ int num_eliminate_blocks) {
CHECK_NOTNULL(A);
Matrix AA;
A->ToDenseMatrix(&AA);
@@ -600,14 +600,14 @@ bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
return true;
};
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
-bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
- int iteration,
- const SparseMatrix* A,
- const double* D,
- const double* b,
- const double* x,
- int num_eliminate_blocks) {
+#ifndef CERES_NO_PROTOCOL_BUFFERS
+static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
+ int iteration,
+ const SparseMatrix* A,
+ const double* D,
+ const double* b,
+ const double* x,
+ int num_eliminate_blocks) {
CHECK_NOTNULL(A);
LinearLeastSquaresProblemProto lsqp;
A->ToProto(lsqp.mutable_a());
@@ -641,13 +641,13 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
return true;
}
#else
-bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
- int iteration,
- const SparseMatrix* A,
- const double* D,
- const double* b,
- const double* x,
- int num_eliminate_blocks) {
+static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
+ int iteration,
+ const SparseMatrix* A,
+ const double* D,
+ const double* b,
+ const double* x,
+ int num_eliminate_blocks) {
LOG(ERROR) << "Dumping least squares problems is only "
<< "supported when Ceres is compiled with "
<< "protocol buffer support.";
@@ -655,9 +655,9 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
}
#endif
-void WriteArrayToFileOrDie(const string& filename,
- const double* x,
- const int size) {
+static void WriteArrayToFileOrDie(const string& filename,
+ const double* x,
+ const int size) {
CHECK_NOTNULL(x);
VLOG(2) << "Writing array to: " << filename;
FILE* fptr = fopen(filename.c_str(), "w");
@@ -668,43 +668,68 @@ void WriteArrayToFileOrDie(const string& filename,
fclose(fptr);
}
-bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
- int iteration,
- const SparseMatrix* A,
- const double* D,
- const double* b,
- const double* x,
- int num_eliminate_blocks) {
+static bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
+ int iteration,
+ const SparseMatrix* A,
+ const double* D,
+ const double* b,
+ const double* x,
+ int num_eliminate_blocks) {
CHECK_NOTNULL(A);
string format_string = JoinPath(directory,
"lm_iteration_%03d");
string filename_prefix =
StringPrintf(format_string.c_str(), iteration);
+ LOG(INFO) << "writing to: " << filename_prefix << "*";
+
+ string matlab_script;
+ StringAppendF(&matlab_script,
+ "function lsqp = lm_iteration_%03d()\n", iteration);
+ StringAppendF(&matlab_script,
+ "lsqp.num_rows = %d;\n", A->num_rows());
+ StringAppendF(&matlab_script,
+ "lsqp.num_cols = %d;\n", A->num_cols());
+
{
string filename = filename_prefix + "_A.txt";
- LOG(INFO) << "writing to: " << filename;
FILE* fptr = fopen(filename.c_str(), "w");
CHECK_NOTNULL(fptr);
A->ToTextFile(fptr);
fclose(fptr);
+ StringAppendF(&matlab_script,
+ "tmp = load('%s', '-ascii');\n", filename.c_str());
+ StringAppendF(
+ &matlab_script,
+ "lsqp.A = sparse(tmp(:, 1) + 1, tmp(:, 2) + 1, tmp(:, 3), %d, %d);\n",
+ A->num_rows(),
+ A->num_cols());
}
+
if (D != NULL) {
string filename = filename_prefix + "_D.txt";
WriteArrayToFileOrDie(filename, D, A->num_cols());
+ StringAppendF(&matlab_script,
+ "lsqp.D = load('%s', '-ascii');\n", filename.c_str());
}
if (b != NULL) {
string filename = filename_prefix + "_b.txt";
WriteArrayToFileOrDie(filename, b, A->num_rows());
+ StringAppendF(&matlab_script,
+ "lsqp.b = load('%s', '-ascii');\n", filename.c_str());
}
if (x != NULL) {
string filename = filename_prefix + "_x.txt";
WriteArrayToFileOrDie(filename, x, A->num_cols());
+ StringAppendF(&matlab_script,
+ "lsqp.x = load('%s', '-ascii');\n", filename.c_str());
}
+ string matlab_filename = filename_prefix + ".m";
+ WriteStringToFileOrDie(matlab_script, matlab_filename);
return true;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc
index b2e3941eea1..08c3ba110d0 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc
@@ -30,13 +30,14 @@
#include "ceres/linear_solver.h"
-#include <glog/logging.h>
#include "ceres/cgnr_solver.h"
+#include "ceres/dense_normal_cholesky_solver.h"
#include "ceres/dense_qr_solver.h"
#include "ceres/iterative_schur_complement_solver.h"
#include "ceres/schur_complement_solver.h"
#include "ceres/sparse_normal_cholesky_solver.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -50,22 +51,24 @@ LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) {
return new CgnrSolver(options);
case SPARSE_NORMAL_CHOLESKY:
-#ifndef CERES_NO_SUITESPARSE
- return new SparseNormalCholeskySolver(options);
-#else
+#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
LOG(WARNING) << "SPARSE_NORMAL_CHOLESKY is not available. Please "
- << "build Ceres with SuiteSparse. Returning NULL.";
+ << "build Ceres with SuiteSparse or CXSparse. "
+ << "Returning NULL.";
return NULL;
-#endif // CERES_NO_SUITESPARSE
+#else
+ return new SparseNormalCholeskySolver(options);
+#endif
case SPARSE_SCHUR:
-#ifndef CERES_NO_SUITESPARSE
- return new SparseSchurComplementSolver(options);
-#else
+#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
LOG(WARNING) << "SPARSE_SCHUR is not available. Please "
- << "build Ceres with SuiteSparse. Returning NULL.";
+ << "build Ceres with SuiteSparse or CXSparse. "
+ << "Returning NULL.";
return NULL;
-#endif // CERES_NO_SUITESPARSE
+#else
+ return new SparseSchurComplementSolver(options);
+#endif
case DENSE_SCHUR:
return new DenseSchurComplementSolver(options);
@@ -76,10 +79,13 @@ LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) {
case DENSE_QR:
return new DenseQRSolver(options);
+ case DENSE_NORMAL_CHOLESKY:
+ return new DenseNormalCholeskySolver(options);
+
default:
LOG(FATAL) << "Unknown linear solver type :"
<< options.type;
- return NULL; // MSVC doesn't understand that LOG(FATAL) never returns.
+ return NULL; // MSVC doesn't understand that LOG(FATAL) never returns.
}
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
index 5860ecc8a77..31f88740b9f 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
@@ -55,10 +55,11 @@ class LinearOperator;
// Ax = b
//
// It is expected that a single instance of a LinearSolver object
-// maybe used multiple times for solving different linear
-// systems. This allows them to cache and reuse information across
-// solves if for example the sparsity of the linear system remains
-// constant.
+// maybe used multiple times for solving multiple linear systems with
+// the same sparsity structure. This allows them to cache and reuse
+// information across solves. This means that calling Solve on the
+// same LinearSolver instance with two different linear systems will
+// result in undefined behaviour.
//
// Subclasses of LinearSolver use two structs to configure themselves.
// The Options struct configures the LinearSolver object for its
@@ -70,10 +71,11 @@ class LinearSolver {
Options()
: type(SPARSE_NORMAL_CHOLESKY),
preconditioner_type(JACOBI),
+ sparse_linear_algebra_library(SUITE_SPARSE),
+ use_block_amd(true),
min_num_iterations(1),
max_num_iterations(1),
num_threads(1),
- constant_sparsity(false),
num_eliminate_blocks(0),
residual_reset_period(10),
row_block_size(Dynamic),
@@ -85,6 +87,11 @@ class LinearSolver {
PreconditionerType preconditioner_type;
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library;
+
+ // See solver.h for explanation of this option.
+ bool use_block_amd;
+
// Number of internal iterations that the solver uses. This
// parameter only makes sense for iterative solvers like CG.
int min_num_iterations;
@@ -93,10 +100,6 @@ class LinearSolver {
// If possible, how many threads can the solver use.
int num_threads;
- // If possible cache and reuse the symbolic factorization across
- // multiple calls.
- bool constant_sparsity;
-
// Eliminate 0 to num_eliminate_blocks - 1 from the Normal
// equations to form a schur complement. Only used by the Schur
// complement based solver. The most common use for this parameter
@@ -121,8 +124,8 @@ class LinearSolver {
// It is expected that these parameters are set programmatically
// rather than manually.
//
- // Please see explicit_schur_complement_solver_impl.h for more
- // details.
+ // Please see schur_complement_solver.h and schur_eliminator.h for
+ // more details.
int row_block_size;
int e_block_size;
int f_block_size;
@@ -244,6 +247,7 @@ class LinearSolver {
const PerSolveOptions& per_solve_options,
double* x) = 0;
+ // Factory
static LinearSolver* Create(const Options& options);
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc
index eeae74e3f95..26e7f4908a4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc
@@ -28,10 +28,11 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-#include <glog/logging.h>
-#include "ceres/internal/eigen.h"
#include "ceres/local_parameterization.h"
+
+#include "ceres/internal/eigen.h"
#include "ceres/rotation.h"
+#include "glog/logging.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc
index 00b2b184729..b948f289f21 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc
@@ -77,6 +77,70 @@ void CauchyLoss::Evaluate(double s, double rho[3]) const {
rho[2] = - c_ * (inv * inv);
}
+void ArctanLoss::Evaluate(double s, double rho[3]) const {
+ const double sum = 1 + s * s * b_;
+ const double inv = 1 / sum;
+ // 'sum' and 'inv' are always positive.
+ rho[0] = a_ * atan2(s, a_);
+ rho[1] = inv;
+ rho[2] = -2 * s * b_ * (inv * inv);
+}
+
+TolerantLoss::TolerantLoss(double a, double b)
+ : a_(a),
+ b_(b),
+ c_(b * log(1.0 + exp(-a / b))) {
+ CHECK_GE(a, 0.0);
+ CHECK_GT(b, 0.0);
+}
+
+void TolerantLoss::Evaluate(double s, double rho[3]) const {
+ const double x = (s - a_) / b_;
+ // The basic equation is rho[0] = b ln(1 + e^x). However, if e^x is too
+ // large, it will overflow. Since numerically 1 + e^x == e^x when the
+ // x is greater than about ln(2^53) for doubles, beyond this threshold
+ // we substitute x for ln(1 + e^x) as a numerically equivalent approximation.
+ static const double kLog2Pow53 = 36.7; // ln(MathLimits<double>::kEpsilon).
+ if (x > kLog2Pow53) {
+ rho[0] = s - a_ - c_;
+ rho[1] = 1.0;
+ rho[2] = 0.0;
+ } else {
+ const double e_x = exp(x);
+ rho[0] = b_ * log(1.0 + e_x) - c_;
+ rho[1] = e_x / (1.0 + e_x);
+ rho[2] = 0.5 / (b_ * (1.0 + cosh(x)));
+ }
+}
+
+ComposedLoss::ComposedLoss(const LossFunction* f, Ownership ownership_f,
+ const LossFunction* g, Ownership ownership_g)
+ : f_(CHECK_NOTNULL(f)),
+ g_(CHECK_NOTNULL(g)),
+ ownership_f_(ownership_f),
+ ownership_g_(ownership_g) {
+}
+
+ComposedLoss::~ComposedLoss() {
+ if (ownership_f_ == DO_NOT_TAKE_OWNERSHIP) {
+ f_.release();
+ }
+ if (ownership_g_ == DO_NOT_TAKE_OWNERSHIP) {
+ g_.release();
+ }
+}
+
+void ComposedLoss::Evaluate(double s, double rho[3]) const {
+ double rho_f[3], rho_g[3];
+ g_->Evaluate(s, rho_g);
+ f_->Evaluate(rho_g[0], rho_f);
+ rho[0] = rho_f[0];
+ // f'(g(s)) * g'(s).
+ rho[1] = rho_f[1] * rho_g[1];
+ // f''(g(s)) * g'(s) * g'(s) + f'(g(s)) * g''(s).
+ rho[2] = rho_f[2] * rho_g[1] * rho_g[1] + rho_f[1] * rho_g[2];
+}
+
void ScaledLoss::Evaluate(double s, double rho[3]) const {
if (rho_.get() == NULL) {
rho[0] = a_ * s;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h b/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h
index b8a3a1a6de6..94b3076e3d7 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h
@@ -33,7 +33,7 @@
#ifndef CERES_INTERNAL_MATRIX_PROTO_H_
#define CERES_INTERNAL_MATRIX_PROTO_H_
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
#include "ceres/matrix.pb.h"
#endif
diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
index 77cb00cb6b4..cfc98a3ebd0 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
@@ -40,6 +40,8 @@ namespace internal {
class Evaluator;
class LinearSolver;
+class SparseMatrix;
+class TrustRegionStrategy;
// Interface for non-linear least squares solvers.
class Minimizer {
@@ -48,53 +50,93 @@ class Minimizer {
// see solver.h for detailed information about the meaning and
// default values of each of these parameters.
struct Options {
+ Options() {
+ Init(Solver::Options());
+ }
+
explicit Options(const Solver::Options& options) {
+ Init(options);
+ }
+
+ void Init(const Solver::Options& options) {
max_num_iterations = options.max_num_iterations;
- max_solver_time_sec = options.max_solver_time_sec;
+ max_solver_time_in_seconds = options.max_solver_time_in_seconds;
+ max_step_solver_retries = 5;
gradient_tolerance = options.gradient_tolerance;
parameter_tolerance = options.parameter_tolerance;
function_tolerance = options.function_tolerance;
min_relative_decrease = options.min_relative_decrease;
eta = options.eta;
- tau = options.tau;
jacobi_scaling = options.jacobi_scaling;
- crash_and_dump_lsqp_on_failure = options.crash_and_dump_lsqp_on_failure;
+ use_nonmonotonic_steps = options.use_nonmonotonic_steps;
+ max_consecutive_nonmonotonic_steps =
+ options.max_consecutive_nonmonotonic_steps;
lsqp_dump_directory = options.lsqp_dump_directory;
lsqp_iterations_to_dump = options.lsqp_iterations_to_dump;
lsqp_dump_format_type = options.lsqp_dump_format_type;
num_eliminate_blocks = options.num_eliminate_blocks;
- logging_type = options.logging_type;
+ max_num_consecutive_invalid_steps =
+ options.max_num_consecutive_invalid_steps;
+ min_trust_region_radius = options.min_trust_region_radius;
+ evaluator = NULL;
+ trust_region_strategy = NULL;
+ jacobian = NULL;
+ callbacks = options.callbacks;
}
int max_num_iterations;
- int max_solver_time_sec;
+ double max_solver_time_in_seconds;
+
+ // Number of times the linear solver should be retried in case of
+ // numerical failure. The retries are done by exponentially scaling up
+ // mu at each retry. This leads to stronger and stronger
+ // regularization making the linear least squares problem better
+ // conditioned at each retry.
+ int max_step_solver_retries;
double gradient_tolerance;
double parameter_tolerance;
double function_tolerance;
double min_relative_decrease;
double eta;
- double tau;
bool jacobi_scaling;
- bool crash_and_dump_lsqp_on_failure;
+ bool use_nonmonotonic_steps;
+ int max_consecutive_nonmonotonic_steps;
vector<int> lsqp_iterations_to_dump;
DumpFormatType lsqp_dump_format_type;
string lsqp_dump_directory;
int num_eliminate_blocks;
- LoggingType logging_type;
+ int max_num_consecutive_invalid_steps;
+ int min_trust_region_radius;
// List of callbacks that are executed by the Minimizer at the end
// of each iteration.
//
- // Client owns these pointers.
+ // The Options struct does not own these pointers.
vector<IterationCallback*> callbacks;
+
+ // Object responsible for evaluating the cost, residuals and
+ // Jacobian matrix. The Options struct does not own this pointer.
+ Evaluator* evaluator;
+
+ // Object responsible for actually computing the trust region
+ // step, and sizing the trust region radius. The Options struct
+ // does not own this pointer.
+ TrustRegionStrategy* trust_region_strategy;
+
+ // Object holding the Jacobian matrix. It is assumed that the
+ // sparsity structure of the matrix has already been initialized
+ // and will remain constant for the life time of the
+ // optimization. The Options struct does not own this pointer.
+ SparseMatrix* jacobian;
};
virtual ~Minimizer() {}
+
+ // Note: The minimizer is expected to update the state of the
+ // parameters array every iteration. This is required for the
+ // StateUpdatingCallback to work.
virtual void Minimize(const Options& options,
- Evaluator* evaluator,
- LinearSolver* linear_solver,
- const double* initial_parameters,
- double* final_parameters,
+ double* parameters,
Solver::Summary* summary) = 0;
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/mutex.h b/extern/libmv/third_party/ceres/internal/ceres/mutex.h
index 6514b107041..5090a71b78d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/mutex.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/mutex.h
@@ -95,11 +95,11 @@
#ifndef CERES_INTERNAL_MUTEX_H_
#define CERES_INTERNAL_MUTEX_H_
-#if defined(NO_THREADS)
+#if defined(CERES_NO_THREADS)
typedef int MutexType; // to keep a lock-count
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
-# define WIN32_LEAN_AND_MEAN // We only need minimal includes
-# ifdef GMUTEX_TRYLOCK
+# define CERES_WIN32_LEAN_AND_MEAN // We only need minimal includes
+# ifdef CERES_GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT
// lines, and change TryLock() to assert(0) or something.
@@ -108,9 +108,9 @@
# endif
# endif
// To avoid macro definition of ERROR.
-# define NOGDI
+# define CERES_NOGDI
// To avoid macro definition of min/max.
-# define NOMINMAX
+# define CERES_NOMINMAX
# include <windows.h>
typedef CRITICAL_SECTION MutexType;
#elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK)
@@ -151,7 +151,7 @@ class Mutex {
inline void Lock(); // Block if needed until free then acquire exclusively
inline void Unlock(); // Release a lock acquired via Lock()
-#ifdef GMUTEX_TRYLOCK
+#ifdef CERES_GMUTEX_TRYLOCK
inline bool TryLock(); // If free, Lock() and return true, else return false
#endif
// Note that on systems that don't support read-write locks, these may
@@ -183,7 +183,7 @@ class Mutex {
};
// Now the implementation of Mutex for various systems
-#if defined(NO_THREADS)
+#if defined(CERES_NO_THREADS)
// When we don't have threads, we can be either reading or writing,
// but not both. We can have lots of readers at once (in no-threads
@@ -199,7 +199,7 @@ Mutex::Mutex() : mutex_(0) { }
Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); }
-#ifdef GMUTEX_TRYLOCK
+#ifdef CERES_GMUTEX_TRYLOCK
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
#endif
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
@@ -220,91 +220,101 @@ void Mutex::ReaderUnlock() { Unlock(); }
#elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK)
-#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
- if (is_safe_ && fncall(&mutex_) != 0) abort(); \
+#define CERES_SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
+ if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
-Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); }
-void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
-void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
-#ifdef GMUTEX_TRYLOCK
+Mutex::~Mutex() { CERES_SAFE_PTHREAD(pthread_rwlock_destroy); }
+void Mutex::Lock() { CERES_SAFE_PTHREAD(pthread_rwlock_wrlock); }
+void Mutex::Unlock() { CERES_SAFE_PTHREAD(pthread_rwlock_unlock); }
+#ifdef CERES_GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_rwlock_trywrlock(&mutex_) == 0 :
true; }
#endif
-void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
-void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
-#undef SAFE_PTHREAD
+void Mutex::ReaderLock() { CERES_SAFE_PTHREAD(pthread_rwlock_rdlock); }
+void Mutex::ReaderUnlock() { CERES_SAFE_PTHREAD(pthread_rwlock_unlock); }
+#undef CERES_SAFE_PTHREAD
#elif defined(CERES_HAVE_PTHREAD)
-#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
- if (is_safe_ && fncall(&mutex_) != 0) abort(); \
+#define CERES_SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
+ if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
-Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); }
-void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
-void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
-#ifdef GMUTEX_TRYLOCK
+Mutex::~Mutex() { CERES_SAFE_PTHREAD(pthread_mutex_destroy); }
+void Mutex::Lock() { CERES_SAFE_PTHREAD(pthread_mutex_lock); }
+void Mutex::Unlock() { CERES_SAFE_PTHREAD(pthread_mutex_unlock); }
+#ifdef CERES_GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_mutex_trylock(&mutex_) == 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); }
void Mutex::ReaderUnlock() { Unlock(); }
-#undef SAFE_PTHREAD
+#undef CERES_SAFE_PTHREAD
#endif
// --------------------------------------------------------------------------
// Some helper classes
-// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
-class MutexLock {
+// Note: The weird "Ceres" prefix for the class is a workaround for having two
+// similar mutex.h files included in the same translation unit. This is a
+// problem because macros do not respect C++ namespaces, and as a result, this
+// does not work well (e.g. inside Chrome). The offending macros are
+// "MutexLock(x) COMPILE_ASSERT(false)". To work around this, "Ceres" is
+// prefixed to the class names; this permits defining the classes.
+
+// CeresMutexLock(mu) acquires mu when constructed and releases it when destroyed.
+class CeresMutexLock {
public:
- explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
- ~MutexLock() { mu_->Unlock(); }
+ explicit CeresMutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
+ ~CeresMutexLock() { mu_->Unlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
- MutexLock(const MutexLock&);
- void operator=(const MutexLock&);
+ CeresMutexLock(const CeresMutexLock&);
+ void operator=(const CeresMutexLock&);
};
-// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
-class ReaderMutexLock {
+// CeresReaderMutexLock and CeresWriterMutexLock do the same, for rwlocks
+class CeresReaderMutexLock {
public:
- explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
- ~ReaderMutexLock() { mu_->ReaderUnlock(); }
+ explicit CeresReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
+ ~CeresReaderMutexLock() { mu_->ReaderUnlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
- ReaderMutexLock(const ReaderMutexLock&);
- void operator=(const ReaderMutexLock&);
+ CeresReaderMutexLock(const CeresReaderMutexLock&);
+ void operator=(const CeresReaderMutexLock&);
};
-class WriterMutexLock {
+class CeresWriterMutexLock {
public:
- explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
- ~WriterMutexLock() { mu_->WriterUnlock(); }
+ explicit CeresWriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
+ ~CeresWriterMutexLock() { mu_->WriterUnlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
- WriterMutexLock(const WriterMutexLock&);
- void operator=(const WriterMutexLock&);
+ CeresWriterMutexLock(const CeresWriterMutexLock&);
+ void operator=(const CeresWriterMutexLock&);
};
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
-#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
-#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
-#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
+#define CeresMutexLock(x) \
+ COMPILE_ASSERT(0, ceres_mutex_lock_decl_missing_var_name)
+#define CeresReaderMutexLock(x) \
+ COMPILE_ASSERT(0, ceres_rmutex_lock_decl_missing_var_name)
+#define CeresWriterMutexLock(x) \
+ COMPILE_ASSERT(0, ceres_wmutex_lock_decl_missing_var_name)
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc b/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc
index f30bbc8b46b..392d728fb32 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc
@@ -32,11 +32,10 @@
#include <cstddef>
#include <vector>
-
-#include <glog/logging.h>
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h
index 4bac1a85828..f20805ca873 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h
@@ -32,13 +32,15 @@
#define CERES_INTERNAL_PARAMETER_BLOCK_H_
#include <cstdlib>
+#include <string>
+#include "ceres/array_utils.h"
#include "ceres/integral_types.h"
-#include <glog/logging.h>
#include "ceres/internal/eigen.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/local_parameterization.h"
-#include "ceres/residual_block_utils.h"
+#include "ceres/stringprintf.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -172,6 +174,19 @@ class ParameterBlock {
return local_parameterization_->Plus(x, delta, x_plus_delta);
}
+ string ToString() const {
+ return StringPrintf("{ user_state=%p, state=%p, size=%d, "
+ "constant=%d, index=%d, state_offset=%d, "
+ "delta_offset=%d }",
+ user_state_,
+ state_,
+ size_,
+ is_constant_,
+ index_,
+ state_offset_,
+ delta_offset_);
+ }
+
private:
void Init(double* user_state,
int size,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc
index fcf8fd53aed..0722fc82c02 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc
@@ -35,10 +35,10 @@
#include <algorithm>
#include <cstring>
#include <vector>
-#include <glog/logging.h>
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
#include "ceres/internal/eigen.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc
new file mode 100644
index 00000000000..20c01566a89
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc
@@ -0,0 +1,184 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: moll.markus@arcor.de (Markus Moll)
+
+#include "ceres/polynomial_solver.h"
+
+#include <cmath>
+#include <cstddef>
+#include "Eigen/Dense"
+#include "ceres/internal/port.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+namespace {
+
+// Balancing function as described by B. N. Parlett and C. Reinsch,
+// "Balancing a Matrix for Calculation of Eigenvalues and Eigenvectors".
+// In: Numerische Mathematik, Volume 13, Number 4 (1969), 293-304,
+// Springer Berlin / Heidelberg. DOI: 10.1007/BF02165404
+void BalanceCompanionMatrix(Matrix* companion_matrix_ptr) {
+ CHECK_NOTNULL(companion_matrix_ptr);
+ Matrix& companion_matrix = *companion_matrix_ptr;
+ Matrix companion_matrix_offdiagonal = companion_matrix;
+ companion_matrix_offdiagonal.diagonal().setZero();
+
+ const int degree = companion_matrix.rows();
+
+ // gamma <= 1 controls how much a change in the scaling has to
+ // lower the 1-norm of the companion matrix to be accepted.
+ //
+ // gamma = 1 seems to lead to cycles (numerical issues?), so
+ // we set it slightly lower.
+ const double gamma = 0.9;
+
+ // Greedily scale row/column pairs until there is no change.
+ bool scaling_has_changed;
+ do {
+ scaling_has_changed = false;
+
+ for (int i = 0; i < degree; ++i) {
+ const double row_norm = companion_matrix_offdiagonal.row(i).lpNorm<1>();
+ const double col_norm = companion_matrix_offdiagonal.col(i).lpNorm<1>();
+
+ // Decompose row_norm/col_norm into mantissa * 2^exponent,
+ // where 0.5 <= mantissa < 1. Discard mantissa (return value
+ // of frexp), as only the exponent is needed.
+ int exponent = 0;
+ std::frexp(row_norm / col_norm, &exponent);
+ exponent /= 2;
+
+ if (exponent != 0) {
+ const double scaled_col_norm = std::ldexp(col_norm, exponent);
+ const double scaled_row_norm = std::ldexp(row_norm, -exponent);
+ if (scaled_col_norm + scaled_row_norm < gamma * (col_norm + row_norm)) {
+ // Accept the new scaling. (Multiplication by powers of 2 should not
+ // introduce rounding errors (ignoring non-normalized numbers and
+ // over- or underflow))
+ scaling_has_changed = true;
+ companion_matrix_offdiagonal.row(i) *= std::ldexp(1.0, -exponent);
+ companion_matrix_offdiagonal.col(i) *= std::ldexp(1.0, exponent);
+ }
+ }
+ }
+ } while (scaling_has_changed);
+
+ companion_matrix_offdiagonal.diagonal() = companion_matrix.diagonal();
+ companion_matrix = companion_matrix_offdiagonal;
+ VLOG(3) << "Balanced companion matrix is\n" << companion_matrix;
+}
+
+void BuildCompanionMatrix(const Vector& polynomial,
+ Matrix* companion_matrix_ptr) {
+ CHECK_NOTNULL(companion_matrix_ptr);
+ Matrix& companion_matrix = *companion_matrix_ptr;
+
+ const int degree = polynomial.size() - 1;
+
+ companion_matrix.resize(degree, degree);
+ companion_matrix.setZero();
+ companion_matrix.diagonal(-1).setOnes();
+ companion_matrix.col(degree - 1) = -polynomial.reverse().head(degree);
+}
+
+// Remove leading terms with zero coefficients.
+Vector RemoveLeadingZeros(const Vector& polynomial_in) {
+ int i = 0;
+ while (i < (polynomial_in.size() - 1) && polynomial_in(i) == 0.0) {
+ ++i;
+ }
+ return polynomial_in.tail(polynomial_in.size() - i);
+}
+} // namespace
+
+bool FindPolynomialRoots(const Vector& polynomial_in,
+ Vector* real,
+ Vector* imaginary) {
+ if (polynomial_in.size() == 0) {
+ LOG(ERROR) << "Invalid polynomial of size 0 passed to FindPolynomialRoots";
+ return false;
+ }
+
+ Vector polynomial = RemoveLeadingZeros(polynomial_in);
+ const int degree = polynomial.size() - 1;
+
+ // Is the polynomial constant?
+ if (degree == 0) {
+ LOG(WARNING) << "Trying to extract roots from a constant "
+ << "polynomial in FindPolynomialRoots";
+ return true;
+ }
+
+ // Divide by leading term
+ const double leading_term = polynomial(0);
+ polynomial /= leading_term;
+
+ // Separately handle linear polynomials.
+ if (degree == 1) {
+ if (real != NULL) {
+ real->resize(1);
+ (*real)(0) = -polynomial(1);
+ }
+ if (imaginary != NULL) {
+ imaginary->resize(1);
+ imaginary->setZero();
+ }
+ }
+
+ // The degree is now known to be at least 2.
+ // Build and balance the companion matrix to the polynomial.
+ Matrix companion_matrix(degree, degree);
+ BuildCompanionMatrix(polynomial, &companion_matrix);
+ BalanceCompanionMatrix(&companion_matrix);
+
+ // Find its (complex) eigenvalues.
+ Eigen::EigenSolver<Matrix> solver(companion_matrix,
+ Eigen::EigenvaluesOnly);
+ if (solver.info() != Eigen::Success) {
+ LOG(ERROR) << "Failed to extract eigenvalues from companion matrix.";
+ return false;
+ }
+
+ // Output roots
+ if (real != NULL) {
+ *real = solver.eigenvalues().real();
+ } else {
+ LOG(WARNING) << "NULL pointer passed as real argument to "
+ << "FindPolynomialRoots. Real parts of the roots will not "
+ << "be returned.";
+ }
+ if (imaginary != NULL) {
+ *imaginary = solver.eigenvalues().imag();
+ }
+ return true;
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h b/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h
new file mode 100644
index 00000000000..1cf07ddb549
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: moll.markus@arcor.de (Markus Moll)
+
+#ifndef CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
+#define CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
+
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+// Use the companion matrix eigenvalues to determine the roots of the polynomial
+//
+// sum_{i=0}^N polynomial(i) x^{N-i}.
+//
+// This function returns true on success, false otherwise.
+// Failure indicates that the polynomial is invalid (of size 0) or
+// that the eigenvalues of the companion matrix could not be computed.
+// On failure, a more detailed message will be written to LOG(ERROR).
+// If real is not NULL, the real parts of the roots will be returned in it.
+// Likewise, if imaginary is not NULL, imaginary parts will be returned in it.
+bool FindPolynomialRoots(const Vector& polynomial,
+ Vector* real,
+ Vector* imaginary);
+
+// Evaluate the polynomial at x using the Horner scheme.
+inline double EvaluatePolynomial(const Vector& polynomial, double x) {
+ double v = 0.0;
+ for (int i = 0; i < polynomial.size(); ++i) {
+ v = v * x + polynomial(i);
+ }
+ return v;
+}
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
index 68242477d6f..c186f527be8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
@@ -37,16 +37,15 @@
#include <string>
#include <utility>
#include <vector>
-
-#include <glog/logging.h>
+#include "ceres/cost_function.h"
+#include "ceres/loss_function.h"
+#include "ceres/map_util.h"
#include "ceres/parameter_block.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
#include "ceres/stl_util.h"
-#include "ceres/map_util.h"
#include "ceres/stringprintf.h"
-#include "ceres/cost_function.h"
-#include "ceres/loss_function.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
index 523860e652a..2ca055448c3 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
@@ -118,7 +118,7 @@ class ProblemImpl {
map<double*, ParameterBlock*> parameter_block_map_;
internal::scoped_ptr<internal::Program> program_;
- DISALLOW_COPY_AND_ASSIGN(ProblemImpl);
+ CERES_DISALLOW_COPY_AND_ASSIGN(ProblemImpl);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.cc b/extern/libmv/third_party/ceres/internal/ceres/program.cc
index 444b1020253..82d76d39233 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/program.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/program.cc
@@ -32,14 +32,18 @@
#include <map>
#include <vector>
+#include "ceres/casts.h"
+#include "ceres/compressed_row_sparse_matrix.h"
+#include "ceres/cost_function.h"
+#include "ceres/evaluator.h"
+#include "ceres/internal/port.h"
+#include "ceres/local_parameterization.h"
+#include "ceres/loss_function.h"
+#include "ceres/map_util.h"
#include "ceres/parameter_block.h"
+#include "ceres/problem.h"
#include "ceres/residual_block.h"
#include "ceres/stl_util.h"
-#include "ceres/map_util.h"
-#include "ceres/problem.h"
-#include "ceres/cost_function.h"
-#include "ceres/loss_function.h"
-#include "ceres/local_parameterization.h"
namespace ceres {
namespace internal {
@@ -69,7 +73,8 @@ vector<ResidualBlock*>* Program::mutable_residual_blocks() {
bool Program::StateVectorToParameterBlocks(const double *state) {
for (int i = 0; i < parameter_blocks_.size(); ++i) {
- if (!parameter_blocks_[i]->SetState(state)) {
+ if (!parameter_blocks_[i]->IsConstant() &&
+ !parameter_blocks_[i]->SetState(state)) {
return false;
}
state += parameter_blocks_[i]->Size();
@@ -86,9 +91,18 @@ void Program::ParameterBlocksToStateVector(double *state) const {
void Program::CopyParameterBlockStateToUserState() {
for (int i = 0; i < parameter_blocks_.size(); ++i) {
- parameter_blocks_[i]->GetState(
- parameter_blocks_[i]->mutable_user_state());
+ parameter_blocks_[i]->GetState(parameter_blocks_[i]->mutable_user_state());
+ }
+}
+
+bool Program::SetParameterBlockStatePtrsToUserStatePtrs() {
+ for (int i = 0; i < parameter_blocks_.size(); ++i) {
+ if (!parameter_blocks_[i]->IsConstant() &&
+ !parameter_blocks_[i]->SetState(parameter_blocks_[i]->user_state())) {
+ return false;
+ }
}
+ return true;
}
bool Program::Plus(const double* state,
@@ -193,40 +207,25 @@ int Program::MaxParametersPerResidualBlock() const {
return max_parameters;
}
-bool Program::Evaluate(double* cost, double* residuals) {
- *cost = 0.0;
-
- // Scratch space is only needed if residuals is NULL.
- scoped_array<double> scratch;
- if (residuals == NULL) {
- scratch.reset(new double[MaxScratchDoublesNeededForEvaluate()]);
- } else {
- // TODO(keir): Is this needed? Check by removing the equivalent statement in
- // dense_evaluator.cc and running the tests.
- VectorRef(residuals, NumResiduals()).setZero();
- }
-
+int Program::MaxResidualsPerResidualBlock() const {
+ int max_residuals = 0;
for (int i = 0; i < residual_blocks_.size(); ++i) {
- ResidualBlock* residual_block = residual_blocks_[i];
-
- // Evaluate the cost function for this residual.
- double residual_cost;
- if (!residual_block->Evaluate(&residual_cost,
- residuals,
- NULL, // No jacobian.
- scratch.get())) {
- return false;
- }
-
- // Accumulate residual cost into the total cost.
- *cost += residual_cost;
+ max_residuals = max(max_residuals,
+ residual_blocks_[i]->NumResiduals());
+ }
+ return max_residuals;
+}
- // Update the residuals cursor.
- if (residuals != NULL) {
- residuals += residual_block->NumResiduals();
- }
+string Program::ToString() const {
+ string ret = "Program dump\n";
+ ret += StringPrintf("Number of parameter blocks: %d\n", NumParameterBlocks());
+ ret += StringPrintf("Number of parameters: %d\n", NumParameters());
+ ret += "Parameters:\n";
+ for (int i = 0; i < parameter_blocks_.size(); ++i) {
+ ret += StringPrintf("%d: %s\n",
+ i, parameter_blocks_[i]->ToString().c_str());
}
- return true;
+ return ret;
}
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.h b/extern/libmv/third_party/ceres/internal/ceres/program.h
index 113d352d562..5002b7e752e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/program.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/program.h
@@ -31,6 +31,7 @@
#ifndef CERES_INTERNAL_PROGRAM_H_
#define CERES_INTERNAL_PROGRAM_H_
+#include <string>
#include <vector>
#include "ceres/internal/port.h"
@@ -71,9 +72,14 @@ class Program {
bool StateVectorToParameterBlocks(const double *state);
void ParameterBlocksToStateVector(double *state) const;
- // Copy internal state out to the user's parameters.
+ // Copy internal state to the user's parameters.
void CopyParameterBlockStateToUserState();
+ // Set the parameter block pointers to the user pointers. Since this
+ // runs parameter block set state internally, which may call local
+ // parameterizations, this can fail. False is returned on failure.
+ bool SetParameterBlockStatePtrsToUserStatePtrs();
+
// Update a state vector for the program given a delta.
bool Plus(const double* state,
const double* delta,
@@ -103,16 +109,11 @@ class Program {
int MaxScratchDoublesNeededForEvaluate() const;
int MaxDerivativesPerResidualBlock() const;
int MaxParametersPerResidualBlock() const;
+ int MaxResidualsPerResidualBlock() const;
- // Evaluate the cost and maybe the residuals for the program. If residuals is
- // NULL, then residuals are not calculated. If the jacobian is needed, instead
- // use the various evaluators (e.g. dense_evaluator.h).
- //
- // This is a trivial implementation of evaluate not intended for use in the
- // core solving loop. The other evaluators, which support constructing the
- // jacobian in addition to the cost and residuals, are considerably
- // complicated by the need to construct the jacobian.
- bool Evaluate(double* cost, double* residuals);
+ // A human-readable dump of the parameter blocks for debugging.
+ // TODO(keir): If necessary, also dump the residual blocks.
+ string ToString() const;
private:
// The Program does not own the ParameterBlock or ResidualBlock objects.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h
index 7ec74b1b269..6c48e7d7643 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h
@@ -120,13 +120,18 @@ class ProgramEvaluator : public Evaluator {
bool Evaluate(const double* state,
double* cost,
double* residuals,
+ double* gradient,
SparseMatrix* jacobian) {
// The parameters are stateful, so set the state before evaluating.
if (!program_->StateVectorToParameterBlocks(state)) {
return false;
}
- if (jacobian) {
+ if (residuals != NULL) {
+ VectorRef(residuals, program_->NumResiduals()).setZero();
+ }
+
+ if (jacobian != NULL) {
jacobian->SetZero();
}
@@ -158,13 +163,16 @@ class ProgramEvaluator : public Evaluator {
// Prepare block residuals if requested.
const ResidualBlock* residual_block = program_->residual_blocks()[i];
- double* block_residuals = (residuals != NULL)
- ? (residuals + residual_layout_[i])
- : NULL;
+ double* block_residuals = NULL;
+ if (residuals != NULL) {
+ block_residuals = residuals + residual_layout_[i];
+ } else if (gradient != NULL) {
+ block_residuals = scratch->residual_block_residuals.get();
+ }
// Prepare block jacobians if requested.
double** block_jacobians = NULL;
- if (jacobian != NULL) {
+ if (jacobian != NULL || gradient != NULL) {
preparer->Prepare(residual_block,
i,
jacobian,
@@ -174,10 +182,11 @@ class ProgramEvaluator : public Evaluator {
// Evaluate the cost, residuals, and jacobians.
double block_cost;
- if (!residual_block->Evaluate(&block_cost,
- block_residuals,
- block_jacobians,
- scratch->scratch.get())) {
+ if (!residual_block->Evaluate(
+ &block_cost,
+ block_residuals,
+ block_jacobians,
+ scratch->residual_block_evaluate_scratch.get())) {
abort = true;
// This ensures that the OpenMP threads have a consistent view of 'abort'. Do
// the flush inside the failure case so that there is usually only one
@@ -188,19 +197,49 @@ class ProgramEvaluator : public Evaluator {
scratch->cost += block_cost;
+ // Store the jacobians, if they were requested.
if (jacobian != NULL) {
jacobian_writer_.Write(i,
residual_layout_[i],
block_jacobians,
jacobian);
}
+
+ // Compute and store the gradient, if it was requested.
+ if (gradient != NULL) {
+ int num_residuals = residual_block->NumResiduals();
+ int num_parameter_blocks = residual_block->NumParameterBlocks();
+ for (int j = 0; j < num_parameter_blocks; ++j) {
+ const ParameterBlock* parameter_block =
+ residual_block->parameter_blocks()[j];
+ if (parameter_block->IsConstant()) {
+ continue;
+ }
+ MatrixRef block_jacobian(block_jacobians[j],
+ num_residuals,
+ parameter_block->LocalSize());
+ VectorRef block_gradient(scratch->gradient.get() +
+ parameter_block->delta_offset(),
+ parameter_block->LocalSize());
+ VectorRef block_residual(block_residuals, num_residuals);
+ block_gradient += block_residual.transpose() * block_jacobian;
+ }
+ }
}
if (!abort) {
- // Sum the cost from each thread.
+ // Sum the cost and gradient (if requested) from each thread.
(*cost) = 0.0;
+ int num_parameters = program_->NumEffectiveParameters();
+ if (gradient != NULL) {
+ VectorRef(gradient, num_parameters).setZero();
+ }
for (int i = 0; i < options_.num_threads; ++i) {
(*cost) += evaluate_scratch_[i].cost;
+ if (gradient != NULL) {
+ VectorRef(gradient, num_parameters) +=
+ VectorRef(evaluate_scratch_[i].gradient.get(), num_parameters);
+ }
}
}
return !abort;
@@ -224,16 +263,28 @@ class ProgramEvaluator : public Evaluator {
}
private:
+ // Per-thread scratch space needed to evaluate and store each residual block.
struct EvaluateScratch {
void Init(int max_parameters_per_residual_block,
- int max_scratch_doubles_needed_for_evaluate) {
+ int max_scratch_doubles_needed_for_evaluate,
+ int max_residuals_per_residual_block,
+ int num_parameters) {
+ residual_block_evaluate_scratch.reset(
+ new double[max_scratch_doubles_needed_for_evaluate]);
+ gradient.reset(new double[num_parameters]);
+ VectorRef(gradient.get(), num_parameters).setZero();
+ residual_block_residuals.reset(
+ new double[max_residuals_per_residual_block]);
jacobian_block_ptrs.reset(
new double*[max_parameters_per_residual_block]);
- scratch.reset(new double[max_scratch_doubles_needed_for_evaluate]);
}
double cost;
- scoped_array<double> scratch;
+ scoped_array<double> residual_block_evaluate_scratch;
+ // The gradient in the local parameterization.
+ scoped_array<double> gradient;
+ // Enough space to store the residual for the largest residual block.
+ scoped_array<double> residual_block_residuals;
scoped_array<double*> jacobian_block_ptrs;
};
@@ -256,11 +307,16 @@ class ProgramEvaluator : public Evaluator {
program.MaxParametersPerResidualBlock();
int max_scratch_doubles_needed_for_evaluate =
program.MaxScratchDoublesNeededForEvaluate();
+ int max_residuals_per_residual_block =
+ program.MaxResidualsPerResidualBlock();
+ int num_parameters = program.NumEffectiveParameters();
EvaluateScratch* evaluate_scratch = new EvaluateScratch[num_threads];
for (int i = 0; i < num_threads; i++) {
evaluate_scratch[i].Init(max_parameters_per_residual_block,
- max_scratch_doubles_needed_for_evaluate);
+ max_scratch_doubles_needed_for_evaluate,
+ max_residuals_per_residual_block,
+ num_parameters);
}
return evaluate_scratch;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/random.h b/extern/libmv/third_party/ceres/internal/ceres/random.h
index 769e0b4dd27..352c0032b5a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/random.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/random.h
@@ -27,21 +27,44 @@
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
+// sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_INTERNAL_RANDOM_H_
#define CERES_INTERNAL_RANDOM_H_
+#include <cmath>
+#include <cstdlib>
+#include "ceres/internal/port.h"
+
namespace ceres {
-inline double RandDouble() {
- double r = rand();
- return r / RAND_MAX;
+inline void SetRandomState(int state) {
+ srand(state);
}
inline int Uniform(int n) {
return rand() % n;
}
+inline double RandDouble() {
+ double r = static_cast<double>(rand());
+ return r / RAND_MAX;
+}
+
+// Box-Muller algorithm for normal random number generation.
+// http://en.wikipedia.org/wiki/Box-Muller_transform
+inline double RandNormal() {
+ double x1, x2, w;
+ do {
+ x1 = 2.0 * RandDouble() - 1.0;
+ x2 = 2.0 * RandDouble() - 1.0;
+ w = x1 * x1 + x2 * x2;
+ } while ( w >= 1.0 || w == 0.0 );
+
+ w = sqrt((-2.0 * log(w)) / w);
+ return x1 * w;
+}
+
} // namespace ceres
#endif // CERES_INTERNAL_RANDOM_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc
index 03867891dba..bdb88b1dd97 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc
@@ -102,8 +102,11 @@ bool ResidualBlock::Evaluate(double* cost,
InvalidateEvaluation(*this, cost, residuals, eval_jacobians);
- if (!cost_function_->Evaluate(parameters.get(), residuals, eval_jacobians) ||
- !IsEvaluationValid(*this,
+ if (!cost_function_->Evaluate(parameters.get(), residuals, eval_jacobians)) {
+ return false;
+ }
+
+ if (!IsEvaluationValid(*this,
parameters.get(),
cost,
residuals,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc
index 28e03130844..9442bb2a1c1 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc
@@ -33,46 +33,17 @@
#include <cmath>
#include <cstddef>
#include <limits>
-#include <glog/logging.h>
-#include "ceres/residual_block.h"
-#include "ceres/parameter_block.h"
-#include "ceres/stringprintf.h"
+#include "ceres/array_utils.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/port.h"
-
-#ifdef _MSC_VER
-# define isfinite _finite
-#endif
+#include "ceres/parameter_block.h"
+#include "ceres/residual_block.h"
+#include "ceres/stringprintf.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
-// It is a near impossibility that user code generates this exact
-// value in normal operation, thus we will use it to fill arrays
-// before passing them to user code. If on return an element of the
-// array still contains this value, we will assume that the user code
-// did not write to that memory location.
-static const double kImpossibleValue = 1e302;
-
-bool IsArrayValid(const int size, const double* x) {
- if (x != NULL) {
- for (int i = 0; i < size; ++i) {
- if (!isfinite(x[i]) || (x[i] == kImpossibleValue)) {
- return false;
- }
- }
- }
- return true;
-}
-
-void InvalidateArray(const int size, double* x) {
- if (x != NULL) {
- for (int i = 0; i < size; ++i) {
- x[i] = kImpossibleValue;
- }
- }
-}
-
void InvalidateEvaluation(const ResidualBlock& block,
double* cost,
double* residuals,
@@ -92,7 +63,7 @@ void InvalidateEvaluation(const ResidualBlock& block,
// Utility routine to print an array of doubles to a string. If the
// array pointer is NULL, it is treated as an array of zeros.
-void AppendArrayToString(const int size, const double* x, string* result) {
+static void AppendArrayToString(const int size, const double* x, string* result) {
for (int i = 0; i < size; ++i) {
if (x == NULL) {
StringAppendF(result, "Not Computed ");
diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h
index 228867cc60c..7051c2112fd 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h
@@ -51,15 +51,6 @@ namespace internal {
class ResidualBlock;
-// Fill the array x with an impossible value that the user code is
-// never expected to compute.
-void InvalidateArray(int size, double* x);
-
-// Check if all the entries of the array x are valid, i.e. all the
-// values in the array should be finite and none of them should be
-// equal to the "impossible" value used by InvalidateArray.
-bool IsArrayValid(int size, const double* x);
-
// Invalidate cost, resdual and jacobian arrays (if not NULL).
void InvalidateEvaluation(const ResidualBlock& block,
double* cost,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc
index ac6d8aa279a..7af275c1dd8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc
@@ -35,11 +35,10 @@
#include <algorithm>
#include <numeric>
#include <vector>
-
-#include <glog/logging.h>
#include "Eigen/Dense"
#include "ceres/cost_function.h"
#include "ceres/internal/scoped_ptr.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc
index 2bc8cdd6bec..2cbe78d133a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc
@@ -32,7 +32,13 @@
#include <ctime>
#include <set>
#include <vector>
+
+#ifndef CERES_NO_CXSPARSE
+#include "cs.h"
+#endif // CERES_NO_CXSPARSE
+
#include "Eigen/Dense"
+#include "glog/logging.h"
#include "ceres/block_random_access_dense_matrix.h"
#include "ceres/block_random_access_matrix.h"
#include "ceres/block_random_access_sparse_matrix.h"
@@ -48,6 +54,7 @@
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
+
namespace ceres {
namespace internal {
@@ -57,7 +64,7 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl(
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
const time_t start_time = time(NULL);
- if (!options_.constant_sparsity || (eliminator_.get() == NULL)) {
+ if (eliminator_.get() == NULL) {
InitStorage(A->block_structure());
DetectStructure(*A->block_structure(),
options_.num_eliminate_blocks,
@@ -88,11 +95,11 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl(
const time_t backsubstitute_time = time(NULL);
summary.termination_type = TOLERANCE;
- VLOG(2) << "time (sec) total: " << backsubstitute_time - start_time
- << " init: " << init_time - start_time
- << " eliminate: " << eliminate_time - init_time
- << " solve: " << solve_time - eliminate_time
- << " backsubstitute: " << backsubstitute_time - solve_time;
+ VLOG(2) << "time (sec) total: " << (backsubstitute_time - start_time)
+ << " init: " << (init_time - start_time)
+ << " eliminate: " << (eliminate_time - init_time)
+ << " solve: " << (solve_time - eliminate_time)
+ << " backsubstitute: " << (backsubstitute_time - solve_time);
return summary;
}
@@ -139,18 +146,33 @@ bool DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
return true;
}
-#ifndef CERES_NO_SUITESPARSE
+
SparseSchurComplementSolver::SparseSchurComplementSolver(
const LinearSolver::Options& options)
- : SchurComplementSolver(options),
- symbolic_factor_(NULL) {
+ : SchurComplementSolver(options) {
+#ifndef CERES_NO_SUITESPARSE
+ factor_ = NULL;
+#endif // CERES_NO_SUITESPARSE
+
+#ifndef CERES_NO_CXSPARSE
+ cxsparse_factor_ = NULL;
+#endif // CERES_NO_CXSPARSE
}
SparseSchurComplementSolver::~SparseSchurComplementSolver() {
- if (symbolic_factor_ != NULL) {
- ss_.Free(symbolic_factor_);
- symbolic_factor_ = NULL;
+#ifndef CERES_NO_SUITESPARSE
+ if (factor_ != NULL) {
+ ss_.Free(factor_);
+ factor_ = NULL;
}
+#endif // CERES_NO_SUITESPARSE
+
+#ifndef CERES_NO_CXSPARSE
+ if (cxsparse_factor_ != NULL) {
+ cxsparse_.Free(cxsparse_factor_);
+ cxsparse_factor_ = NULL;
+ }
+#endif // CERES_NO_CXSPARSE
}
// Determine the non-zero blocks in the Schur Complement matrix, and
@@ -161,13 +183,13 @@ void SparseSchurComplementSolver::InitStorage(
const int num_col_blocks = bs->cols.size();
const int num_row_blocks = bs->rows.size();
- vector<int> blocks(num_col_blocks - num_eliminate_blocks, 0);
+ blocks_.resize(num_col_blocks - num_eliminate_blocks, 0);
for (int i = num_eliminate_blocks; i < num_col_blocks; ++i) {
- blocks[i - num_eliminate_blocks] = bs->cols[i].size;
+ blocks_[i - num_eliminate_blocks] = bs->cols[i].size;
}
set<pair<int, int> > block_pairs;
- for (int i = 0; i < blocks.size(); ++i) {
+ for (int i = 0; i < blocks_.size(); ++i) {
block_pairs.insert(make_pair(i, i));
}
@@ -220,15 +242,34 @@ void SparseSchurComplementSolver::InitStorage(
}
}
- set_lhs(new BlockRandomAccessSparseMatrix(blocks, block_pairs));
+ set_lhs(new BlockRandomAccessSparseMatrix(blocks_, block_pairs));
set_rhs(new double[lhs()->num_rows()]);
}
+bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
+ switch (options().sparse_linear_algebra_library) {
+ case SUITE_SPARSE:
+ return SolveReducedLinearSystemUsingSuiteSparse(solution);
+ case CX_SPARSE:
+ return SolveReducedLinearSystemUsingCXSparse(solution);
+ default:
+ LOG(FATAL) << "Unknown sparse linear algebra library : "
+ << options().sparse_linear_algebra_library;
+ }
+
+ LOG(FATAL) << "Unknown sparse linear algebra library : "
+ << options().sparse_linear_algebra_library;
+ return false;
+}
+
+#ifndef CERES_NO_SUITESPARSE
// Solve the system Sx = r, assuming that the matrix S is stored in a
// BlockRandomAccessSparseMatrix. The linear system is solved using
// CHOLMOD's sparse cholesky factorization routines.
-bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
- // Extract the TripletSparseMatrix that is used for actually storing S.
+bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
+ double* solution) {
+ const time_t start_time = time(NULL);
+
TripletSparseMatrix* tsm =
const_cast<TripletSparseMatrix*>(
down_cast<const BlockRandomAccessSparseMatrix*>(lhs())->matrix());
@@ -245,30 +286,38 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
// The matrix is symmetric, and the upper triangular part of the
// matrix contains the values.
cholmod_lhs->stype = 1;
+ const time_t lhs_time = time(NULL);
cholmod_dense* cholmod_rhs =
ss_.CreateDenseVector(const_cast<double*>(rhs()), num_rows, num_rows);
+ const time_t rhs_time = time(NULL);
// Symbolic factorization is computed if we don't already have one handy.
- if (symbolic_factor_ == NULL) {
- symbolic_factor_ = ss_.AnalyzeCholesky(cholmod_lhs);
+ if (factor_ == NULL) {
+ if (options().use_block_amd) {
+ factor_ = ss_.BlockAnalyzeCholesky(cholmod_lhs, blocks_, blocks_);
+ } else {
+ factor_ = ss_.AnalyzeCholesky(cholmod_lhs);
+ }
+
+ if (VLOG_IS_ON(2)) {
+ cholmod_print_common("Symbolic Analysis", ss_.mutable_cc());
+ }
}
+ CHECK_NOTNULL(factor_);
+
+ const time_t symbolic_time = time(NULL);
cholmod_dense* cholmod_solution =
- ss_.SolveCholesky(cholmod_lhs, symbolic_factor_, cholmod_rhs);
+ ss_.SolveCholesky(cholmod_lhs, factor_, cholmod_rhs);
+
+ const time_t solve_time = time(NULL);
ss_.Free(cholmod_lhs);
cholmod_lhs = NULL;
ss_.Free(cholmod_rhs);
cholmod_rhs = NULL;
- // If sparsity is not constant across calls, then reset the symbolic
- // factorization.
- if (!options().constant_sparsity) {
- ss_.Free(symbolic_factor_);
- symbolic_factor_ = NULL;
- }
-
if (cholmod_solution == NULL) {
LOG(ERROR) << "CHOLMOD solve failed.";
return false;
@@ -277,9 +326,63 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
VectorRef(solution, num_rows)
= VectorRef(static_cast<double*>(cholmod_solution->x), num_rows);
ss_.Free(cholmod_solution);
+ const time_t final_time = time(NULL);
+ VLOG(2) << "time: " << (final_time - start_time)
+ << " lhs : " << (lhs_time - start_time)
+ << " rhs: " << (rhs_time - lhs_time)
+ << " analyze: " << (symbolic_time - rhs_time)
+ << " factor_and_solve: " << (solve_time - symbolic_time)
+ << " cleanup: " << (final_time - solve_time);
return true;
}
+#else
+bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
+ double* solution) {
+ LOG(FATAL) << "No SuiteSparse support in Ceres.";
+ return false;
+}
#endif // CERES_NO_SUITESPARSE
+#ifndef CERES_NO_CXSPARSE
+// Solve the system Sx = r, assuming that the matrix S is stored in a
+// BlockRandomAccessSparseMatrix. The linear system is solved using
+// CXSparse's sparse cholesky factorization routines.
+bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
+ double* solution) {
+ // Extract the TripletSparseMatrix that is used for actually storing S.
+ TripletSparseMatrix* tsm =
+ const_cast<TripletSparseMatrix*>(
+ down_cast<const BlockRandomAccessSparseMatrix*>(lhs())->matrix());
+
+ const int num_rows = tsm->num_rows();
+
+ // The case where there are no f blocks, and the system is block
+ // diagonal.
+ if (num_rows == 0) {
+ return true;
+ }
+
+ cs_di* lhs = CHECK_NOTNULL(cxsparse_.CreateSparseMatrix(tsm));
+ VectorRef(solution, num_rows) = ConstVectorRef(rhs(), num_rows);
+
+ // Compute symbolic factorization if not available.
+ if (cxsparse_factor_ == NULL) {
+ cxsparse_factor_ = CHECK_NOTNULL(cxsparse_.AnalyzeCholesky(lhs));
+ }
+
+ // Solve the linear system.
+ bool ok = cxsparse_.SolveCholesky(lhs, cxsparse_factor_, solution);
+
+ cxsparse_.Free(lhs);
+ return ok;
+}
+#else
+bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
+ double* solution) {
+ LOG(FATAL) << "No CXSparse support in Ceres.";
+ return false;
+}
+#endif // CERES_NO_CXPARSE
+
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h
index 039bc09e3ce..ea1b3184c33 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h
@@ -31,9 +31,13 @@
#ifndef CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_
#define CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_
+#include <set>
+#include <utility>
+
#include "ceres/block_random_access_matrix.h"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
+#include "ceres/cxsparse.h"
#include "ceres/linear_solver.h"
#include "ceres/schur_eliminator.h"
#include "ceres/suitesparse.h"
@@ -128,7 +132,7 @@ class SchurComplementSolver : public BlockSparseMatrixBaseSolver {
scoped_ptr<BlockRandomAccessMatrix> lhs_;
scoped_array<double> rhs_;
- DISALLOW_COPY_AND_ASSIGN(SchurComplementSolver);
+ CERES_DISALLOW_COPY_AND_ASSIGN(SchurComplementSolver);
};
// Dense Cholesky factorization based solver.
@@ -142,10 +146,10 @@ class DenseSchurComplementSolver : public SchurComplementSolver {
virtual void InitStorage(const CompressedRowBlockStructure* bs);
virtual bool SolveReducedLinearSystem(double* solution);
- DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver);
+ CERES_DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver);
};
-#ifndef CERES_NO_SUITESPARSE
+
// Sparse Cholesky factorization based solver.
class SparseSchurComplementSolver : public SchurComplementSolver {
public:
@@ -155,26 +159,26 @@ class SparseSchurComplementSolver : public SchurComplementSolver {
private:
virtual void InitStorage(const CompressedRowBlockStructure* bs);
virtual bool SolveReducedLinearSystem(double* solution);
+ bool SolveReducedLinearSystemUsingSuiteSparse(double* solution);
+ bool SolveReducedLinearSystemUsingCXSparse(double* solution);
+ // Size of the blocks in the Schur complement.
+ vector<int> blocks_;
+#ifndef CERES_NO_SUITESPARSE
SuiteSparse ss_;
// Symbolic factorization of the reduced linear system. Precomputed
- // once and reused if constant_sparsity_ is true.
- cholmod_factor* symbolic_factor_;
- DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver);
-};
-#else // CERES_NO_SUITESPARSE
-class SparseSchurComplementSolver : public SchurComplementSolver {
- public:
- explicit SparseSchurComplementSolver(const LinearSolver::Options& options)
- : SchurComplementSolver(options) {
- LOG(FATAL) << "SPARSE_SCHUR is not available. Please "
- "build Ceres with SuiteSparse.";
- }
+ // once and reused in subsequent calls.
+ cholmod_factor* factor_;
+#endif // CERES_NO_SUITESPARSE
- virtual ~SparseSchurComplementSolver() {}
+#ifndef CERES_NO_CXSPARSE
+ CXSparse cxsparse_;
+ // Cached factorization
+ cs_dis* cxsparse_factor_;
+#endif // CERES_NO_CXSPARSE
+ CERES_DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver);
};
-#endif // CERES_NO_SUITESPARSE
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h
index a388d005424..6120db9b009 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h
@@ -188,7 +188,7 @@ Eliminate(const BlockSparseMatrixBase* A,
typename EigenTypes<kFBlockSize>::ConstVectorRef
diag(D + bs->cols[i].position, block_size);
- MutexLock l(&cell_info->m);
+ CeresMutexLock l(&cell_info->m);
MatrixRef m(cell_info->values, row_stride, col_stride);
m.block(r, c, block_size, block_size).diagonal()
+= diag.array().square().matrix();
@@ -387,7 +387,7 @@ UpdateRhs(const Chunk& chunk,
row.block.size, block_size);
const int block = block_id - num_eliminate_blocks_;
- MutexLock l(rhs_locks_[block]);
+ CeresMutexLock l(rhs_locks_[block]);
typename EigenTypes<kFBlockSize>::VectorRef
(rhs + lhs_row_layout_[block], block_size).noalias()
+= b.transpose() * sj;
@@ -523,7 +523,7 @@ ChunkOuterProduct(const CompressedRowBlockStructure* bs,
const typename EigenTypes<kEBlockSize, kFBlockSize>::ConstMatrixRef
b2(buffer + it2->second, e_block_size, block2_size);
- MutexLock l(&cell_info->m);
+ CeresMutexLock l(&cell_info->m);
MatrixRef m(cell_info->values, row_stride, col_stride);
// We explicitly construct a block object here instead of using
@@ -532,7 +532,29 @@ ChunkOuterProduct(const CompressedRowBlockStructure* bs,
// like the Matrix class does.
Eigen::Block<MatrixRef, kFBlockSize, kFBlockSize>
block(m, r, c, block1_size, block2_size);
- block.noalias() -= b1_transpose_inverse_ete * b2;
+#ifdef CERES_WORK_AROUND_ANDROID_NDK_COMPILER_BUG
+ // Removing the ".noalias()" annotation on the following statement is
+ // necessary to produce a correct build with the Android NDK, including
+ // versions 6, 7, 8, and 8b, when built with STLPort and the
+ // non-standalone toolchain (i.e. ndk-build). This appears to be a
+ // compiler bug; if the workaround is not in place, the line
+ //
+ // block.noalias() -= b1_transpose_inverse_ete * b2;
+ //
+ // gets compiled to
+ //
+ // block.noalias() += b1_transpose_inverse_ete * b2;
+ //
+ // which breaks schur elimination. Introducing a temporary by removing the
+ // .noalias() annotation causes the issue to disappear. Tracking this
+ // issue down was tricky, since the test suite doesn't run when built with
+ // the non-standalone toolchain.
+ //
+ // TODO(keir): Make a reproduction case for this and send it upstream.
+ block -= b1_transpose_inverse_ete * b2;
+#else
+ block.noalias() -= b1_transpose_inverse_ete * b2;
+#endif // CERES_WORK_AROUND_ANDROID_NDK_COMPILER_BUG
}
}
}
@@ -601,7 +623,7 @@ NoEBlockRowOuterProduct(const BlockSparseMatrixBase* A,
&r, &c,
&row_stride, &col_stride);
if (cell_info != NULL) {
- MutexLock l(&cell_info->m);
+ CeresMutexLock l(&cell_info->m);
MatrixRef m(cell_info->values, row_stride, col_stride);
m.block(r, c, block1_size, block1_size)
.selfadjointView<Eigen::Upper>()
@@ -621,7 +643,7 @@ NoEBlockRowOuterProduct(const BlockSparseMatrixBase* A,
}
const int block2_size = bs->cols[row.cells[j].block_id].size;
- MutexLock l(&cell_info->m);
+ CeresMutexLock l(&cell_info->m);
MatrixRef m(cell_info->values, row_stride, col_stride);
m.block(r, c, block1_size, block2_size).noalias() +=
b1.transpose() * ConstMatrixRef(row_values + row.cells[j].position,
@@ -660,7 +682,7 @@ EBlockRowOuterProduct(const BlockSparseMatrixBase* A,
continue;
}
- MutexLock l(&cell_info->m);
+ CeresMutexLock l(&cell_info->m);
MatrixRef m(cell_info->values, row_stride, col_stride);
Eigen::Block<MatrixRef, kFBlockSize, kFBlockSize>
@@ -687,7 +709,7 @@ EBlockRowOuterProduct(const BlockSparseMatrixBase* A,
row.block.size,
block2_size);
- MutexLock l(&cell_info->m);
+ CeresMutexLock l(&cell_info->m);
MatrixRef m(cell_info->values, row_stride, col_stride);
Eigen::Block<MatrixRef, kFBlockSize, kFBlockSize>
block(m, r, c, block1_size, block2_size);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc
index c4fc1da3c2f..1cdff4e6dec 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc
@@ -30,25 +30,14 @@
#include "ceres/schur_ordering.h"
-#include <glog/logging.h>
#include "ceres/graph.h"
#include "ceres/graph_algorithms.h"
+#include "ceres/internal/scoped_ptr.h"
#include "ceres/map_util.h"
#include "ceres/parameter_block.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
-#include "ceres/internal/scoped_ptr.h"
-
-CERES_HASH_NAMESPACE_START
-
-// Allow us to hash pointers as if they were int's
-template<> struct hash< ::ceres::internal::ParameterBlock*> {
- size_t operator()(::ceres::internal::ParameterBlock* x) const {
- return reinterpret_cast<size_t>(x);
- }
-};
-
-CERES_HASH_NAMESPACE_END
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -59,8 +48,7 @@ int ComputeSchurOrdering(const Program& program,
scoped_ptr<Graph< ParameterBlock*> > graph(
CHECK_NOTNULL(CreateHessianGraph(program)));
- int independent_set_size =
- IndependentSetOrdering<ParameterBlock*>(*graph, ordering);
+ int independent_set_size = IndependentSetOrdering(*graph, ordering);
const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
// Add the excluded blocks to back of the ordering vector.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
index 77f04d1d918..66ca93283a1 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
@@ -32,36 +32,32 @@
#include "ceres/solver.h"
#include <vector>
-#include "ceres/levenberg_marquardt.h"
+#include "ceres/problem.h"
+#include "ceres/problem_impl.h"
#include "ceres/program.h"
#include "ceres/solver_impl.h"
#include "ceres/stringprintf.h"
-#include "ceres/problem.h"
namespace ceres {
Solver::~Solver() {}
-// TODO(sameeragarwal): The timing code here should use a sub-second
-// timer.
+// TODO(sameeragarwal): Use subsecond timers.
void Solver::Solve(const Solver::Options& options,
Problem* problem,
Solver::Summary* summary) {
time_t start_time_seconds = time(NULL);
- internal::SolverImpl::Solve(options, problem, summary);
+ internal::ProblemImpl* problem_impl =
+ CHECK_NOTNULL(problem)->problem_impl_.get();
+ internal::SolverImpl::Solve(options, problem_impl, summary);
summary->total_time_in_seconds = time(NULL) - start_time_seconds;
- summary->preprocessor_time_in_seconds =
- summary->total_time_in_seconds - summary->minimizer_time_in_seconds;
}
void Solve(const Solver::Options& options,
Problem* problem,
Solver::Summary* summary) {
- time_t start_time_seconds = time(NULL);
- internal::SolverImpl::Solve(options, problem, summary);
- summary->total_time_in_seconds = time(NULL) - start_time_seconds;
- summary->preprocessor_time_in_seconds =
- summary->total_time_in_seconds - summary->minimizer_time_in_seconds;
+ Solver solver;
+ solver.Solve(options, problem, summary);
}
Solver::Summary::Summary()
@@ -75,6 +71,7 @@ Solver::Summary::Summary()
num_unsuccessful_steps(-1),
preprocessor_time_in_seconds(-1.0),
minimizer_time_in_seconds(-1.0),
+ postprocessor_time_in_seconds(-1.0),
total_time_in_seconds(-1.0),
num_parameter_blocks(-1),
num_parameters(-1),
@@ -93,7 +90,9 @@ Solver::Summary::Summary()
linear_solver_type_given(SPARSE_NORMAL_CHOLESKY),
linear_solver_type_used(SPARSE_NORMAL_CHOLESKY),
preconditioner_type(IDENTITY),
- ordering_type(NATURAL) {
+ ordering_type(NATURAL),
+ trust_region_strategy_type(LEVENBERG_MARQUARDT),
+ sparse_linear_algebra_library(SUITE_SPARSE) {
}
string Solver::Summary::BriefReport() const {
@@ -136,7 +135,7 @@ string Solver::Summary::FullReport() const {
num_parameters);
internal::StringAppendF(&report, "Residual blocks % 10d\n",
num_residual_blocks);
- internal::StringAppendF(&report, "Residual % 10d\n\n",
+ internal::StringAppendF(&report, "Residuals % 10d\n\n",
num_residuals);
} else {
internal::StringAppendF(&report, "%45s %21s\n", "Original", "Reduced");
@@ -183,10 +182,33 @@ string Solver::Summary::FullReport() const {
internal::StringAppendF(&report, "Threads: % 25d% 25d\n",
num_threads_given, num_threads_used);
- internal::StringAppendF(&report, "Linear Solver Threads:% 23d% 25d\n",
+ internal::StringAppendF(&report, "Linear solver threads % 23d% 25d\n",
num_linear_solver_threads_given,
num_linear_solver_threads_used);
+ if (linear_solver_type_used == SPARSE_NORMAL_CHOLESKY ||
+ linear_solver_type_used == SPARSE_SCHUR ||
+ (linear_solver_type_used == ITERATIVE_SCHUR &&
+ (preconditioner_type == SCHUR_JACOBI ||
+ preconditioner_type == CLUSTER_JACOBI ||
+ preconditioner_type == CLUSTER_TRIDIAGONAL))) {
+ internal::StringAppendF(&report, "\nSparse Linear Algebra Library %15s\n",
+ SparseLinearAlgebraLibraryTypeToString(
+ sparse_linear_algebra_library));
+ }
+
+ internal::StringAppendF(&report, "Trust Region Strategy %19s",
+ TrustRegionStrategyTypeToString(
+ trust_region_strategy_type));
+ if (trust_region_strategy_type == DOGLEG) {
+ if (dogleg_type == TRADITIONAL_DOGLEG) {
+ internal::StringAppendF(&report, " (TRADITIONAL)");
+ } else {
+ internal::StringAppendF(&report, " (SUBSPACE)");
+ }
+ }
+ internal::StringAppendF(&report, "\n");
+
if (termination_type == DID_NOT_RUN) {
CHECK(!error.empty())
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
index ed07d9dc6d7..8ef5b98e35f 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
@@ -30,40 +30,29 @@
#include "ceres/solver_impl.h"
+#include <cstdio>
#include <iostream> // NOLINT
#include <numeric>
#include "ceres/evaluator.h"
#include "ceres/gradient_checking_cost_function.h"
-#include "ceres/levenberg_marquardt.h"
+#include "ceres/iteration_callback.h"
+#include "ceres/levenberg_marquardt_strategy.h"
#include "ceres/linear_solver.h"
#include "ceres/map_util.h"
#include "ceres/minimizer.h"
#include "ceres/parameter_block.h"
+#include "ceres/problem.h"
#include "ceres/problem_impl.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
#include "ceres/schur_ordering.h"
#include "ceres/stringprintf.h"
-#include "ceres/iteration_callback.h"
-#include "ceres/problem.h"
+#include "ceres/trust_region_minimizer.h"
namespace ceres {
namespace internal {
namespace {
-void EvaluateCostAndResiduals(ProblemImpl* problem_impl,
- double* cost,
- vector<double>* residuals) {
- CHECK_NOTNULL(cost);
- Program* program = CHECK_NOTNULL(problem_impl)->mutable_program();
- if (residuals != NULL) {
- residuals->resize(program->NumResiduals());
- program->Evaluate(cost, &(*residuals)[0]);
- } else {
- program->Evaluate(cost, NULL);
- }
-}
-
// Callback for updating the user's parameter blocks. Updates are only
// done if the step is successful.
class StateUpdatingCallback : public IterationCallback {
@@ -96,7 +85,7 @@ class LoggingCallback : public IterationCallback {
CallbackReturnType operator()(const IterationSummary& summary) {
const char* kReportRowFormat =
"% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e "
- "rho:% 3.2e mu:% 3.2e li:% 3d";
+ "rho:% 3.2e mu:% 3.2e li:% 3d it:% 3.2e tt:% 3.2e";
string output = StringPrintf(kReportRowFormat,
summary.iteration,
summary.cost,
@@ -104,8 +93,10 @@ class LoggingCallback : public IterationCallback {
summary.gradient_max_norm,
summary.step_norm,
summary.relative_decrease,
- summary.mu,
- summary.linear_solver_iterations);
+ summary.trust_region_radius,
+ summary.linear_solver_iterations,
+ summary.iteration_time_in_seconds,
+ summary.cumulative_time_in_seconds);
if (log_to_stdout_) {
cout << output << endl;
} else {
@@ -118,44 +109,101 @@ class LoggingCallback : public IterationCallback {
const bool log_to_stdout_;
};
+// Basic callback to record the execution of the solver to a file for
+// offline analysis.
+class FileLoggingCallback : public IterationCallback {
+ public:
+ explicit FileLoggingCallback(const string& filename)
+ : fptr_(NULL) {
+ fptr_ = fopen(filename.c_str(), "w");
+ CHECK_NOTNULL(fptr_);
+ }
+
+ virtual ~FileLoggingCallback() {
+ if (fptr_ != NULL) {
+ fclose(fptr_);
+ }
+ }
+
+ virtual CallbackReturnType operator()(const IterationSummary& summary) {
+ fprintf(fptr_,
+ "%4d %e %e\n",
+ summary.iteration,
+ summary.cost,
+ summary.cumulative_time_in_seconds);
+ return SOLVER_CONTINUE;
+ }
+ private:
+ FILE* fptr_;
+};
+
} // namespace
void SolverImpl::Minimize(const Solver::Options& options,
Program* program,
Evaluator* evaluator,
LinearSolver* linear_solver,
- double* initial_parameters,
- double* final_parameters,
+ double* parameters,
Solver::Summary* summary) {
Minimizer::Options minimizer_options(options);
+ // TODO(sameeragarwal): Add support for logging the configuration
+ // and more detailed stats.
+ scoped_ptr<IterationCallback> file_logging_callback;
+ if (!options.solver_log.empty()) {
+ file_logging_callback.reset(new FileLoggingCallback(options.solver_log));
+ minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(),
+ file_logging_callback.get());
+ }
+
LoggingCallback logging_callback(options.minimizer_progress_to_stdout);
if (options.logging_type != SILENT) {
- minimizer_options.callbacks.push_back(&logging_callback);
+ minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(),
+ &logging_callback);
}
- StateUpdatingCallback updating_callback(program, initial_parameters);
+ StateUpdatingCallback updating_callback(program, parameters);
if (options.update_state_every_iteration) {
- minimizer_options.callbacks.push_back(&updating_callback);
- }
-
- LevenbergMarquardt levenberg_marquardt;
-
- time_t start_minimizer_time_seconds = time(NULL);
- levenberg_marquardt.Minimize(minimizer_options,
- evaluator,
- linear_solver,
- initial_parameters,
- final_parameters,
- summary);
- summary->minimizer_time_in_seconds =
- time(NULL) - start_minimizer_time_seconds;
+ // This must get pushed to the front of the callbacks so that it is run
+ // before any of the user callbacks.
+ minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(),
+ &updating_callback);
+ }
+
+ minimizer_options.evaluator = evaluator;
+ scoped_ptr<SparseMatrix> jacobian(evaluator->CreateJacobian());
+ minimizer_options.jacobian = jacobian.get();
+
+ TrustRegionStrategy::Options trust_region_strategy_options;
+ trust_region_strategy_options.linear_solver = linear_solver;
+ trust_region_strategy_options.initial_radius =
+ options.initial_trust_region_radius;
+ trust_region_strategy_options.max_radius = options.max_trust_region_radius;
+ trust_region_strategy_options.lm_min_diagonal = options.lm_min_diagonal;
+ trust_region_strategy_options.lm_max_diagonal = options.lm_max_diagonal;
+ trust_region_strategy_options.trust_region_strategy_type =
+ options.trust_region_strategy_type;
+ trust_region_strategy_options.dogleg_type = options.dogleg_type;
+ scoped_ptr<TrustRegionStrategy> strategy(
+ TrustRegionStrategy::Create(trust_region_strategy_options));
+ minimizer_options.trust_region_strategy = strategy.get();
+
+ TrustRegionMinimizer minimizer;
+ time_t minimizer_start_time = time(NULL);
+ minimizer.Minimize(minimizer_options, parameters, summary);
+ summary->minimizer_time_in_seconds = time(NULL) - minimizer_start_time;
}
void SolverImpl::Solve(const Solver::Options& original_options,
- Problem* problem,
+ ProblemImpl* original_problem_impl,
Solver::Summary* summary) {
+ time_t solver_start_time = time(NULL);
Solver::Options options(original_options);
+ Program* original_program = original_problem_impl->mutable_program();
+ ProblemImpl* problem_impl = original_problem_impl;
+ // Reset the summary object to its default values.
+ *CHECK_NOTNULL(summary) = Solver::Summary();
+
#ifndef CERES_USE_OPENMP
if (options.num_threads > 1) {
@@ -174,8 +222,6 @@ void SolverImpl::Solve(const Solver::Options& original_options,
}
#endif
- // Reset the summary object to its default values;
- *CHECK_NOTNULL(summary) = Solver::Summary();
summary->linear_solver_type_given = options.linear_solver_type;
summary->num_eliminate_blocks_given = original_options.num_eliminate_blocks;
summary->num_threads_given = original_options.num_threads;
@@ -183,32 +229,38 @@ void SolverImpl::Solve(const Solver::Options& original_options,
original_options.num_linear_solver_threads;
summary->ordering_type = original_options.ordering_type;
- ProblemImpl* problem_impl = CHECK_NOTNULL(problem)->problem_impl_.get();
-
summary->num_parameter_blocks = problem_impl->NumParameterBlocks();
summary->num_parameters = problem_impl->NumParameters();
summary->num_residual_blocks = problem_impl->NumResidualBlocks();
summary->num_residuals = problem_impl->NumResiduals();
summary->num_threads_used = options.num_threads;
-
- // Evaluate the initial cost and residual vector (if needed). The
- // initial cost needs to be computed on the original unpreprocessed
- // problem, as it is used to determine the value of the "fixed" part
- // of the objective function after the problem has undergone
- // reduction. Also the initial residuals are in the order in which
- // the user added the ResidualBlocks to the optimization problem.
- EvaluateCostAndResiduals(problem_impl,
- &summary->initial_cost,
- options.return_initial_residuals
- ? &summary->initial_residuals
- : NULL);
+ summary->sparse_linear_algebra_library =
+ options.sparse_linear_algebra_library;
+ summary->trust_region_strategy_type = options.trust_region_strategy_type;
+ summary->dogleg_type = options.dogleg_type;
+
+ // Evaluate the initial cost, residual vector and the jacobian
+ // matrix if requested by the user. The initial cost needs to be
+ // computed on the original unpreprocessed problem, as it is used to
+ // determine the value of the "fixed" part of the objective function
+ // after the problem has undergone reduction.
+ Evaluator::Evaluate(
+ original_program,
+ options.num_threads,
+ &(summary->initial_cost),
+ options.return_initial_residuals ? &summary->initial_residuals : NULL,
+ options.return_initial_gradient ? &summary->initial_gradient : NULL,
+ options.return_initial_jacobian ? &summary->initial_jacobian : NULL);
+ original_program->SetParameterBlockStatePtrsToUserStatePtrs();
// If the user requests gradient checking, construct a new
// ProblemImpl by wrapping the CostFunctions of problem_impl inside
// GradientCheckingCostFunction and replacing problem_impl with
// gradient_checking_problem_impl.
scoped_ptr<ProblemImpl> gradient_checking_problem_impl;
+ // Save the original problem impl so we don't use the gradient
+ // checking one when computing the residuals.
if (options.check_gradients) {
VLOG(1) << "Checking Gradients";
gradient_checking_problem_impl.reset(
@@ -224,8 +276,10 @@ void SolverImpl::Solve(const Solver::Options& original_options,
// Create the three objects needed to minimize: the transformed program, the
// evaluator, and the linear solver.
- scoped_ptr<Program> reduced_program(
- CreateReducedProgram(&options, problem_impl, &summary->error));
+ scoped_ptr<Program> reduced_program(CreateReducedProgram(&options,
+ problem_impl,
+ &summary->fixed_cost,
+ &summary->error));
if (reduced_program == NULL) {
return;
}
@@ -259,19 +313,21 @@ void SolverImpl::Solve(const Solver::Options& original_options,
}
// The optimizer works on contiguous parameter vectors; allocate some.
- Vector initial_parameters(reduced_program->NumParameters());
- Vector optimized_parameters(reduced_program->NumParameters());
+ Vector parameters(reduced_program->NumParameters());
// Collect the discontiguous parameters into a contiguous state vector.
- reduced_program->ParameterBlocksToStateVector(&initial_parameters[0]);
+ reduced_program->ParameterBlocksToStateVector(parameters.data());
+
+ time_t minimizer_start_time = time(NULL);
+ summary->preprocessor_time_in_seconds =
+ minimizer_start_time - solver_start_time;
// Run the optimization.
Minimize(options,
reduced_program.get(),
evaluator.get(),
linear_solver.get(),
- initial_parameters.data(),
- optimized_parameters.data(),
+ parameters.data(),
summary);
// If the user aborted mid-optimization or the optimization
@@ -282,30 +338,45 @@ void SolverImpl::Solve(const Solver::Options& original_options,
return;
}
+ time_t post_process_start_time = time(NULL);
+
// Push the contiguous optimized parameters back to the user's parameters.
- reduced_program->StateVectorToParameterBlocks(&optimized_parameters[0]);
+ reduced_program->StateVectorToParameterBlocks(parameters.data());
reduced_program->CopyParameterBlockStateToUserState();
- // Return the final cost and residuals for the original problem.
- EvaluateCostAndResiduals(problem->problem_impl_.get(),
- &summary->final_cost,
- options.return_final_residuals
- ? &summary->final_residuals
- : NULL);
-
+ // Evaluate the final cost, residual vector and the jacobian
+ // matrix if requested by the user.
+ Evaluator::Evaluate(
+ original_program,
+ options.num_threads,
+ &summary->final_cost,
+ options.return_final_residuals ? &summary->final_residuals : NULL,
+ options.return_final_gradient ? &summary->final_gradient : NULL,
+ options.return_final_jacobian ? &summary->final_jacobian : NULL);
+
+ // Ensure the program state is set to the user parameters on the way out.
+ original_program->SetParameterBlockStatePtrsToUserStatePtrs();
// Stick a fork in it, we're done.
- return;
+ summary->postprocessor_time_in_seconds = time(NULL) - post_process_start_time;
}
// Strips varying parameters and residuals, maintaining order, and updating
// num_eliminate_blocks.
bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
int* num_eliminate_blocks,
+ double* fixed_cost,
string* error) {
int original_num_eliminate_blocks = *num_eliminate_blocks;
vector<ParameterBlock*>* parameter_blocks =
program->mutable_parameter_blocks();
+ scoped_array<double> residual_block_evaluate_scratch;
+ if (fixed_cost != NULL) {
+ residual_block_evaluate_scratch.reset(
+ new double[program->MaxScratchDoublesNeededForEvaluate()]);
+ *fixed_cost = 0.0;
+ }
+
// Mark all the parameters as unused. Abuse the index member of the parameter
// blocks for the marking.
for (int i = 0; i < parameter_blocks->size(); ++i) {
@@ -335,6 +406,17 @@ bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
if (!all_constant) {
(*residual_blocks)[j++] = (*residual_blocks)[i];
+ } else if (fixed_cost != NULL) {
+ // The residual is constant and will be removed, so its cost is
+ // added to the variable fixed_cost.
+ double cost = 0.0;
+ if (!residual_block->Evaluate(
+ &cost, NULL, NULL, residual_block_evaluate_scratch.get())) {
+ *error = StringPrintf("Evaluation of the residual %d failed during "
+ "removal of fixed residual blocks.", i);
+ return false;
+ }
+ *fixed_cost += cost;
}
}
residual_blocks->resize(j);
@@ -367,6 +449,7 @@ bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
Program* SolverImpl::CreateReducedProgram(Solver::Options* options,
ProblemImpl* problem_impl,
+ double* fixed_cost,
string* error) {
Program* original_program = problem_impl->mutable_program();
scoped_ptr<Program> transformed_program(new Program(*original_program));
@@ -397,6 +480,7 @@ Program* SolverImpl::CreateReducedProgram(Solver::Options* options,
if (!RemoveFixedBlocksFromProgram(transformed_program.get(),
&num_eliminate_blocks,
+ fixed_cost,
error)) {
return NULL;
}
@@ -431,13 +515,34 @@ Program* SolverImpl::CreateReducedProgram(Solver::Options* options,
LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
string* error) {
+ if (options->trust_region_strategy_type == DOGLEG) {
+ if (options->linear_solver_type == ITERATIVE_SCHUR ||
+ options->linear_solver_type == CGNR) {
+ *error = "DOGLEG only supports exact factorization based linear "
+ "solvers. If you want to use an iterative solver please "
+ "use LEVENBERG_MARQUARDT as the trust_region_strategy_type";
+ return NULL;
+ }
+ }
+
#ifdef CERES_NO_SUITESPARSE
- if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY) {
- *error = "Can't use SPARSE_NORMAL_CHOLESKY because SuiteSparse was not "
- "enabled when Ceres was built.";
+ if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY &&
+ options->sparse_linear_algebra_library == SUITE_SPARSE) {
+ *error = "Can't use SPARSE_NORMAL_CHOLESKY with SUITESPARSE because "
+ "SuiteSparse was not enabled when Ceres was built.";
+ return NULL;
+ }
+#endif
+
+#ifdef CERES_NO_CXSPARSE
+ if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY &&
+ options->sparse_linear_algebra_library == CX_SPARSE) {
+ *error = "Can't use SPARSE_NORMAL_CHOLESKY with CXSPARSE because "
+ "CXSparse was not enabled when Ceres was built.";
return NULL;
}
-#endif // CERES_NO_SUITESPARSE
+#endif
+
if (options->linear_solver_max_num_iterations <= 0) {
*error = "Solver::Options::linear_solver_max_num_iterations is 0.";
@@ -455,30 +560,32 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
}
LinearSolver::Options linear_solver_options;
- linear_solver_options.constant_sparsity = true;
linear_solver_options.min_num_iterations =
options->linear_solver_min_num_iterations;
linear_solver_options.max_num_iterations =
options->linear_solver_max_num_iterations;
linear_solver_options.type = options->linear_solver_type;
linear_solver_options.preconditioner_type = options->preconditioner_type;
+ linear_solver_options.sparse_linear_algebra_library =
+ options->sparse_linear_algebra_library;
+ linear_solver_options.use_block_amd = options->use_block_amd;
#ifdef CERES_NO_SUITESPARSE
if (linear_solver_options.preconditioner_type == SCHUR_JACOBI) {
*error = "SCHUR_JACOBI preconditioner not suppored. Please build Ceres "
- "with SuiteSparse support";
+ "with SuiteSparse support.";
return NULL;
}
if (linear_solver_options.preconditioner_type == CLUSTER_JACOBI) {
*error = "CLUSTER_JACOBI preconditioner not suppored. Please build Ceres "
- "with SuiteSparse support";
+ "with SuiteSparse support.";
return NULL;
}
if (linear_solver_options.preconditioner_type == CLUSTER_TRIDIAGONAL) {
*error = "CLUSTER_TRIDIAGONAL preconditioner not suppored. Please build "
- "Ceres with SuiteSparse support";
+ "Ceres with SuiteSparse support.";
return NULL;
}
#endif
@@ -489,23 +596,23 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
if ((linear_solver_options.num_eliminate_blocks == 0) &&
IsSchurType(linear_solver_options.type)) {
-#ifndef CERES_NO_SUITESPARSE
+#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
+ LOG(INFO) << "No elimination block remaining switching to DENSE_QR.";
+ linear_solver_options.type = DENSE_QR;
+#else
LOG(INFO) << "No elimination block remaining "
<< "switching to SPARSE_NORMAL_CHOLESKY.";
linear_solver_options.type = SPARSE_NORMAL_CHOLESKY;
-#else
- LOG(INFO) << "No elimination block remaining switching to DENSE_QR.";
- linear_solver_options.type = DENSE_QR;
-#endif // CERES_NO_SUITESPARSE
+#endif
}
-#ifdef CERES_NO_SUITESPARSE
+#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
if (linear_solver_options.type == SPARSE_SCHUR) {
- *error = "Can't use SPARSE_SCHUR because SuiteSparse was not "
- "enabled when Ceres was built.";
+ *error = "Can't use SPARSE_SCHUR because neither SuiteSparse nor"
+ "CXSparse was enabled when Ceres was compiled.";
return NULL;
}
-#endif // CERES_NO_SUITESPARSE
+#endif
// The matrix used for storing the dense Schur complement has a
// single lock guarding the whole matrix. Running the
@@ -578,15 +685,18 @@ bool SolverImpl::ApplyUserOrdering(const ProblemImpl& problem_impl,
// Find the minimum index of any parameter block to the given residual.
// Parameter blocks that have indices greater than num_eliminate_blocks are
// considered to have an index equal to num_eliminate_blocks.
-int MinParameterBlock(const ResidualBlock* residual_block,
- int num_eliminate_blocks) {
+static int MinParameterBlock(const ResidualBlock* residual_block,
+ int num_eliminate_blocks) {
int min_parameter_block_position = num_eliminate_blocks;
for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[i];
- DCHECK_NE(parameter_block->index(), -1)
- << "Did you forget to call Program::SetParameterOffsetsAndIndex()?";
- min_parameter_block_position = std::min(parameter_block->index(),
- min_parameter_block_position);
+ if (!parameter_block->IsConstant()) {
+ CHECK_NE(parameter_block->index(), -1)
+ << "Did you forget to call Program::SetParameterOffsetsAndIndex()? "
+ << "This is a Ceres bug; please contact the developers!";
+ min_parameter_block_position = std::min(parameter_block->index(),
+ min_parameter_block_position);
+ }
}
return min_parameter_block_position;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
index 957ebcc65df..11b44de6f42 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
@@ -31,6 +31,9 @@
#ifndef CERES_INTERNAL_SOLVER_IMPL_H_
#define CERES_INTERNAL_SOLVER_IMPL_H_
+#include <string>
+#include <vector>
+#include "ceres/internal/port.h"
#include "ceres/solver.h"
namespace ceres {
@@ -46,15 +49,18 @@ class SolverImpl {
// Mirrors the interface in solver.h, but exposes implementation
// details for testing internally.
static void Solve(const Solver::Options& options,
- Problem* problem,
+ ProblemImpl* problem_impl,
Solver::Summary* summary);
// Create the transformed Program, which has all the fixed blocks
// and residuals eliminated, and in the case of automatic schur
// ordering, has the E blocks first in the resulting program, with
// options.num_eliminate_blocks set appropriately.
+ // If fixed_cost is not NULL, the residual blocks that are removed
+ // are evaluated and the sum of their cost is returned in fixed_cost.
static Program* CreateReducedProgram(Solver::Options* options,
ProblemImpl* problem_impl,
+ double* fixed_cost,
string* error);
// Create the appropriate linear solver, taking into account any
@@ -92,16 +98,18 @@ class SolverImpl {
Program* program,
Evaluator* evaluator,
LinearSolver* linear_solver,
- double* initial_parameters,
- double* final_parameters,
+ double* parameters,
Solver::Summary* summary);
// Remove the fixed or unused parameter blocks and residuals
// depending only on fixed parameters from the problem. Also updates
// num_eliminate_blocks, since removed parameters changes the point
// at which the eliminated blocks is valid.
+ // If fixed_cost is not NULL, the residual blocks that are removed
+ // are evaluated and the sum of their cost is returned in fixed_cost.
static bool RemoveFixedBlocksFromProgram(Program* program,
int* num_eliminate_blocks,
+ double* fixed_cost,
string* error);
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h
index 562210dfec8..1b19f887946 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h
@@ -86,7 +86,7 @@ class SparseMatrix : public LinearOperator {
// sparse matrix.
virtual void ToDenseMatrix(Matrix* dense_matrix) const = 0;
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
// Dump the sparse matrix to a proto. Destroys the contents of proto.
virtual void ToProto(SparseMatrixProto* proto) const = 0;
#endif
diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
index 59222dc374d..9e00b4402dc 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
@@ -28,13 +28,16 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-#ifndef CERES_NO_SUITESPARSE
-
#include "ceres/sparse_normal_cholesky_solver.h"
#include <algorithm>
#include <cstring>
#include <ctime>
+
+#ifndef CERES_NO_CXSPARSE
+#include "cs.h"
+#endif
+
#include "ceres/compressed_row_sparse_matrix.h"
#include "ceres/linear_solver.h"
#include "ceres/suitesparse.h"
@@ -48,13 +51,30 @@ namespace internal {
SparseNormalCholeskySolver::SparseNormalCholeskySolver(
const LinearSolver::Options& options)
- : options_(options), symbolic_factor_(NULL) {}
+ : options_(options) {
+#ifndef CERES_NO_SUITESPARSE
+ factor_ = NULL;
+#endif
+
+#ifndef CERES_NO_CXSPARSE
+ cxsparse_factor_ = NULL;
+#endif // CERES_NO_CXSPARSE
+}
SparseNormalCholeskySolver::~SparseNormalCholeskySolver() {
- if (symbolic_factor_ != NULL) {
- ss_.Free(symbolic_factor_);
- symbolic_factor_ = NULL;
+#ifndef CERES_NO_SUITESPARSE
+ if (factor_ != NULL) {
+ ss_.Free(factor_);
+ factor_ = NULL;
}
+#endif
+
+#ifndef CERES_NO_CXSPARSE
+ if (cxsparse_factor_ != NULL) {
+ cxsparse_.Free(cxsparse_factor_);
+ cxsparse_factor_ = NULL;
+ }
+#endif // CERES_NO_CXSPARSE
}
LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl(
@@ -62,6 +82,93 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl(
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double * x) {
+ switch (options_.sparse_linear_algebra_library) {
+ case SUITE_SPARSE:
+ return SolveImplUsingSuiteSparse(A, b, per_solve_options, x);
+ case CX_SPARSE:
+ return SolveImplUsingCXSparse(A, b, per_solve_options, x);
+ default:
+ LOG(FATAL) << "Unknown sparse linear algebra library : "
+ << options_.sparse_linear_algebra_library;
+ }
+
+ LOG(FATAL) << "Unknown sparse linear algebra library : "
+ << options_.sparse_linear_algebra_library;
+ return LinearSolver::Summary();
+}
+
+#ifndef CERES_NO_CXSPARSE
+LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse(
+ CompressedRowSparseMatrix* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double * x) {
+ LinearSolver::Summary summary;
+ summary.num_iterations = 1;
+ const int num_cols = A->num_cols();
+ Vector Atb = Vector::Zero(num_cols);
+ A->LeftMultiply(b, Atb.data());
+
+ if (per_solve_options.D != NULL) {
+ // Temporarily append a diagonal block to the A matrix, but undo
+ // it before returning the matrix to the user.
+ CompressedRowSparseMatrix D(per_solve_options.D, num_cols);
+ A->AppendRows(D);
+ }
+
+ VectorRef(x, num_cols).setZero();
+
+ // Wrap the augmented Jacobian in a compressed sparse column matrix.
+ cs_di At = cxsparse_.CreateSparseMatrixTransposeView(A);
+
+ // Compute the normal equations. J'J delta = J'f and solve them
+ // using a sparse Cholesky factorization. Notice that when compared
+ // to SuiteSparse we have to explicitly compute the transpose of Jt,
+ // and then the normal equations before they can be
+ // factorized. CHOLMOD/SuiteSparse on the other hand can just work
+ // off of Jt to compute the Cholesky factorization of the normal
+ // equations.
+ cs_di* A2 = cs_transpose(&At, 1);
+ cs_di* AtA = cs_multiply(&At,A2);
+
+ cxsparse_.Free(A2);
+ if (per_solve_options.D != NULL) {
+ A->DeleteRows(num_cols);
+ }
+
+ // Compute symbolic factorization if not available.
+ if (cxsparse_factor_ == NULL) {
+ cxsparse_factor_ = CHECK_NOTNULL(cxsparse_.AnalyzeCholesky(AtA));
+ }
+
+ // Solve the linear system.
+ if (cxsparse_.SolveCholesky(AtA, cxsparse_factor_, Atb.data())) {
+ VectorRef(x, Atb.rows()) = Atb;
+ summary.termination_type = TOLERANCE;
+ }
+
+ cxsparse_.Free(AtA);
+ return summary;
+}
+#else
+LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse(
+ CompressedRowSparseMatrix* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double * x) {
+ LOG(FATAL) << "No CXSparse support in Ceres.";
+
+ // Unreachable but MSVC does not know this.
+ return LinearSolver::Summary();
+}
+#endif
+
+#ifndef CERES_NO_SUITESPARSE
+LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
+ CompressedRowSparseMatrix* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double * x) {
const time_t start_time = time(NULL);
const int num_cols = A->num_cols();
@@ -84,13 +191,25 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl(
cholmod_dense* rhs = ss_.CreateDenseVector(Atb.data(), num_cols, num_cols);
const time_t init_time = time(NULL);
- if (symbolic_factor_ == NULL) {
- symbolic_factor_ = CHECK_NOTNULL(ss_.AnalyzeCholesky(lhs.get()));
+ if (factor_ == NULL) {
+ if (options_.use_block_amd) {
+ factor_ = ss_.BlockAnalyzeCholesky(lhs.get(),
+ A->col_blocks(),
+ A->row_blocks());
+ } else {
+ factor_ = ss_.AnalyzeCholesky(lhs.get());
+ }
+
+ if (VLOG_IS_ON(2)) {
+ cholmod_print_common("Symbolic Analysis", ss_.mutable_cc());
+ }
}
+ CHECK_NOTNULL(factor_);
+
const time_t symbolic_time = time(NULL);
- cholmod_dense* sol = ss_.SolveCholesky(lhs.get(), symbolic_factor_, rhs);
+ cholmod_dense* sol = ss_.SolveCholesky(lhs.get(), factor_, rhs);
const time_t solve_time = time(NULL);
ss_.Free(rhs);
@@ -100,11 +219,6 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl(
A->DeleteRows(num_cols);
}
- if (!options_.constant_sparsity) {
- ss_.Free(symbolic_factor_);
- symbolic_factor_ = NULL;
- }
-
summary.num_iterations = 1;
if (sol != NULL) {
memcpy(x, sol->x, num_cols * sizeof(*x));
@@ -115,15 +229,25 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl(
}
const time_t cleanup_time = time(NULL);
- VLOG(2) << "time (sec) total: " << cleanup_time - start_time
- << " init: " << init_time - start_time
- << " symbolic: " << symbolic_time - init_time
- << " solve: " << solve_time - symbolic_time
- << " cleanup: " << cleanup_time - solve_time;
+ VLOG(2) << "time (sec) total: " << (cleanup_time - start_time)
+ << " init: " << (init_time - start_time)
+ << " symbolic: " << (symbolic_time - init_time)
+ << " solve: " << (solve_time - symbolic_time)
+ << " cleanup: " << (cleanup_time - solve_time);
return summary;
}
+#else
+LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
+ CompressedRowSparseMatrix* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double * x) {
+ LOG(FATAL) << "No SuiteSparse support in Ceres.";
+
+ // Unreachable but MSVC does not know this.
+ return LinearSolver::Summary();
+}
+#endif
} // namespace internal
} // namespace ceres
-
-#endif // CERES_NO_SUITESPARSE
diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h
index ce1d6d285be..40d9e0a0327 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h
@@ -34,13 +34,10 @@
#ifndef CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_
#define CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_
-#ifndef CERES_NO_SUITESPARSE
-
-#include "cholmod.h"
-#include "cholmod_core.h"
+#include "ceres/cxsparse.h"
#include "ceres/linear_solver.h"
-#include "ceres/suitesparse.h"
#include "ceres/internal/macros.h"
+#include "ceres/suitesparse.h"
namespace ceres {
namespace internal {
@@ -61,17 +58,36 @@ class SparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver {
const LinearSolver::PerSolveOptions& options,
double* x);
- const LinearSolver::Options options_;
+ LinearSolver::Summary SolveImplUsingSuiteSparse(
+ CompressedRowSparseMatrix* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& options,
+ double* x);
+
+ // Crashes if CSparse is not installed.
+ LinearSolver::Summary SolveImplUsingCXSparse(
+ CompressedRowSparseMatrix* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& options,
+ double* x);
+
+#ifndef CERES_NO_SUITESPARSE
SuiteSparse ss_;
+ // Cached factorization
+ cholmod_factor* factor_;
+#endif // CERES_NO_SUITESPARSE
+#ifndef CERES_NO_CXSPARSE
+ CXSparse cxsparse_;
// Cached factorization
- cholmod_factor* symbolic_factor_;
- DISALLOW_COPY_AND_ASSIGN(SparseNormalCholeskySolver);
+ cs_dis* cxsparse_factor_;
+#endif // CERES_NO_CXSPARSE
+
+ const LinearSolver::Options options_;
+ CERES_DISALLOW_COPY_AND_ASSIGN(SparseNormalCholeskySolver);
};
} // namespace internal
} // namespace ceres
-#endif // CERES_NO_SUITESPARSE
-
#endif // CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/split.cc b/extern/libmv/third_party/ceres/internal/ceres/split.cc
index 4fa1bd468b9..c65c8a5bb5d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/split.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/split.cc
@@ -31,6 +31,7 @@
#include <string>
#include <vector>
#include <iterator>
+#include "ceres/split.h"
#include "ceres/internal/port.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/split.h b/extern/libmv/third_party/ceres/internal/ceres/split.h
new file mode 100644
index 00000000000..ec579e974da
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/split.h
@@ -0,0 +1,21 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: keir@google.com (Keir Mierle)
+
+#ifndef CERES_INTERNAL_SPLIT_H_
+#define VISION_OPTIMIZATION_LEAST_SQUARES_INTERNAL_SPLIT_H_
+
+#include <string>
+#include <vector>
+#include "ceres/internal/port.h"
+
+namespace ceres {
+
+// Split a string using one or more character delimiters, presented as a
+// nul-terminated c string. Append the components to 'result'. If there are
+// consecutive delimiters, this function skips over all of them.
+void SplitStringUsing(const string& full, const char* delim,
+ vector<string>* res);
+
+} // namespace ceres
+
+#endif // CERES_INTERNAL_SPLIT_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
index c0f35225bc3..396a48b7d97 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
@@ -34,6 +34,7 @@
#include <string>
#include <vector>
+#include "ceres/stringprintf.h"
#include "ceres/internal/port.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h
index 30b974e7ae5..f2f907ab32d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h
@@ -54,34 +54,34 @@ namespace internal {
// N.B.: As the GCC manual states, "[s]ince non-static C++ methods
// have an implicit 'this' argument, the arguments of such methods
// should be counted from two, not one."
-#define PRINTF_ATTRIBUTE(string_index, first_to_check) \
+#define CERES_PRINTF_ATTRIBUTE(string_index, first_to_check) \
__attribute__((__format__ (__printf__, string_index, first_to_check)))
-#define SCANF_ATTRIBUTE(string_index, first_to_check) \
+#define CERES_SCANF_ATTRIBUTE(string_index, first_to_check) \
__attribute__((__format__ (__scanf__, string_index, first_to_check)))
#else
-#define PRINTF_ATTRIBUTE(string_index, first_to_check)
+#define CERES_PRINTF_ATTRIBUTE(string_index, first_to_check)
#endif
// Return a C++ string.
extern string StringPrintf(const char* format, ...)
// Tell the compiler to do printf format string checking.
- PRINTF_ATTRIBUTE(1,2);
+ CERES_PRINTF_ATTRIBUTE(1,2);
// Store result into a supplied string and return it.
extern const string& SStringPrintf(string* dst, const char* format, ...)
// Tell the compiler to do printf format string checking.
- PRINTF_ATTRIBUTE(2,3);
+ CERES_PRINTF_ATTRIBUTE(2,3);
// Append result to a supplied string.
extern void StringAppendF(string* dst, const char* format, ...)
// Tell the compiler to do printf format string checking.
- PRINTF_ATTRIBUTE(2,3);
+ CERES_PRINTF_ATTRIBUTE(2,3);
// Lower-level routine that takes a va_list and appends to a specified string.
// All other routines are just convenience wrappers around it.
extern void StringAppendV(string* dst, const char* format, va_list ap);
-#undef PRINTF_ATTRIBUTE
+#undef CERES_PRINTF_ATTRIBUTE
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
index 1cf6a7496a7..cf3c48f84e6 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
@@ -29,15 +29,14 @@
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_NO_SUITESPARSE
-
#include "ceres/suitesparse.h"
+#include <vector>
#include "cholmod.h"
#include "ceres/compressed_row_sparse_matrix.h"
#include "ceres/triplet_sparse_matrix.h"
namespace ceres {
namespace internal {
-
cholmod_sparse* SuiteSparse::CreateSparseMatrix(TripletSparseMatrix* A) {
cholmod_triplet triplet;
@@ -111,6 +110,13 @@ cholmod_dense* SuiteSparse::CreateDenseVector(const double* x,
}
cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A) {
+ // Cholmod can try multiple re-ordering strategies to find a fill
+ // reducing ordering. Here we just tell it use AMD with automatic
+ // matrix dependence choice of supernodal versus simplicial
+ // factorization.
+ cc_.nmethods = 1;
+ cc_.method[0].ordering = CHOLMOD_AMD;
+ cc_.supernodal = CHOLMOD_AUTO;
cholmod_factor* factor = cholmod_analyze(A, &cc_);
CHECK_EQ(cc_.status, CHOLMOD_OK)
<< "Cholmod symbolic analysis failed " << cc_.status;
@@ -118,6 +124,153 @@ cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A) {
return factor;
}
+cholmod_factor* SuiteSparse::BlockAnalyzeCholesky(
+ cholmod_sparse* A,
+ const vector<int>& row_blocks,
+ const vector<int>& col_blocks) {
+ vector<int> ordering;
+ if (!BlockAMDOrdering(A, row_blocks, col_blocks, &ordering)) {
+ return NULL;
+ }
+ return AnalyzeCholeskyWithUserOrdering(A, ordering);
+}
+
+cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(cholmod_sparse* A,
+ const vector<int>& ordering) {
+ CHECK_EQ(ordering.size(), A->nrow);
+ cc_.nmethods = 1 ;
+ cc_.method[0].ordering = CHOLMOD_GIVEN;
+ cholmod_factor* factor =
+ cholmod_analyze_p(A, const_cast<int*>(&ordering[0]), NULL, 0, &cc_);
+ CHECK_EQ(cc_.status, CHOLMOD_OK)
+ << "Cholmod symbolic analysis failed " << cc_.status;
+ CHECK_NOTNULL(factor);
+ return factor;
+}
+
+bool SuiteSparse::BlockAMDOrdering(const cholmod_sparse* A,
+ const vector<int>& row_blocks,
+ const vector<int>& col_blocks,
+ vector<int>* ordering) {
+ const int num_row_blocks = row_blocks.size();
+ const int num_col_blocks = col_blocks.size();
+
+ // Arrays storing the compressed column structure of the matrix
+ // incoding the block sparsity of A.
+ vector<int> block_cols;
+ vector<int> block_rows;
+
+ ScalarMatrixToBlockMatrix(A,
+ row_blocks,
+ col_blocks,
+ &block_rows,
+ &block_cols);
+
+ cholmod_sparse_struct block_matrix;
+ block_matrix.nrow = num_row_blocks;
+ block_matrix.ncol = num_col_blocks;
+ block_matrix.nzmax = block_rows.size();
+ block_matrix.p = reinterpret_cast<void*>(&block_cols[0]);
+ block_matrix.i = reinterpret_cast<void*>(&block_rows[0]);
+ block_matrix.x = NULL;
+ block_matrix.stype = A->stype;
+ block_matrix.itype = CHOLMOD_INT;
+ block_matrix.xtype = CHOLMOD_PATTERN;
+ block_matrix.dtype = CHOLMOD_DOUBLE;
+ block_matrix.sorted = 1;
+ block_matrix.packed = 1;
+
+ vector<int> block_ordering(num_row_blocks);
+ if (!cholmod_amd(&block_matrix, NULL, 0, &block_ordering[0], &cc_)) {
+ return false;
+ }
+
+ BlockOrderingToScalarOrdering(row_blocks, block_ordering, ordering);
+ return true;
+}
+
+void SuiteSparse::ScalarMatrixToBlockMatrix(const cholmod_sparse* A,
+ const vector<int>& row_blocks,
+ const vector<int>& col_blocks,
+ vector<int>* block_rows,
+ vector<int>* block_cols) {
+ CHECK_NOTNULL(block_rows)->clear();
+ CHECK_NOTNULL(block_cols)->clear();
+ const int num_row_blocks = row_blocks.size();
+ const int num_col_blocks = col_blocks.size();
+
+ vector<int> row_block_starts(num_row_blocks);
+ for (int i = 0, cursor = 0; i < num_row_blocks; ++i) {
+ row_block_starts[i] = cursor;
+ cursor += row_blocks[i];
+ }
+
+ // The reinterpret_cast is needed here because CHOLMOD stores arrays
+ // as void*.
+ const int* scalar_cols = reinterpret_cast<const int*>(A->p);
+ const int* scalar_rows = reinterpret_cast<const int*>(A->i);
+
+ // This loop extracts the block sparsity of the scalar sparse matrix
+ // A. It does so by iterating over the columns, but only considering
+ // the columns corresponding to the first element of each column
+ // block. Within each column, the inner loop iterates over the rows,
+ // and detects the presence of a row block by checking for the
+ // presence of a non-zero entry corresponding to its first element.
+ block_cols->push_back(0);
+ int c = 0;
+ for (int col_block = 0; col_block < num_col_blocks; ++col_block) {
+ int column_size = 0;
+ for (int idx = scalar_cols[c]; idx < scalar_cols[c + 1]; ++idx) {
+ vector<int>::const_iterator it = lower_bound(row_block_starts.begin(),
+ row_block_starts.end(),
+ scalar_rows[idx]);
+ // Since we are using lower_bound, it will return the row id
+ // where the row block starts. For everything but the first row
+ // of the block, where these values will be the same, we can
+ // skip, as we only need the first row to detect the presence of
+ // the block.
+ //
+ // For rows all but the first row in the last row block,
+ // lower_bound will return row_block_starts.end(), but those can
+ // be skipped like the rows in other row blocks too.
+ if (it == row_block_starts.end() || *it != scalar_rows[idx]) {
+ continue;
+ }
+
+ block_rows->push_back(it - row_block_starts.begin());
+ ++column_size;
+ }
+ block_cols->push_back(block_cols->back() + column_size);
+ c += col_blocks[col_block];
+ }
+}
+
+void SuiteSparse::BlockOrderingToScalarOrdering(
+ const vector<int>& blocks,
+ const vector<int>& block_ordering,
+ vector<int>* scalar_ordering) {
+ CHECK_EQ(blocks.size(), block_ordering.size());
+ const int num_blocks = blocks.size();
+
+ // block_starts = [0, block1, block1 + block2 ..]
+ vector<int> block_starts(num_blocks);
+ for (int i = 0, cursor = 0; i < num_blocks ; ++i) {
+ block_starts[i] = cursor;
+ cursor += blocks[i];
+ }
+
+ scalar_ordering->resize(block_starts.back() + blocks.back());
+ int cursor = 0;
+ for (int i = 0; i < num_blocks; ++i) {
+ const int block_id = block_ordering[i];
+ const int block_size = blocks[block_id];
+ int block_position = block_starts[block_id];
+ for (int j = 0; j < block_size; ++j) {
+ (*scalar_ordering)[cursor++] = block_position++;
+ }
+ }
+}
+
bool SuiteSparse::Cholesky(cholmod_sparse* A, cholmod_factor* L) {
CHECK_NOTNULL(A);
CHECK_NOTNULL(L);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
index 091e67a69a9..eb691c0c0ed 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
@@ -37,6 +37,7 @@
#include <cstring>
#include <string>
+#include <vector>
#include <glog/logging.h>
#include "cholmod.h"
@@ -105,12 +106,35 @@ class SuiteSparse {
cholmod_sdmult(A, 0, alpha_, beta_, x, y, &cc_);
}
- // Analyze the sparsity structure of the matrix A compute the
- // symbolic factorization of A. A is not modified, only the pattern
- // of non-zeros of A is used, the actual numerical values in A are
- // of no consequence. Caller owns the result.
+ // Find an ordering of A or AA' (if A is unsymmetric) that minimizes
+ // the fill-in in the Cholesky factorization of the corresponding
+ // matrix. This is done by using the AMD algorithm.
+ //
+ // Using this ordering, the symbolic Cholesky factorization of A (or
+ // AA') is computed and returned.
+ //
+ // A is not modified, only the pattern of non-zeros of A is used,
+ // the actual numerical values in A are of no consequence.
+ //
+ // Caller owns the result.
cholmod_factor* AnalyzeCholesky(cholmod_sparse* A);
+ cholmod_factor* BlockAnalyzeCholesky(cholmod_sparse* A,
+ const vector<int>& row_blocks,
+ const vector<int>& col_blocks);
+
+ // If A is symmetric, then compute the symbolic Cholesky
+ // factorization of A(ordering, ordering). If A is unsymmetric, then
+ // compute the symbolic factorization of
+ // A(ordering,:) A(ordering,:)'.
+ //
+ // A is not modified, only the pattern of non-zeros of A is used,
+ // the actual numerical values in A are of no consequence.
+ //
+ // Caller owns the result.
+ cholmod_factor* AnalyzeCholeskyWithUserOrdering(cholmod_sparse* A,
+ const vector<int>& ordering);
+
// Use the symbolic factorization in L, to find the numerical
// factorization for the matrix A or AA^T. Return true if
// successful, false otherwise. L contains the numeric factorization
@@ -129,6 +153,56 @@ class SuiteSparse {
cholmod_factor* L,
cholmod_dense* b);
+ // By virtue of the modeling layer in Ceres being block oriented,
+ // all the matrices used by Ceres are also block oriented. When
+ // doing sparse direct factorization of these matrices the
+ // fill-reducing ordering algorithms (in particular AMD) can either
+ // be run on the block or the scalar form of these matrices. The two
+ // SuiteSparse::AnalyzeCholesky methods allows the the client to
+ // compute the symbolic factorization of a matrix by either using
+ // AMD on the matrix or a user provided ordering of the rows.
+ //
+ // But since the underlying matrices are block oriented, it is worth
+ // running AMD on just the block structre of these matrices and then
+ // lifting these block orderings to a full scalar ordering. This
+ // preserves the block structure of the permuted matrix, and exposes
+ // more of the super-nodal structure of the matrix to the numerical
+ // factorization routines.
+ //
+ // Find the block oriented AMD ordering of a matrix A, whose row and
+ // column blocks are given by row_blocks, and col_blocks
+ // respectively. The matrix may or may not be symmetric. The entries
+ // of col_blocks do not need to sum to the number of columns in
+ // A. If this is the case, only the first sum(col_blocks) are used
+ // to compute the ordering.
+ bool BlockAMDOrdering(const cholmod_sparse* A,
+ const vector<int>& row_blocks,
+ const vector<int>& col_blocks,
+ vector<int>* ordering);
+
+ // Given a set of blocks and a permutation of these blocks, compute
+ // the corresponding "scalar" ordering, where the scalar ordering of
+ // size sum(blocks).
+ static void BlockOrderingToScalarOrdering(const vector<int>& blocks,
+ const vector<int>& block_ordering,
+ vector<int>* scalar_ordering);
+
+ // Extract the block sparsity pattern of the scalar sparse matrix
+ // A and return it in compressed column form. The compressed column
+ // form is stored in two vectors block_rows, and block_cols, which
+ // correspond to the row and column arrays in a compressed column sparse
+ // matrix.
+ //
+ // If c_ij is the block in the matrix A corresponding to row block i
+ // and column block j, then it is expected that A contains at least
+ // one non-zero entry corresponding to the top left entry of c_ij,
+ // as that entry is used to detect the presence of a non-zero c_ij.
+ static void ScalarMatrixToBlockMatrix(const cholmod_sparse* A,
+ const vector<int>& row_blocks,
+ const vector<int>& col_blocks,
+ vector<int>* block_rows,
+ vector<int>* block_cols);
+
void Free(cholmod_sparse* m) { cholmod_free_sparse(&m, &cc_); }
void Free(cholmod_dense* m) { cholmod_free_dense(&m, &cc_); }
void Free(cholmod_factor* m) { cholmod_free_factor(&m, &cc_); }
diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc
index 247ab2e697b..ed8677ea18a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc
@@ -32,12 +32,12 @@
#include <algorithm>
#include <cstddef>
-#include <glog/logging.h>
-#include "ceres/matrix_proto.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/matrix_proto.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -82,7 +82,7 @@ TripletSparseMatrix::TripletSparseMatrix(const TripletSparseMatrix& orig)
CopyData(orig);
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
TripletSparseMatrix::TripletSparseMatrix(const SparseMatrixProto& outer_proto) {
CHECK(outer_proto.has_triplet_matrix());
@@ -130,7 +130,7 @@ bool TripletSparseMatrix::AllTripletsWithinBounds() const {
void TripletSparseMatrix::Reserve(int new_max_num_nonzeros) {
CHECK_LE(num_nonzeros_, new_max_num_nonzeros)
- << "Reallocation will cause data loss";
+ << "Reallocation will cause data loss";
// Nothing to do if we have enough space already.
if (new_max_num_nonzeros <= max_num_nonzeros_)
@@ -214,7 +214,7 @@ void TripletSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
}
}
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
void TripletSparseMatrix::ToProto(SparseMatrixProto *proto) const {
proto->Clear();
diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h
index 300e74d0bbc..89a645bd879 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h
@@ -50,7 +50,7 @@ class TripletSparseMatrix : public SparseMatrix {
TripletSparseMatrix();
TripletSparseMatrix(int num_rows, int num_cols, int max_num_nonzeros);
explicit TripletSparseMatrix(const TripletSparseMatrix& orig);
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
explicit TripletSparseMatrix(const SparseMatrixProto& proto);
#endif
@@ -65,7 +65,7 @@ class TripletSparseMatrix : public SparseMatrix {
virtual void SquaredColumnNorm(double* x) const;
virtual void ScaleColumns(const double* scale);
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
-#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
+#ifndef CERES_NO_PROTOCOL_BUFFERS
virtual void ToProto(SparseMatrixProto *proto) const;
#endif
virtual void ToTextFile(FILE* file) const;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
new file mode 100644
index 00000000000..76c4f8a7580
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
@@ -0,0 +1,550 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/trust_region_minimizer.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <cmath>
+#include <cstring>
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "Eigen/Core"
+#include "ceres/array_utils.h"
+#include "ceres/evaluator.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/linear_least_squares_problems.h"
+#include "ceres/sparse_matrix.h"
+#include "ceres/trust_region_strategy.h"
+#include "ceres/types.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+namespace {
+// Small constant for various floating point issues.
+const double kEpsilon = 1e-12;
+} // namespace
+
+// Execute the list of IterationCallbacks sequentially. If any one of
+// the callbacks does not return SOLVER_CONTINUE, then stop and return
+// its status.
+CallbackReturnType TrustRegionMinimizer::RunCallbacks(
+ const IterationSummary& iteration_summary) {
+ for (int i = 0; i < options_.callbacks.size(); ++i) {
+ const CallbackReturnType status =
+ (*options_.callbacks[i])(iteration_summary);
+ if (status != SOLVER_CONTINUE) {
+ return status;
+ }
+ }
+ return SOLVER_CONTINUE;
+}
+
+// Compute a scaling vector that is used to improve the conditioning
+// of the Jacobian.
+void TrustRegionMinimizer::EstimateScale(const SparseMatrix& jacobian,
+ double* scale) const {
+ jacobian.SquaredColumnNorm(scale);
+ for (int i = 0; i < jacobian.num_cols(); ++i) {
+ scale[i] = 1.0 / (kEpsilon + sqrt(scale[i]));
+ }
+}
+
+void TrustRegionMinimizer::Init(const Minimizer::Options& options) {
+ options_ = options;
+ sort(options_.lsqp_iterations_to_dump.begin(),
+ options_.lsqp_iterations_to_dump.end());
+}
+
+bool TrustRegionMinimizer::MaybeDumpLinearLeastSquaresProblem(
+ const int iteration,
+ const SparseMatrix* jacobian,
+ const double* residuals,
+ const double* step) const {
+ // TODO(sameeragarwal): Since the use of trust_region_radius has
+ // moved inside TrustRegionStrategy, its not clear how we dump the
+ // regularization vector/matrix anymore.
+ //
+ // Doing this right requires either an API change to the
+ // TrustRegionStrategy and/or how LinearLeastSquares problems are
+ // stored on disk.
+ //
+ // For now, we will just not dump the regularizer.
+ return (!binary_search(options_.lsqp_iterations_to_dump.begin(),
+ options_.lsqp_iterations_to_dump.end(),
+ iteration) ||
+ DumpLinearLeastSquaresProblem(options_.lsqp_dump_directory,
+ iteration,
+ options_.lsqp_dump_format_type,
+ jacobian,
+ NULL,
+ residuals,
+ step,
+ options_.num_eliminate_blocks));
+}
+
+void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
+ double* parameters,
+ Solver::Summary* summary) {
+ time_t start_time = time(NULL);
+ time_t iteration_start_time = start_time;
+ Init(options);
+
+ summary->termination_type = NO_CONVERGENCE;
+ summary->num_successful_steps = 0;
+ summary->num_unsuccessful_steps = 0;
+
+ Evaluator* evaluator = CHECK_NOTNULL(options_.evaluator);
+ SparseMatrix* jacobian = CHECK_NOTNULL(options_.jacobian);
+ TrustRegionStrategy* strategy = CHECK_NOTNULL(options_.trust_region_strategy);
+
+ const int num_parameters = evaluator->NumParameters();
+ const int num_effective_parameters = evaluator->NumEffectiveParameters();
+ const int num_residuals = evaluator->NumResiduals();
+
+ VectorRef x_min(parameters, num_parameters);
+ Vector x = x_min;
+ double x_norm = x.norm();
+
+ Vector residuals(num_residuals);
+ Vector trust_region_step(num_effective_parameters);
+ Vector delta(num_effective_parameters);
+ Vector x_plus_delta(num_parameters);
+ Vector gradient(num_effective_parameters);
+ Vector model_residuals(num_residuals);
+ Vector scale(num_effective_parameters);
+
+ IterationSummary iteration_summary;
+ iteration_summary.iteration = 0;
+ iteration_summary.step_is_valid = false;
+ iteration_summary.step_is_successful = false;
+ iteration_summary.cost = summary->initial_cost;
+ iteration_summary.cost_change = 0.0;
+ iteration_summary.gradient_max_norm = 0.0;
+ iteration_summary.step_norm = 0.0;
+ iteration_summary.relative_decrease = 0.0;
+ iteration_summary.trust_region_radius = strategy->Radius();
+ // TODO(sameeragarwal): Rename eta to linear_solver_accuracy or
+ // something similar across the board.
+ iteration_summary.eta = options_.eta;
+ iteration_summary.linear_solver_iterations = 0;
+ iteration_summary.step_solver_time_in_seconds = 0;
+
+ // Do initial cost and Jacobian evaluation.
+ double cost = 0.0;
+ if (!evaluator->Evaluate(x.data(), &cost, residuals.data(), NULL, jacobian)) {
+ LOG(WARNING) << "Terminating: Residual and Jacobian evaluation failed.";
+ summary->termination_type = NUMERICAL_FAILURE;
+ return;
+ }
+
+ int num_consecutive_nonmonotonic_steps = 0;
+ double minimum_cost = cost;
+ double reference_cost = cost;
+ double accumulated_reference_model_cost_change = 0.0;
+ double candidate_cost = cost;
+ double accumulated_candidate_model_cost_change = 0.0;
+
+ gradient.setZero();
+ jacobian->LeftMultiply(residuals.data(), gradient.data());
+ iteration_summary.gradient_max_norm = gradient.lpNorm<Eigen::Infinity>();
+
+ if (options_.jacobi_scaling) {
+ EstimateScale(*jacobian, scale.data());
+ jacobian->ScaleColumns(scale.data());
+ } else {
+ scale.setOnes();
+ }
+
+ // The initial gradient max_norm is bounded from below so that we do
+ // not divide by zero.
+ const double gradient_max_norm_0 =
+ max(iteration_summary.gradient_max_norm, kEpsilon);
+ const double absolute_gradient_tolerance =
+ options_.gradient_tolerance * gradient_max_norm_0;
+
+ if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
+ summary->termination_type = GRADIENT_TOLERANCE;
+ VLOG(1) << "Terminating: Gradient tolerance reached."
+ << "Relative gradient max norm: "
+ << iteration_summary.gradient_max_norm / gradient_max_norm_0
+ << " <= " << options_.gradient_tolerance;
+ return;
+ }
+
+ iteration_summary.iteration_time_in_seconds =
+ time(NULL) - iteration_start_time;
+ iteration_summary.cumulative_time_in_seconds = time(NULL) - start_time +
+ summary->preprocessor_time_in_seconds;
+ summary->iterations.push_back(iteration_summary);
+
+ // Call the various callbacks.
+ switch (RunCallbacks(iteration_summary)) {
+ case SOLVER_TERMINATE_SUCCESSFULLY:
+ summary->termination_type = USER_SUCCESS;
+ VLOG(1) << "Terminating: User callback returned USER_SUCCESS.";
+ return;
+ case SOLVER_ABORT:
+ summary->termination_type = USER_ABORT;
+ VLOG(1) << "Terminating: User callback returned USER_ABORT.";
+ return;
+ case SOLVER_CONTINUE:
+ break;
+ default:
+ LOG(FATAL) << "Unknown type of user callback status";
+ }
+
+ int num_consecutive_invalid_steps = 0;
+ while (true) {
+ iteration_start_time = time(NULL);
+ if (iteration_summary.iteration >= options_.max_num_iterations) {
+ summary->termination_type = NO_CONVERGENCE;
+ VLOG(1) << "Terminating: Maximum number of iterations reached.";
+ break;
+ }
+
+ const double total_solver_time = iteration_start_time - start_time +
+ summary->preprocessor_time_in_seconds;
+ if (total_solver_time >= options_.max_solver_time_in_seconds) {
+ summary->termination_type = NO_CONVERGENCE;
+ VLOG(1) << "Terminating: Maximum solver time reached.";
+ break;
+ }
+
+ iteration_summary = IterationSummary();
+ iteration_summary = summary->iterations.back();
+ iteration_summary.iteration = summary->iterations.back().iteration + 1;
+ iteration_summary.step_is_valid = false;
+ iteration_summary.step_is_successful = false;
+
+ const time_t strategy_start_time = time(NULL);
+ TrustRegionStrategy::PerSolveOptions per_solve_options;
+ per_solve_options.eta = options_.eta;
+ TrustRegionStrategy::Summary strategy_summary =
+ strategy->ComputeStep(per_solve_options,
+ jacobian,
+ residuals.data(),
+ trust_region_step.data());
+
+ iteration_summary.step_solver_time_in_seconds =
+ time(NULL) - strategy_start_time;
+ iteration_summary.linear_solver_iterations =
+ strategy_summary.num_iterations;
+
+ if (!MaybeDumpLinearLeastSquaresProblem(iteration_summary.iteration,
+ jacobian,
+ residuals.data(),
+ trust_region_step.data())) {
+ LOG(FATAL) << "Tried writing linear least squares problem: "
+ << options.lsqp_dump_directory << "but failed.";
+ }
+
+ double new_model_cost = 0.0;
+ if (strategy_summary.termination_type != FAILURE) {
+ // new_model_cost = 1/2 |f + J * step|^2
+ model_residuals = residuals;
+ jacobian->RightMultiply(trust_region_step.data(), model_residuals.data());
+ new_model_cost = model_residuals.squaredNorm() / 2.0;
+
+ // In exact arithmetic, this would never be the case. But poorly
+ // conditioned matrices can give rise to situations where the
+ // new_model_cost can actually be larger than half the squared
+ // norm of the residual vector. We allow for small tolerance
+ // around cost and beyond that declare the step to be invalid.
+ if ((1.0 - new_model_cost / cost) < -kEpsilon) {
+ VLOG(1) << "Invalid step: current_cost: " << cost
+ << " new_model_cost " << new_model_cost
+ << " absolute difference " << (cost - new_model_cost)
+ << " relative difference " << (1.0 - new_model_cost/cost);
+ } else {
+ iteration_summary.step_is_valid = true;
+ }
+ }
+
+ if (!iteration_summary.step_is_valid) {
+ // Invalid steps can happen due to a number of reasons, and we
+ // allow a limited number of successive failures, and return with
+ // NUMERICAL_FAILURE if this limit is exceeded.
+ if (++num_consecutive_invalid_steps >=
+ options_.max_num_consecutive_invalid_steps) {
+ summary->termination_type = NUMERICAL_FAILURE;
+ LOG(WARNING) << "Terminating. Number of successive invalid steps more "
+ << "than "
+ << "Solver::Options::max_num_consecutive_invalid_steps: "
+ << options_.max_num_consecutive_invalid_steps;
+ return;
+ }
+
+ // We are going to try and reduce the trust region radius and
+ // solve again. To do this, we are going to treat this iteration
+ // as an unsuccessful iteration. Since the various callbacks are
+ // still executed, we are going to fill the iteration summary
+ // with data that assumes a step of length zero and no progress.
+ iteration_summary.cost = cost;
+ iteration_summary.cost_change = 0.0;
+ iteration_summary.gradient_max_norm =
+ summary->iterations.back().gradient_max_norm;
+ iteration_summary.step_norm = 0.0;
+ iteration_summary.relative_decrease = 0.0;
+ iteration_summary.eta = options_.eta;
+ } else {
+ // The step is numerically valid, so now we can judge its quality.
+ num_consecutive_invalid_steps = 0;
+
+ // We allow some slop around 0, and clamp the model_cost_change
+ // at kEpsilon * min(1.0, cost) from below.
+ //
+ // In exact arithmetic this should never be needed, as we are
+ // guaranteed to new_model_cost <= cost. However, due to various
+ // numerical issues, it is possible that new_model_cost is
+ // nearly equal to cost, and the difference is a small negative
+ // number. To make sure that the relative_decrease computation
+ // remains sane, as clamp the difference (cost - new_model_cost)
+ // from below at a small positive number.
+ //
+ // This number is the minimum of kEpsilon * (cost, 1.0), which
+ // ensures that it will never get too large in absolute value,
+ // while scaling down proportionally with the magnitude of the
+ // cost. This is important for problems where the minimum of the
+ // objective function is near zero.
+ const double model_cost_change =
+ max(kEpsilon * min(1.0, cost), cost - new_model_cost);
+
+ // Undo the Jacobian column scaling.
+ delta = (trust_region_step.array() * scale.array()).matrix();
+ iteration_summary.step_norm = delta.norm();
+
+ // Convergence based on parameter_tolerance.
+ const double step_size_tolerance = options_.parameter_tolerance *
+ (x_norm + options_.parameter_tolerance);
+ if (iteration_summary.step_norm <= step_size_tolerance) {
+ VLOG(1) << "Terminating. Parameter tolerance reached. "
+ << "relative step_norm: "
+ << iteration_summary.step_norm /
+ (x_norm + options_.parameter_tolerance)
+ << " <= " << options_.parameter_tolerance;
+ summary->termination_type = PARAMETER_TOLERANCE;
+ return;
+ }
+
+ if (!evaluator->Plus(x.data(), delta.data(), x_plus_delta.data())) {
+ summary->termination_type = NUMERICAL_FAILURE;
+ LOG(WARNING) << "Terminating. Failed to compute "
+ << "Plus(x, delta, x_plus_delta).";
+ return;
+ }
+
+ // Try this step.
+ double new_cost;
+ if (!evaluator->Evaluate(x_plus_delta.data(),
+ &new_cost,
+ NULL, NULL, NULL)) {
+ // If the evaluation of the new cost fails, treat it as a step
+ // with high cost.
+ LOG(WARNING) << "Step failed to evaluate. "
+ << "Treating it as step with infinite cost";
+ new_cost = numeric_limits<double>::max();
+ }
+
+ VLOG(2) << "old cost: " << cost << " new cost: " << new_cost;
+ iteration_summary.cost_change = cost - new_cost;
+ const double absolute_function_tolerance =
+ options_.function_tolerance * cost;
+ if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) {
+ VLOG(1) << "Terminating. Function tolerance reached. "
+ << "|cost_change|/cost: "
+ << fabs(iteration_summary.cost_change) / cost
+ << " <= " << options_.function_tolerance;
+ summary->termination_type = FUNCTION_TOLERANCE;
+ return;
+ }
+
+ const double relative_decrease =
+ iteration_summary.cost_change / model_cost_change;
+
+ const double historical_relative_decrease =
+ (reference_cost - new_cost) /
+ (accumulated_reference_model_cost_change + model_cost_change);
+
+ // If monotonic steps are being used, then the relative_decrease
+ // is the usual ratio of the change in objective function value
+ // divided by the change in model cost.
+ //
+ // If non-monotonic steps are allowed, then we take the maximum
+ // of the relative_decrease and the
+ // historical_relative_decrease, which measures the increase
+ // from a reference iteration. The model cost change is
+ // estimated by accumulating the model cost changes since the
+ // reference iteration. The historical relative_decrease offers
+ // a boost to a step which is not too bad compared to the
+ // reference iteration, allowing for non-monotonic steps.
+ iteration_summary.relative_decrease =
+ options.use_nonmonotonic_steps
+ ? max(relative_decrease, historical_relative_decrease)
+ : relative_decrease;
+
+ iteration_summary.step_is_successful =
+ iteration_summary.relative_decrease > options_.min_relative_decrease;
+
+ if (iteration_summary.step_is_successful) {
+ accumulated_candidate_model_cost_change += model_cost_change;
+ accumulated_reference_model_cost_change += model_cost_change;
+ if (relative_decrease <= options_.min_relative_decrease) {
+ VLOG(2) << "Non-monotonic step! "
+ << " relative_decrease: " << relative_decrease
+ << " historical_relative_decrease: "
+ << historical_relative_decrease;
+ }
+ }
+ }
+
+ if (iteration_summary.step_is_successful) {
+ ++summary->num_successful_steps;
+ strategy->StepAccepted(iteration_summary.relative_decrease);
+ x = x_plus_delta;
+ x_norm = x.norm();
+
+ // Step looks good, evaluate the residuals and Jacobian at this
+ // point.
+ if (!evaluator->Evaluate(x.data(),
+ &cost,
+ residuals.data(),
+ NULL,
+ jacobian)) {
+ summary->termination_type = NUMERICAL_FAILURE;
+ LOG(WARNING) << "Terminating: Residual and Jacobian evaluation failed.";
+ return;
+ }
+
+ gradient.setZero();
+ jacobian->LeftMultiply(residuals.data(), gradient.data());
+ iteration_summary.gradient_max_norm = gradient.lpNorm<Eigen::Infinity>();
+
+ if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
+ summary->termination_type = GRADIENT_TOLERANCE;
+ VLOG(1) << "Terminating: Gradient tolerance reached."
+ << "Relative gradient max norm: "
+ << iteration_summary.gradient_max_norm / gradient_max_norm_0
+ << " <= " << options_.gradient_tolerance;
+ return;
+ }
+
+ if (options_.jacobi_scaling) {
+ jacobian->ScaleColumns(scale.data());
+ }
+
+ // Update the best, reference and candidate iterates.
+ //
+ // Based on algorithm 10.1.2 (page 357) of "Trust Region
+ // Methods" by Conn Gould & Toint, or equations 33-40 of
+ // "Non-monotone trust-region algorithms for nonlinear
+ // optimization subject to convex constraints" by Phil Toint,
+ // Mathematical Programming, 77, 1997.
+ if (cost < minimum_cost) {
+ // A step that improves solution quality was found.
+ x_min = x;
+ minimum_cost = cost;
+ // Set the candidate iterate to the current point.
+ candidate_cost = cost;
+ num_consecutive_nonmonotonic_steps = 0;
+ accumulated_candidate_model_cost_change = 0.0;
+ } else {
+ ++num_consecutive_nonmonotonic_steps;
+ if (cost > candidate_cost) {
+ // The current iterate is has a higher cost than the
+ // candidate iterate. Set the candidate to this point.
+ VLOG(2) << "Updating the candidate iterate to the current point.";
+ candidate_cost = cost;
+ accumulated_candidate_model_cost_change = 0.0;
+ }
+
+ // At this point we have made too many non-monotonic steps and
+ // we are going to reset the value of the reference iterate so
+ // as to force the algorithm to descend.
+ //
+ // This is the case because the candidate iterate has a value
+ // greater than minimum_cost but smaller than the reference
+ // iterate.
+ if (num_consecutive_nonmonotonic_steps ==
+ options.max_consecutive_nonmonotonic_steps) {
+ VLOG(2) << "Resetting the reference point to the candidate point";
+ reference_cost = candidate_cost;
+ accumulated_reference_model_cost_change =
+ accumulated_candidate_model_cost_change;
+ }
+ }
+ } else {
+ ++summary->num_unsuccessful_steps;
+ if (iteration_summary.step_is_valid) {
+ strategy->StepRejected(iteration_summary.relative_decrease);
+ } else {
+ strategy->StepIsInvalid();
+ }
+ }
+
+ iteration_summary.cost = cost + summary->fixed_cost;
+ iteration_summary.trust_region_radius = strategy->Radius();
+ if (iteration_summary.trust_region_radius <
+ options_.min_trust_region_radius) {
+ summary->termination_type = PARAMETER_TOLERANCE;
+ VLOG(1) << "Termination. Minimum trust region radius reached.";
+ return;
+ }
+
+ iteration_summary.iteration_time_in_seconds =
+ time(NULL) - iteration_start_time;
+ iteration_summary.cumulative_time_in_seconds = time(NULL) - start_time +
+ summary->preprocessor_time_in_seconds;
+ summary->iterations.push_back(iteration_summary);
+
+ switch (RunCallbacks(iteration_summary)) {
+ case SOLVER_TERMINATE_SUCCESSFULLY:
+ summary->termination_type = USER_SUCCESS;
+ VLOG(1) << "Terminating: User callback returned USER_SUCCESS.";
+ return;
+ case SOLVER_ABORT:
+ summary->termination_type = USER_ABORT;
+ VLOG(1) << "Terminating: User callback returned USER_ABORT.";
+ return;
+ case SOLVER_CONTINUE:
+ break;
+ default:
+ LOG(FATAL) << "Unknown type of user callback status";
+ }
+ }
+}
+
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h
new file mode 100644
index 00000000000..a4f5ba3674d
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_
+#define CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_
+
+#include "ceres/minimizer.h"
+#include "ceres/solver.h"
+#include "ceres/types.h"
+
+namespace ceres {
+namespace internal {
+
+// Generic trust region minimization algorithm. The heavy lifting is
+// done by a TrustRegionStrategy object passed in as one of the
+// arguments to the Minimize method.
+//
+// For example usage, see SolverImpl::Minimize.
+class TrustRegionMinimizer : public Minimizer {
+ public:
+ ~TrustRegionMinimizer() {}
+ virtual void Minimize(const Minimizer::Options& options,
+ double* parameters,
+ Solver::Summary* summary);
+
+ private:
+ void Init(const Minimizer::Options& options);
+ void EstimateScale(const SparseMatrix& jacobian, double* scale) const;
+ CallbackReturnType RunCallbacks(const IterationSummary& iteration_summary);
+ bool MaybeDumpLinearLeastSquaresProblem( const int iteration,
+ const SparseMatrix* jacobian,
+ const double* residuals,
+ const double* step) const;
+
+ Minimizer::Options options_;
+};
+
+} // namespace internal
+} // namespace ceres
+#endif // CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc
new file mode 100644
index 00000000000..89bc19d084b
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc
@@ -0,0 +1,27 @@
+#include "ceres/trust_region_strategy.h"
+#include "ceres/dogleg_strategy.h"
+#include "ceres/levenberg_marquardt_strategy.h"
+
+namespace ceres {
+namespace internal {
+
+TrustRegionStrategy::~TrustRegionStrategy() {}
+
+TrustRegionStrategy* TrustRegionStrategy::Create(const Options& options) {
+ switch (options.trust_region_strategy_type) {
+ case LEVENBERG_MARQUARDT:
+ return new LevenbergMarquardtStrategy(options);
+ case DOGLEG:
+ return new DoglegStrategy(options);
+ default:
+ LOG(FATAL) << "Unknown trust region strategy: "
+ << options.trust_region_strategy_type;
+ }
+
+ LOG(FATAL) << "Unknown trust region strategy: "
+ << options.trust_region_strategy_type;
+ return NULL;
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h
new file mode 100644
index 00000000000..391da97d5eb
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h
@@ -0,0 +1,148 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_TRUST_REGION_STRATEGY_H_
+#define CERES_INTERNAL_TRUST_REGION_STRATEGY_H_
+
+#include "ceres/types.h"
+
+namespace ceres {
+namespace internal {
+
+class LinearSolver;
+class SparseMatrix;
+
+// Interface for classes implementing various trust region strategies
+// for nonlinear least squares problems.
+//
+// The object is expected to maintain and update a trust region
+// radius, which it then uses to solve for the trust region step using
+// the jacobian matrix and residual vector.
+//
+// Here the term trust region radius is used loosely, as the strategy
+// is free to treat it as guidance and violate it as need be. e.g.,
+// the LevenbergMarquardtStrategy uses the inverse of the trust region
+// radius to scale the damping term, which controls the step size, but
+// does not set a hard limit on its size.
+class TrustRegionStrategy {
+public:
+ struct Options {
+ Options()
+ : trust_region_strategy_type(LEVENBERG_MARQUARDT),
+ initial_radius(1e4),
+ max_radius(1e32),
+ lm_min_diagonal(1e-6),
+ lm_max_diagonal(1e32),
+ dogleg_type(TRADITIONAL_DOGLEG) {
+ }
+
+ TrustRegionStrategyType trust_region_strategy_type;
+ // Linear solver used for actually solving the trust region step.
+ LinearSolver* linear_solver;
+ double initial_radius;
+ double max_radius;
+
+ // Minimum and maximum values of the diagonal damping matrix used
+ // by LevenbergMarquardtStrategy. The DoglegStrategy also uses
+ // these bounds to construct a regularizing diagonal to ensure
+ // that the Gauss-Newton step computation is of full rank.
+ double lm_min_diagonal;
+ double lm_max_diagonal;
+
+ // Further specify which dogleg method to use
+ DoglegType dogleg_type;
+ };
+
+ // Per solve options.
+ struct PerSolveOptions {
+ // Forcing sequence for inexact solves.
+ double eta;
+ };
+
+ struct Summary {
+ Summary()
+ : residual_norm(0.0),
+ num_iterations(-1),
+ termination_type(FAILURE) {
+ }
+
+ // If the trust region problem is,
+ //
+ // 1/2 x'Ax + b'x + c,
+ //
+ // then
+ //
+ // residual_norm = |Ax -b|
+ double residual_norm;
+
+ // Number of iterations used by the linear solver. If a linear
+ // solver was not called (e.g., DogLegStrategy after an
+ // unsuccessful step), then this would be zero.
+ int num_iterations;
+
+ // Status of the linear solver used to solve the Newton system.
+ LinearSolverTerminationType termination_type;
+ };
+
+ virtual ~TrustRegionStrategy();
+
+ // Use the current radius to solve for the trust region step.
+ virtual Summary ComputeStep(const PerSolveOptions& per_solve_options,
+ SparseMatrix* jacobian,
+ const double* residuals,
+ double* step) = 0;
+
+ // Inform the strategy that the current step has been accepted, and
+ // that the ratio of the decrease in the non-linear objective to the
+ // decrease in the trust region model is step_quality.
+ virtual void StepAccepted(double step_quality) = 0;
+
+ // Inform the strategy that the current step has been rejected, and
+ // that the ratio of the decrease in the non-linear objective to the
+ // decrease in the trust region model is step_quality.
+ virtual void StepRejected(double step_quality) = 0;
+
+ // Inform the strategy that the current step has been rejected
+ // because it was found to be numerically invalid.
+ // StepRejected/StepAccepted will not be called for this step, and
+ // the strategy is free to do what it wants with this information.
+ virtual void StepIsInvalid() = 0;
+
+ // Current trust region radius.
+ virtual double Radius() const = 0;
+
+ // Factory.
+ static TrustRegionStrategy* Create(const Options& options);
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_TRUST_REGION_STRATEGY_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/types.cc b/extern/libmv/third_party/ceres/internal/ceres/types.cc
index 860f8a43f37..05e573ff6d5 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/types.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/types.cc
@@ -37,8 +37,9 @@ namespace ceres {
const char* LinearSolverTypeToString(LinearSolverType solver_type) {
switch (solver_type) {
- CASESTR(SPARSE_NORMAL_CHOLESKY);
+ CASESTR(DENSE_NORMAL_CHOLESKY);
CASESTR(DENSE_QR);
+ CASESTR(SPARSE_NORMAL_CHOLESKY);
CASESTR(DENSE_SCHUR);
CASESTR(SPARSE_SCHUR);
CASESTR(ITERATIVE_SCHUR);
@@ -61,6 +62,16 @@ const char* PreconditionerTypeToString(
}
}
+const char* SparseLinearAlgebraLibraryTypeToString(
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) {
+ switch (sparse_linear_algebra_library_type) {
+ CASESTR(SUITE_SPARSE);
+ CASESTR(CX_SPARSE);
+ default:
+ return "UNKNOWN";
+ }
+}
+
const char* OrderingTypeToString(OrderingType ordering_type) {
switch (ordering_type) {
CASESTR(NATURAL);
@@ -87,6 +98,28 @@ const char* SolverTerminationTypeToString(
}
}
+#if 0 /* UNUSED */
+static const char* SparseLinearAlgebraTypeToString(
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) {
+ switch (sparse_linear_algebra_library_type) {
+ CASESTR(CX_SPARSE);
+ CASESTR(SUITE_SPARSE);
+ default:
+ return "UNKNOWN";
+ }
+}
+#endif
+
+const char* TrustRegionStrategyTypeToString(
+ TrustRegionStrategyType trust_region_strategy_type) {
+ switch (trust_region_strategy_type) {
+ CASESTR(LEVENBERG_MARQUARDT);
+ CASESTR(DOGLEG);
+ default:
+ return "UNKNOWN";
+ }
+}
+
#undef CASESTR
bool IsSchurType(LinearSolverType type) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc
index fd41648a7af..564cc54493e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc
@@ -34,11 +34,11 @@
#include <set>
#include <vector>
#include <utility>
-
-#include <glog/logging.h>
#include "ceres/block_structure.h"
#include "ceres/collections_port.h"
+#include "ceres/visibility.h"
#include "ceres/graph.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
index aca77528215..4caad03d7a1 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
@@ -33,11 +33,9 @@
#include <algorithm>
#include <functional>
#include <iterator>
-#include <numeric>
#include <set>
#include <utility>
#include <vector>
-#include <glog/logging.h>
#include "Eigen/Dense"
#include "ceres/block_random_access_sparse_matrix.h"
#include "ceres/block_sparse_matrix.h"
@@ -46,10 +44,11 @@
#include "ceres/detect_structure.h"
#include "ceres/graph.h"
#include "ceres/graph_algorithms.h"
+#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_solver.h"
#include "ceres/schur_eliminator.h"
#include "ceres/visibility.h"
-#include "ceres/internal/scoped_ptr.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -253,7 +252,6 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner(
}
int r = 0;
- set<pair<int, int> > skipped_pairs;
const int num_row_blocks = bs.rows.size();
const int num_eliminate_blocks = options_.num_eliminate_blocks;
@@ -304,8 +302,6 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner(
for (; block2 != f_blocks.end(); ++block2) {
if (IsBlockPairInPreconditioner(*block1, *block2)) {
block_pairs_.insert(make_pair(*block1, *block2));
- } else {
- skipped_pairs.insert(make_pair(*block1, *block2));
}
}
}
@@ -322,17 +318,13 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner(
if (block1 <= block2) {
if (IsBlockPairInPreconditioner(block1, block2)) {
block_pairs_.insert(make_pair(block1, block2));
- } else {
- skipped_pairs.insert(make_pair(block1, block2));
}
}
}
}
}
- VLOG(1) << "Block pair stats: "
- << block_pairs_.size() << " included "
- << skipped_pairs.size() << " excluded";
+ VLOG(1) << "Block pair stats: " << block_pairs_.size();
}
// Initialize the SchurEliminator.
@@ -341,7 +333,6 @@ void VisibilityBasedPreconditioner::InitEliminator(
LinearSolver::Options eliminator_options;
eliminator_options.num_eliminate_blocks = options_.num_eliminate_blocks;
eliminator_options.num_threads = options_.num_threads;
- eliminator_options.constant_sparsity = true;
DetectStructure(bs, options_.num_eliminate_blocks,
&eliminator_options.row_block_size,
@@ -352,9 +343,9 @@ void VisibilityBasedPreconditioner::InitEliminator(
eliminator_->Init(options_.num_eliminate_blocks, &bs);
}
-// Compute the values of the preconditioner matrix and factorize it.
-bool VisibilityBasedPreconditioner::Compute(const BlockSparseMatrixBase& A,
- const double* D) {
+// Update the values of the preconditioner matrix and factorize it.
+bool VisibilityBasedPreconditioner::Update(const BlockSparseMatrixBase& A,
+ const double* D) {
const time_t start_time = time(NULL);
const int num_rows = m_->num_rows();
CHECK_GT(num_rows, 0);
@@ -448,12 +439,21 @@ bool VisibilityBasedPreconditioner::Factorize() {
// matrix contains the values.
lhs->stype = 1;
- // Symbolic factorization is computed if we don't already have one
- // handy.
+ // Symbolic factorization is computed if we don't already have one handy.
if (factor_ == NULL) {
- factor_ = ss_.AnalyzeCholesky(lhs);
+ if (options_.use_block_amd) {
+ factor_ = ss_.BlockAnalyzeCholesky(lhs, block_size_, block_size_);
+ } else {
+ factor_ = ss_.AnalyzeCholesky(lhs);
+ }
+
+ if (VLOG_IS_ON(2)) {
+ cholmod_print_common("Symbolic Analysis", ss_.mutable_cc());
+ }
}
+ CHECK_NOTNULL(factor_);
+
bool status = ss_.Cholesky(lhs, factor_);
ss_.Free(lhs);
return status;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
index fa095ca1dd8..888c65eba3a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
@@ -133,7 +133,7 @@ class SchurEliminatorBase;
// options.num_eliminate_blocks = num_points;
// VisibilityBasedPreconditioner preconditioner(
// *A.block_structure(), options);
-// preconditioner.Compute(A, NULL);
+// preconditioner.Update(A, NULL);
// preconditioner.RightMultiply(x, y);
//
@@ -160,7 +160,7 @@ class VisibilityBasedPreconditioner : public LinearOperator {
const LinearSolver::Options& options);
virtual ~VisibilityBasedPreconditioner();
- // Compute the numerical value of the preconditioner for the linear
+ // Update the numerical value of the preconditioner for the linear
// system:
//
// | A | x = |b|
@@ -171,12 +171,12 @@ class VisibilityBasedPreconditioner : public LinearOperator {
//
// D can be NULL, in which case its interpreted as a diagonal matrix
// of size zero.
- bool Compute(const BlockSparseMatrixBase& A,
- const double* D);
+ bool Update(const BlockSparseMatrixBase& A, const double* D);
+
// LinearOperator interface. Since the operator is symmetric,
// LeftMultiply and num_cols are just calls to RightMultiply and
- // num_rows respectively. Compute() must be called before
+ // num_rows respectively. Update() must be called before
// RightMultiply can be called.
virtual void RightMultiply(const double* x, double* y) const;
virtual void LeftMultiply(const double* x, double* y) const {
@@ -244,7 +244,7 @@ class VisibilityBasedPreconditioner : public LinearOperator {
// Temporary vector used by RightMultiply.
cholmod_dense* tmp_rhs_;
- DISALLOW_COPY_AND_ASSIGN(VisibilityBasedPreconditioner);
+ CERES_DISALLOW_COPY_AND_ASSIGN(VisibilityBasedPreconditioner);
};
#else // SuiteSparse
// If SuiteSparse is not compiled in, the preconditioner is not
@@ -261,7 +261,7 @@ class VisibilityBasedPreconditioner : public LinearOperator {
virtual void LeftMultiply(const double* x, double* y) const {}
virtual int num_rows() const { return -1; }
virtual int num_cols() const { return -1; }
- bool Compute(const BlockSparseMatrixBase& A, const double* D) {
+ bool Update(const BlockSparseMatrixBase& A, const double* D) {
return false;
}
};
diff --git a/extern/libmv/third_party/ceres/mkfiles.sh b/extern/libmv/third_party/ceres/mkfiles.sh
index d335829aa2c..d335829aa2c 100755..100644
--- a/extern/libmv/third_party/ceres/mkfiles.sh
+++ b/extern/libmv/third_party/ceres/mkfiles.sh
diff --git a/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch b/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch
index bbb366e22bc..c01a17c7992 100644
--- a/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch
+++ b/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch
@@ -1,10 +1,10 @@
-Index: internal/ceres/collections_port.h
-===================================================================
---- internal/ceres/collections_port.h (revision 47730)
-+++ internal/ceres/collections_port.h (working copy)
-@@ -53,7 +53,7 @@
+diff --git a/internal/ceres/collections_port.h b/internal/ceres/collections_port.h
+index a356cc0..c2fce90 100644
+--- a/internal/ceres/collections_port.h
++++ b/internal/ceres/collections_port.h
+@@ -77,7 +77,7 @@ struct HashMap : std::tr1::unordered_map<K, V> {};
template<typename K>
- struct HashSet : tr1::unordered_set<K> {};
+ struct HashSet : std::tr1::unordered_set<K> {};
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__)
diff --git a/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch b/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch
new file mode 100644
index 00000000000..f3200fb8e0a
--- /dev/null
+++ b/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch
@@ -0,0 +1,50 @@
+diff --git a/internal/ceres/block_random_access_dense_matrix.cc b/internal/ceres/block_random_access_dense_matrix.cc
+index aedfc74..0f95e89 100644
+--- a/internal/ceres/block_random_access_dense_matrix.cc
++++ b/internal/ceres/block_random_access_dense_matrix.cc
+@@ -28,12 +28,12 @@
+ //
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
+
++#include "glog/logging.h"
+ #include "ceres/block_random_access_dense_matrix.h"
+
+ #include <vector>
+ #include "ceres/internal/eigen.h"
+ #include "ceres/internal/scoped_ptr.h"
+-#include "glog/logging.h"
+
+ namespace ceres {
+ namespace internal {
+diff --git a/internal/ceres/block_random_access_sparse_matrix.cc b/internal/ceres/block_random_access_sparse_matrix.cc
+index f789436..9ed62ce 100644
+--- a/internal/ceres/block_random_access_sparse_matrix.cc
++++ b/internal/ceres/block_random_access_sparse_matrix.cc
+@@ -28,6 +28,7 @@
+ //
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
+
++#include "glog/logging.h"
+ #include "ceres/block_random_access_sparse_matrix.h"
+
+ #include <algorithm>
+@@ -39,7 +40,6 @@
+ #include "ceres/mutex.h"
+ #include "ceres/triplet_sparse_matrix.h"
+ #include "ceres/types.h"
+-#include "glog/logging.h"
+
+ namespace ceres {
+ namespace internal {
+diff --git a/internal/ceres/schur_complement_solver.cc b/internal/ceres/schur_complement_solver.cc
+index b9224d8..2cbe78d 100644
+--- a/internal/ceres/schur_complement_solver.cc
++++ b/internal/ceres/schur_complement_solver.cc
+@@ -38,6 +38,7 @@
+ #endif // CERES_NO_CXSPARSE
+
+ #include "Eigen/Dense"
++#include "glog/logging.h"
+ #include "ceres/block_random_access_dense_matrix.h"
+ #include "ceres/block_random_access_matrix.h"
+ #include "ceres/block_random_access_sparse_matrix.h"
diff --git a/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch b/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch
deleted file mode 100644
index c3129d8e02b..00000000000
--- a/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git a/internal/ceres/residual_block_utils.cc b/internal/ceres/residual_block_utils.cc
-index ed3499b..28e0313 100644
---- a/internal/ceres/residual_block_utils.cc
-+++ b/internal/ceres/residual_block_utils.cc
-@@ -40,6 +40,10 @@
- #include "ceres/internal/eigen.h"
- #include "ceres/internal/port.h"
-
-+#ifdef _MSC_VER
-+# define isfinite _finite
-+#endif
-+
- namespace ceres {
- namespace internal {
-
diff --git a/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch b/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch
new file mode 100644
index 00000000000..03f1c500d9a
--- /dev/null
+++ b/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch
@@ -0,0 +1,199 @@
+diff --git a/internal/ceres/file.cc b/internal/ceres/file.cc
+index 387f359..6fe7557 100644
+--- a/internal/ceres/file.cc
++++ b/internal/ceres/file.cc
+@@ -31,6 +31,7 @@
+ // Really simple file IO.
+
+ #include <cstdio>
++#include "file.h"
+ #include "glog/logging.h"
+
+ namespace ceres {
+diff --git a/internal/ceres/linear_least_squares_problems.cc b/internal/ceres/linear_least_squares_problems.cc
+index 3e3bcd0..a91e254 100644
+--- a/internal/ceres/linear_least_squares_problems.cc
++++ b/internal/ceres/linear_least_squares_problems.cc
+@@ -573,13 +573,13 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() {
+ return problem;
+ }
+
+-bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
+- int iteration,
+- const SparseMatrix* A,
+- const double* D,
+- const double* b,
+- const double* x,
+- int num_eliminate_blocks) {
++static bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
++ int iteration,
++ const SparseMatrix* A,
++ const double* D,
++ const double* b,
++ const double* x,
++ int num_eliminate_blocks) {
+ CHECK_NOTNULL(A);
+ Matrix AA;
+ A->ToDenseMatrix(&AA);
+@@ -601,13 +601,13 @@ bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
+ };
+
+ #ifndef CERES_NO_PROTOCOL_BUFFERS
+-bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
+- int iteration,
+- const SparseMatrix* A,
+- const double* D,
+- const double* b,
+- const double* x,
+- int num_eliminate_blocks) {
++static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
++ int iteration,
++ const SparseMatrix* A,
++ const double* D,
++ const double* b,
++ const double* x,
++ int num_eliminate_blocks) {
+ CHECK_NOTNULL(A);
+ LinearLeastSquaresProblemProto lsqp;
+ A->ToProto(lsqp.mutable_a());
+@@ -641,13 +641,13 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
+ return true;
+ }
+ #else
+-bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
+- int iteration,
+- const SparseMatrix* A,
+- const double* D,
+- const double* b,
+- const double* x,
+- int num_eliminate_blocks) {
++static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
++ int iteration,
++ const SparseMatrix* A,
++ const double* D,
++ const double* b,
++ const double* x,
++ int num_eliminate_blocks) {
+ LOG(ERROR) << "Dumping least squares problems is only "
+ << "supported when Ceres is compiled with "
+ << "protocol buffer support.";
+@@ -655,9 +655,9 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
+ }
+ #endif
+
+-void WriteArrayToFileOrDie(const string& filename,
+- const double* x,
+- const int size) {
++static void WriteArrayToFileOrDie(const string& filename,
++ const double* x,
++ const int size) {
+ CHECK_NOTNULL(x);
+ VLOG(2) << "Writing array to: " << filename;
+ FILE* fptr = fopen(filename.c_str(), "w");
+@@ -668,13 +668,13 @@ void WriteArrayToFileOrDie(const string& filename,
+ fclose(fptr);
+ }
+
+-bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
+- int iteration,
+- const SparseMatrix* A,
+- const double* D,
+- const double* b,
+- const double* x,
+- int num_eliminate_blocks) {
++static bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
++ int iteration,
++ const SparseMatrix* A,
++ const double* D,
++ const double* b,
++ const double* x,
++ int num_eliminate_blocks) {
+ CHECK_NOTNULL(A);
+ string format_string = JoinPath(directory,
+ "lm_iteration_%03d");
+diff --git a/internal/ceres/residual_block_utils.cc b/internal/ceres/residual_block_utils.cc
+index ff18e21..9442bb2 100644
+--- a/internal/ceres/residual_block_utils.cc
++++ b/internal/ceres/residual_block_utils.cc
+@@ -63,7 +63,7 @@ void InvalidateEvaluation(const ResidualBlock& block,
+
+ // Utility routine to print an array of doubles to a string. If the
+ // array pointer is NULL, it is treated as an array of zeros.
+-void AppendArrayToString(const int size, const double* x, string* result) {
++static void AppendArrayToString(const int size, const double* x, string* result) {
+ for (int i = 0; i < size; ++i) {
+ if (x == NULL) {
+ StringAppendF(result, "Not Computed ");
+diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc
+index 2802a75..8ef5b98 100644
+--- a/internal/ceres/solver_impl.cc
++++ b/internal/ceres/solver_impl.cc
+@@ -685,8 +685,8 @@ bool SolverImpl::ApplyUserOrdering(const ProblemImpl& problem_impl,
+ // Find the minimum index of any parameter block to the given residual.
+ // Parameter blocks that have indices greater than num_eliminate_blocks are
+ // considered to have an index equal to num_eliminate_blocks.
+-int MinParameterBlock(const ResidualBlock* residual_block,
+- int num_eliminate_blocks) {
++static int MinParameterBlock(const ResidualBlock* residual_block,
++ int num_eliminate_blocks) {
+ int min_parameter_block_position = num_eliminate_blocks;
+ for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) {
+ ParameterBlock* parameter_block = residual_block->parameter_blocks()[i];
+diff --git a/internal/ceres/split.cc b/internal/ceres/split.cc
+index 4fa1bd4..c65c8a5 100644
+--- a/internal/ceres/split.cc
++++ b/internal/ceres/split.cc
+@@ -31,6 +31,7 @@
+ #include <string>
+ #include <vector>
+ #include <iterator>
++#include "ceres/split.h"
+ #include "ceres/internal/port.h"
+
+ namespace ceres {
+diff --git a/internal/ceres/stringprintf.cc b/internal/ceres/stringprintf.cc
+index c0f3522..396a48b 100644
+--- a/internal/ceres/stringprintf.cc
++++ b/internal/ceres/stringprintf.cc
+@@ -34,6 +34,7 @@
+ #include <string>
+ #include <vector>
+
++#include "ceres/stringprintf.h"
+ #include "ceres/internal/port.h"
+
+ namespace ceres {
+diff --git a/internal/ceres/types.cc b/internal/ceres/types.cc
+index 2e950c5..05e573f 100644
+--- a/internal/ceres/types.cc
++++ b/internal/ceres/types.cc
+@@ -98,7 +98,8 @@ const char* SolverTerminationTypeToString(
+ }
+ }
+
+-const char* SparseLinearAlgebraTypeToString(
++#if 0 /* UNUSED */
++static const char* SparseLinearAlgebraTypeToString(
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) {
+ switch (sparse_linear_algebra_library_type) {
+ CASESTR(CX_SPARSE);
+@@ -107,6 +108,7 @@ const char* SparseLinearAlgebraTypeToString(
+ return "UNKNOWN";
+ }
+ }
++#endif
+
+ const char* TrustRegionStrategyTypeToString(
+ TrustRegionStrategyType trust_region_strategy_type) {
+diff --git a/internal/ceres/visibility.cc b/internal/ceres/visibility.cc
+index 9d80654..564cc54 100644
+--- a/internal/ceres/visibility.cc
++++ b/internal/ceres/visibility.cc
+@@ -36,6 +36,7 @@
+ #include <utility>
+ #include "ceres/block_structure.h"
+ #include "ceres/collections_port.h"
++#include "ceres/visibility.h"
+ #include "ceres/graph.h"
+ #include "glog/logging.h"
+
diff --git a/extern/libmv/third_party/ceres/patches/series b/extern/libmv/third_party/ceres/patches/series
index dbe955ae61e..a6874318923 100644
--- a/extern/libmv/third_party/ceres/patches/series
+++ b/extern/libmv/third_party/ceres/patches/series
@@ -1 +1,3 @@
-msvc_isfinite.patch
+collections_port.h.mingw.patch
+msvc_glog_fix.patch
+no_previous_declaration_fix.patch \ No newline at end of file
diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.cpp b/intern/audaspace/FX/AUD_IIRFilterReader.cpp
index 06880818692..8f78c110d1f 100644
--- a/intern/audaspace/FX/AUD_IIRFilterReader.cpp
+++ b/intern/audaspace/FX/AUD_IIRFilterReader.cpp
@@ -34,7 +34,7 @@ AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader,
const std::vector<float>& a) :
AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b)
{
- if(m_a.size())
+ if(m_a.empty() == false)
{
for(int i = 1; i < m_a.size(); i++)
m_a[i] /= m_a[0];
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
index c3f3f46d188..f68d41f6a1c 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
@@ -767,7 +767,7 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume)
/**************************** Threading Code **********************************/
/******************************************************************************/
-void* AUD_openalRunThread(void* device)
+static void *AUD_openalRunThread(void *device)
{
AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device;
dev->updateStreams();
@@ -993,7 +993,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
AUD_THROW(AUD_ERROR_OPENAL, open_error);
// at least try to set the frequency
- ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 };
+ ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 };
ALCint* attributes = attribs;
if(specs.rate == AUD_RATE_INVALID)
attributes = NULL;
diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp
index 238249bc7c8..dd58e5a7398 100644
--- a/intern/audaspace/Python/AUD_PyAPI.cpp
+++ b/intern/audaspace/Python/AUD_PyAPI.cpp
@@ -80,7 +80,7 @@ typedef enum
// ====================================================================
-static PyObject* AUDError;
+static PyObject *AUDError;
static const char* device_not_3d_error = "Device is not a 3D device!";
@@ -92,7 +92,7 @@ Factory_dealloc(Factory* self)
if(self->factory)
delete reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory);
Py_XDECREF(self->child_list);
- Py_TYPE(self)->tp_free((PyObject*)self);
+ Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *
@@ -139,7 +139,7 @@ PyDoc_STRVAR(M_aud_Factory_sine_doc,
":rtype: :class:`Factory`");
static PyObject *
-Factory_sine(PyTypeObject* type, PyObject* args)
+Factory_sine(PyTypeObject* type, PyObject *args)
{
float frequency;
double rate = 44100;
@@ -179,7 +179,7 @@ PyDoc_STRVAR(M_aud_Factory_file_doc,
"playback of that factory.");
static PyObject *
-Factory_file(PyTypeObject* type, PyObject* args)
+Factory_file(PyTypeObject* type, PyObject *args)
{
const char* filename = NULL;
@@ -218,7 +218,7 @@ PyDoc_STRVAR(M_aud_Factory_lowpass_doc,
":rtype: :class:`Factory`");
static PyObject *
-Factory_lowpass(Factory* self, PyObject* args)
+Factory_lowpass(Factory* self, PyObject *args)
{
float frequency;
float Q = 0.5;
@@ -232,7 +232,7 @@ Factory_lowpass(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -260,7 +260,7 @@ PyDoc_STRVAR(M_aud_Factory_delay_doc,
":rtype: :class:`Factory`");
static PyObject *
-Factory_delay(Factory* self, PyObject* args)
+Factory_delay(Factory* self, PyObject *args)
{
float delay;
@@ -273,7 +273,7 @@ Factory_delay(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -301,7 +301,7 @@ PyDoc_STRVAR(M_aud_Factory_join_doc,
"(channels and samplerate).");
static PyObject *
-Factory_join(Factory* self, PyObject* object)
+Factory_join(Factory* self, PyObject *object)
{
PyTypeObject* type = Py_TYPE(self);
@@ -346,7 +346,7 @@ PyDoc_STRVAR(M_aud_Factory_highpass_doc,
":rtype: :class:`Factory`");
static PyObject *
-Factory_highpass(Factory* self, PyObject* args)
+Factory_highpass(Factory* self, PyObject *args)
{
float frequency;
float Q = 0.5;
@@ -360,7 +360,7 @@ Factory_highpass(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -388,7 +388,7 @@ PyDoc_STRVAR(M_aud_Factory_limit_doc,
":rtype: :class:`Factory`");
static PyObject *
-Factory_limit(Factory* self, PyObject* args)
+Factory_limit(Factory* self, PyObject *args)
{
float start, end;
@@ -401,7 +401,7 @@ Factory_limit(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -432,7 +432,7 @@ PyDoc_STRVAR(M_aud_Factory_pitch_doc,
":attr:`Handle.pitch` instead.");
static PyObject *
-Factory_pitch(Factory* self, PyObject* args)
+Factory_pitch(Factory* self, PyObject *args)
{
float factor;
@@ -445,7 +445,7 @@ Factory_pitch(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -474,7 +474,7 @@ PyDoc_STRVAR(M_aud_Factory_volume_doc,
":attr:`Handle.volume` instead.");
static PyObject *
-Factory_volume(Factory* self, PyObject* args)
+Factory_volume(Factory* self, PyObject *args)
{
float volume;
@@ -487,7 +487,7 @@ Factory_volume(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -517,7 +517,7 @@ PyDoc_STRVAR(M_aud_Factory_fadein_doc,
".. note:: Before the fade starts it plays silence.");
static PyObject *
-Factory_fadein(Factory* self, PyObject* args)
+Factory_fadein(Factory* self, PyObject *args)
{
float start, length;
@@ -530,7 +530,7 @@ Factory_fadein(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -561,7 +561,7 @@ PyDoc_STRVAR(M_aud_Factory_fadeout_doc,
"the length of the factory is not altered.");
static PyObject *
-Factory_fadeout(Factory* self, PyObject* args)
+Factory_fadeout(Factory* self, PyObject *args)
{
float start, length;
@@ -574,7 +574,7 @@ Factory_fadeout(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -603,7 +603,7 @@ PyDoc_STRVAR(M_aud_Factory_loop_doc,
":attr:`Handle.loop_count` instead.");
static PyObject *
-Factory_loop(Factory* self, PyObject* args)
+Factory_loop(Factory* self, PyObject *args)
{
int loop;
@@ -616,7 +616,7 @@ Factory_loop(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -644,7 +644,7 @@ PyDoc_STRVAR(M_aud_Factory_mix_doc,
"(channels and samplerate).");
static PyObject *
-Factory_mix(Factory* self, PyObject* object)
+Factory_mix(Factory* self, PyObject *object)
{
PyTypeObject* type = Py_TYPE(self);
@@ -692,7 +692,7 @@ Factory_pingpong(Factory* self)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -731,7 +731,7 @@ Factory_reverse(Factory* self)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -795,7 +795,7 @@ PyDoc_STRVAR(M_aud_Factory_square_doc,
":rtype: :class:`Factory`");
static PyObject *
-Factory_square(Factory* self, PyObject* args)
+Factory_square(Factory* self, PyObject *args)
{
float threshold = 0;
@@ -808,7 +808,7 @@ Factory_square(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -842,10 +842,10 @@ PyDoc_STRVAR(M_aud_Factory_filter_doc,
":rtype: :class:`Factory`");
static PyObject *
-Factory_filter(Factory* self, PyObject* args)
+Factory_filter(Factory* self, PyObject *args)
{
- PyObject* py_b;
- PyObject* py_a = NULL;
+ PyObject *py_b;
+ PyObject *py_a = NULL;
Py_ssize_t py_a_len;
Py_ssize_t py_b_len;
@@ -868,7 +868,7 @@ Factory_filter(Factory* self, PyObject* args)
}
std::vector<float> a, b;
- PyObject* py_value;
+ PyObject *py_value;
float value;
for(Py_ssize_t i = 0; i < py_b_len; i++)
@@ -911,7 +911,7 @@ Factory_filter(Factory* self, PyObject* args)
if(parent != NULL)
{
Py_INCREF(self);
- parent->child_list = (PyObject*)self;
+ parent->child_list = (PyObject *)self;
try
{
@@ -1040,7 +1040,7 @@ Handle_dealloc(Handle* self)
{
if(self->handle)
delete reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle);
- Py_TYPE(self)->tp_free((PyObject*)self);
+ Py_TYPE(self)->tp_free((PyObject *)self);
}
PyDoc_STRVAR(M_aud_Handle_pause_doc,
@@ -1135,7 +1135,7 @@ Handle_get_position(Handle *self, void* nothing)
}
static int
-Handle_set_position(Handle *self, PyObject* args, void* nothing)
+Handle_set_position(Handle *self, PyObject *args, void* nothing)
{
float position;
@@ -1180,7 +1180,7 @@ Handle_get_keep(Handle *self, void* nothing)
}
static int
-Handle_set_keep(Handle *self, PyObject* args, void* nothing)
+Handle_set_keep(Handle *self, PyObject *args, void* nothing)
{
if(!PyBool_Check(args))
{
@@ -1239,7 +1239,7 @@ Handle_get_volume(Handle *self, void* nothing)
}
static int
-Handle_set_volume(Handle *self, PyObject* args, void* nothing)
+Handle_set_volume(Handle *self, PyObject *args, void* nothing)
{
float volume;
@@ -1278,7 +1278,7 @@ Handle_get_pitch(Handle *self, void* nothing)
}
static int
-Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
+Handle_set_pitch(Handle *self, PyObject *args, void* nothing)
{
float pitch;
@@ -1317,7 +1317,7 @@ Handle_get_loop_count(Handle *self, void* nothing)
}
static int
-Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
+Handle_set_loop_count(Handle *self, PyObject *args, void* nothing)
{
int loops;
@@ -1366,7 +1366,7 @@ Handle_get_location(Handle *self, void* nothing)
}
static int
-Handle_set_location(Handle *self, PyObject* args, void* nothing)
+Handle_set_location(Handle *self, PyObject *args, void* nothing)
{
float x, y, z;
@@ -1422,7 +1422,7 @@ Handle_get_velocity(Handle *self, void* nothing)
}
static int
-Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
+Handle_set_velocity(Handle *self, PyObject *args, void* nothing)
{
float x, y, z;
@@ -1478,7 +1478,7 @@ Handle_get_orientation(Handle *self, void* nothing)
}
static int
-Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
+Handle_set_orientation(Handle *self, PyObject *args, void* nothing)
{
float w, x, y, z;
@@ -1533,7 +1533,7 @@ Handle_get_relative(Handle *self, void* nothing)
}
static int
-Handle_set_relative(Handle *self, PyObject* args, void* nothing)
+Handle_set_relative(Handle *self, PyObject *args, void* nothing)
{
if(!PyBool_Check(args))
{
@@ -1591,7 +1591,7 @@ Handle_get_volume_minimum(Handle *self, void* nothing)
}
static int
-Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
+Handle_set_volume_minimum(Handle *self, PyObject *args, void* nothing)
{
float volume;
@@ -1646,7 +1646,7 @@ Handle_get_volume_maximum(Handle *self, void* nothing)
}
static int
-Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
+Handle_set_volume_maximum(Handle *self, PyObject *args, void* nothing)
{
float volume;
@@ -1702,7 +1702,7 @@ Handle_get_distance_reference(Handle *self, void* nothing)
}
static int
-Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
+Handle_set_distance_reference(Handle *self, PyObject *args, void* nothing)
{
float distance;
@@ -1758,7 +1758,7 @@ Handle_get_distance_maximum(Handle *self, void* nothing)
}
static int
-Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
+Handle_set_distance_maximum(Handle *self, PyObject *args, void* nothing)
{
float distance;
@@ -1814,7 +1814,7 @@ Handle_get_attenuation(Handle *self, void* nothing)
}
static int
-Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
+Handle_set_attenuation(Handle *self, PyObject *args, void* nothing)
{
float factor;
@@ -1875,7 +1875,7 @@ Handle_get_cone_angle_inner(Handle *self, void* nothing)
}
static int
-Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
+Handle_set_cone_angle_inner(Handle *self, PyObject *args, void* nothing)
{
float angle;
@@ -1930,7 +1930,7 @@ Handle_get_cone_angle_outer(Handle *self, void* nothing)
}
static int
-Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
+Handle_set_cone_angle_outer(Handle *self, PyObject *args, void* nothing)
{
float angle;
@@ -1985,7 +1985,7 @@ Handle_get_cone_volume_outer(Handle *self, void* nothing)
}
static int
-Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
+Handle_set_cone_volume_outer(Handle *self, PyObject *args, void* nothing)
{
float volume;
@@ -2105,7 +2105,7 @@ Device_dealloc(Device* self)
{
if(self->device)
delete reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device);
- Py_TYPE(self)->tp_free((PyObject*)self);
+ Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *
@@ -2201,8 +2201,8 @@ PyDoc_STRVAR(M_aud_Device_play_doc,
static PyObject *
Device_play(Device *self, PyObject *args, PyObject *kwds)
{
- PyObject* object;
- PyObject* keepo = NULL;
+ PyObject *object;
+ PyObject *keepo = NULL;
bool keep = false;
@@ -2402,7 +2402,7 @@ Device_get_volume(Device *self, void* nothing)
}
static int
-Device_set_volume(Device *self, PyObject* args, void* nothing)
+Device_set_volume(Device *self, PyObject *args, void* nothing)
{
float volume;
@@ -2449,7 +2449,7 @@ Device_get_listener_location(Device *self, void* nothing)
}
static int
-Device_set_listener_location(Device *self, PyObject* args, void* nothing)
+Device_set_listener_location(Device *self, PyObject *args, void* nothing)
{
float x, y, z;
@@ -2504,7 +2504,7 @@ Device_get_listener_velocity(Device *self, void* nothing)
}
static int
-Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
+Device_set_listener_velocity(Device *self, PyObject *args, void* nothing)
{
float x, y, z;
@@ -2559,7 +2559,7 @@ Device_get_listener_orientation(Device *self, void* nothing)
}
static int
-Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
+Device_set_listener_orientation(Device *self, PyObject *args, void* nothing)
{
float w, x, y, z;
@@ -2614,7 +2614,7 @@ Device_get_speed_of_sound(Device *self, void* nothing)
}
static int
-Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
+Device_set_speed_of_sound(Device *self, PyObject *args, void* nothing)
{
float speed;
@@ -2670,7 +2670,7 @@ Device_get_doppler_factor(Device *self, void* nothing)
}
static int
-Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
+Device_set_doppler_factor(Device *self, PyObject *args, void* nothing)
{
float factor;
@@ -2724,7 +2724,7 @@ Device_get_distance_model(Device *self, void* nothing)
}
static int
-Device_set_distance_model(Device *self, PyObject* args, void* nothing)
+Device_set_distance_model(Device *self, PyObject *args, void* nothing)
{
int model;
@@ -2833,7 +2833,7 @@ Factory_empty()
}
Factory*
-checkFactory(PyObject* factory)
+checkFactory(PyObject *factory)
{
if(!PyObject_TypeCheck(factory, &FactoryType))
{
@@ -2862,7 +2862,7 @@ static struct PyModuleDef audmodule = {
PyMODINIT_FUNC
PyInit_aud(void)
{
- PyObject* m;
+ PyObject *m;
if(PyType_Ready(&FactoryType) < 0)
return NULL;
@@ -2878,13 +2878,13 @@ PyInit_aud(void)
return NULL;
Py_INCREF(&FactoryType);
- PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
+ PyModule_AddObject(m, "Factory", (PyObject *)&FactoryType);
Py_INCREF(&DeviceType);
- PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
+ PyModule_AddObject(m, "Device", (PyObject *)&DeviceType);
Py_INCREF(&HandleType);
- PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
+ PyModule_AddObject(m, "Handle", (PyObject *)&HandleType);
AUDError = PyErr_NewException("aud.error", NULL, NULL);
Py_INCREF(AUDError);
diff --git a/intern/audaspace/Python/AUD_PyAPI.h b/intern/audaspace/Python/AUD_PyAPI.h
index 7a7e87ec67d..0183a2df6b2 100644
--- a/intern/audaspace/Python/AUD_PyAPI.h
+++ b/intern/audaspace/Python/AUD_PyAPI.h
@@ -46,7 +46,7 @@ typedef void AUD_Reference_AUD_IHandle;
typedef struct {
PyObject_HEAD
- PyObject* child_list;
+ PyObject *child_list;
AUD_Reference_AUD_IFactory* factory;
} Factory;
@@ -63,9 +63,9 @@ typedef struct {
PyMODINIT_FUNC
PyInit_aud(void);
-extern PyObject* Device_empty();
-extern PyObject* Factory_empty();
-extern Factory* checkFactory(PyObject* factory);
+extern PyObject *Device_empty();
+extern PyObject *Factory_empty();
+extern Factory *checkFactory(PyObject *factory);
#ifdef __cplusplus
}
diff --git a/intern/audaspace/intern/AUD_IFactory.h b/intern/audaspace/intern/AUD_IFactory.h
index a7c214bb5a1..95b4643072e 100644
--- a/intern/audaspace/intern/AUD_IFactory.h
+++ b/intern/audaspace/intern/AUD_IFactory.h
@@ -45,7 +45,7 @@ public:
/**
* Destroys the factory.
*/
- virtual ~AUD_IFactory(){}
+ virtual ~AUD_IFactory() {}
/**
* Creates a reader for playback of the sound source.
diff --git a/intern/audaspace/intern/AUD_IReader.h b/intern/audaspace/intern/AUD_IReader.h
index 8e0e03dd95d..c2c9e607b55 100644
--- a/intern/audaspace/intern/AUD_IReader.h
+++ b/intern/audaspace/intern/AUD_IReader.h
@@ -42,7 +42,7 @@ public:
/**
* Destroys the reader.
*/
- virtual ~AUD_IReader(){}
+ virtual ~AUD_IReader() {}
/**
* Tells whether the source provides seeking functionality or not.
diff --git a/intern/audaspace/intern/AUD_IWriter.h b/intern/audaspace/intern/AUD_IWriter.h
index 3c92661c75d..5406577dd50 100644
--- a/intern/audaspace/intern/AUD_IWriter.h
+++ b/intern/audaspace/intern/AUD_IWriter.h
@@ -41,7 +41,7 @@ public:
/**
* Destroys the writer.
*/
- virtual ~AUD_IWriter(){}
+ virtual ~AUD_IWriter() {}
/**
* Returns how many samples have been written so far.
diff --git a/intern/audaspace/intern/AUD_PyInit.h b/intern/audaspace/intern/AUD_PyInit.h
index 8c045e60f37..95a60cd57bb 100644
--- a/intern/audaspace/intern/AUD_PyInit.h
+++ b/intern/audaspace/intern/AUD_PyInit.h
@@ -40,7 +40,7 @@ extern "C" {
/**
* Initalizes the Python module.
*/
-extern PyObject* AUD_initPython(void);
+extern PyObject *AUD_initPython(void);
#ifdef __cplusplus
}
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 337eebe4be0..90eeb4b4758 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -56,6 +56,7 @@ add_definitions(-DWITH_CUDA)
add_definitions(-DWITH_MULTI)
include_directories(
+ SYSTEM
${BOOST_INCLUDE_DIR}
${OPENIMAGEIO_INCLUDE_DIRS}
${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO)
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 2e2897d0443..83b3f731ffe 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -9,6 +9,8 @@ set(INC
../render
../subd
)
+set(INC_SYS
+)
set(LIBRARIES
cycles_device
@@ -38,6 +40,7 @@ if(WITH_CYCLES_PARTIO)
endif()
include_directories(${INC})
+include_directories(SYSTEM ${INC_SYS})
if(WITH_CYCLES_TEST)
set(SRC
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 4a60a329e2b..6292c09fbb1 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -25,7 +25,7 @@ bl_info = {
"location": "Info header, render engine menu",
"description": "Cycles Render Engine integration",
"warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Dev:2.6/Source/Render/Cycles",
+ "wiki_url": "http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles",
"tracker_url": "",
"support": 'OFFICIAL',
"category": "Render"}
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 7f3eca471e6..0fadfa0afc8 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -242,11 +242,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=1024,
)
- cls.resolution_divider = IntProperty(
- name="Resolution Divider",
- description="For viewport render, the number of lower resolutions to render before the full resolution",
- min=1, max=512,
- default=4,
+ cls.preview_start_resolution = IntProperty(
+ name="Start Resolution",
+ description="Resolution to start rendering preview at, progressively increasing it to the full viewport size",
+ min=8, max=16384,
+ default=64,
)
cls.debug_reset_timeout = FloatProperty(
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 7486edf2319..4d44dc84fdf 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -216,7 +216,7 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub = col.column(align=True)
sub.label(text="Viewport:")
- sub.prop(cscene, "resolution_divider")
+ sub.prop(cscene, "preview_start_resolution")
class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
@@ -513,6 +513,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
lamp = context.lamp
clamp = lamp.cycles
cscene = context.scene.cycles
+ device_type = context.user_preferences.system.compute_device_type
layout.prop(lamp, "type", expand=True)
@@ -531,7 +532,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
sub.prop(lamp, "size", text="Size X")
sub.prop(lamp, "size_y", text="Size Y")
- if not cscene.progressive and cscene.device == 'CPU':
+ if not cscene.progressive and (device_type == 'NONE' or cscene.device == 'CPU'):
col.prop(clamp, "samples")
col = split.column()
@@ -656,6 +657,7 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
world = context.world
cworld = world.cycles
cscene = context.scene.cycles
+ device_type = context.user_preferences.system.compute_device_type
col = layout.column()
@@ -663,7 +665,7 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
sub = col.row(align=True)
sub.active = cworld.sample_as_light
sub.prop(cworld, "sample_map_resolution")
- if not cscene.progressive and cscene.device == 'CPU':
+ if not cscene.progressive and (device_type == 'NONE' or cscene.device == 'CPU'):
sub.prop(cworld, "samples")
@@ -976,6 +978,7 @@ def get_panels():
bpy.types.DATA_PT_camera,
bpy.types.DATA_PT_camera_display,
bpy.types.DATA_PT_lens,
+ bpy.types.DATA_PT_customdata,
bpy.types.DATA_PT_custom_props_mesh,
bpy.types.DATA_PT_custom_props_camera,
bpy.types.DATA_PT_custom_props_lamp,
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 96d5bb61ff8..d9220b76835 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -183,7 +183,7 @@ static struct PyModuleDef module = {
NULL, NULL, NULL, NULL
};
-CCLDeviceInfo *compute_device_list(DeviceType type)
+static CCLDeviceInfo *compute_device_list(DeviceType type)
{
/* device list stored static */
static ccl::vector<CCLDeviceInfo> device_list;
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 5930a2800bf..7b80c520e72 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -372,12 +372,6 @@ void BlenderSession::synchronize()
return;
}
- /* if the session is still resetting the device come back later */
- if(session->resetting()) {
- tag_update();
- return;
- }
-
/* increase samples, but never decrease */
session->set_samples(session_params.samples);
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 9758d9bf92a..ebf8bb45420 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -403,7 +403,7 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
BL::Image b_image(b_image_node.image());
ImageTextureNode *image = new ImageTextureNode();
/* todo: handle generated/builtin images */
- if(b_image)
+ if(b_image && b_image.source() != BL::Image::source_MOVIE)
image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
@@ -416,7 +416,7 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
BL::ShaderNodeTexEnvironment b_env_node(b_node);
BL::Image b_image(b_env_node.image());
EnvironmentTextureNode *env = new EnvironmentTextureNode();
- if(b_image)
+ if(b_image && b_image.source() != BL::Image::source_MOVIE)
env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current());
env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 907573cf072..b4990eb815a 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -368,7 +368,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
params.tile_size = make_int2(tile_x, tile_y);
}
- params.resolution = 1 << get_int(cscene, "resolution_divider");
+ params.start_resolution = get_int(cscene, "preview_start_resolution");
/* other parameters */
params.threads = b_scene.render().threads();
@@ -379,7 +379,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
if(background) {
params.progressive = false;
- params.resolution = 1;
+ params.start_resolution = INT_MAX;
}
else
params.progressive = true;
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index d0fca9a9fb9..46fbead9bc1 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -37,7 +37,7 @@ struct RenderResult;
ID *rna_Object_to_mesh(void *_self, void *reports, void *scene, int apply_modifiers, int settings);
void rna_Main_meshes_remove(void *bmain, void *reports, void *mesh);
void rna_Object_create_duplilist(void *ob, void *reports, void *sce);
-void rna_Object_free_duplilist(void *ob, void *reports);
+void rna_Object_free_duplilist(void *ob);
void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h, const char *layername);
@@ -89,7 +89,7 @@ static inline void object_create_duplilist(BL::Object self, BL::Scene scene)
static inline void object_free_duplilist(BL::Object self)
{
- rna_Object_free_duplilist(self.ptr.data, NULL);
+ rna_Object_free_duplilist(self.ptr.data);
}
static inline bool BKE_object_is_modified(BL::Object self, BL::Scene scene, bool preview)
diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt
index 131a7a1f750..ba5c3785eac 100644
--- a/intern/cycles/bvh/CMakeLists.txt
+++ b/intern/cycles/bvh/CMakeLists.txt
@@ -7,6 +7,8 @@ set(INC
../util
../device
)
+set(INC_SYS
+)
set(SRC
bvh.cpp
@@ -28,5 +30,6 @@ set(SRC_HEADERS
)
include_directories(${INC})
+include_directories(SYSTEM ${INC_SYS})
add_library(cycles_bvh ${SRC} ${SRC_HEADERS})
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index 6038abd815e..1d7c6ef4be3 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -6,6 +6,8 @@ set(INC
../kernel/osl
../util
../render
+)
+set(INC_SYS
${OPENGL_INCLUDE_DIR}
${GLEW_INCLUDE_PATH}
)
@@ -31,5 +33,6 @@ set(SRC_HEADERS
add_definitions(-DGLEW_STATIC)
include_directories(${INC})
+include_directories(SYSTEM ${INC_SYS})
add_library(cycles_device ${SRC} ${SRC_HEADERS})
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 8e3bc408399..2ee2e044618 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -115,7 +115,6 @@ public:
virtual void task_add(DeviceTask& task) = 0;
virtual void task_wait() = 0;
virtual void task_cancel() = 0;
- virtual bool task_cancelled() = 0;
/* opengl drawing */
virtual void draw_pixels(device_memory& mem, int y, int w, int h,
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index e2f612ee233..4c54671b0d0 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -273,11 +273,6 @@ public:
{
task_pool.cancel();
}
-
- bool task_cancelled()
- {
- return task_pool.cancelled();
- }
};
Device *device_cpu_create(DeviceInfo& info, int threads)
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index acc1086cc35..c8dcfdc2f3d 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -892,11 +892,6 @@ public:
{
task_pool.cancel();
}
-
- bool task_cancelled()
- {
- return task_pool.cancelled();
- }
};
Device *device_cuda_create(DeviceInfo& info, bool background)
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index 4923e5c9e66..546ffe5e4b9 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -312,14 +312,6 @@ public:
foreach(SubDevice& sub, devices)
sub.device->task_cancel();
}
-
- bool task_cancelled()
- {
- foreach(SubDevice& sub, devices)
- if (sub.device->task_cancelled())
- return true;
- return false;
- }
};
Device *device_multi_create(DeviceInfo& info, bool background)
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index ed7229d49da..673ffdf79fd 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -724,11 +724,6 @@ public:
{
task_pool.cancel();
}
-
- bool task_cancelled()
- {
- return task_pool.cancelled();
- }
};
Device *device_opencl_create(DeviceInfo& info, bool background)
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index b43aca24496..df8a9b1d5b4 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -5,6 +5,8 @@ set(INC
osl
svm
)
+set(INC_SYS
+)
set(SRC
kernel.cpp
@@ -135,6 +137,7 @@ endif()
# CPU module
include_directories(${INC})
+include_directories(SYSTEM ${INC_SYS})
add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_SVM_HEADERS})
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index e1b474d8537..7fa987197c9 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -134,7 +134,7 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa
/* Panorama Camera */
-__device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, Ray *ray)
+__device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray)
{
Transform rastertocamera = kernel_data.cam.rastertocamera;
float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
@@ -151,6 +151,26 @@ __device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float ra
ray->D = panorama_to_direction(kg, Pcamera.x, Pcamera.y);
+ /* modify ray for depth of field */
+ float aperturesize = kernel_data.cam.aperturesize;
+
+ if(aperturesize > 0.0f) {
+ /* sample point on aperture */
+ float2 lensuv = camera_sample_aperture(kg, lens_u, lens_v)*aperturesize;
+
+ /* compute point on plane of focus */
+ float3 D = normalize(ray->D);
+ float3 Pfocus = D * kernel_data.cam.focaldistance;
+
+ /* calculate orthonormal coordinates perpendicular to D */
+ float3 U, V;
+ make_orthonormals(D, &U, &V);
+
+ /* update ray for effect of lens */
+ ray->P = U * lensuv.x + V * lensuv.y;
+ ray->D = normalize(Pfocus - ray->P);
+ }
+
/* indicates ray should not receive any light, outside of the lens */
if(len_squared(ray->D) == 0.0f) {
ray->t = 0.0f;
@@ -206,7 +226,7 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo
else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
camera_sample_orthographic(kg, raster_x, raster_y, ray);
else
- camera_sample_panorama(kg, raster_x, raster_y, ray);
+ camera_sample_panorama(kg, raster_x, raster_y, lens_u, lens_v, ray);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h
index afc53b1117a..d0b588a88d4 100644
--- a/intern/cycles/kernel/kernel_montecarlo.h
+++ b/intern/cycles/kernel/kernel_montecarlo.h
@@ -46,16 +46,19 @@ __device void to_unit_disk(float *x, float *y)
if(a > -b) {
if(a > b) {
r = a;
- phi = M_PI_4_F *(b/a);
- } else {
- r = b;
- phi = M_PI_4_F *(2.0f - a/b);
- }
- } else {
+ phi = M_PI_4_F *(b/a);
+ }
+ else {
+ r = b;
+ phi = M_PI_4_F *(2.0f - a/b);
+ }
+ }
+ else {
if(a < b) {
r = -a;
phi = M_PI_4_F *(4.0f + b/a);
- } else {
+ }
+ else {
r = -b;
if(b != 0.0f)
phi = M_PI_4_F *(6.0f - a/b);
diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt
index d4ea8b12f5a..65d7a7ad53b 100644
--- a/intern/cycles/kernel/osl/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/CMakeLists.txt
@@ -7,6 +7,8 @@ set(INC
../../util
../../device
)
+set(INC_SYS
+)
set(SRC
background.cpp
@@ -39,6 +41,7 @@ set(HEADER_SRC
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}")
include_directories(${INC})
+include_directories(SYSTEM ${INC_SYS})
add_library(cycles_kernel_osl ${SRC} ${HEADER_SRC})
diff --git a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp
index cb6be6959f5..2c545ca55e7 100644
--- a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp
+++ b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp
@@ -90,8 +90,11 @@ public:
float cosNH = m_N.dot(H);
float cosHO = fabsf(omega_out.dot(H));
+ if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f))
+ return Color3(0, 0, 0);
+
float cosNHdivHO = cosNH / cosHO;
- cosNHdivHO = max(cosNHdivHO, 0.00001f);
+ cosNHdivHO = max(cosNHdivHO, 1e-5f);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
@@ -134,28 +137,32 @@ public:
float cosNH = m_N.dot(H);
float cosHO = fabsf(omega_out.dot(H));
- float cosNHdivHO = cosNH / cosHO;
- cosNHdivHO = max(cosNHdivHO, 0.00001f);
+ if(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f) {
+ float cosNHdivHO = cosNH / cosHO;
+ cosNHdivHO = max(cosNHdivHO, 1e-5f);
- float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
- float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
+ float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
+ float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
- float sinNH2 = 1 - cosNH * cosNH;
- float sinNH4 = sinNH2 * sinNH2;
- float cotangent2 = (cosNH * cosNH) / sinNH2;
+ float sinNH2 = 1 - cosNH * cosNH;
+ float sinNH4 = sinNH2 * sinNH2;
+ float cotangent2 = (cosNH * cosNH) / sinNH2;
- float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
- float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
+ float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
+ float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
- float power = 0.25f * (D * G) / cosNO;
+ float power = 0.25f * (D * G) / cosNO;
- eval.setValue(power, power, power);
+ eval.setValue(power, power, power);
- // TODO: find a better approximation for the retroreflective bounce
- domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
- domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
- domega_in_dx *= 125;
- domega_in_dy *= 125;
+ // TODO: find a better approximation for the retroreflective bounce
+ domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
+ domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
+ domega_in_dx *= 125;
+ domega_in_dy *= 125;
+ }
+ else
+ pdf = 0;
}
else
pdf = 0;
diff --git a/intern/cycles/kernel/osl/nodes/CMakeLists.txt b/intern/cycles/kernel/osl/nodes/CMakeLists.txt
index 729d4dae1c9..541076f84c9 100644
--- a/intern/cycles/kernel/osl/nodes/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/nodes/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC_OSL
node_output_surface.osl
node_output_volume.osl
node_particle_info.osl
+ node_rgb_ramp.osl
node_separate_rgb.osl
node_sky_texture.osl
node_texture_coordinate.osl
diff --git a/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl b/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl
index a8dd65ae23b..e0cbc2cc569 100644
--- a/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl
+++ b/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl
@@ -23,34 +23,35 @@
float gradient(point p, string type)
{
- float x, y;
+ float x, y, z;
x = p[0];
y = p[1];
+ z = p[2];
float result = 0.0;
if(type == "Linear") {
- result = (1.0 + x)/2.0;
+ result = x;
}
else if(type == "Quadratic") {
- float r = max((1.0 + x)/2.0, 0.0);
+ float r = max(x, 0.0);
result = r*r;
}
else if(type == "Easing") {
- float r = min(max((1.0 + x)/2.0, 0.0), 1.0);
+ float r = min(max(x, 0.0), 1.0);
float t = r*r;
result = (3.0*t - 2.0*t*r);
}
else if(type == "Diagonal") {
- result = (2.0 + x + y)/4.0;
+ result = (x + y)/2.0;
}
else if(type == "Radial") {
- result = atan2(y, x)/(2*M_PI) + 0.5;
+ result = atan2(y, x)/(2.0*M_PI) + 0.5;
}
else {
- float r = max(1.0 - sqrt(x*x + y*y + p[2]*p[2]), 0.0);
+ float r = max(1.0 - sqrt(x*x + y*y + z*z), 0.0);
if(type == "Quadratic Sphere")
result = r*r;
diff --git a/intern/cycles/kernel/osl/nodes/node_magic_texture.osl b/intern/cycles/kernel/osl/nodes/node_magic_texture.osl
index 0b6e980debc..c013ebfe658 100644
--- a/intern/cycles/kernel/osl/nodes/node_magic_texture.osl
+++ b/intern/cycles/kernel/osl/nodes/node_magic_texture.osl
@@ -21,56 +21,56 @@
/* Magic */
-color magic(point p, int n, float turbulence)
+color magic(point p, int n, float distortion)
{
- float turb = turbulence/5.0;
+ float dist = distortion;
float x = sin((p[0] + p[1] + p[2])*5.0);
float y = cos((-p[0] + p[1] - p[2])*5.0);
float z = -cos((-p[0] - p[1] + p[2])*5.0);
if(n > 0) {
- x *= turb;
- y *= turb;
- z *= turb;
+ x *= dist;
+ y *= dist;
+ z *= dist;
y = -cos(x-y+z);
- y *= turb;
+ y *= dist;
if(n > 1) {
- x= cos(x-y-z);
- x *= turb;
+ x = cos(x-y-z);
+ x *= dist;
if(n > 2) {
- z= sin(-x-y-z);
- z *= turb;
+ z = sin(-x-y-z);
+ z *= dist;
if(n > 3) {
- x= -cos(-x+y-z);
- x *= turb;
+ x = -cos(-x+y-z);
+ x *= dist;
if(n > 4) {
- y= -sin(-x+y+z);
- y *= turb;
+ y = -sin(-x+y+z);
+ y *= dist;
if(n > 5) {
- y= -cos(-x+y+z);
- y *= turb;
+ y = -cos(-x+y+z);
+ y *= dist;
if(n > 6) {
- x= cos(x+y+z);
- x *= turb;
+ x = cos(x+y+z);
+ x *= dist;
if(n > 7) {
- z= sin(x+y-z);
- z *= turb;
+ z = sin(x+y-z);
+ z *= dist;
if(n > 8) {
- x= -cos(-x-y+z);
- x *= turb;
+ x = -cos(-x-y+z);
+ x *= dist;
if(n > 9) {
- y= -sin(x-y+z);
- y *= turb;
+ y = -sin(x-y+z);
+ y *= dist;
}
}
}
@@ -82,11 +82,11 @@ color magic(point p, int n, float turbulence)
}
}
- if(turb != 0.0) {
- turb *= 2.0;
- x /= turb;
- y /= turb;
- z /= turb;
+ if(dist != 0.0) {
+ dist *= 2.0;
+ x /= dist;
+ y /= dist;
+ z /= dist;
}
return color(0.5 - x, 0.5 - y, 0.5 - z);
@@ -94,10 +94,11 @@ color magic(point p, int n, float turbulence)
shader node_magic_texture(
int Depth = 2,
- float Turbulence = 5.0,
+ float Distortion = 5.0,
+ float Scale = 5.0,
point Vector = P,
output color Color = color(0.0, 0.0, 0.0))
{
- Color = magic(Vector, Depth, Turbulence);
+ Color = magic(Vector*Scale, Depth, Distortion);
}
diff --git a/intern/cycles/kernel/osl/nodes/node_mix.osl b/intern/cycles/kernel/osl/nodes/node_mix.osl
index 661e543fdd8..2ce342c49cd 100644
--- a/intern/cycles/kernel/osl/nodes/node_mix.osl
+++ b/intern/cycles/kernel/osl/nodes/node_mix.osl
@@ -239,8 +239,8 @@ color node_mix_soft(float t, color col1, color col2)
{
float tm = 1.0 - t;
- color one= color(1.0);
- color scr= one - (one - col2)*(one - col1);
+ color one = color(1.0);
+ color scr = one - (one - col2)*(one - col1);
return tm*col1 + t*((one - col1)*col2*col1 + col1*scr);
}
diff --git a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl b/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl
index 3e1a6862660..7d125d50fd6 100644
--- a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl
+++ b/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl
@@ -37,14 +37,14 @@ float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float
int i;
for(i = 0; i < (int)octaves; i++) {
- value += noise_basis(p, basis) * pwr;
+ value += noise("perlin", p) * pwr;
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if(rmd != 0.0)
- value += rmd * noise_basis(p, basis) * pwr;
+ value += rmd * noise("perlin", p) * pwr;
return value;
}
@@ -65,14 +65,14 @@ float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunar
int i;
for(i = 0; i < (int)octaves; i++) {
- value *= (pwr * noise_basis(p, basis) + 1.0);
+ value *= (pwr * noise("perlin", p) + 1.0);
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if(rmd != 0.0)
- value *= (rmd * pwr * noise_basis(p, basis) + 1.0); /* correct? */
+ value *= (rmd * pwr * noise("perlin", p) + 1.0); /* correct? */
return value;
}
@@ -93,11 +93,11 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna
int i;
/* first unscaled octave of function; later octaves are scaled */
- value = offset + noise_basis(p, basis);
+ value = offset + noise("perlin", p);
p *= lacunarity;
for(i = 1; i < (int)octaves; i++) {
- increment = (noise_basis(p, basis) + offset) * pwr * value;
+ increment = (noise("perlin", p) + offset) * pwr * value;
value += increment;
pwr *= pwHL;
p *= lacunarity;
@@ -105,7 +105,7 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna
rmd = octaves - floor(octaves);
if(rmd != 0.0) {
- increment = (noise_basis(p, basis) + offset) * pwr * value;
+ increment = (noise("perlin", p) + offset) * pwr * value;
value += rmd * increment;
}
@@ -127,7 +127,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float
float pwr = pwHL;
int i;
- result = noise_basis(p, basis) + offset;
+ result = noise("perlin", p) + offset;
weight = gain * result;
p *= lacunarity;
@@ -135,7 +135,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float
if(weight > 1.0)
weight = 1.0;
- signal = (noise_basis(p, basis) + offset) * pwr;
+ signal = (noise("perlin", p) + offset) * pwr;
pwr *= pwHL;
result += weight * signal;
weight *= gain * signal;
@@ -144,7 +144,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float
rmd = octaves - floor(octaves);
if(rmd != 0.0)
- result += rmd * ((noise_basis(p, basis) + offset) * pwr);
+ result += rmd * ((noise("perlin", p) + offset) * pwr);
return result;
}
@@ -164,7 +164,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float
float pwr = pwHL;
int i;
- signal = offset - fabs(noise_basis(p, basis));
+ signal = offset - fabs(noise("perlin", p));
signal *= signal;
result = signal;
weight = 1.0;
@@ -172,7 +172,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float
for(i = 1; i < (int)octaves; i++) {
p *= lacunarity;
weight = clamp(signal * gain, 0.0, 1.0);
- signal = offset - fabs(noise_basis(p, basis));
+ signal = offset - fabs(noise("perlin", p));
signal *= signal;
signal *= weight;
result += signal * pwr;
diff --git a/intern/cycles/kernel/osl/nodes/node_rgb_ramp.osl b/intern/cycles/kernel/osl/nodes/node_rgb_ramp.osl
new file mode 100644
index 00000000000..2bc10f31cb3
--- /dev/null
+++ b/intern/cycles/kernel/osl/nodes/node_rgb_ramp.osl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+#include "oslutil.h"
+
+shader node_rgb_ramp(
+ color ramp_color[RAMP_TABLE_SIZE] = {0.0},
+ float ramp_alpha[RAMP_TABLE_SIZE] = {0.0},
+
+ float Fac = 0.0,
+ output color Color = color(0.0, 0.0, 0.0),
+ output float Alpha = 1.0
+ )
+{
+ float f = clamp(Fac, 0.0, 1.0)*(RAMP_TABLE_SIZE-1);
+
+ int i = (int)f;
+ float t = f - (float)i;
+
+ Color = ramp_color[i];
+ Alpha = ramp_alpha[i];
+
+ if (t > 0.0) {
+ Color = (1.0 - t)*Color + t*ramp_color[i+1];
+ Alpha = (1.0 - t)*Alpha + t*ramp_alpha[i+1];
+ }
+}
+
diff --git a/intern/cycles/kernel/osl/nodes/node_texture.h b/intern/cycles/kernel/osl/nodes/node_texture.h
index b00bf6ab31f..7cd0742ffe8 100644
--- a/intern/cycles/kernel/osl/nodes/node_texture.h
+++ b/intern/cycles/kernel/osl/nodes/node_texture.h
@@ -156,7 +156,7 @@ float noise_basis(point p, string basis)
float result = 0.0;
if (basis == "Perlin")
- result = noise(p);
+ result = noise(p); /* returns perlin noise in range 0..1 */
if (basis == "Voronoi F1")
result = voronoi_F1S(p);
if (basis == "Voronoi F2")
diff --git a/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl b/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl
index f24f154be84..db08b64de1c 100644
--- a/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl
+++ b/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl
@@ -22,60 +22,27 @@
/* Voronoi */
shader node_voronoi_texture(
- string DistanceMetric = "Actual Distance",
string Coloring = "Intensity",
- float Weight1 = 1.0,
- float Weight2 = 0.0,
- float Weight3 = 0.0,
- float Weight4 = 0.0,
- float Exponent = 2.5,
- float Intensity = 1.0,
float Scale = 5.0,
point Vector = P,
output float Fac = 0.0,
output color Color = color(0.0, 0.0, 0.0))
{
- float exponent = max(Exponent, 1e-5);
-
- float aw1 = fabs(Weight1);
- float aw2 = fabs(Weight2);
- float aw3 = fabs(Weight3);
- float aw4 = fabs(Weight4);
- float sc = (aw1 + aw2 + aw3 + aw4);
-
- if(sc != 0.0)
- sc = Intensity/sc;
-
/* compute distance and point coordinate of 4 nearest neighbours */
float da[4];
point pa[4];
- voronoi(Vector*Scale, DistanceMetric, exponent, da, pa);
-
- /* Scalar output */
- Fac = sc * fabs(Weight1*da[0] + Weight2*da[1] + Weight3*da[2] + Weight4*da[3]);
+ voronoi(Vector*Scale, "Distance Squared", 1.0, da, pa);
/* Colored output */
if(Coloring == "Intensity") {
- Color = color(Fac, Fac, Fac);
+ Fac = fabs(da[0]);
+ Color = color(Fac);
}
else {
- Color = aw1*cellnoise_color(pa[0]);
- Color += aw2*cellnoise_color(pa[1]);
- Color += aw3*cellnoise_color(pa[2]);
- Color += aw4*cellnoise_color(pa[3]);
-
- if(Coloring != "Position") {
- float t1 = min((da[1] - da[0])*10.0, 1.0);
+ Color = cellnoise_color(pa[0]);
+ Fac = (Color[0]+Color[1]+Color[2])*(1.0/3.0);
- if(Coloring == "Position, Outline, and Intensity")
- Color *= t1*Fac;
- else if(Coloring == "Position and Outline")
- Color *= t1*sc;
- }
- else {
- Color *= sc;
- }
}
}
diff --git a/intern/cycles/kernel/osl/nodes/oslutil.h b/intern/cycles/kernel/osl/nodes/oslutil.h
index 08611187a3c..6c91684d9a6 100644
--- a/intern/cycles/kernel/osl/nodes/oslutil.h
+++ b/intern/cycles/kernel/osl/nodes/oslutil.h
@@ -29,6 +29,9 @@
#ifndef CCL_OSLUTIL_H
#define CCL_OSLUTIL_H
+/* NB: must match the value in kernel_types.h */
+#define RAMP_TABLE_SIZE 256
+
// Return wireframe opacity factor [0, 1] given a geometry type in
// ("triangles", "polygons" or "patches"), and a line_width in raster
// or world space depending on the last (raster) boolean argument.
diff --git a/intern/cycles/kernel/svm/bsdf.h b/intern/cycles/kernel/svm/bsdf.h
index 1a90eab0cd1..cfb6321a918 100644
--- a/intern/cycles/kernel/svm/bsdf.h
+++ b/intern/cycles/kernel/svm/bsdf.h
@@ -58,7 +58,8 @@ __device float fresnel_dielectric(float eta, const float3 N,
neta = 1 / eta;
Nn = N;
*is_inside = false;
- } else {
+ }
+ else {
// we are inside the surface,
cos = -cos;
neta = eta;
@@ -74,7 +75,8 @@ __device float fresnel_dielectric(float eta, const float3 N,
*dTdy = make_float3(0.0f, 0.0f, 0.0f);
#endif
return 1; // total internal reflection
- } else {
+ }
+ else {
float dnp = sqrtf(arg);
float nK = (neta * cos)- dnp;
*T = -(neta * I)+(nK * Nn);
diff --git a/intern/cycles/kernel/svm/bsdf_diffuse.h b/intern/cycles/kernel/svm/bsdf_diffuse.h
index 45e82a566c0..edf8dd93341 100644
--- a/intern/cycles/kernel/svm/bsdf_diffuse.h
+++ b/intern/cycles/kernel/svm/bsdf_diffuse.h
@@ -144,9 +144,10 @@ __device int bsdf_translucent_sample(const ShaderData *sd, const ShaderClosure *
*domega_in_dx *= -125.0f;
*domega_in_dy *= -125.0f;
#endif
- } else
+ }
+ else {
*pdf = 0;
-
+ }
return LABEL_TRANSMIT|LABEL_DIFFUSE;
}
diff --git a/intern/cycles/kernel/svm/bsdf_microfacet.h b/intern/cycles/kernel/svm/bsdf_microfacet.h
index 01e3acb76e8..d8f0310bd02 100644
--- a/intern/cycles/kernel/svm/bsdf_microfacet.h
+++ b/intern/cycles/kernel/svm/bsdf_microfacet.h
@@ -210,7 +210,8 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur
#endif
}
}
- } else {
+ }
+ else {
// CAUTION: the i and o variables are inverted relative to the paper
// eq. 39 - compute actual refractive direction
float3 R, T;
@@ -443,7 +444,8 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC
#endif
}
}
- } else {
+ }
+ else {
// CAUTION: the i and o variables are inverted relative to the paper
// eq. 39 - compute actual refractive direction
float3 R, T;
diff --git a/intern/cycles/kernel/svm/bsdf_ward.h b/intern/cycles/kernel/svm/bsdf_ward.h
index 86bca69425d..6ae45948a73 100644
--- a/intern/cycles/kernel/svm/bsdf_ward.h
+++ b/intern/cycles/kernel/svm/bsdf_ward.h
@@ -127,19 +127,22 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo
float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = tanPhi * cosPhi;
- } else if(randu < 0.5f) {
+ }
+ else if(randu < 0.5f) {
float val = 1 - 4 * (0.5f - randu);
float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
// phi = M_PI_F - phi;
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = -tanPhi * cosPhi;
- } else if(randu < 0.75f) {
+ }
+ else if(randu < 0.75f) {
float val = 4 * (randu - 0.5f);
float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
//phi = M_PI_F + phi;
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = tanPhi * cosPhi;
- } else {
+ }
+ else {
float val = 1 - 4 * (1 - randu);
float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
// phi = 2 * M_PI_F - phi;
diff --git a/intern/cycles/kernel/svm/bsdf_westin.h b/intern/cycles/kernel/svm/bsdf_westin.h
index 6193d81c244..3e7c27f44a4 100644
--- a/intern/cycles/kernel/svm/bsdf_westin.h
+++ b/intern/cycles/kernel/svm/bsdf_westin.h
@@ -196,8 +196,10 @@ __device int bsdf_westin_sheen_sample(const ShaderData *sd, const ShaderClosure
*domega_in_dx *= 125.0f;
*domega_in_dy *= 125.0f;
#endif
- } else
+ }
+ else {
pdf = 0;
+ }
return LABEL_REFLECT|LABEL_DIFFUSE;
}
diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h
index ed17d3fc985..bce11d62923 100644
--- a/intern/cycles/kernel/svm/svm_hsv.h
+++ b/intern/cycles/kernel/svm/svm_hsv.h
@@ -69,11 +69,11 @@ __device float3 hsv_to_rgb(float3 hsv)
s = hsv.y;
v = hsv.z;
- if(s==0.0f) {
+ if(s == 0.0f) {
rgb = make_float3(v, v, v);
}
else {
- if(h==1.0f)
+ if(h == 1.0f)
h = 0.0f;
h *= 6.0f;
diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h
index dfaf43acbd4..224a1d96543 100644
--- a/intern/cycles/kernel/svm/svm_noise.h
+++ b/intern/cycles/kernel/svm/svm_noise.h
@@ -104,7 +104,7 @@ __device float grad(int hash, float x, float y, float z)
// use vectors pointing to the edges of the cube
int h = hash & 15;
float u = h<8 ? x : y;
- float v = h<4 ? y : h==12||h==14 ? x : z;
+ float v = h<4 ? y : h == 12 || h == 14 ? x : z;
return ((h&1) ? -u : u) + ((h&2) ? -v : v);
}
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 85b476e60d9..6b8e3702d03 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -9,6 +9,9 @@ set(INC
../util
${GLEW_INCLUDE_PATH}
)
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
set(SRC
attribute.cpp
@@ -64,6 +67,7 @@ set(SRC_HEADERS
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}")
include_directories(${INC})
+include_directories(SYSTEM ${INC_SYS})
add_library(cycles_render ${SRC} ${SRC_HEADERS})
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index e44caa90f12..3fd7a1b28e3 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -245,7 +245,7 @@ void Camera::device_free(Device *device, DeviceScene *dscene)
bool Camera::modified(const Camera& cam)
{
- return !((shuttertime== cam.shuttertime) &&
+ return !((shuttertime == cam.shuttertime) &&
(aperturesize == cam.aperturesize) &&
(blades == cam.blades) &&
(bladesrotation == cam.bladesrotation) &&
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index da563c9c4ec..699e6979990 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -123,6 +123,8 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
max_samples *= (max_bounce + transparent_max_bounce + 2);
int dimensions = PRNG_BASE_NUM + max_samples*PRNG_BOUNCE_NUM;
+ dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
+
uint *directions = dscene->sobol_directions.resize(SOBOL_BITS*dimensions);
sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 1f03ab4e347..eabb97e7238 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1021,7 +1021,7 @@ void NormalNode::compile(SVMCompiler& compiler)
void NormalNode::compile(OSLCompiler& compiler)
{
- compiler.parameter_vector("Direction", direction);
+ compiler.parameter_normal("Direction", direction);
compiler.add(this, "node_normal");
}
@@ -2768,6 +2768,19 @@ void RGBRampNode::compile(SVMCompiler& compiler)
void RGBRampNode::compile(OSLCompiler& compiler)
{
+ /* OSL shader only takes separate RGB and A array, split the RGBA base array */
+ /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */
+ float ramp_color[RAMP_TABLE_SIZE][3];
+ float ramp_alpha[RAMP_TABLE_SIZE];
+ for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
+ ramp_color[i][0] = ramp[i].x;
+ ramp_color[i][1] = ramp[i].y;
+ ramp_color[i][2] = ramp[i].z;
+ ramp_alpha[i] = ramp[i].w;
+ }
+ compiler.parameter_color_array("ramp_color", ramp_color, RAMP_TABLE_SIZE);
+ compiler.parameter_array("ramp_alpha", ramp_alpha, RAMP_TABLE_SIZE);
+
compiler.add(this, "node_rgb_ramp");
}
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index dbd6b0ac9d9..6d23097d7a8 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -154,14 +154,43 @@ string OSLCompiler::id(ShaderNode *node)
return stream.str();
}
-string OSLCompiler::compatible_name(const char *name)
+string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
{
- string sname = name;
+ string sname(input->name);
size_t i;
+ /* strip whitespace */
while((i = sname.find(" ")) != string::npos)
sname.replace(i, 1, "");
+ /* if output exists with the same name, add "In" suffix */
+ foreach(ShaderOutput *output, node->outputs) {
+ if (strcmp(input->name, output->name)==0) {
+ sname += "In";
+ break;
+ }
+ }
+
+ return sname;
+}
+
+string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
+{
+ string sname(output->name);
+ size_t i;
+
+ /* strip whitespace */
+ while((i = sname.find(" ")) != string::npos)
+ sname.replace(i, 1, "");
+
+ /* if output exists with the same name, add "In" suffix */
+ foreach(ShaderInput *input, node->inputs) {
+ if (strcmp(input->name, output->name)==0) {
+ sname += "Out";
+ break;
+ }
+ }
+
return sname;
}
@@ -198,21 +227,22 @@ void OSLCompiler::add(ShaderNode *node, const char *name)
else if(input->default_value != ShaderInput::NONE)
continue;
+ string param_name = compatible_name(node, input);
switch(input->type) {
case SHADER_SOCKET_COLOR:
- parameter_color(compatible_name(input->name).c_str(), input->value);
+ parameter_color(param_name.c_str(), input->value);
break;
case SHADER_SOCKET_POINT:
- parameter_point(compatible_name(input->name).c_str(), input->value);
+ parameter_point(param_name.c_str(), input->value);
break;
case SHADER_SOCKET_VECTOR:
- parameter_vector(compatible_name(input->name).c_str(), input->value);
+ parameter_vector(param_name.c_str(), input->value);
break;
case SHADER_SOCKET_NORMAL:
- parameter_normal(compatible_name(input->name).c_str(), input->value);
+ parameter_normal(param_name.c_str(), input->value);
break;
case SHADER_SOCKET_FLOAT:
- parameter(compatible_name(input->name).c_str(), input->value.x);
+ parameter(param_name.c_str(), input->value.x);
break;
case SHADER_SOCKET_CLOSURE:
break;
@@ -242,12 +272,8 @@ void OSLCompiler::add(ShaderNode *node, const char *name)
/* connect shaders */
string id_from = id(input->link->parent);
string id_to = id(node);
- string param_from = compatible_name(input->link->name);
- string param_to = compatible_name(input->name);
-
- /* avoid name conflict with same input/output socket name */
- if(input->link->parent->input(input->link->name))
- param_from += "_";
+ string param_from = compatible_name(input->link->parent, input->link);
+ string param_to = compatible_name(node, input);
ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
}
@@ -309,6 +335,70 @@ void OSLCompiler::parameter(const char *name, const Transform& tfm)
ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&tfm);
}
+void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
+{
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
+ TypeDesc type = TypeDesc::TypeFloat;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, f);
+}
+
+void OSLCompiler::parameter_color_array(const char *name, const float f[][3], int arraylen)
+{
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
+ TypeDesc type = TypeDesc::TypeColor;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, f);
+}
+
+void OSLCompiler::parameter_vector_array(const char *name, const float f[][3], int arraylen)
+{
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
+ TypeDesc type = TypeDesc::TypeVector;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, f);
+}
+
+void OSLCompiler::parameter_normal_array(const char *name, const float f[][3], int arraylen)
+{
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
+ TypeDesc type = TypeDesc::TypeNormal;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, f);
+}
+
+void OSLCompiler::parameter_point_array(const char *name, const float f[][3], int arraylen)
+{
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
+ TypeDesc type = TypeDesc::TypePoint;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, f);
+}
+
+void OSLCompiler::parameter_array(const char *name, const int f[], int arraylen)
+{
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
+ TypeDesc type = TypeDesc::TypeInt;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, f);
+}
+
+void OSLCompiler::parameter_array(const char *name, const char * const s[], int arraylen)
+{
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
+ TypeDesc type = TypeDesc::TypeString;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, s);
+}
+
+void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int arraylen)
+{
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
+ TypeDesc type = TypeDesc::TypeMatrix;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, (const float *)tfm);
+}
+
void OSLCompiler::find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input)
{
ShaderNode *node = (input->link)? input->link->parent: NULL;
@@ -483,6 +573,14 @@ void OSLCompiler::parameter_vector(const char *name, float3 f)
{
}
+void OSLCompiler::parameter_point(const char *name, float3 f)
+{
+}
+
+void OSLCompiler::parameter_normal(const char *name, float3 f)
+{
+}
+
void OSLCompiler::parameter(const char *name, int f)
{
}
@@ -499,6 +597,38 @@ void OSLCompiler::parameter(const char *name, const Transform& tfm)
{
}
+void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
+{
+}
+
+void OSLCompiler::parameter_color_array(const char *name, const float f[][3], int arraylen)
+{
+}
+
+void OSLCompiler::parameter_vector_array(const char *name, const float f[][3], int arraylen)
+{
+}
+
+void OSLCompiler::parameter_normal_array(const char *name, const float f[][3], int arraylen)
+{
+}
+
+void OSLCompiler::parameter_point_array(const char *name, const float f[][3], int arraylen)
+{
+}
+
+void OSLCompiler::parameter_array(const char *name, const int f[], int arraylen)
+{
+}
+
+void OSLCompiler::parameter_array(const char *name, const char * const s[], int arraylen)
+{
+}
+
+void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int arraylen)
+{
+}
+
#endif /* WITH_OSL */
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 329cf9a4828..90107a34a98 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -37,6 +37,7 @@ class OSLGlobals;
class Scene;
class ShaderGraph;
class ShaderNode;
+class ShaderInput;
class ShaderOutput;
#ifdef WITH_OSL
@@ -79,6 +80,15 @@ public:
void parameter(const char *name, ustring str);
void parameter(const char *name, const Transform& tfm);
+ void parameter_array(const char *name, const float f[], int arraylen);
+ void parameter_color_array(const char *name, const float f[][3], int arraylen);
+ void parameter_vector_array(const char *name, const float f[][3], int arraylen);
+ void parameter_normal_array(const char *name, const float f[][3], int arraylen);
+ void parameter_point_array(const char *name, const float f[][3], int arraylen);
+ void parameter_array(const char *name, const int f[], int arraylen);
+ void parameter_array(const char *name, const char * const s[], int arraylen);
+ void parameter_array(const char *name, const Transform tfm[], int arraylen);
+
ShaderType output_type() { return current_type; }
bool background;
@@ -87,7 +97,8 @@ private:
string id(ShaderNode *node);
void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
bool node_skip_input(ShaderNode *node, ShaderInput *input);
- string compatible_name(const char *name);
+ string compatible_name(ShaderNode *node, ShaderInput *input);
+ string compatible_name(ShaderNode *node, ShaderOutput *output);
void find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input);
void generate_nodes(const set<ShaderNode*>& nodes);
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 05c57ba48ec..cd410e4e011 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -36,7 +36,7 @@ CCL_NAMESPACE_BEGIN
Session::Session(const SessionParams& params_)
: params(params_),
- tile_manager(params.progressive, params.samples, params.tile_size, params.resolution,
+ tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution,
(params.background)? 1: max(params.device.multi_devices.size(), 1))
{
device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
@@ -140,12 +140,6 @@ void Session::reset_gpu(BufferParams& buffer_params, int samples)
pause_cond.notify_all();
}
-bool Session::resetting_gpu() const
-{
- /* no need to wait for gpu device */
- return false;
-}
-
bool Session::draw_gpu(BufferParams& buffer_params)
{
/* block for buffer access */
@@ -296,11 +290,6 @@ void Session::reset_cpu(BufferParams& buffer_params, int samples)
pause_cond.notify_all();
}
-bool Session::resetting_cpu() const
-{
- return device->task_cancelled();
-}
-
bool Session::draw_cpu(BufferParams& buffer_params)
{
thread_scoped_lock display_lock(display_mutex);
@@ -343,7 +332,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
rtile.h = tile.h;
rtile.start_sample = tile_manager.state.sample;
rtile.num_samples = tile_manager.state.num_samples;
- rtile.resolution = tile_manager.state.resolution;
+ rtile.resolution = tile_manager.state.resolution_divider;
tile_lock.unlock();
@@ -595,14 +584,6 @@ void Session::reset(BufferParams& buffer_params, int samples)
reset_cpu(buffer_params, samples);
}
-bool Session::resetting() const
-{
- if(device_use_gl)
- return resetting_gpu();
- else
- return resetting_cpu();
-}
-
void Session::set_samples(int samples)
{
if(samples != params.samples) {
@@ -668,7 +649,7 @@ void Session::update_scene()
void Session::update_status_time(bool show_pause, bool show_done)
{
int sample = tile_manager.state.sample;
- int resolution = tile_manager.state.resolution;
+ int resolution = tile_manager.state.resolution_divider;
int num_tiles = tile_manager.state.num_tiles;
int tile = tile_manager.state.num_rendered_tiles;
@@ -757,7 +738,7 @@ void Session::tonemap()
task.rgba = display->rgba.device_pointer;
task.buffer = buffers->buffer.device_pointer;
task.sample = tile_manager.state.sample;
- task.resolution = tile_manager.state.resolution;
+ task.resolution = tile_manager.state.resolution_divider;
tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
if(task.w > 0 && task.h > 0) {
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index e45753d22a0..eda8b3da60e 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -48,7 +48,7 @@ public:
bool experimental;
int samples;
int2 tile_size;
- int resolution;
+ int start_resolution;
int threads;
double cancel_timeout;
@@ -64,7 +64,7 @@ public:
experimental = false;
samples = INT_MAX;
tile_size = make_int2(64, 64);
- resolution = 4;
+ start_resolution = INT_MAX;
threads = 0;
cancel_timeout = 0.1;
@@ -81,7 +81,7 @@ public:
&& progressive == params.progressive
&& experimental == params.experimental
&& tile_size == params.tile_size
- && resolution == params.resolution
+ && start_resolution == params.start_resolution
&& threads == params.threads
&& cancel_timeout == params.cancel_timeout
&& reset_timeout == params.reset_timeout
@@ -116,7 +116,6 @@ public:
bool ready_to_reset();
void reset(BufferParams& params, int samples);
- bool resetting() const;
void set_samples(int samples);
void set_pause(bool pause);
@@ -140,12 +139,10 @@ protected:
void run_cpu();
bool draw_cpu(BufferParams& params);
void reset_cpu(BufferParams& params, int samples);
- bool resetting_cpu() const;
void run_gpu();
bool draw_gpu(BufferParams& params);
void reset_gpu(BufferParams& params, int samples);
- bool resetting_gpu() const;
bool acquire_tile(Device *tile_device, RenderTile& tile);
void update_tile_sample(RenderTile& tile);
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index b4156fd9471..874f1a6b3aa 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -23,11 +23,11 @@
CCL_NAMESPACE_BEGIN
-TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int resolution_, int num_devices_)
+TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_, int num_devices_)
{
progressive = progressive_;
tile_size = tile_size_;
- resolution = resolution_;
+ start_resolution = start_resolution_;
num_devices = num_devices_;
BufferParams buffer_params;
@@ -42,6 +42,18 @@ void TileManager::reset(BufferParams& params_, int num_samples_)
{
params = params_;
+ int divider = 1;
+ int w = params.width, h = params.height;
+
+ if(start_resolution != INT_MAX) {
+ while(w*h > start_resolution*start_resolution) {
+ w = max(1, w/2);
+ h = max(1, h/2);
+
+ divider *= 2;
+ }
+ }
+
num_samples = num_samples_;
state.buffer = BufferParams();
@@ -49,7 +61,7 @@ void TileManager::reset(BufferParams& params_, int num_samples_)
state.num_tiles = 0;
state.num_rendered_tiles = 0;
state.num_samples = 0;
- state.resolution = resolution;
+ state.resolution_divider = divider;
state.tiles.clear();
}
@@ -60,7 +72,7 @@ void TileManager::set_samples(int num_samples_)
void TileManager::set_tiles()
{
- int resolution = state.resolution;
+ int resolution = state.resolution_divider;
int image_w = max(1, params.width/resolution);
int image_h = max(1, params.height/resolution);
@@ -104,7 +116,7 @@ list<Tile>::iterator TileManager::next_center_tile(int device)
{
list<Tile>::iterator iter, best = state.tiles.end();
- int resolution = state.resolution;
+ int resolution = state.resolution_divider;
int image_w = max(1, params.width/resolution);
int image_h = max(1, params.height/resolution);
@@ -167,7 +179,7 @@ bool TileManager::next_tile(Tile& tile, int device)
bool TileManager::done()
{
- return (state.sample+state.num_samples >= num_samples && state.resolution == 1);
+ return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1);
}
bool TileManager::next()
@@ -175,9 +187,9 @@ bool TileManager::next()
if(done())
return false;
- if(progressive && state.resolution > 1) {
+ if(progressive && state.resolution_divider > 1) {
state.sample = 0;
- state.resolution /= 2;
+ state.resolution_divider /= 2;
state.num_samples = 1;
set_tiles();
}
@@ -189,7 +201,7 @@ bool TileManager::next()
else
state.num_samples = num_samples;
- state.resolution = 1;
+ state.resolution_divider = 1;
set_tiles();
}
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index 29f2b1ef9f9..d820f74e3bd 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -51,13 +51,13 @@ public:
BufferParams buffer;
int sample;
int num_samples;
- int resolution;
+ int resolution_divider;
int num_tiles;
int num_rendered_tiles;
list<Tile> tiles;
} state;
- TileManager(bool progressive, int num_samples, int2 tile_size, int resolution, int num_devices = 1);
+ TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution, int num_devices = 1);
~TileManager();
void reset(BufferParams& params, int num_samples);
@@ -72,10 +72,8 @@ protected:
bool progressive;
int num_samples;
int2 tile_size;
- int resolution;
- int num_devices;
-
int start_resolution;
+ int num_devices;
list<Tile>::iterator next_center_tile(int device = 0);
};
diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt
index 75f70753ddf..c0986e9c173 100644
--- a/intern/cycles/subd/CMakeLists.txt
+++ b/intern/cycles/subd/CMakeLists.txt
@@ -6,6 +6,8 @@ set(INC
../kernel/svm
../render
)
+set(INC_SYS
+)
set(SRC
subd_build.cpp
@@ -31,5 +33,6 @@ set(SRC_HEADERS
)
include_directories(${INC})
+include_directories(SYSTEM ${INC_SYS})
add_library(cycles_subd ${SRC} ${SRC_HEADERS})
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index ae8403a14a8..c677f2b13f4 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -1,6 +1,8 @@
set(INC
.
+)
+set(INC_SYS
${GLEW_INCLUDE_PATH}
${OPENGL_INCLUDE_DIR}
)
@@ -64,5 +66,6 @@ set(SRC_HEADERS
)
include_directories(${INC})
+include_directories(SYSTEM ${INC_SYS})
add_library(cycles_util ${SRC} ${SRC_HEADERS})
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 71a5dedeaa4..0b6f020ade5 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -26,7 +26,9 @@
#ifndef __KERNEL_OPENCL__
-#define _USE_MATH_DEFINES
+#ifdef _MSC_VER
+# define _USE_MATH_DEFINES
+#endif
#include <float.h>
#include <math.h>
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index 2b209c135f4..ea0abd6f54f 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -38,8 +38,6 @@ TaskPool::~TaskPool()
void TaskPool::push(Task *task, bool front)
{
- thread_scoped_lock num_lock(num_mutex);
-
TaskScheduler::Entry entry;
entry.task = task;
@@ -104,17 +102,22 @@ void TaskPool::wait_work()
void TaskPool::cancel()
{
- thread_scoped_lock num_lock(num_mutex);
-
do_cancel = true;
TaskScheduler::clear(this);
+
+ {
+ thread_scoped_lock num_lock(num_mutex);
+
+ while(num)
+ num_cond.wait(num_lock);
+ }
+
+ do_cancel = false;
}
void TaskPool::stop()
{
- thread_scoped_lock num_lock(num_mutex);
-
TaskScheduler::clear(this);
assert(num == 0);
@@ -127,20 +130,20 @@ bool TaskPool::cancelled()
void TaskPool::num_decrease(int done)
{
+ num_mutex.lock();
num -= done;
+
assert(num >= 0);
-
- if(num == 0) {
- do_cancel = false;
-
+ if(num == 0)
num_cond.notify_all();
- }
+
+ num_mutex.unlock();
}
void TaskPool::num_increase()
{
+ thread_scoped_lock num_lock(num_mutex);
num++;
-
num_cond.notify_all();
}
@@ -236,11 +239,7 @@ void TaskScheduler::thread_run(int thread_id)
delete entry.task;
/* notify pool task was done */
- {
- /* not called from TaskPool, have to explicitly lock the mutex here */
- thread_scoped_lock num_lock(entry.pool->num_mutex);
- entry.pool->num_decrease(1);
- }
+ entry.pool->num_decrease(1);
}
}
diff --git a/intern/dualcon/intern/Projections.cpp b/intern/dualcon/intern/Projections.cpp
index 2a52cc9972a..f00d998591f 100644
--- a/intern/dualcon/intern/Projections.cpp
+++ b/intern/dualcon/intern/Projections.cpp
@@ -92,12 +92,12 @@ static void crossProduct(double res[3], const double a[3], const double b[3])
/**
* Method to perform dot product
*/
-int64_t dotProduct(const int64_t a[3], const int64_t b[3])
+static int64_t dotProduct(const int64_t a[3], const int64_t b[3])
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
-void normalize(double a[3])
+static void normalize(double a[3])
{
double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
if (mag > 0) {
diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp
index 894ab6b0873..c96415bfb54 100644
--- a/intern/dualcon/intern/dualcon_c_api.cpp
+++ b/intern/dualcon/intern/dualcon_c_api.cpp
@@ -32,7 +32,7 @@
#define isnan(n) _isnan(n)
#endif
-void veccopy(float dst[3], const float src[3])
+static void veccopy(float dst[3], const float src[3])
{
dst[0] = src[0];
dst[1] = src[1];
diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp
index 9f44e7bbfdf..c74f8bf2f46 100644
--- a/intern/dualcon/intern/octree.cpp
+++ b/intern/dualcon/intern/octree.cpp
@@ -345,11 +345,13 @@ void Octree::addTriangle(Triangle *trian, int triind)
delete proj;
}
-void print_depth(int height, int maxDepth)
+#if 0
+static void print_depth(int height, int maxDepth)
{
for (int i = 0; i < maxDepth - height; i++)
printf(" ");
}
+#endif
InternalNode *Octree::addTriangle(InternalNode *node, CubeTriangleIsect *p, int height)
{
@@ -2108,8 +2110,8 @@ void pseudoInverse(const _Matrix_Type_ &a,
svd.matrixU().adjoint();
}
-void solve_least_squares(const float halfA[], const float b[],
- const float midpoint[], float rvalue[])
+static void solve_least_squares(const float halfA[], const float b[],
+ const float midpoint[], float rvalue[])
{
/* calculate pseudo-inverse */
Eigen::MatrixXf A(3, 3), pinv(3, 3);
@@ -2126,8 +2128,8 @@ void solve_least_squares(const float halfA[], const float b[],
rvalue[i] = result(i);
}
-void minimize(float rvalue[3], float mp[3], const float pts[12][3],
- const float norms[12][3], const int parity[12])
+static void minimize(float rvalue[3], float mp[3], const float pts[12][3],
+ const float norms[12][3], const int parity[12])
{
float ata[6] = {0, 0, 0, 0, 0, 0};
float atb[3] = {0, 0, 0};
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index ae30458a5e5..87ab3c013c6 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -387,11 +387,12 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
* \param windowhandle The handle to the window
* \param mode The new grab state of the cursor.
* \param bounds The grab ragion (optional) - left,top,right,bottom
+ * \param mouse_ungrab_xy XY for new mouse location (optional) - x,y
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
GHOST_TGrabCursorMode mode,
- int *bounds);
+ int bounds[4], int mouse_ungrab_xy[2]);
/***************************************************************************************
* Access to mouse button and keyboard states.
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index a1a1acfca75..7ec6417ca4f 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -303,7 +303,7 @@ public:
* \param grab The new grab state of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds) { return GHOST_kSuccess; }
+ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { return GHOST_kSuccess; }
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow")
diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h
index e52d6a7e6a0..aa7969d68ad 100644
--- a/intern/ghost/GHOST_Rect.h
+++ b/intern/ghost/GHOST_Rect.h
@@ -70,8 +70,7 @@ public:
/**
* Destructor.
*/
- virtual ~GHOST_Rect()
- {};
+ virtual ~GHOST_Rect() {}
/**
* Access to rectangle width.
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 0a4325930d5..88d02c46f61 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -355,10 +355,11 @@ GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
GHOST_TGrabCursorMode mode,
- int *bounds)
+ int bounds[4], int mouse_ungrab_xy[2])
{
GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
GHOST_Rect bounds_rect, bounds_win;
+ GHOST_TInt32 mouse_ungrab_xy_global[2];
if (bounds) {
/* if this is X11 specific we need a function that converts */
@@ -368,7 +369,16 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
}
- return window->setCursorGrab(mode, bounds ? &bounds_rect : NULL);
+ if (mouse_ungrab_xy) {
+ if (bounds == NULL)
+ window->getClientBounds(bounds_win);
+ window->clientToScreen(mouse_ungrab_xy[0], bounds_win.getHeight() - mouse_ungrab_xy[1],
+ mouse_ungrab_xy_global[0], mouse_ungrab_xy_global[1]);
+ }
+
+ return window->setCursorGrab(mode,
+ bounds ? &bounds_rect : NULL,
+ mouse_ungrab_xy ? mouse_ungrab_xy_global : NULL);
}
diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp
index b8660b3038e..014eef85aa8 100644
--- a/intern/ghost/intern/GHOST_EventManager.cpp
+++ b/intern/ghost/intern/GHOST_EventManager.cpp
@@ -70,7 +70,7 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
{
GHOST_TUns32 numEvents = 0;
TEventStack::iterator p;
- for (p = m_events.begin(); p != m_events.end(); p++) {
+ for (p = m_events.begin(); p != m_events.end(); ++p) {
if ((*p)->getType() == type) {
numEvents++;
}
@@ -82,7 +82,7 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
GHOST_IEvent *GHOST_EventManager::peekEvent()
{
GHOST_IEvent *event = 0;
- if (m_events.size() > 0) {
+ if (m_events.empty() == false) {
event = m_events.back();
}
return event;
@@ -110,7 +110,7 @@ bool GHOST_EventManager::dispatchEvent(GHOST_IEvent *event)
if (event) {
handled = true;
TConsumerVector::iterator iter;
- for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) {
+ for (iter = m_consumers.begin(); iter != m_consumers.end(); ++iter) {
if ((*iter)->processEvent(event)) {
handled = false;
}
@@ -212,7 +212,7 @@ void GHOST_EventManager::removeWindowEvents(GHOST_IWindow *window)
iter = m_events.begin();
}
else {
- iter++;
+ ++iter;
}
}
}
@@ -236,7 +236,7 @@ void GHOST_EventManager::removeTypeEvents(GHOST_TEventType type, GHOST_IWindow *
iter = m_events.begin();
}
else {
- iter++;
+ ++iter;
}
}
}
@@ -254,7 +254,7 @@ GHOST_IEvent *GHOST_EventManager::popEvent()
void GHOST_EventManager::disposeEvents()
{
- while (m_events.size() > 0) {
+ while (m_events.empty() == false) {
GHOST_ASSERT(m_events[0], "invalid event");
delete m_events[0];
m_events.pop_front();
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index 2baf0f6fa42..2c213752f94 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -107,7 +107,7 @@ class GHOST_NDOFManager
public:
GHOST_NDOFManager(GHOST_System&);
- virtual ~GHOST_NDOFManager() {};
+ virtual ~GHOST_NDOFManager() {}
// whether multi-axis functionality is available (via the OS or driver)
// does not imply that a device is plugged in or being used
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 7bc40287dc3..fed3bdbc8f0 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -355,16 +355,18 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
/* alphanumerical or punctuation key that is remappable in int'l keyboards */
if ((recvChar >= 'A') && (recvChar <= 'Z')) {
return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
- } else if ((recvChar >= 'a') && (recvChar <= 'z')) {
+ }
+ else if ((recvChar >= 'a') && (recvChar <= 'z')) {
return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
- } else {
+ }
+ else {
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
KeyboardLayoutRef keyLayout;
UCKeyboardLayout *uchrData;
KLGetCurrentKeyboardLayout(&keyLayout);
KLGetKeyboardLayoutProperty(keyLayout, kKLuchrData, (const void **)
- &uchrData);
+ &uchrData);
/*get actual character value of the "remappable" keys in int'l keyboards,
if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
then fallback on using the received charactersIgnoringModifiers */
@@ -457,7 +459,8 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
buf[FIRSTFILEBUFLG - 1] = '\0';
return 1;
- } else {
+ }
+ else {
return 0;
}
}
@@ -870,29 +873,30 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
// SetMouseCoalescingEnabled(false, NULL);
//TODO : implement timer ??
-
- /*do {
+#if 0
+ do {
GHOST_TimerManager* timerMgr = getTimerManager();
if (waitForEvent) {
- GHOST_TUns64 next = timerMgr->nextFireTime();
- double timeOut;
-
- if (next == GHOST_kFireTimeNever) {
- timeOut = kEventDurationForever;
- } else {
- timeOut = (double)(next - getMilliSeconds())/1000.0;
- if (timeOut < 0.0)
- timeOut = 0.0;
- }
+ GHOST_TUns64 next = timerMgr->nextFireTime();
+ double timeOut;
+
+ if (next == GHOST_kFireTimeNever) {
+ timeOut = kEventDurationForever;
+ }
+ else {
+ timeOut = (double)(next - getMilliSeconds())/1000.0;
+ if (timeOut < 0.0)
+ timeOut = 0.0;
+ }
- ::ReceiveNextEvent(0, NULL, timeOut, false, &event);
+ ::ReceiveNextEvent(0, NULL, timeOut, false, &event);
}
if (timerMgr->fireTimers(getMilliSeconds())) {
- anyProcessed = true;
+ anyProcessed = true;
}
- */
+#endif
do {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -963,7 +967,9 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
[NSApp sendEvent:event];
[pool drain];
} while (event!= nil);
- //} while (waitForEvent && !anyProcessed); Needed only for timer implementation
+#if 0
+ } while (waitForEvent && !anyProcessed); // Needed only for timer implementation
+#endif
if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent();
@@ -1285,12 +1291,13 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
if (m_windowManager->getAnyModifiedState())
{
int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved.\nDo you really want to quit ?",
- @"Cancel", @"Quit Anyway", nil);
+ @"Cancel", @"Quit Anyway", nil);
if (shouldQuit == NSAlertAlternateReturn)
{
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );
return GHOST_kExitNow;
- } else {
+ }
+ else {
//Give back focus to the blender window if user selected cancel quit
NSArray *windowsList = [NSApp orderedWindows];
if ([windowsList count]) {
@@ -1405,7 +1412,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventT
ct.Active = GHOST_kTabletModeNone;
break;
}
- } else {
+ }
+ else {
// pointer is leaving - return to mouse
ct.Active = GHOST_kTabletModeNone;
}
@@ -1694,7 +1702,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
if ([event type] == NSKeyDown) {
pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyDown, window, keyCode, ascii, utf8_buf) );
//printf("Key down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf);
- } else {
+ }
+ else {
pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyUp, window, keyCode, 0, '\0') );
//printf("Key up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf);
}
@@ -1780,7 +1789,8 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
if(temp_buff) {
return temp_buff;
- } else {
+ }
+ else {
return NULL;
}
}
diff --git a/intern/ghost/intern/GHOST_SystemPaths.h b/intern/ghost/intern/GHOST_SystemPaths.h
index 53cad347293..22879c71e1e 100644
--- a/intern/ghost/intern/GHOST_SystemPaths.h
+++ b/intern/ghost/intern/GHOST_SystemPaths.h
@@ -40,13 +40,13 @@ protected:
* Constructor.
* Protected default constructor to force use of static createSystem member.
*/
- GHOST_SystemPaths() {};
+ GHOST_SystemPaths() {}
/**
* Destructor.
* Protected default constructor to force use of static dispose member.
*/
- virtual ~GHOST_SystemPaths() {};
+ virtual ~GHOST_SystemPaths() {}
public:
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index e75ecfb641e..232bea6749b 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -983,8 +983,7 @@ GHOST_SystemX11::processEvent(XEvent *xe)
default: {
#ifdef WITH_X11_XINPUT
- if (xe->type == window->GetXTablet().MotionEvent)
- {
+ if (xe->type == window->GetXTablet().MotionEvent) {
XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
/* stroke might begin without leading ProxyIn event,
@@ -993,23 +992,23 @@ GHOST_SystemX11::processEvent(XEvent *xe)
setTabletMode(window, data->deviceid);
window->GetXTablet().CommonData.Pressure =
- data->axis_data[2] / ((float)window->GetXTablet().PressureLevels);
-
+ data->axis_data[2] / ((float)window->GetXTablet().PressureLevels);
+
/* the (short) cast and the &0xffff is bizarre and unexplained anywhere,
* but I got garbage data without it. Found it in the xidump.c source --matt */
window->GetXTablet().CommonData.Xtilt =
- (short)(data->axis_data[3] & 0xffff) / ((float)window->GetXTablet().XtiltLevels);
+ (short)(data->axis_data[3] & 0xffff) / ((float)window->GetXTablet().XtiltLevels);
window->GetXTablet().CommonData.Ytilt =
- (short)(data->axis_data[4] & 0xffff) / ((float)window->GetXTablet().YtiltLevels);
+ (short)(data->axis_data[4] & 0xffff) / ((float)window->GetXTablet().YtiltLevels);
}
- else if (xe->type == window->GetXTablet().ProxInEvent)
- {
+ else if (xe->type == window->GetXTablet().ProxInEvent) {
XProximityNotifyEvent *data = (XProximityNotifyEvent *)xe;
setTabletMode(window, data->deviceid);
}
- else if (xe->type == window->GetXTablet().ProxOutEvent)
+ else if (xe->type == window->GetXTablet().ProxOutEvent) {
window->GetXTablet().CommonData.Active = GHOST_kTabletModeNone;
+ }
#endif // WITH_X11_XINPUT
break;
}
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 92bffe46357..bc556490d12 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -210,8 +210,8 @@ public:
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
XIM
- getX11_XIM(
- ) {
+ getX11_XIM()
+ {
return m_xim;
}
#endif
@@ -235,7 +235,7 @@ public:
*/
void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
-#if WITH_XDND
+#ifdef WITH_XDND
/**
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
* Called by GHOST_DropTargetX11 class.
diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp
index b1186507028..601359984de 100644
--- a/intern/ghost/intern/GHOST_TimerManager.cpp
+++ b/intern/ghost/intern/GHOST_TimerManager.cpp
@@ -104,7 +104,7 @@ GHOST_TUns64 GHOST_TimerManager::nextFireTime()
GHOST_TUns64 smallest = GHOST_kFireTimeNever;
TTimerVector::iterator iter;
- for (iter = m_timers.begin(); iter != m_timers.end(); iter++) {
+ for (iter = m_timers.begin(); iter != m_timers.end(); ++iter) {
GHOST_TUns64 next = (*iter)->getNext();
if (next < smallest)
@@ -119,7 +119,7 @@ bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time)
TTimerVector::iterator iter;
bool anyProcessed = false;
- for (iter = m_timers.begin(); iter != m_timers.end(); iter++) {
+ for (iter = m_timers.begin(); iter != m_timers.end(); ++iter) {
if (fireTimer(time, *iter))
anyProcessed = true;
}
@@ -156,7 +156,7 @@ bool GHOST_TimerManager::fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task)
void GHOST_TimerManager::disposeTimers()
{
- while (m_timers.size() > 0) {
+ while (m_timers.empty() == false) {
delete m_timers[0];
m_timers.erase(m_timers.begin());
}
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index eb80a073b44..fd3ff4f85f0 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -38,6 +38,7 @@
#include "GHOST_Window.h"
+#include <assert.h>
GHOST_Window::GHOST_Window(
GHOST_TUns32 width, GHOST_TUns32 height,
@@ -105,11 +106,18 @@ GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible)
}
}
-GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds)
+GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2])
{
if (m_cursorGrab == mode)
return GHOST_kSuccess;
+ /* override with new location */
+ if (mouse_ungrab_xy) {
+ assert(mode == GHOST_kGrabDisable);
+ m_cursorGrabInitPos[0] = mouse_ungrab_xy[0];
+ m_cursorGrabInitPos[1] = mouse_ungrab_xy[1];
+ }
+
if (setWindowCursorGrab(mode)) {
if (mode == GHOST_kGrabDisable)
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 3043b107aa1..fd870327fd4 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -178,7 +178,7 @@ public:
* \param mode The new grab state of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds);
+ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]);
/**
* Gets the cursor grab region, if unset the window is used.
@@ -192,14 +192,14 @@ public:
*/
virtual GHOST_TSuccess setProgressBar(float progress) {
return GHOST_kFailure;
- };
+ }
/**
* Hides the progress bar in the icon
*/
virtual GHOST_TSuccess endProgressBar() {
return GHOST_kFailure;
- };
+ }
/**
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
@@ -284,7 +284,7 @@ protected:
*/
virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) {
return GHOST_kSuccess;
- };
+ }
/**
* Sets the cursor shape on the window using
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 31589003131..dc05fe42a70 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -670,7 +670,8 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title)
[m_window setRepresentedFilename:@""];
}
- } else {
+ }
+ else {
[m_window setTitle:windowTitle];
[m_window setRepresentedFilename:@""];
}
@@ -1288,7 +1289,8 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c
if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
tmpCursor = m_customCursor;
- } else {
+ }
+ else {
switch (cursor) {
case GHOST_kStandardCursorDestroy:
tmpCursor = [NSCursor disappearingItemCursor];
diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp
index 1816c57a150..daf1c2f2d22 100644
--- a/intern/ghost/intern/GHOST_WindowManager.cpp
+++ b/intern/ghost/intern/GHOST_WindowManager.cpp
@@ -195,7 +195,7 @@ GHOST_IWindow *GHOST_WindowManager::getWindowAssociatedWithOSWindow(void *osWind
{
std::vector<GHOST_IWindow *>::iterator iter;
- for (iter = m_windows.begin(); iter != m_windows.end(); iter++) {
+ for (iter = m_windows.begin(); iter != m_windows.end(); ++iter) {
if ((*iter)->getOSWindow() == osWindow)
return *iter;
}
@@ -208,7 +208,7 @@ bool GHOST_WindowManager::getAnyModifiedState()
bool isAnyModified = false;
std::vector<GHOST_IWindow *>::iterator iter;
- for (iter = m_windows.begin(); iter != m_windows.end(); iter++) {
+ for (iter = m_windows.begin(); iter != m_windows.end(); ++iter) {
if ((*iter)->getModifiedState())
isAnyModified = true;
}
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 4ad95fcab53..dd1930a241b 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -76,7 +76,7 @@ typedef struct {
*/
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
-#define _NET_WM_STATE_TOGGLE 2
+// #define _NET_WM_STATE_TOGGLE 2 // UNUSED
/*
import bpy
@@ -1326,7 +1326,7 @@ GHOST_WindowX11::
c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
- for (; it != m_standard_cursors.end(); it++) {
+ for (; it != m_standard_cursors.end(); ++it) {
XFreeCursor(m_display, it->second);
}
diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c
index 0eb37a58be2..aba80784a72 100644
--- a/intern/ghost/test/multitest/EventToBuf.c
+++ b/intern/ghost/test/multitest/EventToBuf.c
@@ -208,7 +208,8 @@ void event_to_buf(GHOST_EventHandle evt, char buf[128])
char *s= GHOST_GetTitle(win);
pos += sprintf(pos, " - win: %s", s);
free(s);
- } else {
+ }
+ else {
pos+= sprintf(pos, " - sys evt");
}
switch (type) {
diff --git a/intern/guardedalloc/test/simpletest/memtest.c b/intern/guardedalloc/test/simpletest/memtest.c
index 7c6a0a2d546..749e2500dd1 100644
--- a/intern/guardedalloc/test/simpletest/memtest.c
+++ b/intern/guardedalloc/test/simpletest/memtest.c
@@ -94,7 +94,8 @@ int main (int argc, char *argv[])
if (verbose) {
if (error_status) {
fprintf(stderr, "|--* Memory test FAILED\n|\n");
- } else {
+ }
+ else {
fprintf(stderr, "|--* Memory tested as good (as it should be)\n|\n");
}
}
@@ -130,7 +131,8 @@ int main (int argc, char *argv[])
if (verbose) {
if (retval) {
fprintf(stderr, "|--* Memory test failed (as it should be)\n");
- } else {
+ }
+ else {
fprintf(stderr, "|--* Memory test FAILED to find corrupted blocks \n");
}
}
@@ -147,7 +149,8 @@ int main (int argc, char *argv[])
if (verbose) {
if (error_status) {
fprintf(stderr,"|\n|--* Errors were detected\n");
- } else {
+ }
+ else {
fprintf(stderr,"|\n|--* Test exited succesfully\n");
}
diff --git a/intern/iksolver/intern/IK_QJacobianSolver.h b/intern/iksolver/intern/IK_QJacobianSolver.h
index ead2b150b40..646f952b9ff 100644
--- a/intern/iksolver/intern/IK_QJacobianSolver.h
+++ b/intern/iksolver/intern/IK_QJacobianSolver.h
@@ -53,12 +53,12 @@ class IK_QJacobianSolver
{
public:
IK_QJacobianSolver();
- ~IK_QJacobianSolver() {};
+ ~IK_QJacobianSolver() {}
// setup pole vector constraint
void SetPoleVectorConstraint(IK_QSegment *tip, MT_Vector3& goal,
MT_Vector3& polegoal, float poleangle, bool getangle);
- float GetPoleAngle() { return m_poleangle; };
+ float GetPoleAngle() { return m_poleangle; }
// call setup once before solving, if it fails don't solve
bool Setup(IK_QSegment *root, std::list<IK_QTask*>& tasks);
diff --git a/intern/iksolver/intern/IK_QSegment.h b/intern/iksolver/intern/IK_QSegment.h
index 25a8fbc0804..b40bf3739ff 100644
--- a/intern/iksolver/intern/IK_QSegment.h
+++ b/intern/iksolver/intern/IK_QSegment.h
@@ -158,10 +158,10 @@ public:
virtual void UpdateAngleApply()=0;
// set joint limits
- virtual void SetLimit(int, MT_Scalar, MT_Scalar) {};
+ virtual void SetLimit(int, MT_Scalar, MT_Scalar) {}
// set joint weights (per axis)
- virtual void SetWeight(int, MT_Scalar) {};
+ virtual void SetWeight(int, MT_Scalar) {}
virtual void SetBasis(const MT_Matrix3x3& basis) { m_basis = basis; }
diff --git a/intern/iksolver/intern/IK_QTask.h b/intern/iksolver/intern/IK_QTask.h
index 45b1e59e606..baf1c346d62 100644
--- a/intern/iksolver/intern/IK_QTask.h
+++ b/intern/iksolver/intern/IK_QTask.h
@@ -49,7 +49,7 @@ public:
bool active,
const IK_QSegment *segment
);
- virtual ~IK_QTask() {};
+ virtual ~IK_QTask() {}
int Id() const
{ return m_size; }
@@ -119,7 +119,7 @@ public:
const MT_Matrix3x3& goal
);
- MT_Scalar Distance() const { return m_distance; };
+ MT_Scalar Distance() const { return m_distance; }
void ComputeJacobian(IK_QJacobian& jacobian);
private:
diff --git a/intern/iksolver/intern/IK_Solver.cpp b/intern/iksolver/intern/IK_Solver.cpp
index 6c2e30932bb..c1a4ffcb1e8 100644
--- a/intern/iksolver/intern/IK_Solver.cpp
+++ b/intern/iksolver/intern/IK_Solver.cpp
@@ -43,7 +43,7 @@ using namespace std;
class IK_QSolver {
public:
IK_QSolver() : root(NULL) {
- };
+ }
IK_QJacobianSolver solver;
IK_QSegment *root;
@@ -51,7 +51,7 @@ public:
};
// FIXME: locks still result in small "residual" changes to the locked axes...
-IK_QSegment *CreateSegment(int flag, bool translate)
+static IK_QSegment *CreateSegment(int flag, bool translate)
{
int ndof = 0;
ndof += (flag & IK_XDOF) ? 1 : 0;
@@ -348,7 +348,7 @@ float IK_SolverGetPoleAngle(IK_Solver *solver)
return qsolver->solver.GetPoleAngle();
}
-void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3], float weight)
+static void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3], float weight)
{
if (solver == NULL || root == NULL)
return;
diff --git a/intern/iksolver/intern/MT_ExpMap.h b/intern/iksolver/intern/MT_ExpMap.h
index 9485428dc9f..65bbe4d4ad5 100644
--- a/intern/iksolver/intern/MT_ExpMap.h
+++ b/intern/iksolver/intern/MT_ExpMap.h
@@ -103,7 +103,7 @@ public:
const MT_Quaternion &q
) {
setRotation(q);
- };
+ }
/**
* Accessors
@@ -118,7 +118,7 @@ public:
vector(
) const {
return m_v;
- };
+ }
/**
* Set the exponential map from a quaternion
diff --git a/intern/iksolver/intern/TNT/cmat.h b/intern/iksolver/intern/TNT/cmat.h
index 146afdc79d7..fd3a1851262 100644
--- a/intern/iksolver/intern/TNT/cmat.h
+++ b/intern/iksolver/intern/TNT/cmat.h
@@ -182,7 +182,7 @@ class Matrix
// constructors
- Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
+ Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {}
Matrix(const Matrix<T> &A)
{
diff --git a/intern/iksolver/intern/TNT/vec.h b/intern/iksolver/intern/TNT/vec.h
index ff1b5c0ea0e..5d4ef14bf73 100644
--- a/intern/iksolver/intern/TNT/vec.h
+++ b/intern/iksolver/intern/TNT/vec.h
@@ -164,7 +164,7 @@ class Vector
// constructors
- Vector() : v_(0), vm1_(0), n_(0) {};
+ Vector() : v_(0), vm1_(0), n_(0) {}
Vector(const Vector<T> &A) : v_(0), vm1_(0), n_(0)
{
diff --git a/intern/itasc/kdl/utilities/utility_io.cpp b/intern/itasc/kdl/utilities/utility_io.cpp
index e16a85167bc..8656b05545c 100644
--- a/intern/itasc/kdl/utilities/utility_io.cpp
+++ b/intern/itasc/kdl/utilities/utility_io.cpp
@@ -39,7 +39,7 @@ namespace KDL {
}
}
// Eats until the end of the line
- int _EatUntilEndOfLine( std::istream& is, int* countp=NULL) {
+static int _EatUntilEndOfLine( std::istream& is, int* countp=NULL) {
int ch;
int count;
count = 0;
@@ -53,7 +53,7 @@ namespace KDL {
}
// Eats until the end of the comment
- int _EatUntilEndOfComment( std::istream& is, int* countp=NULL) {
+static int _EatUntilEndOfComment( std::istream& is, int* countp=NULL) {
int ch;
int count;
count = 0;
@@ -75,7 +75,7 @@ namespace KDL {
// Eats space-like characters and comments
// possibly returns the number of space-like characters eaten.
-int _EatSpace( std::istream& is,int* countp=NULL) {
+static int _EatSpace( std::istream& is,int* countp=NULL) {
int ch;
int count;
count=-1;
diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h
index 801ee154d40..cfff5d10e4f 100644
--- a/intern/memutil/MEM_CacheLimiter.h
+++ b/intern/memutil/MEM_CacheLimiter.h
@@ -123,20 +123,11 @@ public:
parent->touch(this);
}
- void set_priority(int priority) {
- this->priority = priority;
- }
-
- int get_priority(void) {
- return this->priority;
- }
-
private:
friend class MEM_CacheLimiter<T>;
T * data;
int refcount;
- int priority;
typename std::list<MEM_CacheLimiterHandle<T> *, MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator me;
MEM_CacheLimiter<T> * parent;
};
@@ -171,7 +162,6 @@ public:
}
void enforce_limits() {
- MEM_CachePriorityQueue priority_queue;
size_t max = MEM_CacheLimiter_get_maximum();
size_t mem_in_use, cur_size;
@@ -179,9 +169,10 @@ public:
return;
}
- if(getDataSize) {
+ if (getDataSize) {
mem_in_use = total_size();
- } else {
+ }
+ else {
mem_in_use = MEM_get_memory_in_use();
}
@@ -189,23 +180,24 @@ public:
return;
}
- priority_queue = get_priority_queue();
-
- while (!priority_queue.empty() && mem_in_use > max) {
- MEM_CacheElementPtr elem = priority_queue.top();
+ while (!queue.empty() && mem_in_use > max) {
+ MEM_CacheElementPtr elem = get_least_priority_destroyable_element();
- priority_queue.pop();
+ if (!elem)
+ break;
- if(getDataSize) {
+ if (getDataSize) {
cur_size = getDataSize(elem->get()->get_data());
- } else {
+ }
+ else {
cur_size = mem_in_use;
}
if (elem->destroy_if_possible()) {
if (getDataSize) {
mem_in_use -= cur_size;
- } else {
+ }
+ else {
mem_in_use -= cur_size - MEM_get_memory_in_use();
}
}
@@ -229,14 +221,6 @@ private:
typedef std::list<MEM_CacheElementPtr, MEM_Allocator<MEM_CacheElementPtr> > MEM_CacheQueue;
typedef typename MEM_CacheQueue::iterator iterator;
- struct compare_element_priority : public std::binary_function<MEM_CacheElementPtr, MEM_CacheElementPtr, bool> {
- bool operator()(const MEM_CacheElementPtr left_elem, const MEM_CacheElementPtr right_elem) const {
- return left_elem->get_priority() > right_elem->get_priority();
- }
- };
-
- typedef std::priority_queue<MEM_CacheElementPtr, std::vector<MEM_CacheElementPtr>, compare_element_priority > MEM_CachePriorityQueue;
-
size_t total_size() {
size_t size = 0;
for (iterator it = queue.begin(); it != queue.end(); it++) {
@@ -245,28 +229,35 @@ private:
return size;
}
- MEM_CachePriorityQueue get_priority_queue(void) {
- MEM_CachePriorityQueue priority_queue;
+ MEM_CacheElementPtr get_least_priority_destroyable_element(void) {
+ if (queue.empty())
+ return NULL;
+
+ if (!getItemPriority)
+ return *queue.begin();
+
+ MEM_CacheElementPtr best_match_elem = NULL;
+ int best_match_priority = 0;
iterator it;
int i;
for (it = queue.begin(), i = 0; it != queue.end(); it++, i++) {
MEM_CacheElementPtr elem = *it;
- int priority;
+
+ if (!elem->can_destroy())
+ continue;
/* by default 0 means higherst priority element */
- priority = -(queue.size() - i - 1);
+ int priority = -(queue.size() - i - 1);
+ priority = getItemPriority(elem->get()->get_data(), priority);
- if (getItemPriority) {
- priority = getItemPriority(elem->get()->get_data(), priority);
+ if (priority < best_match_priority || best_match_elem == NULL) {
+ best_match_priority = priority;
+ best_match_elem = elem;
}
-
- elem->set_priority(priority);
-
- priority_queue.push(elem);
}
- return priority_queue;
+ return best_match_elem;
}
MEM_CacheQueue queue;
diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h
index 722a0a8fd3b..09cf5c95854 100644
--- a/intern/memutil/MEM_SmartPtr.h
+++ b/intern/memutil/MEM_SmartPtr.h
@@ -86,7 +86,7 @@
* private :
* MEM_SmartPtr<foo> m_foo;
* }
- *
+ *
* You may also safely construct vectors of MEM_SmartPtrs and
* have the vector own stuff you put into it.
*
@@ -167,7 +167,7 @@ public :
Ref(
) const {
return *m_val;
- }
+ }
/**
* Assignment operator - ownership is transfered from rhs to lhs.
@@ -207,7 +207,7 @@ public :
Release(
) const {
T* temp = m_val;
- (const_cast<MEM_SmartPtr *>(this))->m_val = NULL;
+ (const_cast<MEM_SmartPtr *>(this))->m_val = NULL;
return temp;
}
diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c
index a1ae6bd81c0..a6597986c0a 100644
--- a/intern/mikktspace/mikktspace.c
+++ b/intern/mikktspace/mikktspace.c
@@ -1063,6 +1063,7 @@ static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupT
const int iNrMaxGroups = iNrTrianglesIn*3;
int iNrActiveGroups = 0;
int iOffset = 0, f=0, i=0;
+ (void)iNrMaxGroups; /* quiet warnings in non debug mode */
for (f=0; f<iNrTrianglesIn; f++)
{
for (i=0; i<3; i++)
@@ -1094,6 +1095,7 @@ static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupT
const tbool bOrPre2 = (pTriInfos[neigh_indexL].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE;
const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE;
assert(bAnswer || bDiff);
+ (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */
}
if (neigh_indexR>=0) // neighbor
{
@@ -1104,6 +1106,7 @@ static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupT
const tbool bOrPre2 = (pTriInfos[neigh_indexR].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE;
const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE;
assert(bAnswer || bDiff);
+ (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */
}
// update offset
diff --git a/intern/opencolorio/ocio_capi.cpp b/intern/opencolorio/ocio_capi.cpp
index ec8012cc30f..cc45eb9b2dd 100644
--- a/intern/opencolorio/ocio_capi.cpp
+++ b/intern/opencolorio/ocio_capi.cpp
@@ -47,13 +47,13 @@
#endif
#define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type()
-#define MEM_DELETE(what, type) { what->~type(); MEM_freeN(what); } (void)0
+#define MEM_DELETE(what, type) if(what) { what->~type(); MEM_freeN(what); } (void)0
static void OCIO_reportError(const char *err)
{
std::cerr << "OpenColorIO Error: " << err << std::endl;
- OCIO_abort();
+ // OCIO_abort();
}
static void OCIO_reportException(Exception &exception)
@@ -75,6 +75,13 @@ ConstConfigRcPtr *OCIO_getCurrentConfig(void)
OCIO_reportException(exception);
}
+ MEM_DELETE(config, ConstConfigRcPtr);
+
+ return NULL;
+}
+
+ConstConfigRcPtr *OCIO_getDefaultConfig(void)
+{
return NULL;
}
@@ -102,6 +109,8 @@ ConstConfigRcPtr *OCIO_configCreateFromEnv(void)
OCIO_reportException(exception);
}
+ MEM_DELETE(config, ConstConfigRcPtr);
+
return NULL;
}
@@ -120,6 +129,8 @@ ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename)
OCIO_reportException(exception);
}
+ MEM_DELETE(config, ConstConfigRcPtr);
+
return NULL;
}
@@ -164,9 +175,10 @@ ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const c
}
catch (Exception &exception) {
OCIO_reportException(exception);
- MEM_DELETE(cs, ConstColorSpaceRcPtr);
}
+ MEM_DELETE(cs, ConstColorSpaceRcPtr);
+
return NULL;
}
@@ -290,6 +302,11 @@ int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs)
return true;
}
+int OCIO_colorSpaceIsData(ConstColorSpaceRcPtr *cs)
+{
+ return ((*cs)->isData());
+}
+
void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs)
{
MEM_DELETE(cs, ConstColorSpaceRcPtr);
@@ -309,6 +326,8 @@ ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config,
OCIO_reportException(exception);
}
+ MEM_DELETE(p, ConstProcessorRcPtr);
+
return 0;
}
@@ -326,6 +345,8 @@ ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTran
OCIO_reportException(exception);
}
+ MEM_DELETE(p, ConstProcessorRcPtr);
+
return NULL;
}
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index f0edd25ac14..0218ccfafcd 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -59,6 +59,7 @@ extern "C" {
ConstConfigRcPtr *OCIO_getCurrentConfig(void);
+ConstConfigRcPtr *OCIO_getDefaultConfig(void);
void OCIO_setCurrentConfig(const ConstConfigRcPtr *config);
ConstConfigRcPtr *OCIO_configCreateFromEnv(void);
@@ -72,6 +73,7 @@ ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const c
int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name);
int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs);
+int OCIO_colorSpaceIsData(ConstColorSpaceRcPtr *cs);
void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs);
diff --git a/intern/opencolorio/ocio_capi_stub.cpp b/intern/opencolorio/ocio_capi_stub.cpp
index a601cd3be91..2112b88ad72 100644
--- a/intern/opencolorio/ocio_capi_stub.cpp
+++ b/intern/opencolorio/ocio_capi_stub.cpp
@@ -56,6 +56,11 @@ ConstConfigRcPtr *OCIO_getCurrentConfig(void)
return CONFIG_DEFAULT;
}
+ConstConfigRcPtr *OCIO_getDefaultConfig(void)
+{
+ return CONFIG_DEFAULT;
+}
+
void OCIO_setCurrentConfig(const ConstConfigRcPtr *)
{
}
@@ -169,6 +174,11 @@ int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs)
return 1;
}
+int OCIO_colorSpaceIsData(ConstColorSpaceRcPtr *cs)
+{
+ return 0;
+}
+
void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs)
{
}
diff --git a/intern/raskter/CMakeLists.txt b/intern/raskter/CMakeLists.txt
index de6d2c33b7f..3e1368d8eb0 100644
--- a/intern/raskter/CMakeLists.txt
+++ b/intern/raskter/CMakeLists.txt
@@ -33,11 +33,8 @@ set(INC_SYS
set(SRC
raskter.c
- raskter_mt.c
- raskter_kdtree.c
raskter.h
- raskter_kdtree.h
)
blender_add_lib(bf_intern_raskter "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c
index 875dfc8a63b..c79bcc4a76d 100644
--- a/intern/raskter/raskter.c
+++ b/intern/raskter/raskter.c
@@ -24,28 +24,49 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
/** \file raskter.c
* \ingroup RASKTER
*/
#include <stdlib.h>
#include "raskter.h"
-//#define __PLX__FAKE_AA__
-//#define __PLX_KD_TREE__
-#ifdef __PLX_KD_TREE__
-#include "kdtree.h"
-#endif
-
-
-// this is needed for inlining behavior
-#if defined _MSC_VER
-# define DO_INLINE __inline
-#elif defined (__sun) || defined (__sun__)
-# define DO_INLINE
-#else
-# define DO_INLINE static inline
-#endif
+/* from BLI_utildefines.h */
+#define MIN2(x, y) ( (x) < (y) ? (x) : (y) )
+#define MAX2(x, y) ( (x) > (y) ? (x) : (y) )
+
+struct PolyVert {
+ int x;
+ int y;
+};
+
+struct e_Status {
+ int x;
+ int ybeg;
+ int xshift;
+ int xdir;
+ int drift;
+ int drift_inc;
+ int drift_dec;
+ int num;
+ struct e_Status *e_next;
+};
+
+struct r_BufferStats {
+ float *buf;
+ int sizex;
+ int sizey;
+ int ymin;
+ int ymax;
+ int xmin;
+ int xmax;
+};
+
+struct r_FillContext {
+ struct e_Status *all_edges, *possible_edges;
+ struct r_BufferStats rb;
+};
/*
* Sort all the edges of the input polygon by Y, then by X, of the "first" vertex encountered.
@@ -55,113 +76,121 @@
* just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate
* for now.
*/
-void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge) {
- int i;
- int xbeg;
- int ybeg;
- int xend;
- int yend;
- int dx;
- int dy;
- int temp_pos;
- int xdist;
- struct e_status *e_new;
- struct e_status *next_edge;
- struct e_status **next_edge_ref;
- struct poly_vert *v;
- /* set up pointers */
- v = verts;
- ctx->all_edges = NULL;
- /* initialize some boundaries */
- ctx->rb.xmax = v[0].x;
- ctx->rb.xmin = v[0].x;
- ctx->rb.ymax = v[0].y;
- ctx->rb.ymin = v[0].y;
- /* loop all verts */
- for(i = 0; i < num_verts; i++) {
- /* determine beginnings and endings of edges, linking last vertex to first vertex */
- xbeg = v[i].x;
- ybeg = v[i].y;
- /* keep track of our x and y bounds */
- if(xbeg >= ctx->rb.xmax) {
- ctx->rb.xmax = xbeg;
- } else if(xbeg <= ctx->rb.xmin) {
- ctx->rb.xmin = xbeg;
- }
- if(ybeg >= ctx->rb.ymax) {
- ctx->rb.ymax= ybeg;
- } else if(ybeg <= ctx->rb.ymin) {
- ctx->rb.ymin=ybeg;
- }
- if(i) {
- /* we're not at the last vert, so end of the edge is the previous vertex */
- xend = v[i - 1].x;
- yend = v[i - 1].y;
- } else {
- /* we're at the first vertex, so the "end" of this edge is the last vertex */
- xend = v[num_verts - 1].x;
- yend = v[num_verts - 1].y;
- }
- /* make sure our edges are facing the correct direction */
- if(ybeg > yend) {
- /* flip the Xs */
- temp_pos = xbeg;
- xbeg = xend;
- xend = temp_pos;
- /* flip the Ys */
- temp_pos = ybeg;
- ybeg = yend;
- yend = temp_pos;
- }
-
- /* calculate y delta */
- dy = yend - ybeg;
- /* dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) */
- if(dy) {
- /* create the edge and determine it's slope (for incremental line drawing) */
- e_new = open_edge++;
-
- /* calculate x delta */
- dx = xend - xbeg;
- if(dx > 0) {
- e_new->xdir = 1;
- xdist = dx;
- } else {
- e_new->xdir = -1;
- xdist = -dx;
- }
-
- e_new->x = xbeg;
- e_new->ybeg = ybeg;
- e_new->num = dy;
- e_new->drift_dec = dy;
-
- /* calculate deltas for incremental drawing */
- if(dx >= 0) {
- e_new->drift = 0;
- } else {
- e_new->drift = -dy + 1;
- }
- if(dy >= xdist) {
- e_new->drift_inc = xdist;
- e_new->xshift = 0;
- } else {
- e_new->drift_inc = xdist % dy;
- e_new->xshift = (xdist / dy) * e_new->xdir;
- }
- next_edge_ref = &ctx->all_edges;
- /* link in all the edges, in sorted order */
- for(;;) {
- next_edge = *next_edge_ref;
- if(!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) {
- e_new->e_next = next_edge;
- *next_edge_ref = e_new;
- break;
- }
- next_edge_ref = &next_edge->e_next;
- }
- }
- }
+static void preprocess_all_edges(struct r_FillContext *ctx,
+ struct PolyVert *verts, int num_verts, struct e_Status *open_edge)
+{
+ int i;
+ int xbeg;
+ int ybeg;
+ int xend;
+ int yend;
+ int dx;
+ int dy;
+ int temp_pos;
+ int xdist;
+ struct e_Status *e_new;
+ struct e_Status *next_edge;
+ struct e_Status **next_edge_ref;
+ struct PolyVert *v;
+ /* set up pointers */
+ v = verts;
+ ctx->all_edges = NULL;
+ /* initialize some boundaries */
+ ctx->rb.xmax = v[0].x;
+ ctx->rb.xmin = v[0].x;
+ ctx->rb.ymax = v[0].y;
+ ctx->rb.ymin = v[0].y;
+ /* loop all verts */
+ for (i = 0; i < num_verts; i++) {
+ /* determine beginnings and endings of edges, linking last vertex to first vertex */
+ xbeg = v[i].x;
+ ybeg = v[i].y;
+ /* keep track of our x and y bounds */
+ if (xbeg >= ctx->rb.xmax) {
+ ctx->rb.xmax = xbeg;
+ }
+ else if (xbeg <= ctx->rb.xmin) {
+ ctx->rb.xmin = xbeg;
+ }
+ if (ybeg >= ctx->rb.ymax) {
+ ctx->rb.ymax= ybeg;
+ }
+ else if (ybeg <= ctx->rb.ymin) {
+ ctx->rb.ymin=ybeg;
+ }
+ if (i) {
+ /* we're not at the last vert, so end of the edge is the previous vertex */
+ xend = v[i - 1].x;
+ yend = v[i - 1].y;
+ }
+ else {
+ /* we're at the first vertex, so the "end" of this edge is the last vertex */
+ xend = v[num_verts - 1].x;
+ yend = v[num_verts - 1].y;
+ }
+ /* make sure our edges are facing the correct direction */
+ if (ybeg > yend) {
+ /* flip the Xs */
+ temp_pos = xbeg;
+ xbeg = xend;
+ xend = temp_pos;
+ /* flip the Ys */
+ temp_pos = ybeg;
+ ybeg = yend;
+ yend = temp_pos;
+ }
+
+ /* calculate y delta */
+ dy = yend - ybeg;
+ /* dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) */
+ if (dy) {
+ /* create the edge and determine it's slope (for incremental line drawing) */
+ e_new = open_edge++;
+
+ /* calculate x delta */
+ dx = xend - xbeg;
+ if (dx > 0) {
+ e_new->xdir = 1;
+ xdist = dx;
+ }
+ else {
+ e_new->xdir = -1;
+ xdist = -dx;
+ }
+
+ e_new->x = xbeg;
+ e_new->ybeg = ybeg;
+ e_new->num = dy;
+ e_new->drift_dec = dy;
+
+ /* calculate deltas for incremental drawing */
+ if (dx >= 0) {
+ e_new->drift = 0;
+ }
+ else {
+ e_new->drift = -dy + 1;
+ }
+ if (dy >= xdist) {
+ e_new->drift_inc = xdist;
+ e_new->xshift = 0;
+ }
+ else {
+ e_new->drift_inc = xdist % dy;
+ e_new->xshift = (xdist / dy) * e_new->xdir;
+ }
+ next_edge_ref = &ctx->all_edges;
+ /* link in all the edges, in sorted order */
+ for (;;) {
+ next_edge = *next_edge_ref;
+ if (!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) {
+ e_new->e_next = next_edge;
+ *next_edge_ref = e_new;
+ break;
+ }
+ next_edge_ref = &next_edge->e_next;
+ }
+ }
+ }
}
/*
@@ -169,1364 +198,261 @@ void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, i
* for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need
* if it ends up being coupled with this function.
*/
-static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, float intensity) {
- int x_curr; /* current pixel position in X */
- int y_curr; /* current scan line being drawn */
- int yp; /* y-pixel's position in frame buffer */
- int swixd = 0; /* whether or not edges switched position in X */
- float *cpxl; /* pixel pointers... */
- float *mpxl;
- float *spxl;
- struct e_status *e_curr; /* edge pointers... */
- struct e_status *e_temp;
- struct e_status *edgbuf;
- struct e_status **edgec;
-
-
- /*
- * If the number of verts specified to render as a polygon is less than 3,
- * return immediately. Obviously we cant render a poly with sides < 3. The
- * return for this we set to 1, simply so it can be distinguished from the
- * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter.
- * which is a failure to allocate memory.
- */
- if(num_verts < 3) {
- return(1);
- }
-
- /*
- * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data
- * multiplied by the number of edges, which is always equal to the number of verts in
- * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for
- * the preceeding error, which was a rasterization request on a 2D poly with less than
- * 3 sides.
- */
- if((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) {
- return(0);
- }
-
- /*
- * Do some preprocessing on all edges. This constructs a table structure in memory of all
- * the edge properties and can "flip" some edges so sorting works correctly.
- */
- preprocess_all_edges(ctx, verts, num_verts, edgbuf);
-
- /* can happen with a zero area mask */
- if (ctx->all_edges == NULL) {
- free(edgbuf);
- return(1);
- }
- /*
- * Set the pointer for tracking the edges currently in processing to NULL to make sure
- * we don't get some crazy value after initialization.
- */
- ctx->possible_edges = NULL;
-
- /*
- * Loop through all scan lines to be drawn. Since we sorted by Y values during
- * preprocess_all_edges(), we can already exact values for the lowest and
- * highest Y values we could possibly need by induction. The preprocessing sorted
- * out edges by Y position, we can cycle the current edge being processed once
- * it runs out of Y pixels. When we have no more edges, meaning the current edge
- * is NULL after setting the "current" edge to be the previous current edge's
- * "next" edge in the Y sorted edge connection chain, we can stop looping Y values,
- * since we can't possibly have more scan lines if we ran out of edges. :)
- *
- * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here.
- * Will get changed once DEM code gets in.
- */
- for(y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) {
-
- /*
- * Link any edges that start on the current scan line into the list of
- * edges currently needed to draw at least this, if not several, scan lines.
- */
-
- /*
- * Set the current edge to the beginning of the list of edges to be rasterized
- * into this scan line.
- *
- * We could have lots of edge here, so iterate over all the edges needed. The
- * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting
- * so we safely cycle edges to thier own "next" edges in order.
- *
- * At each iteration, make sure we still have a non-NULL edge.
- */
- for(edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) {
- x_curr = ctx->all_edges->x; /* Set current X position. */
- for(;;) { /* Start looping edges. Will break when edges run out. */
- e_curr = *edgec; /* Set up a current edge pointer. */
- if(!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */
- e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */
- *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */
- ctx->all_edges->e_next = e_curr; /* Set up the next edge. */
- edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */
- ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */
- break; /* Stop looping edges (since we ran out or hit empty X span. */
- } else {
- edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */
- }
- }
- }
-
- /*
- * Determine the current scan line's offset in the pixel buffer based on its Y position.
- * Basically we just multiply the current scan line's Y value by the number of pixels in each line.
- */
- yp = y_curr * ctx->rb.sizex;
- /*
- * Set a "scan line pointer" in memory. The location of the buffer plus the row offset.
- */
- spxl = ctx->rb.buf + (yp);
- /*
- * Set up the current edge to the first (in X) edge. The edges which could possibly be in this
- * list were determined in the preceeding edge loop above. They were already sorted in X by the
- * initial processing function.
- *
- * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge
- * we will eventually hit a NULL when the list runs out.
- */
- for(e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) {
- /*
- * Calculate a span of pixels to fill on the current scan line.
- *
- * Set the current pixel pointer by adding the X offset to the scan line's start offset.
- * Cycle the current edge the next edge.
- * Set the max X value to draw to be one less than the next edge's first pixel. This way we are
- * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than
- * one time because it's on a vertex connecting two edges)
- *
- * Then blast through all the pixels in the span, advancing the pointer and setting the color to white.
- *
- * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor,
- * but for now it is done here until the DEM code comes in.
- */
-
- /* set up xmin and xmax bounds on this scan line */
- cpxl = spxl + MAX2(e_curr->x, 0);
- e_curr = e_curr->e_next;
- mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1;
-
- if((y_curr >= 0) && (y_curr < ctx->rb.sizey)) {
- /* draw the pixels. */
- for(; cpxl <= mpxl; *cpxl++ += intensity);
- }
- }
-
- /*
- * Loop through all edges of polygon that could be hit by this scan line,
- * and figure out their x-intersections with the next scan line.
- *
- * Either A.) we wont have any more edges to test, or B.) we just add on the
- * slope delta computed in preprocessing step. Since this draws non-antialiased
- * polygons, we dont have fractional positions, so we only move in x-direction
- * when needed to get all the way to the next pixel over...
- */
- for(edgec = &ctx->possible_edges; (e_curr = *edgec);) {
- if(!(--(e_curr->num))) {
- *edgec = e_curr->e_next;
- } else {
- e_curr->x += e_curr->xshift;
- if((e_curr->drift += e_curr->drift_inc) > 0) {
- e_curr->x += e_curr->xdir;
- e_curr->drift -= e_curr->drift_dec;
- }
- edgec = &e_curr->e_next;
- }
- }
- /*
- * It's possible that some edges may have crossed during the last step, so we'll be sure
- * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges
- * sorted by x-intersection coordinate. We'll always scan through at least once to see if
- * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial
- * pass, then we know we need to sort by x, so then cycle through edges again and perform
- * the sort.-
- */
- if(ctx->possible_edges) {
- for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
- /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */
- if(e_curr->x > e_curr->e_next->x) {
- *edgec = e_curr->e_next;
- /* exchange the pointers */
- e_temp = e_curr->e_next->e_next;
- e_curr->e_next->e_next = e_curr;
- e_curr->e_next = e_temp;
- /* set flag that we had at least one switch */
- swixd = 1;
- }
- }
- /* if we did have a switch, look for more (there will more if there was one) */
- for(;;) {
- /* reset exchange flag so it's only set if we encounter another one */
- swixd = 0;
- for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
- /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */
- if(e_curr->x > e_curr->e_next->x) {
- *edgec = e_curr->e_next;
- /* exchange the pointers */
- e_temp = e_curr->e_next->e_next;
- e_curr->e_next->e_next = e_curr;
- e_curr->e_next = e_temp;
- /* flip the exchanged flag */
- swixd = 1;
- }
- }
- /* if we had no exchanges, we're done reshuffling the pointers */
- if(!swixd) {
- break;
- }
- }
- }
- }
-
- free(edgbuf);
- return 1;
+static int rast_scan_fill(struct r_FillContext *ctx, struct PolyVert *verts, int num_verts, float intensity)
+{
+ int x_curr; /* current pixel position in X */
+ int y_curr; /* current scan line being drawn */
+ int yp; /* y-pixel's position in frame buffer */
+ int swixd = 0; /* whether or not edges switched position in X */
+ float *cpxl; /* pixel pointers... */
+ float *mpxl;
+ float *spxl;
+ struct e_Status *e_curr; /* edge pointers... */
+ struct e_Status *e_temp;
+ struct e_Status *edgbuf;
+ struct e_Status **edgec;
+
+
+ /*
+ * If the number of verts specified to render as a polygon is less than 3,
+ * return immediately. Obviously we cant render a poly with sides < 3. The
+ * return for this we set to 1, simply so it can be distinguished from the
+ * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter.
+ * which is a failure to allocate memory.
+ */
+ if (num_verts < 3) {
+ return(1);
+ }
+
+ /*
+ * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data
+ * multiplied by the number of edges, which is always equal to the number of verts in
+ * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for
+ * the preceeding error, which was a rasterization request on a 2D poly with less than
+ * 3 sides.
+ */
+ if ((edgbuf = (struct e_Status *)(malloc(sizeof(struct e_Status) * num_verts))) == NULL) {
+ return(0);
+ }
+
+ /*
+ * Do some preprocessing on all edges. This constructs a table structure in memory of all
+ * the edge properties and can "flip" some edges so sorting works correctly.
+ */
+ preprocess_all_edges(ctx, verts, num_verts, edgbuf);
+
+ /* can happen with a zero area mask */
+ if (ctx->all_edges == NULL) {
+ free(edgbuf);
+ return(1);
+ }
+ /*
+ * Set the pointer for tracking the edges currently in processing to NULL to make sure
+ * we don't get some crazy value after initialization.
+ */
+ ctx->possible_edges = NULL;
+
+ /*
+ * Loop through all scan lines to be drawn. Since we sorted by Y values during
+ * preprocess_all_edges(), we can already exact values for the lowest and
+ * highest Y values we could possibly need by induction. The preprocessing sorted
+ * out edges by Y position, we can cycle the current edge being processed once
+ * it runs out of Y pixels. When we have no more edges, meaning the current edge
+ * is NULL after setting the "current" edge to be the previous current edge's
+ * "next" edge in the Y sorted edge connection chain, we can stop looping Y values,
+ * since we can't possibly have more scan lines if we ran out of edges. :)
+ *
+ * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here.
+ * Will get changed once DEM code gets in.
+ */
+ for (y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) {
+
+ /*
+ * Link any edges that start on the current scan line into the list of
+ * edges currently needed to draw at least this, if not several, scan lines.
+ */
+
+ /*
+ * Set the current edge to the beginning of the list of edges to be rasterized
+ * into this scan line.
+ *
+ * We could have lots of edge here, so iterate over all the edges needed. The
+ * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting
+ * so we safely cycle edges to thier own "next" edges in order.
+ *
+ * At each iteration, make sure we still have a non-NULL edge.
+ */
+ for (edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) {
+ x_curr = ctx->all_edges->x; /* Set current X position. */
+ for (;;) { /* Start looping edges. Will break when edges run out. */
+ e_curr = *edgec; /* Set up a current edge pointer. */
+ if (!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */
+ e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */
+ *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */
+ ctx->all_edges->e_next = e_curr; /* Set up the next edge. */
+ edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */
+ ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */
+ break; /* Stop looping edges (since we ran out or hit empty X span. */
+ }
+ else {
+ edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */
+ }
+ }
+ }
+
+ /*
+ * Determine the current scan line's offset in the pixel buffer based on its Y position.
+ * Basically we just multiply the current scan line's Y value by the number of pixels in each line.
+ */
+ yp = y_curr * ctx->rb.sizex;
+ /*
+ * Set a "scan line pointer" in memory. The location of the buffer plus the row offset.
+ */
+ spxl = ctx->rb.buf + (yp);
+ /*
+ * Set up the current edge to the first (in X) edge. The edges which could possibly be in this
+ * list were determined in the preceeding edge loop above. They were already sorted in X by the
+ * initial processing function.
+ *
+ * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge
+ * we will eventually hit a NULL when the list runs out.
+ */
+ for (e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) {
+ /*
+ * Calculate a span of pixels to fill on the current scan line.
+ *
+ * Set the current pixel pointer by adding the X offset to the scan line's start offset.
+ * Cycle the current edge the next edge.
+ * Set the max X value to draw to be one less than the next edge's first pixel. This way we are
+ * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than
+ * one time because it's on a vertex connecting two edges)
+ *
+ * Then blast through all the pixels in the span, advancing the pointer and setting the color to white.
+ *
+ * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor,
+ * but for now it is done here until the DEM code comes in.
+ */
+
+ /* set up xmin and xmax bounds on this scan line */
+ cpxl = spxl + MAX2(e_curr->x, 0);
+ e_curr = e_curr->e_next;
+ mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1;
+
+ if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) {
+ /* draw the pixels. */
+ for (; cpxl <= mpxl; *cpxl++ += intensity) {}
+ }
+ }
+
+ /*
+ * Loop through all edges of polygon that could be hit by this scan line,
+ * and figure out their x-intersections with the next scan line.
+ *
+ * Either A.) we wont have any more edges to test, or B.) we just add on the
+ * slope delta computed in preprocessing step. Since this draws non-antialiased
+ * polygons, we dont have fractional positions, so we only move in x-direction
+ * when needed to get all the way to the next pixel over...
+ */
+ for (edgec = &ctx->possible_edges; (e_curr = *edgec);) {
+ if (!(--(e_curr->num))) {
+ *edgec = e_curr->e_next;
+ }
+ else {
+ e_curr->x += e_curr->xshift;
+ if ((e_curr->drift += e_curr->drift_inc) > 0) {
+ e_curr->x += e_curr->xdir;
+ e_curr->drift -= e_curr->drift_dec;
+ }
+ edgec = &e_curr->e_next;
+ }
+ }
+ /*
+ * It's possible that some edges may have crossed during the last step, so we'll be sure
+ * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges
+ * sorted by x-intersection coordinate. We'll always scan through at least once to see if
+ * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial
+ * pass, then we know we need to sort by x, so then cycle through edges again and perform
+ * the sort.-
+ */
+ if (ctx->possible_edges) {
+ for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
+ /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */
+ if (e_curr->x > e_curr->e_next->x) {
+ *edgec = e_curr->e_next;
+ /* exchange the pointers */
+ e_temp = e_curr->e_next->e_next;
+ e_curr->e_next->e_next = e_curr;
+ e_curr->e_next = e_temp;
+ /* set flag that we had at least one switch */
+ swixd = 1;
+ }
+ }
+ /* if we did have a switch, look for more (there will more if there was one) */
+ for (;;) {
+ /* reset exchange flag so it's only set if we encounter another one */
+ swixd = 0;
+ for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
+ /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */
+ if (e_curr->x > e_curr->e_next->x) {
+ *edgec = e_curr->e_next;
+ /* exchange the pointers */
+ e_temp = e_curr->e_next->e_next;
+ e_curr->e_next->e_next = e_curr;
+ e_curr->e_next = e_temp;
+ /* flip the exchanged flag */
+ swixd = 1;
+ }
+ }
+ /* if we had no exchanges, we're done reshuffling the pointers */
+ if (!swixd) {
+ break;
+ }
+ }
+ }
+ }
+
+ free(edgbuf);
+ return 1;
}
int PLX_raskterize(float(*base_verts)[2], int num_base_verts,
- float *buf, int buf_x, int buf_y, int do_mask_AA) {
- int subdiv_AA = (do_mask_AA != 0)? 0:0;
- int i; /* i: Loop counter. */
- int sAx;
- int sAy;
- struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */
- struct r_fill_context ctx = {0};
- const float buf_x_f = (float)(buf_x);
- const float buf_y_f = (float)(buf_y);
- float div_offset=(1.0f / (float)(subdiv_AA));
- float div_offset_static = 0.5f * (float)(subdiv_AA) * div_offset;
- /*
- * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert
- * data structure multiplied by the number of base_verts.
- *
- * In the event of a failure to allocate the memory, return 0, so this error can
- * be distinguished as a memory allocation error.
- */
- if((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) {
- return(0);
- }
-
- ctx.rb.buf = buf; /* Set the output buffer pointer. */
- ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */
- ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */
- /*
- * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are
- * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates
- * in the buffer-space coordinates passed in inside buf_x and buf_y.
- *
- * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel
- * drawn will be 1.0f in value, there is no anti-aliasing.
- */
-
- if(!subdiv_AA) {
- for(i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */
- ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */
- ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */
- }
-
- i = rast_scan_fill(&ctx, ply, num_base_verts,1.0f); /* Call our rasterizer, passing in the integer coords for each vert. */
- } else {
- for(sAx=0; sAx < subdiv_AA; sAx++) {
- for(sAy=0; sAy < subdiv_AA; sAy++) {
- for(i=0; i < num_base_verts; i++) {
- ply[i].x = (int)((base_verts[i][0]*buf_x_f)+0.5f - div_offset_static + (div_offset*(float)(sAx)));
- ply[i].y = (int)((base_verts[i][1]*buf_y_f)+0.5f - div_offset_static + (div_offset*(float)(sAy)));
- }
- i = rast_scan_fill(&ctx, ply, num_base_verts,(1.0f / (float)(subdiv_AA*subdiv_AA)));
- }
- }
- }
- free(ply); /* Free the memory allocated for the integer coordinate table. */
- return(i); /* Return the value returned by the rasterizer. */
-}
-
-/*
- * This function clips drawing to the frame buffer. That clipping will likely be moved into the preprocessor
- * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need
- * if it ends up being coupled with this function.
- */
-static int rast_scan_feather(struct r_fill_context *ctx,
- float(*base_verts_f)[2], int num_base_verts,
- struct poly_vert *feather_verts, float(*feather_verts_f)[2], int num_feather_verts) {
- int x_curr; /* current pixel position in X */
- int y_curr; /* current scan line being drawn */
- int yp; /* y-pixel's position in frame buffer */
- int swixd = 0; /* whether or not edges switched position in X */
- float *cpxl; /* pixel pointers... */
- float *mpxl;
- float *spxl;
- struct e_status *e_curr; /* edge pointers... */
- struct e_status *e_temp;
- struct e_status *edgbuf;
- struct e_status **edgec;
-
- /* from dem */
- int a; // a = temporary pixel index buffer loop counter
- float fsz; // size of the frame
- unsigned int rsl; // long used for finding fast 1.0/sqrt
- float rsf; // float used for finding fast 1.0/sqrt
- const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt
-
- //unsigned int gradientFillOffset;
- float t;
- float ud; // ud = unscaled edge distance
- float dmin; // dmin = minimum edge distance
- float odist; // odist = current outer edge distance
- float idist; // idist = current inner edge distance
- float dx; // dx = X-delta (used for distance proportion calculation)
- float dy; // dy = Y-delta (used for distance proportion calculation)
- float xpxw = (1.0f / (float)(ctx->rb.sizex)); // xpxw = normalized pixel width
- float ypxh = (1.0f / (float)(ctx->rb.sizey)); // ypxh = normalized pixel height
-#ifdef __PLX_KD_TREE__
- void *res_kdi;
- void *res_kdo;
- float clup[2];
-#endif
-
- /*
- * If the number of verts specified to render as a polygon is less than 3,
- * return immediately. Obviously we cant render a poly with sides < 3. The
- * return for this we set to 1, simply so it can be distinguished from the
- * next place we could return,
- * which is a failure to allocate memory.
- */
- if(num_feather_verts < 3) {
- return(1);
- }
-
- /*
- * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data
- * multiplied by the number of edges, which is always equal to the number of verts in
- * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for
- * the preceeding error, which was a rasterization request on a 2D poly with less than
- * 3 sides.
- */
- if((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_feather_verts))) == NULL) {
- return(0);
- }
-
- /*
- * Do some preprocessing on all edges. This constructs a table structure in memory of all
- * the edge properties and can "flip" some edges so sorting works correctly.
- */
- preprocess_all_edges(ctx, feather_verts, num_feather_verts, edgbuf);
-
- /* can happen with a zero area mask */
- if (ctx->all_edges == NULL) {
- free(edgbuf);
- return(1);
- }
-
- /*
- * Set the pointer for tracking the edges currently in processing to NULL to make sure
- * we don't get some crazy value after initialization.
- */
- ctx->possible_edges = NULL;
-
- /*
- * Loop through all scan lines to be drawn. Since we sorted by Y values during
- * preprocess_all_edges(), we can already exact values for the lowest and
- * highest Y values we could possibly need by induction. The preprocessing sorted
- * out edges by Y position, we can cycle the current edge being processed once
- * it runs out of Y pixels. When we have no more edges, meaning the current edge
- * is NULL after setting the "current" edge to be the previous current edge's
- * "next" edge in the Y sorted edge connection chain, we can stop looping Y values,
- * since we can't possibly have more scan lines if we ran out of edges. :)
- *
- * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here.
- * Will get changed once DEM code gets in.
- */
- for(y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) {
-
- /*
- * Link any edges that start on the current scan line into the list of
- * edges currently needed to draw at least this, if not several, scan lines.
- */
-
- /*
- * Set the current edge to the beginning of the list of edges to be rasterized
- * into this scan line.
- *
- * We could have lots of edge here, so iterate over all the edges needed. The
- * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting
- * so we safely cycle edges to thier own "next" edges in order.
- *
- * At each iteration, make sure we still have a non-NULL edge.
- */
- for(edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) {
- x_curr = ctx->all_edges->x; /* Set current X position. */
- for(;;) { /* Start looping edges. Will break when edges run out. */
- e_curr = *edgec; /* Set up a current edge pointer. */
- if(!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */
- e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */
- *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */
- ctx->all_edges->e_next = e_curr; /* Set up the next edge. */
- edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */
- ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */
- break; /* Stop looping edges (since we ran out or hit empty X span. */
- } else {
- edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */
- }
- }
- }
-
- /*
- * Determine the current scan line's offset in the pixel buffer based on its Y position.
- * Basically we just multiply the current scan line's Y value by the number of pixels in each line.
- */
- yp = y_curr * ctx->rb.sizex;
- /*
- * Set a "scan line pointer" in memory. The location of the buffer plus the row offset.
- */
- spxl = ctx->rb.buf + (yp);
- /*
- * Set up the current edge to the first (in X) edge. The edges which could possibly be in this
- * list were determined in the preceeding edge loop above. They were already sorted in X by the
- * initial processing function.
- *
- * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge
- * we will eventually hit a NULL when the list runs out.
- */
- for(e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) {
- /*
- * Calculate a span of pixels to fill on the current scan line.
- *
- * Set the current pixel pointer by adding the X offset to the scan line's start offset.
- * Cycle the current edge the next edge.
- * Set the max X value to draw to be one less than the next edge's first pixel. This way we are
- * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than
- * one time because it's on a vertex connecting two edges)
- *
- * Then blast through all the pixels in the span, advancing the pointer and setting the color to white.
- *
- * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor,
- * but for now it is done here until the DEM code comes in.
- */
-
- /* set up xmin and xmax bounds on this scan line */
- cpxl = spxl + MAX2(e_curr->x, 0);
- e_curr = e_curr->e_next;
- mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1;
-
- if((y_curr >= 0) && (y_curr < ctx->rb.sizey)) {
- t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * xpxw;
- fsz = ((float)(y_curr) + 0.5f) * ypxh;
- /* draw the pixels. */
- for(; cpxl <= mpxl; cpxl++, t += xpxw) {
- //do feather check
- // first check that pixel isn't already full, and only operate if it is not
- if(*cpxl < 0.9999f) {
-#ifndef __PLX_KD_TREE__
- dmin = 2.0f; // reset min distance to edge pixel
- for(a = 0; a < num_feather_verts; a++) { // loop through all outer edge buffer pixels
- dx = t - feather_verts_f[a][0]; // set dx to gradient pixel column - outer edge pixel row
- dy = fsz - feather_verts_f[a][1]; // set dy to gradient pixel row - outer edge pixel column
- ud = dx * dx + dy * dy; // compute sum of squares
- if(ud < dmin) { // if our new sum of squares is less than the current minimum
- dmin = ud; // set a new minimum equal to the new lower value
- }
- }
- odist = dmin; // cast outer min to a float
- rsf = odist * 0.5f; //
- rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored
- rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate
- odist = *(float *)&rsl; // reciprocal square root
- odist = odist * (rsopf - (rsf * odist * odist)); // -- ** this line can be iterated for more accuracy ** --
- odist = odist * (rsopf - (rsf * odist * odist));
- dmin = 2.0f; // reset min distance to edge pixel
- for(a = 0; a < num_base_verts; a++) { // loop through all inside edge pixels
- dx = t - base_verts_f[a][0]; // compute delta in Y from gradient pixel to inside edge pixel
- dy = fsz - base_verts_f[a][1]; // compute delta in X from gradient pixel to inside edge pixel
- ud = dx * dx + dy * dy; // compute sum of squares
- if(ud < dmin) { // if our new sum of squares is less than the current minimum we've found
- dmin = ud; // set a new minimum equal to the new lower value
- }
- }
- idist = dmin; // cast inner min to a float
- rsf = idist * 0.5f; //
- rsl = *(unsigned int *)&idist; //
- rsl = 0x5f3759df - (rsl >> 1); // see notes above
- idist = *(float *)&rsl; //
- idist = idist * (rsopf - (rsf * idist * idist)); //
- idist = idist * (rsopf - (rsf * idist * idist));
- /*
- * Note once again that since we are using reciprocals of distance values our
- * proportion is already the correct intensity, and does not need to be
- * subtracted from 1.0 like it would have if we used real distances.
- */
-#else
- clup[0]=t;
- clup[1]=fsz;
- res_kdi=kd_nearestf(ctx->kdi,clup);
- res_kdo=kd_nearestf(ctx->kdo,clup);
- kd_res_itemf(res_kdi,clup);
- dx=t-clup[0];
- dy=fsz-clup[1];
- idist=dx*dx+dy*dy;
- rsf = idist * 0.5f; //
- rsl = *(unsigned int *)&idist; //
- rsl = 0x5f3759df - (rsl >> 1); // see notes above
- idist = *(float *)&rsl; //
- idist = idist * (rsopf - (rsf * idist * idist)); //
- idist = idist * (rsopf - (rsf * idist * idist));
- kd_res_itemf(res_kdo,clup);
- dx=t-clup[0];
- dy=fsz-clup[1];
- odist=dx*dx+dy*dy;
- rsf = odist * 0.5f; //
- rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored
- rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate
- odist = *(float *)&rsl; // reciprocal square root
- odist = odist * (rsopf - (rsf * odist * odist)); // -- ** this line can be iterated for more accuracy ** --
- odist = odist * (rsopf - (rsf * odist * odist));
-
-#endif
- /* set intensity, do the += so overlapping gradients are additive */
- *cpxl = (idist / (idist+odist));
- }
- }
- }
- }
-
- /*
- * Loop through all edges of polygon that could be hit by this scan line,
- * and figure out their x-intersections with the next scan line.
- *
- * Either A.) we wont have any more edges to test, or B.) we just add on the
- * slope delta computed in preprocessing step. Since this draws non-antialiased
- * polygons, we dont have fractional positions, so we only move in x-direction
- * when needed to get all the way to the next pixel over...
- */
- for(edgec = &ctx->possible_edges; (e_curr = *edgec);) {
- if(!(--(e_curr->num))) {
- *edgec = e_curr->e_next;
- } else {
- e_curr->x += e_curr->xshift;
- if((e_curr->drift += e_curr->drift_inc) > 0) {
- e_curr->x += e_curr->xdir;
- e_curr->drift -= e_curr->drift_dec;
- }
- edgec = &e_curr->e_next;
- }
- }
- /*
- * It's possible that some edges may have crossed during the last step, so we'll be sure
- * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges
- * sorted by x-intersection coordinate. We'll always scan through at least once to see if
- * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial
- * pass, then we know we need to sort by x, so then cycle through edges again and perform
- * the sort.-
- */
- if(ctx->possible_edges) {
- for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
- /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */
- if(e_curr->x > e_curr->e_next->x) {
- *edgec = e_curr->e_next;
- /* exchange the pointers */
- e_temp = e_curr->e_next->e_next;
- e_curr->e_next->e_next = e_curr;
- e_curr->e_next = e_temp;
- /* set flag that we had at least one switch */
- swixd = 1;
- }
- }
- /* if we did have a switch, look for more (there will more if there was one) */
- for(;;) {
- /* reset exchange flag so it's only set if we encounter another one */
- swixd = 0;
- for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
- /* again, if current edge hits scan line at higher X than next edge,
- * exchange the edges and set flag */
- if(e_curr->x > e_curr->e_next->x) {
- *edgec = e_curr->e_next;
- /* exchange the pointers */
- e_temp = e_curr->e_next->e_next;
- e_curr->e_next->e_next = e_curr;
- e_curr->e_next = e_temp;
- /* flip the exchanged flag */
- swixd = 1;
- }
- }
- /* if we had no exchanges, we're done reshuffling the pointers */
- if(!swixd) {
- break;
- }
- }
- }
- }
-
- free(edgbuf);
- return 1;
+ float *buf, int buf_x, int buf_y)
+{
+ int i; /* i: Loop counter. */
+ struct PolyVert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */
+ struct r_FillContext ctx = {0};
+ const float buf_x_f = (float)(buf_x);
+ const float buf_y_f = (float)(buf_y);
+ /*
+ * Allocate enough memory for our PolyVert list. It'll be the size of the PolyVert
+ * data structure multiplied by the number of base_verts.
+ *
+ * In the event of a failure to allocate the memory, return 0, so this error can
+ * be distinguished as a memory allocation error.
+ */
+ if ((ply = (struct PolyVert *)(malloc(sizeof(struct PolyVert) * num_base_verts))) == NULL) {
+ return(0);
+ }
+
+ ctx.rb.buf = buf; /* Set the output buffer pointer. */
+ ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */
+ ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */
+ /*
+ * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are
+ * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates
+ * in the buffer-space coordinates passed in inside buf_x and buf_y.
+ *
+ * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel
+ * drawn will be 1.0f in value, there is no anti-aliasing.
+ */
+
+ for (i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */
+ ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */
+ ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */
+ }
+
+ i = rast_scan_fill(&ctx, ply, num_base_verts,1.0f); /* Call our rasterizer, passing in the integer coords for each vert. */
+
+ free(ply); /* Free the memory allocated for the integer coordinate table. */
+ return(i); /* Return the value returned by the rasterizer. */
}
-
-int PLX_raskterize_feather(float(*base_verts)[2], int num_base_verts, float(*feather_verts)[2], int num_feather_verts,
- float *buf, int buf_x, int buf_y) {
- //void plx_floatsort(float(*f)[2], unsigned int n, int sortby);
- int i; /* i: Loop counter. */
- struct poly_vert *fe; /* fe: Pointer to a list of integer buffer-space feather vertex coords. */
- struct r_fill_context ctx = {0};
-
- /* for faster multiply */
- const float buf_x_f = (float)buf_x;
- const float buf_y_f = (float)buf_y;
-#ifdef __PLX_KD_TREE__
- ctx.kdi = kd_create(2);
- ctx.kdo = kd_create(2);
-#endif
- /*
- * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert
- * data structure multiplied by the number of verts.
- *
- * In the event of a failure to allocate the memory, return 0, so this error can
- * be distinguished as a memory allocation error.
- */
- if((fe = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_feather_verts))) == NULL) {
- return(0);
- }
-
- /*
- * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are
- * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates
- * in the buffer-space coordinates passed in inside buf_x and buf_y.
- *
- * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel
- * drawn will be 1.0f in value, there is no anti-aliasing.
- */
- for(i = 0; i < num_feather_verts; i++) { /* Loop over all verts. */
- fe[i].x = (int)((feather_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */
- fe[i].y = (int)((feather_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */
-#ifdef __PLX_KD_TREE__
- kd_insertf(ctx.kdo,feather_verts[i],NULL);
- }
- for(i=0;i<num_base_verts;i++){
- kd_insertf(ctx.kdi,base_verts[i],NULL);
-#endif
- }
-
- ctx.rb.buf = buf; /* Set the output buffer pointer. */
- ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */
- ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */
- /* pre-sort the sets of edge verts on y */
- //plx_floatsort(base_verts,num_base_verts,0);
- //plx_floatsort(base_verts,num_base_verts,1);
- //plx_floatsort(feather_verts,num_feather_verts,0);
- //plx_floatsort(feather_verts,num_feather_verts,1);
- /* Call our rasterizer, passing in the integer coords for each vert. */
- i = rast_scan_feather(&ctx, base_verts, num_base_verts, fe, feather_verts, num_feather_verts);
- free(fe);
- return i; /* Return the value returned by the rasterizer. */
-}
-
-#ifndef __PLX__FAKE_AA__
-
-static int get_range_expanded_pixel_coord(float normalized_value, int max_value) {
- return (int)((normalized_value * (float)(max_value)) + 0.5f);
-}
-
-DO_INLINE float get_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y) {
- if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) {
- return 0.0f;
- }
- return buf[(pos_y * buf_x) + pos_x];
-}
-
-DO_INLINE float get_pixel_intensity_bilinear(float *buf, int buf_x, int buf_y, float u, float v) {
- int a;
- int b;
- int a_plus_1;
- int b_plus_1;
- float prop_u;
- float prop_v;
- float inv_prop_u;
- float inv_prop_v;
- if(u<0.0f || u>1.0f || v<0.0f || v>1.0f) {
- return 0.0f;
- }
- u = u * (float)(buf_x) - 0.5f;
- v = v * (float)(buf_y) - 0.5f;
- a = (int)(u);
- b = (int)(v);
- prop_u = u - (float)(a);
- prop_v = v - (float)(b);
- inv_prop_u = 1.0f - prop_u;
- inv_prop_v = 1.0f - prop_v;
- a_plus_1 = MIN2((buf_x-1),a+1);
- b_plus_1 = MIN2((buf_y-1),b+1);
- return (buf[(b * buf_x) + a] * inv_prop_u + buf[(b*buf_x)+(a_plus_1)] * prop_u)*inv_prop_v+(buf[((b_plus_1) * buf_x)+a] * inv_prop_u + buf[((b_plus_1)*buf_x)+(a_plus_1)] * prop_u) * prop_v;
-
-}
-
-DO_INLINE void set_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y, float intensity) {
- if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) {
- return;
- }
- buf[(pos_y * buf_x) + pos_x] = intensity;
-}
-#endif
-
-int PLX_antialias_buffer(float *buf, int buf_x, int buf_y) {
-#ifdef __PLX__FAKE_AA__
-#ifdef __PLX_GREY_AA__
- int i=0;
- int sz = buf_x * buf_y;
- for(i=0; i<sz; i++) {
- buf[i] *= 0.5f;
- }
-#endif
- (void)buf_x;
- (void)buf_y;
- (void)buf;
- return 1;
-#else
- const float jump01 = 1.0f;
- const float jump02 = 1.0f;
- const float jump03 = 1.0f;
- const float jump04 = 1.0f;
- const float jump05 = 1.0f;
- const float jump06 = 1.5f;
- const float jump07 = 2.0f;
- const float jump08 = 2.0f;
- const float jump09 = 2.0f;
- const float jump10 = 2.0f;
- const float jump11 = 4.0f;
- const float jump12 = 8.0f;
-
- const float edge_threshold = 0.063f;
- const float edge_threshold_min = 0.0312f;
- const float quality_subpix = 1.0f;
-
- float fpcx,fpcy;
- float fpsqx,fpsqy;
- float fprevx,fprevy;
- float fpfowx,fpfowy;
- float offset_dgx,offset_dgy;
- float pci;
- float pdi;
- float pri;
- float pui;
- float pli;
- float uli;
- float dri;
- float uri;
- float dli;
- float udi;
- float lri;
- float fsi;
- float ti;
- float cdi;
- float bi;
- float uui;
- float ddi;
- float eri;
- float efi;
- float cci;
- float ltz;
- float spX;
- float inv_r;
- float spP;
- float gdc;
- float sdc;
- float gedc;
- float sedc;
- float glu;
- float slu;
- float gr;
- float sr;
- float grexp;
- float r;
- float grc;
- float lre;
- float ude;
- float lre0;
- float ude0;
- float lre1;
- float ude1;
- float lre2;
- float ude2;
- float lre3;
- float ude3;
- float sdst;
- float tg0;
- float tg1;
- float tg2;
- float tg3;
- float tg4;
- float tg5;
- float tg6;
- float tg7;
- float ugrad;
- float dgrad;
- float grad;
- float gradexp;
- float revdst;
- float fowdst;
- float dst;
- float dsts;
- float inv_dsts;
- float pxOff;
- float gpxOff;
- float tgpxOff;
- float opx;
- float opy;
- int uls;
- int sph;
- int revsph;
- int fowsph;
- int lrsp;
- int done;
- int revpp;
- int revdone;
- int fowdone;
- int tug_of_war;
- int curr_x=0;
- int curr_y=0;
- opx = (1.0f / (float)(buf_x));
- opy = (1.0f / (float)(buf_y));
- for(curr_y=0; curr_y < buf_y; curr_y++) {
- for(curr_x=0; curr_x < buf_x; curr_x++) {
- fpcx = ((float)(curr_x) + 0.5f) * opx;
- fpcy = ((float)(curr_y) + 0.5f) * opy;
-//#define __PLX_BILINEAR_INITIAL_SAMPLES__ 1
-#ifdef __PLX_BILINEAR_INITIAL_SAMPLES__
- lumaM = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posM_x, posM_y);
- lumaS = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posM_x, posM_y + opy);
- lumaE = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posM_x + opx, posM_y);
- lumaN = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posM_x, posM_y - opy);
- lumaW = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posM_x - opx, posM_y);
-#else
- pci = get_pixel_intensity(buf, buf_x, buf_y, curr_x, curr_y);
- pdi = get_pixel_intensity(buf, buf_x, buf_y, curr_x, curr_y + 1);
- pri = get_pixel_intensity(buf, buf_x, buf_y, curr_x + 1, curr_y);
- pui = get_pixel_intensity(buf, buf_x, buf_y, curr_x, curr_y - 1);
- pli = get_pixel_intensity(buf, buf_x, buf_y, curr_x - 1, curr_y);
-#endif
- gdc = MAX2(pdi, pci);
- sdc = MIN2(pdi, pci);
- gedc = MAX2(pri, gdc);
- sedc = MIN2(pri, sdc);
- glu = MAX2(pui, pli);
- slu = MIN2(pui, pli);
- gr = MAX2(glu, gedc);
- sr = MIN2(slu, sedc);
- grexp = gr * edge_threshold;
- r = gr - sr;
- grc = MAX2(edge_threshold_min, grexp);
-
- done = r < grc ? 1:0;
- if(done) {
- set_pixel_intensity(buf, buf_x, buf_y, curr_x, curr_y, pci);
- } else {
-
- uli = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpcx - opx, fpcy - opy);
- dri = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpcx + opx, fpcy + opy);
- uri = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpcx + opx, fpcy - opy);
- dli = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpcx - opx, fpcy + opy);
-
- udi = pui + pdi;
- lri = pli + pri;
- inv_r = 1.0f/r;
- spP = udi + lri;
- lre0 = (-2.0f * pci) + udi;
- ude0 = (-2.0f * pci) + lri;
-
- fsi = uri + dri;
- ti = uli + uri;
- lre1 = (-2.0f * pri) + fsi;
- ude1 = (-2.0f * pui) + ti;
-
- cdi = uli + dli;
- bi = dli + dri;
- lre3 = (ABS(lre0) * 2.0f) + ABS(lre1);
- ude3 = (ABS(ude0) * 2.0f) + ABS(ude1);
- lre2 = (-2.0f * pli) + cdi;
- ude2 = (-2.0f * pdi) + bi;
- lre = ABS(lre2) + lre3;
- ude = ABS(ude2) + ude3;
-
- spX = cdi + fsi;
- sdst = 1.0f / (float)(buf_x);
- lrsp = lre >= ude ? 1:0;
- tg0 = spP * 2.0f + spX;
-
- if(!lrsp) {
- pui = pli;
- pdi = pri;
- } else {
- sdst = 1.0f / (float)(buf_y);
- }
- tg1 = (tg0 * (1.0f/12.0f)) - pci;
-
- ugrad = pui - pci;
- dgrad = pdi - pci;
- uui = pui + pci;
- ddi = pdi + pci;
- revpp = (ABS(ugrad)) >= (ABS(dgrad)) ? 1:0;
- grad = MAX2(ABS(ugrad), ABS(dgrad));
- if(revpp) {
- sdst = -sdst;
- }
- tg2 = MAX2(MIN2(ABS(tg1) * inv_r,1.0f),0.0f);
-
- fpsqx = fpcx;
- fpsqy = fpcy;
- offset_dgx = (!lrsp) ? 0.0f:(1.0f / (float)(buf_x));
- offset_dgy = (lrsp) ? 0.0f:(1.0f / (float)(buf_y));
- if(!lrsp) {
- fpsqx += sdst * 0.5f;
- } else {
- fpsqy += sdst * 0.5f;
- }
-
- fprevx = fpsqx - offset_dgx * jump01;
- fprevy = fpsqy - offset_dgy * jump01;
- fpfowx = fpsqx + offset_dgx * jump01;
- fpfowy = fpsqy + offset_dgy * jump01;
- tg3 = ((-2.0f)*tg2) + 3.0f;
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- tg4 = tg2 * tg2;
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
-
- if(!revpp) {
- uui = ddi;
- }
- gradexp = grad * 1.0f/4.0f;
- cci =pci - uui * 0.5f;
- tg5 = tg3 * tg4;
- ltz = cci < 0.0f ? 1:0;
-
- eri -= uui * 0.5f;
- efi -= uui * 0.5f;
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump02;
- fprevy -= offset_dgy * jump02;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump02;
- fpfowy += offset_dgy * jump02;
- }
-
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx, fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump03;
- fprevy -= offset_dgy * jump03;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump03;
- fpfowy += offset_dgy * jump03;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump04;
- fprevy -= offset_dgy * jump04;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump04;
- fpfowy += offset_dgy * jump04;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump05;
- fprevy -= offset_dgy * jump05;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump05;
- fpfowy += offset_dgy * jump05;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump06;
- fprevy -= offset_dgy * jump06;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump06;
- fpfowy += offset_dgy * jump06;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump07;
- fprevy -= offset_dgy * jump07;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump07;
- fpfowy += offset_dgy * jump07;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump08;
- fprevy -= offset_dgy * jump08;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump08;
- fpfowy += offset_dgy * jump08;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump09;
- fprevy -= offset_dgy * jump09;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump09;
- fpfowy += offset_dgy * jump09;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump10;
- fprevy -= offset_dgy * jump10;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump10;
- fpfowy += offset_dgy * jump10;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump11;
- fprevy -= offset_dgy * jump11;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump11;
- fpfowy += offset_dgy * jump11;
- }
- if(tug_of_war) {
- if(!revdone) {
- eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy);
- }
- if(!fowdone) {
- efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy);
- }
- if(!revdone) {
- eri = eri - uui * 0.5;
- }
- if(!fowdone) {
- efi = efi - uui * 0.5;
- }
- revdone = (ABS(eri)) >= gradexp ? 1:0;
- fowdone = (ABS(efi)) >= gradexp ? 1:0;
- if(!revdone) {
- fprevx -= offset_dgx * jump12;
- fprevy -= offset_dgy * jump12;
- }
- tug_of_war = (!revdone) || (!fowdone) ? 1:0;
- if(!fowdone) {
- fpfowx += offset_dgx * jump12;
- fpfowy += offset_dgy * jump12;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- revdst = fpcx - fprevx;
- fowdst = fpfowx - fpcx;
- if(!lrsp) {
- revdst = fpcy - fprevy;
- fowdst = fpfowy - fpcy;
- }
-
- revsph = ((eri < 0.0f) ? 1:0) != ltz ? 1:0;
- dsts = (fowdst + revdst);
- fowsph = ((efi < 0.0f) ? 1:0) != ltz ? 1:0;
- inv_dsts = 1.0f/dsts;
-
- uls = revdst < fowdst ? 1:0;
- dst = MIN2(revdst, fowdst);
- sph = (uls==1) ? revsph:fowsph;
- tg6 = tg5 * tg5;
- pxOff = (dst * (-inv_dsts)) + 0.5f;
- tg7 = tg6 * quality_subpix;
-
- gpxOff = (sph==1) ? pxOff : 0.0f;
- tgpxOff = MAX2(gpxOff, tg7);
- if(!lrsp) {
- fpcx += tgpxOff * sdst;
- } else {
- fpcy += tgpxOff * sdst;
- }
- set_pixel_intensity(buf,buf_x,buf_y,curr_x,curr_y,get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpcx,fpcy));
- }
- }
- }
- return 1;
-
-#endif
-}
-
-#define SWAP_POLYVERT(a,b) point_temp[0]=(a)[0]; point_temp[1]=(a)[1]; (a)[0]=(b)[0]; (a)[1]=(b)[1]; (b)[0]=point_temp[0]; (b)[1]=point_temp[1];
-#define __PLX_SMALL_COUNT__ 13
-static void plx_floatsort(float(*f)[2], unsigned int n, int sortby) {
- unsigned int a;
- unsigned int b;
- unsigned int c;
- unsigned int d=1;
- unsigned int hold;
- unsigned int index_list[50];
- int index_offset=0;
- float t[2];
- float point_temp[2];
-
- hold=n;
- for(;;) {
- if(hold-d < __PLX_SMALL_COUNT__) {
- for(b=d+1; b<=hold; b++) {
- t[1]=f[b][1];
- t[0]=f[b][0];
- for(a=b-1; a>=d; a--) {
- if(f[a][sortby] <= t[sortby]) {
- break;
- }
- f[a+1][1]=f[a][1];
- f[a+1][0]=f[a][0];
- }
- f[a+1][1]=t[1];
- f[a+1][0]=t[0];
- }
- if(index_offset < 0) {
- break;
- }
- hold=index_list[index_offset--];
- d=index_list[index_offset--];
- } else {
- c=(d+hold) >> 1;
- SWAP_POLYVERT(f[c],f[d+1])
- if(f[d][sortby] > f[hold][sortby]) {
- SWAP_POLYVERT(f[d],f[hold])
- }
- if(f[d+1][sortby] > f[hold][sortby]) {
- SWAP_POLYVERT(f[d+1],f[hold])
- }
- if(f[d][sortby] > f[d+1][sortby]) {
- SWAP_POLYVERT(f[d],f[d+1])
- }
- a=d+1;
- b=hold;
- t[0]=f[d+1][0];
- t[1]=f[d+1][1];
- for(;;) {
- do a++;
- while(f[a][sortby] < t[sortby]);
- do b--;
- while(f[b][sortby] > t[sortby]);
- if(b < a) {
- break;
- }
- SWAP_POLYVERT(f[a],f[b])
- }
- f[d+1][0]=f[b][0];
- f[d+1][1]=f[b][1];
- f[b][0]=t[0];
- f[b][1]=t[1];
- index_offset+=2;
- if(index_offset > __PLX_SMALL_COUNT__) {
- return;
- }
- if(hold-a+1 >= b-d) {
- index_list[index_offset]=hold;
- index_list[index_offset-1]=a;
- hold=b-1;
- } else {
- index_list[index_offset]=b-1;
- index_list[index_offset-1]=d;
- d=a;
- }
- }
- }
-}
-
-static int plx_find_lower_bound(float v, float(*a)[2], int num_feather_verts) {
- int x;
- int l;
- int r;
- l=1;
- r=num_feather_verts;
- for(;;) {
- // interpolation style search
- //x=l+(v-a[l][1])*(r-l) / (a[r][1]-a[l][1]);
-
- // binary search
- x=(l+r) / 2;
- if(v<a[x][1]) {
- r=x-1;
- } else {
- l=x+1;
- }
- if((v>a[x-1][1] && v <= a[x][1]) || l>r) {
- break;
- }
- }
- if(v>a[x-1][1] && v <= a[x][1]) {
- return x;
- } else {
- return num_feather_verts;
- }
-}
-
-static int plx_find_upper_bound(float v, float(*a)[2], int num_feather_verts) {
- int x;
- int l;
- int r;
- l=1;
- r=num_feather_verts;
- for(;;) {
- // interpolation style search
- //x=l+(v-a[l][1])*(r-l) / (a[r][1]-a[l][1]);
-
- // binary search
- x=(l+r) / 2;
- if(v<a[x][1]) {
- r=x-1;
- } else {
- l=x+1;
- }
- if((v>=a[x-1][1] && v < a[x][1]) || l>r) {
- break;
- }
- }
- if(v>=a[x-1][1] && v < a[x][1]) {
- return x-1;
- } else {
- return num_feather_verts;
- }
-}
-
diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h
index cf679dd37c0..cf691a9784b 100644
--- a/intern/raskter/raskter.h
+++ b/intern/raskter/raskter.h
@@ -27,80 +27,14 @@
/** \file raskter.h
* \ingroup RASKTER
*/
-/* from BLI_utildefines.h */
-#define MIN2(x, y) ( (x) < (y) ? (x) : (y) )
-#define MAX2(x, y) ( (x) > (y) ? (x) : (y) )
-#define ABS(a) ( (a) < 0 ? (-(a)) : (a) )
-
-struct poly_vert {
- int x;
- int y;
-};
-
-struct scan_line {
- int xstart;
- int xend;
-};
-
-struct scan_line_batch {
- int num;
- int ystart;
- struct scan_line *slines;
-};
-
-struct e_status {
- int x;
- int ybeg;
- int xshift;
- int xdir;
- int drift;
- int drift_inc;
- int drift_dec;
- int num;
- struct e_status *e_next;
-};
-
-struct r_buffer_stats {
- float *buf;
- int sizex;
- int sizey;
- int ymin;
- int ymax;
- int xmin;
- int xmax;
-};
-
-struct r_fill_context {
- struct e_status *all_edges, *possible_edges;
- struct r_buffer_stats rb;
- struct scan_line *bounds;
- void *kdo; //only used with kd tree
- void *kdi; //only used with kd tree
- int *bound_indexes;
- int bounds_length;
-};
-
-struct layer_init_data {
- struct poly_vert *imask;
- struct poly_vert *omask;
- struct scan_line *bounds;
- int *bound_indexes;
- int bounds_length;
-};
#ifdef __cplusplus
extern "C" {
#endif
-void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge);
-int PLX_init_base_data(struct layer_init_data *mlayer_data, float(*base_verts)[2], int num_base_verts,
- float *buf, int buf_x, int buf_y);
int PLX_raskterize(float (*base_verts)[2], int num_base_verts,
- float *buf, int buf_x, int buf_y, int do_mask_AA);
-int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts,
- float (*feather_verts)[2], int num_feather_verts,
- float *buf, int buf_x, int buf_y);
-int PLX_antialias_buffer(float *buf, int buf_x, int buf_y);
+ float *buf, int buf_x, int buf_y);
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/raskter/raskter_kdtree.c b/intern/raskter/raskter_kdtree.c
deleted file mode 100644
index 06fbc5dccd0..00000000000
--- a/intern/raskter/raskter_kdtree.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
-This file is part of ``kdtree'', a library for working with kd-trees.
-Copyright (C) 2007-2011 John Tsiombikas <nuclear@member.fsf.org>
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-/* single nearest neighbor search written by Tamas Nepusz <tamas@cs.rhul.ac.uk> */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include "raskter_kdtree.h"
-
-#if defined(WIN32) || defined(__WIN32__)
-#include <malloc.h>
-#endif
-
-#ifdef USE_LIST_NODE_ALLOCATOR
-
-#ifndef NO_PTHREADS
-#include <pthread.h>
-#else
-
-#ifndef I_WANT_THREAD_BUGS
-#error "You are compiling with the fast list node allocator, with pthreads disabled! This WILL break if used from multiple threads."
-#endif /* I want thread bugs */
-
-#endif /* pthread support */
-#endif /* use list node allocator */
-
-struct kdhyperrect {
- int dim;
- double *min, *max; /* minimum/maximum coords */
-};
-
-struct kdnode {
- double *pos;
- int dir;
- void *data;
-
- struct kdnode *left, *right; /* negative/positive side */
-};
-
-struct res_node {
- struct kdnode *item;
- double dist_sq;
- struct res_node *next;
-};
-
-struct kdtree {
- int dim;
- struct kdnode *root;
- struct kdhyperrect *rect;
- void (*destr)(void*);
-};
-
-struct kdres {
- struct kdtree *tree;
- struct res_node *rlist, *riter;
- int size;
-};
-
-#define SQ(x) ((x) * (x))
-
-
-static void clear_rec(struct kdnode *node, void (*destr)(void*));
-static int insert_rec(struct kdnode **node, const double *pos, void *data, int dir, int dim);
-static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq);
-static void clear_results(struct kdres *set);
-
-static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max);
-static void hyperrect_free(struct kdhyperrect *rect);
-static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect);
-static void hyperrect_extend(struct kdhyperrect *rect, const double *pos);
-static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos);
-
-#ifdef USE_LIST_NODE_ALLOCATOR
-static struct res_node *alloc_resnode(void);
-static void free_resnode(struct res_node*);
-#else
-#define alloc_resnode() malloc(sizeof(struct res_node))
-#define free_resnode(n) free(n)
-#endif
-
-
-
-struct kdtree *kd_create(int k)
-{
- struct kdtree *tree;
-
- if(!(tree = malloc(sizeof *tree))) {
- return 0;
- }
-
- tree->dim = k;
- tree->root = 0;
- tree->destr = 0;
- tree->rect = 0;
-
- return tree;
-}
-
-void kd_free(struct kdtree *tree)
-{
- if(tree) {
- kd_clear(tree);
- free(tree);
- }
-}
-
-static void clear_rec(struct kdnode *node, void (*destr)(void*))
-{
- if(!node) return;
-
- clear_rec(node->left, destr);
- clear_rec(node->right, destr);
-
- if(destr) {
- destr(node->data);
- }
- free(node->pos);
- free(node);
-}
-
-void kd_clear(struct kdtree *tree)
-{
- clear_rec(tree->root, tree->destr);
- tree->root = 0;
-
- if (tree->rect) {
- hyperrect_free(tree->rect);
- tree->rect = 0;
- }
-}
-
-void kd_data_destructor(struct kdtree *tree, void (*destr)(void*))
-{
- tree->destr = destr;
-}
-
-
-static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim)
-{
- int new_dir;
- struct kdnode *node;
-
- if(!*nptr) {
- if(!(node = malloc(sizeof *node))) {
- return -1;
- }
- if(!(node->pos = malloc(dim * sizeof *node->pos))) {
- free(node);
- return -1;
- }
- memcpy(node->pos, pos, dim * sizeof *node->pos);
- node->data = data;
- node->dir = dir;
- node->left = node->right = 0;
- *nptr = node;
- return 0;
- }
-
- node = *nptr;
- new_dir = (node->dir + 1) % dim;
- if(pos[node->dir] < node->pos[node->dir]) {
- return insert_rec(&(*nptr)->left, pos, data, new_dir, dim);
- }
- return insert_rec(&(*nptr)->right, pos, data, new_dir, dim);
-}
-
-int kd_insert(struct kdtree *tree, const double *pos, void *data)
-{
- if (insert_rec(&tree->root, pos, data, 0, tree->dim)) {
- return -1;
- }
-
- if (tree->rect == 0) {
- tree->rect = hyperrect_create(tree->dim, pos, pos);
- } else {
- hyperrect_extend(tree->rect, pos);
- }
-
- return 0;
-}
-
-int kd_insertf(struct kdtree *tree, const float *pos, void *data)
-{
- static double sbuf[16];
- double *bptr, *buf = 0;
- int res, dim = tree->dim;
-
- if(dim > 16) {
-#ifndef NO_ALLOCA
- if(dim <= 256)
- bptr = buf = alloca(dim * sizeof *bptr);
- else
-#endif
- if(!(bptr = buf = malloc(dim * sizeof *bptr))) {
- return -1;
- }
- } else {
- bptr = buf = sbuf;
- }
-
- while(dim-- > 0) {
- *bptr++ = *pos++;
- }
-
- res = kd_insert(tree, buf, data);
-#ifndef NO_ALLOCA
- if(tree->dim > 256)
-#else
- if(tree->dim > 16)
-#endif
- free(buf);
- return res;
-}
-
-int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data)
-{
- double buf[3];
- buf[0] = x;
- buf[1] = y;
- buf[2] = z;
- return kd_insert(tree, buf, data);
-}
-
-int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data)
-{
- double buf[3];
- buf[0] = x;
- buf[1] = y;
- buf[2] = z;
- return kd_insert(tree, buf, data);
-}
-
-static int find_nearest(struct kdnode *node, const double *pos, double range, struct res_node *list, int ordered, int dim)
-{
- double dist_sq, dx;
- int i, ret, added_res = 0;
-
- if(!node) return 0;
-
- dist_sq = 0;
- for(i=0; i<dim; i++) {
- dist_sq += SQ(node->pos[i] - pos[i]);
- }
- if(dist_sq <= SQ(range)) {
- if(rlist_insert(list, node, ordered ? dist_sq : -1.0) == -1) {
- return -1;
- }
- added_res = 1;
- }
-
- dx = pos[node->dir] - node->pos[node->dir];
-
- ret = find_nearest(dx <= 0.0 ? node->left : node->right, pos, range, list, ordered, dim);
- if(ret >= 0 && fabs(dx) < range) {
- added_res += ret;
- ret = find_nearest(dx <= 0.0 ? node->right : node->left, pos, range, list, ordered, dim);
- }
- if(ret == -1) {
- return -1;
- }
- added_res += ret;
-
- return added_res;
-}
-
-#if 0
-static int find_nearest_n(struct kdnode *node, const double *pos, double range, int num, struct rheap *heap, int dim)
-{
- double dist_sq, dx;
- int i, ret, added_res = 0;
-
- if(!node) return 0;
-
- /* if the photon is close enough, add it to the result heap */
- dist_sq = 0;
- for(i=0; i<dim; i++) {
- dist_sq += SQ(node->pos[i] - pos[i]);
- }
- if(dist_sq <= range_sq) {
- if(heap->size >= num) {
- /* get furthest element */
- struct res_node *maxelem = rheap_get_max(heap);
-
- /* and check if the new one is closer than that */
- if(maxelem->dist_sq > dist_sq) {
- rheap_remove_max(heap);
-
- if(rheap_insert(heap, node, dist_sq) == -1) {
- return -1;
- }
- added_res = 1;
-
- range_sq = dist_sq;
- }
- } else {
- if(rheap_insert(heap, node, dist_sq) == -1) {
- return =1;
- }
- added_res = 1;
- }
- }
-
-
- /* find signed distance from the splitting plane */
- dx = pos[node->dir] - node->pos[node->dir];
-
- ret = find_nearest_n(dx <= 0.0 ? node->left : node->right, pos, range, num, heap, dim);
- if(ret >= 0 && fabs(dx) < range) {
- added_res += ret;
- ret = find_nearest_n(dx <= 0.0 ? node->right : node->left, pos, range, num, heap, dim);
- }
-
-}
-#endif
-
-static void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect)
-{
- int dir = node->dir;
- int i;
- double dummy, dist_sq;
- struct kdnode *nearer_subtree, *farther_subtree;
- double *nearer_hyperrect_coord, *farther_hyperrect_coord;
-
- /* Decide whether to go left or right in the tree */
- dummy = pos[dir] - node->pos[dir];
- if (dummy <= 0) {
- nearer_subtree = node->left;
- farther_subtree = node->right;
- nearer_hyperrect_coord = rect->max + dir;
- farther_hyperrect_coord = rect->min + dir;
- } else {
- nearer_subtree = node->right;
- farther_subtree = node->left;
- nearer_hyperrect_coord = rect->min + dir;
- farther_hyperrect_coord = rect->max + dir;
- }
-
- if (nearer_subtree) {
- /* Slice the hyperrect to get the hyperrect of the nearer subtree */
- dummy = *nearer_hyperrect_coord;
- *nearer_hyperrect_coord = node->pos[dir];
- /* Recurse down into nearer subtree */
- kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect);
- /* Undo the slice */
- *nearer_hyperrect_coord = dummy;
- }
-
- /* Check the distance of the point at the current node, compare it
- * with our best so far */
- dist_sq = 0;
- for(i=0; i < rect->dim; i++) {
- dist_sq += SQ(node->pos[i] - pos[i]);
- }
- if (dist_sq < *result_dist_sq) {
- *result = node;
- *result_dist_sq = dist_sq;
- }
-
- if (farther_subtree) {
- /* Get the hyperrect of the farther subtree */
- dummy = *farther_hyperrect_coord;
- *farther_hyperrect_coord = node->pos[dir];
- /* Check if we have to recurse down by calculating the closest
- * point of the hyperrect and see if it's closer than our
- * minimum distance in result_dist_sq. */
- if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) {
- /* Recurse down into farther subtree */
- kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect);
- }
- /* Undo the slice on the hyperrect */
- *farther_hyperrect_coord = dummy;
- }
-}
-
-struct kdres *kd_nearest(struct kdtree *kd, const double *pos)
-{
- struct kdhyperrect *rect;
- struct kdnode *result;
- struct kdres *rset;
- double dist_sq;
- int i;
-
- if (!kd) return 0;
- if (!kd->rect) return 0;
-
- /* Allocate result set */
- if(!(rset = malloc(sizeof *rset))) {
- return 0;
- }
- if(!(rset->rlist = alloc_resnode())) {
- free(rset);
- return 0;
- }
- rset->rlist->next = 0;
- rset->tree = kd;
-
- /* Duplicate the bounding hyperrectangle, we will work on the copy */
- if (!(rect = hyperrect_duplicate(kd->rect))) {
- kd_res_free(rset);
- return 0;
- }
-
- /* Our first guesstimate is the root node */
- result = kd->root;
- dist_sq = 0;
- for (i = 0; i < kd->dim; i++)
- dist_sq += SQ(result->pos[i] - pos[i]);
-
- /* Search for the nearest neighbour recursively */
- kd_nearest_i(kd->root, pos, &result, &dist_sq, rect);
-
- /* Free the copy of the hyperrect */
- hyperrect_free(rect);
-
- /* Store the result */
- if (result) {
- if (rlist_insert(rset->rlist, result, -1.0) == -1) {
- kd_res_free(rset);
- return 0;
- }
- rset->size = 1;
- kd_res_rewind(rset);
- return rset;
- } else {
- kd_res_free(rset);
- return 0;
- }
-}
-
-struct kdres *kd_nearestf(struct kdtree *tree, const float *pos)
-{
- static double sbuf[16];
- double *bptr, *buf = 0;
- int dim = tree->dim;
- struct kdres *res;
-
- if(dim > 16) {
-#ifndef NO_ALLOCA
- if(dim <= 256)
- bptr = buf = alloca(dim * sizeof *bptr);
- else
-#endif
- if(!(bptr = buf = malloc(dim * sizeof *bptr))) {
- return 0;
- }
- } else {
- bptr = buf = sbuf;
- }
-
- while(dim-- > 0) {
- *bptr++ = *pos++;
- }
-
- res = kd_nearest(tree, buf);
-#ifndef NO_ALLOCA
- if(tree->dim > 256)
-#else
- if(tree->dim > 16)
-#endif
- free(buf);
- return res;
-}
-
-struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z)
-{
- double pos[3];
- pos[0] = x;
- pos[1] = y;
- pos[2] = z;
- return kd_nearest(tree, pos);
-}
-
-struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z)
-{
- double pos[3];
- pos[0] = x;
- pos[1] = y;
- pos[2] = z;
- return kd_nearest(tree, pos);
-}
-
-/* ---- nearest N search ---- */
-/*
-static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num)
-{
- int ret;
- struct kdres *rset;
-
- if(!(rset = malloc(sizeof *rset))) {
- return 0;
- }
- if(!(rset->rlist = alloc_resnode())) {
- free(rset);
- return 0;
- }
- rset->rlist->next = 0;
- rset->tree = kd;
-
- if((ret = find_nearest_n(kd->root, pos, range, num, rset->rlist, kd->dim)) == -1) {
- kd_res_free(rset);
- return 0;
- }
- rset->size = ret;
- kd_res_rewind(rset);
- return rset;
-}*/
-
-struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range)
-{
- int ret;
- struct kdres *rset;
-
- if(!(rset = malloc(sizeof *rset))) {
- return 0;
- }
- if(!(rset->rlist = alloc_resnode())) {
- free(rset);
- return 0;
- }
- rset->rlist->next = 0;
- rset->tree = kd;
-
- if((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) {
- kd_res_free(rset);
- return 0;
- }
- rset->size = ret;
- kd_res_rewind(rset);
- return rset;
-}
-
-struct kdres *kd_nearest_rangef(struct kdtree *kd, const float *pos, float range)
-{
- static double sbuf[16];
- double *bptr, *buf = 0;
- int dim = kd->dim;
- struct kdres *res;
-
- if(dim > 16) {
-#ifndef NO_ALLOCA
- if(dim <= 256)
- bptr = buf = alloca(dim * sizeof *bptr);
- else
-#endif
- if(!(bptr = buf = malloc(dim * sizeof *bptr))) {
- return 0;
- }
- } else {
- bptr = buf = sbuf;
- }
-
- while(dim-- > 0) {
- *bptr++ = *pos++;
- }
-
- res = kd_nearest_range(kd, buf, range);
-#ifndef NO_ALLOCA
- if(kd->dim > 256)
-#else
- if(kd->dim > 16)
-#endif
- free(buf);
- return res;
-}
-
-struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range)
-{
- double buf[3];
- buf[0] = x;
- buf[1] = y;
- buf[2] = z;
- return kd_nearest_range(tree, buf, range);
-}
-
-struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range)
-{
- double buf[3];
- buf[0] = x;
- buf[1] = y;
- buf[2] = z;
- return kd_nearest_range(tree, buf, range);
-}
-
-void kd_res_free(struct kdres *rset)
-{
- clear_results(rset);
- free_resnode(rset->rlist);
- free(rset);
-}
-
-int kd_res_size(struct kdres *set)
-{
- return (set->size);
-}
-
-void kd_res_rewind(struct kdres *rset)
-{
- rset->riter = rset->rlist->next;
-}
-
-int kd_res_end(struct kdres *rset)
-{
- return rset->riter == 0;
-}
-
-int kd_res_next(struct kdres *rset)
-{
- rset->riter = rset->riter->next;
- return rset->riter != 0;
-}
-
-void *kd_res_item(struct kdres *rset, double *pos)
-{
- if(rset->riter) {
- if(pos) {
- memcpy(pos, rset->riter->item->pos, rset->tree->dim * sizeof *pos);
- }
- return rset->riter->item->data;
- }
- return 0;
-}
-
-void *kd_res_itemf(struct kdres *rset, float *pos)
-{
- if(rset->riter) {
- if(pos) {
- int i;
- for(i=0; i<rset->tree->dim; i++) {
- pos[i] = rset->riter->item->pos[i];
- }
- }
- return rset->riter->item->data;
- }
- return 0;
-}
-
-void *kd_res_item3(struct kdres *rset, double *x, double *y, double *z)
-{
- if(rset->riter) {
- if(*x) *x = rset->riter->item->pos[0];
- if(*y) *y = rset->riter->item->pos[1];
- if(*z) *z = rset->riter->item->pos[2];
- }
- return 0;
-}
-
-void *kd_res_item3f(struct kdres *rset, float *x, float *y, float *z)
-{
- if(rset->riter) {
- if(*x) *x = rset->riter->item->pos[0];
- if(*y) *y = rset->riter->item->pos[1];
- if(*z) *z = rset->riter->item->pos[2];
- }
- return 0;
-}
-
-void *kd_res_item_data(struct kdres *set)
-{
- return kd_res_item(set, 0);
-}
-
-/* ---- hyperrectangle helpers ---- */
-static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max)
-{
- size_t size = dim * sizeof(double);
- struct kdhyperrect* rect = 0;
-
- if (!(rect = malloc(sizeof(struct kdhyperrect)))) {
- return 0;
- }
-
- rect->dim = dim;
- if (!(rect->min = malloc(size))) {
- free(rect);
- return 0;
- }
- if (!(rect->max = malloc(size))) {
- free(rect->min);
- free(rect);
- return 0;
- }
- memcpy(rect->min, min, size);
- memcpy(rect->max, max, size);
-
- return rect;
-}
-
-static void hyperrect_free(struct kdhyperrect *rect)
-{
- free(rect->min);
- free(rect->max);
- free(rect);
-}
-
-static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect)
-{
- return hyperrect_create(rect->dim, rect->min, rect->max);
-}
-
-static void hyperrect_extend(struct kdhyperrect *rect, const double *pos)
-{
- int i;
-
- for (i=0; i < rect->dim; i++) {
- if (pos[i] < rect->min[i]) {
- rect->min[i] = pos[i];
- }
- if (pos[i] > rect->max[i]) {
- rect->max[i] = pos[i];
- }
- }
-}
-
-static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos)
-{
- int i;
- double result = 0;
-
- for (i=0; i < rect->dim; i++) {
- if (pos[i] < rect->min[i]) {
- result += SQ(rect->min[i] - pos[i]);
- } else if (pos[i] > rect->max[i]) {
- result += SQ(rect->max[i] - pos[i]);
- }
- }
-
- return result;
-}
-
-/* ---- static helpers ---- */
-
-#ifdef USE_LIST_NODE_ALLOCATOR
-/* special list node allocators. */
-static struct res_node *free_nodes;
-
-#ifndef NO_PTHREADS
-static pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-static struct res_node *alloc_resnode(void)
-{
- struct res_node *node;
-
-#ifndef NO_PTHREADS
- pthread_mutex_lock(&alloc_mutex);
-#endif
-
- if(!free_nodes) {
- node = malloc(sizeof *node);
- } else {
- node = free_nodes;
- free_nodes = free_nodes->next;
- node->next = 0;
- }
-
-#ifndef NO_PTHREADS
- pthread_mutex_unlock(&alloc_mutex);
-#endif
-
- return node;
-}
-
-static void free_resnode(struct res_node *node)
-{
-#ifndef NO_PTHREADS
- pthread_mutex_lock(&alloc_mutex);
-#endif
-
- node->next = free_nodes;
- free_nodes = node;
-
-#ifndef NO_PTHREADS
- pthread_mutex_unlock(&alloc_mutex);
-#endif
-}
-#endif /* list node allocator or not */
-
-
-/* inserts the item. if dist_sq is >= 0, then do an ordered insert */
-/* TODO make the ordering code use heapsort */
-static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq)
-{
- struct res_node *rnode;
-
- if(!(rnode = alloc_resnode())) {
- return -1;
- }
- rnode->item = item;
- rnode->dist_sq = dist_sq;
-
- if(dist_sq >= 0.0) {
- while(list->next && list->next->dist_sq < dist_sq) {
- list = list->next;
- }
- }
- rnode->next = list->next;
- list->next = rnode;
- return 0;
-}
-
-static void clear_results(struct kdres *rset)
-{
- struct res_node *tmp, *node = rset->rlist->next;
-
- while(node) {
- tmp = node;
- node = node->next;
- free_resnode(tmp);
- }
-
- rset->rlist->next = 0;
-}
diff --git a/intern/raskter/raskter_kdtree.h b/intern/raskter/raskter_kdtree.h
deleted file mode 100644
index da80e422a80..00000000000
--- a/intern/raskter/raskter_kdtree.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-This file is part of ``kdtree'', a library for working with kd-trees.
-Copyright (C) 2007-2011 John Tsiombikas <nuclear@member.fsf.org>
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-#ifndef _KDTREE_H_
-#define _KDTREE_H_
-#define USE_LIST_NODE_ALLOCATOR
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct kdtree;
-struct kdres;
-
-
-/* create a kd-tree for "k"-dimensional data */
-struct kdtree *kd_create(int k);
-
-/* free the struct kdtree */
-void kd_free(struct kdtree *tree);
-
-/* remove all the elements from the tree */
-void kd_clear(struct kdtree *tree);
-
-/* if called with non-null 2nd argument, the function provided
- * will be called on data pointers (see kd_insert) when nodes
- * are to be removed from the tree.
- */
-void kd_data_destructor(struct kdtree *tree, void (*destr)(void*));
-
-/* insert a node, specifying its position, and optional data */
-int kd_insert(struct kdtree *tree, const double *pos, void *data);
-int kd_insertf(struct kdtree *tree, const float *pos, void *data);
-int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data);
-int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data);
-
-/* Find the nearest node from a given point.
- *
- * This function returns a pointer to a result set with at most one element.
- */
-struct kdres *kd_nearest(struct kdtree *tree, const double *pos);
-struct kdres *kd_nearestf(struct kdtree *tree, const float *pos);
-struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z);
-struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z);
-
-/* Find the N nearest nodes from a given point.
- *
- * This function returns a pointer to a result set, with at most N elements,
- * which can be manipulated with the kd_res_* functions.
- * The returned pointer can be null as an indication of an error. Otherwise
- * a valid result set is always returned which may contain 0 or more elements.
- * The result set must be deallocated with kd_res_free after use.
- */
-/*
-struct kdres *kd_nearest_n(struct kdtree *tree, const double *pos, int num);
-struct kdres *kd_nearest_nf(struct kdtree *tree, const float *pos, int num);
-struct kdres *kd_nearest_n3(struct kdtree *tree, double x, double y, double z);
-struct kdres *kd_nearest_n3f(struct kdtree *tree, float x, float y, float z);
-*/
-
-/* Find any nearest nodes from a given point within a range.
- *
- * This function returns a pointer to a result set, which can be manipulated
- * by the kd_res_* functions.
- * The returned pointer can be null as an indication of an error. Otherwise
- * a valid result set is always returned which may contain 0 or more elements.
- * The result set must be deallocated with kd_res_free after use.
- */
-struct kdres *kd_nearest_range(struct kdtree *tree, const double *pos, double range);
-struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range);
-struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range);
-struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range);
-
-/* frees a result set returned by kd_nearest_range() */
-void kd_res_free(struct kdres *set);
-
-/* returns the size of the result set (in elements) */
-int kd_res_size(struct kdres *set);
-
-/* rewinds the result set iterator */
-void kd_res_rewind(struct kdres *set);
-
-/* returns non-zero if the set iterator reached the end after the last element */
-int kd_res_end(struct kdres *set);
-
-/* advances the result set iterator, returns non-zero on success, zero if
- * there are no more elements in the result set.
- */
-int kd_res_next(struct kdres *set);
-
-/* returns the data pointer (can be null) of the current result set item
- * and optionally sets its position to the pointers(s) if not null.
- */
-void *kd_res_item(struct kdres *set, double *pos);
-void *kd_res_itemf(struct kdres *set, float *pos);
-void *kd_res_item3(struct kdres *set, double *x, double *y, double *z);
-void *kd_res_item3f(struct kdres *set, float *x, float *y, float *z);
-
-/* equivalent to kd_res_item(set, 0) */
-void *kd_res_item_data(struct kdres *set);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _KDTREE_H_ */
diff --git a/intern/raskter/raskter_mt.c b/intern/raskter/raskter_mt.c
deleted file mode 100644
index feda624d668..00000000000
--- a/intern/raskter/raskter_mt.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2012 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Peter Larabell.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-/** \file raskter_mt.c
- * \ingroup RASKTER
- */
-#include <stdlib.h>
-
-#include "raskter.h"
-static int rast_scan_init(struct layer_init_data *mlayer_data, struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) {
- int x_curr; /* current pixel position in X */
- int y_curr; /* current scan line being drawn */
- int yp; /* y-pixel's position in frame buffer */
- int swixd = 0; /* whether or not edges switched position in X */
- int i=0; /* counter */
- float *cpxl; /* pixel pointers... */
- float *mpxl;
- float *spxl;
- struct e_status *e_curr; /* edge pointers... */
- struct e_status *e_temp;
- struct e_status *edgbuf;
- struct e_status **edgec;
-
-
- if(num_verts < 3) {
- return(1);
- }
-
- if((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) {
- return(0);
- }
-
- /* set initial bounds length to 0 */
- mlayer_data->bounds_length=0;
-
- /* round 1, count up all the possible spans in the base buffer */
- preprocess_all_edges(ctx, verts, num_verts, edgbuf);
-
- /* can happen with a zero area mask */
- if (ctx->all_edges == NULL) {
- free(edgbuf);
- return(1);
- }
- ctx->possible_edges = NULL;
-
- for(y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) {
-
- for(edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) {
- x_curr = ctx->all_edges->x; /* Set current X position. */
- for(;;) { /* Start looping edges. Will break when edges run out. */
- e_curr = *edgec; /* Set up a current edge pointer. */
- if(!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */
- e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */
- *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */
- ctx->all_edges->e_next = e_curr; /* Set up the next edge. */
- edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */
- ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */
- break; /* Stop looping edges (since we ran out or hit empty X span. */
- } else {
- edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */
- }
- }
- }
-
- yp = y_curr * ctx->rb.sizex;
- spxl = ctx->rb.buf + (yp);
-
- for(e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) {
-
- /* set up xmin and xmax bounds on this scan line */
- cpxl = spxl + MAX2(e_curr->x, 0);
- e_curr = e_curr->e_next;
- mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1;
-
- if((y_curr >= 0) && (y_curr < ctx->rb.sizey)) {
- mlayer_data->bounds_length++;
- }
- }
-
- for(edgec = &ctx->possible_edges; (e_curr = *edgec);) {
- if(!(--(e_curr->num))) {
- *edgec = e_curr->e_next;
- } else {
- e_curr->x += e_curr->xshift;
- if((e_curr->drift += e_curr->drift_inc) > 0) {
- e_curr->x += e_curr->xdir;
- e_curr->drift -= e_curr->drift_dec;
- }
- edgec = &e_curr->e_next;
- }
- }
- if(ctx->possible_edges) {
- for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
- /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */
- if(e_curr->x > e_curr->e_next->x) {
- *edgec = e_curr->e_next;
- /* exchange the pointers */
- e_temp = e_curr->e_next->e_next;
- e_curr->e_next->e_next = e_curr;
- e_curr->e_next = e_temp;
- /* set flag that we had at least one switch */
- swixd = 1;
- }
- }
- /* if we did have a switch, look for more (there will more if there was one) */
- for(;;) {
- /* reset exchange flag so it's only set if we encounter another one */
- swixd = 0;
- for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
- /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */
- if(e_curr->x > e_curr->e_next->x) {
- *edgec = e_curr->e_next;
- /* exchange the pointers */
- e_temp = e_curr->e_next->e_next;
- e_curr->e_next->e_next = e_curr;
- e_curr->e_next = e_temp;
- /* flip the exchanged flag */
- swixd = 1;
- }
- }
- /* if we had no exchanges, we're done reshuffling the pointers */
- if(!swixd) {
- break;
- }
- }
- }
- }
-
-
-/*initialize index buffer and bounds buffers*/
- //gets the +1 for dummy at the end
- if((mlayer_data->bound_indexes = (int *)(malloc(sizeof(int) * ctx->rb.sizey+1)))==NULL) {
- return(0);
- }
- //gets the +1 for dummy at the start
- if((mlayer_data->bounds = (struct scan_line *)(malloc(sizeof(struct scan_line) * mlayer_data->bounds_length+1)))==NULL){
- return(0);
- }
- //init all the indexes to zero (are they already zeroed from malloc???)
- for(i=0;i<ctx->rb.sizey+1;i++){
- mlayer_data->bound_indexes[i]=0;
- }
- /* round 2, fill in the full list of bounds, and create indexes to the list... */
- preprocess_all_edges(ctx, verts, num_verts, edgbuf);
-
- /* can happen with a zero area mask */
- if (ctx->all_edges == NULL) {
- free(edgbuf);
- return(1);
- }
- ctx->possible_edges = NULL;
-
- /* restart i as a counter for total span placement in buffer */
- i=1;
- for(y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) {
-
- for(edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) {
- x_curr = ctx->all_edges->x; /* Set current X position. */
- for(;;) { /* Start looping edges. Will break when edges run out. */
- e_curr = *edgec; /* Set up a current edge pointer. */
- if(!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */
- e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */
- *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */
- ctx->all_edges->e_next = e_curr; /* Set up the next edge. */
- edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */
- ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */
- break; /* Stop looping edges (since we ran out or hit empty X span. */
- } else {
- edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */
- }
- }
- }
-
- yp = y_curr * ctx->rb.sizex;
- spxl = ctx->rb.buf + (yp);
- if((y_curr >=0) && (y_curr < ctx->rb.sizey)){
- ctx->bound_indexes[y_curr]=i;
- }
- for(e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) {
-
- /* set up xmin and xmax bounds on this scan line */
- cpxl = spxl + MAX2(e_curr->x, 0);
- e_curr = e_curr->e_next;
- mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1;
-
- if((y_curr >= 0) && (y_curr < ctx->rb.sizey)) {
- mlayer_data->bounds[i].xstart=cpxl-spxl;
- mlayer_data->bounds[i].xend=mpxl-spxl;
- i++;
- }
- }
-
- for(edgec = &ctx->possible_edges; (e_curr = *edgec);) {
- if(!(--(e_curr->num))) {
- *edgec = e_curr->e_next;
- } else {
- e_curr->x += e_curr->xshift;
- if((e_curr->drift += e_curr->drift_inc) > 0) {
- e_curr->x += e_curr->xdir;
- e_curr->drift -= e_curr->drift_dec;
- }
- edgec = &e_curr->e_next;
- }
- }
- if(ctx->possible_edges) {
- for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
- /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */
- if(e_curr->x > e_curr->e_next->x) {
- *edgec = e_curr->e_next;
- /* exchange the pointers */
- e_temp = e_curr->e_next->e_next;
- e_curr->e_next->e_next = e_curr;
- e_curr->e_next = e_temp;
- /* set flag that we had at least one switch */
- swixd = 1;
- }
- }
- /* if we did have a switch, look for more (there will more if there was one) */
- for(;;) {
- /* reset exchange flag so it's only set if we encounter another one */
- swixd = 0;
- for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) {
- /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */
- if(e_curr->x > e_curr->e_next->x) {
- *edgec = e_curr->e_next;
- /* exchange the pointers */
- e_temp = e_curr->e_next->e_next;
- e_curr->e_next->e_next = e_curr;
- e_curr->e_next = e_temp;
- /* flip the exchanged flag */
- swixd = 1;
- }
- }
- /* if we had no exchanges, we're done reshuffling the pointers */
- if(!swixd) {
- break;
- }
- }
- }
- }
-
- free(edgbuf);
- return 1;
-}
-
-/* static */ int PLX_init_base_data(struct layer_init_data *mlayer_data, float(*base_verts)[2], int num_base_verts,
- float *buf, int buf_x, int buf_y) {
- int i; /* i: Loop counter. */
- struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */
- struct r_fill_context ctx = {0};
- const float buf_x_f = (float)(buf_x);
- const float buf_y_f = (float)(buf_y);
- if((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) {
- return(0);
- }
- ctx.rb.buf = buf; /* Set the output buffer pointer. */
- ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */
- ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */
- for(i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */
- ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */
- ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */
- }
- i = rast_scan_init(mlayer_data, &ctx, ply, num_base_verts); /* Call our rasterizer, passing in the integer coords for each vert. */
- free(ply); /* Free the memory allocated for the integer coordinate table. */
- return(i); /* Return the value returned by the rasterizer. */
-}
-
diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp
index b45fef26504..4bbf8e0a82b 100644
--- a/intern/smoke/intern/smoke_API.cpp
+++ b/intern/smoke/intern/smoke_API.cpp
@@ -28,7 +28,6 @@
* \ingroup smoke
*/
-
#include "FLUID_3D.h"
#include "WTURBULENCE.h"
@@ -36,6 +35,8 @@
#include <stdlib.h>
#include <math.h>
+#include "../extern/smoke_API.h" /* to ensure valid prototypes */
+
// y in smoke is z in blender
extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef)
{
@@ -283,10 +284,12 @@ extern "C" void smoke_get_ob_velocity(FLUID_3D *fluid, float **x, float **y, flo
*z = fluid->_zVelocityOb;
}
+#if 0
extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid)
{
return fluid->_obstaclesAnim;
}
+#endif
extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
{
diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h
index 6e9f6007e0b..a3d367a6fef 100644
--- a/intern/string/STR_String.h
+++ b/intern/string/STR_String.h
@@ -88,8 +88,16 @@ public:
inline ~STR_String() { delete[] this->m_data; }
// Operations
- STR_String& Format(const char *fmt, ...); // Set formatted text to string
- STR_String& FormatAdd(const char *fmt, ...); // Add formatted text to string
+ STR_String& Format(const char *fmt, ...) // Set formatted text to string
+#ifdef __GNUC__
+ __attribute__ ((format(printf, 2, 3)))
+#endif
+ ;
+ STR_String& FormatAdd(const char *fmt, ...) // Add formatted text to string
+#ifdef __GNUC__
+ __attribute__ ((format(printf, 2, 3)))
+#endif
+ ;
inline void Clear() { this->m_len = this->m_data[0] = 0; }
inline const STR_String & Reverse()
{
@@ -208,12 +216,10 @@ protected:
#endif
};
-inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length()); }
-inline STR_String operator+(rcSTR_String lhs, char rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1); }
-inline STR_String operator+(char lhs, rcSTR_String rhs) { return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length()); }
-inline STR_String operator+(rcSTR_String lhs, const char *rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs)); }
-inline STR_String operator+(const char *lhs, rcSTR_String rhs) { return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length()); }
-
+inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length()); }
+inline STR_String operator+(rcSTR_String lhs, char rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1); }
+inline STR_String operator+(char lhs, rcSTR_String rhs) { return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length()); }
+inline STR_String operator+(rcSTR_String lhs, const char *rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs)); }
+inline STR_String operator+(const char *lhs, rcSTR_String rhs) { return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length()); }
#endif //__STR_STRING_H__
-
diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp
index 4b2261e89f9..283b44380ee 100644
--- a/intern/string/intern/STR_String.cpp
+++ b/intern/string/intern/STR_String.cpp
@@ -738,4 +738,3 @@ int STR_String::Serialize(pCStream stream)
return this->m_len + sizeof(this->m_len);
}
#endif
-
diff --git a/release/bin/blender-softwaregl b/release/bin/blender-softwaregl
deleted file mode 100755
index 970a7870760..00000000000
--- a/release/bin/blender-softwaregl
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-BF_DIST_BIN=`dirname "$0"`
-BF_PROGRAM="blender" # BF_PROGRAM=`basename "$0"`-bin
-exitcode=0
-
-LD_LIBRARY_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARY_PATH}
-
-if [ -n "$LD_LIBRARYN32_PATH" ]; then
- LD_LIBRARYN32_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARYN32_PATH}
-fi
-if [ -n "$LD_LIBRARYN64_PATH" ]; then
- LD_LIBRARYN64_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARYN64_PATH}
-fi
-if [ -n "$LD_LIBRARY_PATH_64" ]; then
- LD_LIBRARY_PATH_64=${BF_DIST_BIN}/lib:${LD_LIBRARY_PATH_64}
-fi
-
-# Workaround for half-transparent windows when compiz is enabled
-XLIB_SKIP_ARGB_VISUALS=1
-
-export LD_LIBRARY_PATH LD_LIBRARYN32_PATH LD_LIBRARYN64_PATH LD_LIBRARY_PATH_64 LD_PRELOAD XLIB_SKIP_ARGB_VISUALS
-
-"$BF_DIST_BIN/$BF_PROGRAM" ${1+"$@"}
-exitcode=$?
-exit $exitcode
diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend
index 6f6c6646e31..773136a2f7d 100644
--- a/release/datafiles/startup.blend
+++ b/release/datafiles/startup.blend
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/brown00.png b/release/scripts/freestyle/data/env_map/brown00.png
new file mode 100755
index 00000000000..855f06f4fb9
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/brown00.png
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray00.png b/release/scripts/freestyle/data/env_map/gray00.png
new file mode 100755
index 00000000000..7c9b1a8149e
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/gray00.png
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray01.png b/release/scripts/freestyle/data/env_map/gray01.png
new file mode 100755
index 00000000000..06542908e6b
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/gray01.png
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray02.png b/release/scripts/freestyle/data/env_map/gray02.png
new file mode 100755
index 00000000000..0208f4920d9
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/gray02.png
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray03.png b/release/scripts/freestyle/data/env_map/gray03.png
new file mode 100755
index 00000000000..aab9b957c21
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/gray03.png
Binary files differ
diff --git a/release/scripts/freestyle/style_modules/ChainingIterators.py b/release/scripts/freestyle/style_modules/ChainingIterators.py
new file mode 100755
index 00000000000..f2d953ddc14
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/ChainingIterators.py
@@ -0,0 +1,731 @@
+#
+# Filename : ChainingIterators.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Chaining Iterators to be used with chaining operators
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+
+## the natural chaining iterator
+## It follows the edges of same nature following the topology of
+## objects with preseance on silhouettes, then borders,
+## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
+## You can specify whether to stay in the selection or not.
+class pyChainSilhouetteIterator(ChainingIterator):
+ def __init__(self, stayInSelection=1):
+ ChainingIterator.__init__(self, stayInSelection, 1,None,1)
+ def getExactTypeName(self):
+ return "pyChainSilhouetteIterator"
+ def init(self):
+ pass
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ tvertex = self.getVertex()
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.mate(self.getCurrentEdge())
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getId() == mateVE.getId() ):
+ winner = ve
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for i in range(len(natures)):
+ currentNature = self.getCurrentEdge().getNature()
+ if(natures[i] & currentNature):
+ count=0
+ while(it.isEnd() == 0):
+ visitNext = 0
+ oNature = it.getObject().getNature()
+ if(oNature & natures[i] != 0):
+ if(natures[i] != oNature):
+ for j in range(i):
+ if(natures[j] & oNature != 0):
+ visitNext = 1
+ break
+ if(visitNext != 0):
+ break
+ count = count+1
+ winner = it.getObject()
+ it.increment()
+ if(count != 1):
+ winner = None
+ break
+ return winner
+
+## the natural chaining iterator
+## It follows the edges of same nature on the same
+## objects with preseance on silhouettes, then borders,
+## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
+## You can specify whether to stay in the selection or not.
+## You can specify whether to chain iterate over edges that were
+## already visited or not.
+class pyChainSilhouetteGenericIterator(ChainingIterator):
+ def __init__(self, stayInSelection=1, stayInUnvisited=1):
+ ChainingIterator.__init__(self, stayInSelection, stayInUnvisited,None,1)
+ def getExactTypeName(self):
+ return "pyChainSilhouetteGenericIterator"
+ def init(self):
+ pass
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ tvertex = self.getVertex()
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.mate(self.getCurrentEdge())
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getId() == mateVE.getId() ):
+ winner = ve
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for i in range(len(natures)):
+ currentNature = self.getCurrentEdge().getNature()
+ if(natures[i] & currentNature):
+ count=0
+ while(it.isEnd() == 0):
+ visitNext = 0
+ oNature = it.getObject().getNature()
+ ve = it.getObject()
+ if(ve.getId() == self.getCurrentEdge().getId()):
+ it.increment()
+ continue
+ if(oNature & natures[i] != 0):
+ if(natures[i] != oNature):
+ for j in range(i):
+ if(natures[j] & oNature != 0):
+ visitNext = 1
+ break
+ if(visitNext != 0):
+ break
+ count = count+1
+ winner = ve
+ it.increment()
+ if(count != 1):
+ winner = None
+ break
+ return winner
+
+class pyExternalContourChainingIterator(ChainingIterator):
+ def __init__(self):
+ ChainingIterator.__init__(self, 0, 1,None,1)
+ self._isExternalContour = ExternalContourUP1D()
+
+ def getExactTypeName(self):
+ return "pyExternalContourIterator"
+
+ def init(self):
+ self._nEdges = 0
+ self._isInSelection = 1
+
+ def checkViewEdge(self, ve, orientation):
+ if(orientation != 0):
+ vertex = ve.B()
+ else:
+ vertex = ve.A()
+ it = AdjacencyIterator(vertex,1,1)
+ while(it.isEnd() == 0):
+ ave = it.getObject()
+ if(self._isExternalContour(ave)):
+ return 1
+ it.increment()
+ print("pyExternlContourChainingIterator : didn't find next edge")
+ return 0
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(self._isExternalContour(ve)):
+ if (ve.getTimeStamp() == GetTimeStampCF()):
+ winner = ve
+ it.increment()
+
+ self._nEdges = self._nEdges+1
+ if(winner == None):
+ orient = 1
+ it = AdjacencyIterator(iter)
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(it.isIncoming() != 0):
+ orient = 0
+ good = self.checkViewEdge(ve,orient)
+ if(good != 0):
+ winner = ve
+ it.increment()
+ return winner
+
+## the natural chaining iterator
+## with a sketchy multiple touch
+class pySketchyChainSilhouetteIterator(ChainingIterator):
+ def __init__(self, nRounds=3,stayInSelection=1):
+ ChainingIterator.__init__(self, stayInSelection, 0,None,1)
+ self._timeStamp = GetTimeStampCF()+nRounds
+ self._nRounds = nRounds
+ def getExactTypeName(self):
+ return "pySketchyChainSilhouetteIterator"
+ def init(self):
+ self._timeStamp = GetTimeStampCF()+self._nRounds
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ tvertex = self.getVertex()
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.mate(self.getCurrentEdge())
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getId() == mateVE.getId() ):
+ winner = ve
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for i in range(len(natures)):
+ currentNature = self.getCurrentEdge().getNature()
+ if(natures[i] & currentNature):
+ count=0
+ while(it.isEnd() == 0):
+ visitNext = 0
+ oNature = it.getObject().getNature()
+ ve = it.getObject()
+ if(ve.getId() == self.getCurrentEdge().getId()):
+ it.increment()
+ continue
+ if(oNature & natures[i] != 0):
+ if(natures[i] != oNature):
+ for j in range(i):
+ if(natures[j] & oNature != 0):
+ visitNext = 1
+ break
+ if(visitNext != 0):
+ break
+ count = count+1
+ winner = ve
+ it.increment()
+ if(count != 1):
+ winner = None
+ break
+ if(winner == None):
+ winner = self.getCurrentEdge()
+ if(winner.getChainingTimeStamp() == self._timeStamp):
+ winner = None
+ return winner
+
+
+# Chaining iterator designed for sketchy style.
+# can chain several times the same ViewEdge
+# in order to produce multiple strokes per ViewEdge.
+class pySketchyChainingIterator(ChainingIterator):
+ def __init__(self, nRounds=3, stayInSelection=1):
+ ChainingIterator.__init__(self, stayInSelection, 0,None,1)
+ self._timeStamp = GetTimeStampCF()+nRounds
+ self._nRounds = nRounds
+ def getExactTypeName(self):
+ return "pySketchyChainingIterator"
+
+ def init(self):
+ self._timeStamp = GetTimeStampCF()+self._nRounds
+
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getId() == self.getCurrentEdge().getId()):
+ it.increment()
+ continue
+ winner = ve
+ it.increment()
+ if(winner == None):
+ winner = self.getCurrentEdge()
+ if(winner.getChainingTimeStamp() == self._timeStamp):
+ return None
+ return winner
+
+
+## Chaining iterator that fills small occlusions
+## percent
+## The max length of the occluded part
+## expressed in % of the total chain length
+class pyFillOcclusionsRelativeChainingIterator(ChainingIterator):
+ def __init__(self, percent):
+ ChainingIterator.__init__(self, 0, 1,None,1)
+ self._length = 0
+ self._percent = float(percent)
+ def getExactTypeName(self):
+ return "pyFillOcclusionsChainingIterator"
+ def init(self):
+ # each time we're evaluating a chain length
+ # we try to do it once. Thus we reinit
+ # the chain length here:
+ self._length = 0
+ def traverse(self, iter):
+ winner = None
+ winnerOrientation = 0
+ print(self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond())
+ it = AdjacencyIterator(iter)
+ tvertex = self.getVertex()
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.mate(self.getCurrentEdge())
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getId() == mateVE.getId() ):
+ winner = ve
+ if(it.isIncoming() == 0):
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for nat in natures:
+ if(self.getCurrentEdge().getNature() & nat != 0):
+ count=0
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getNature() & nat != 0):
+ count = count+1
+ winner = ve
+ if(it.isIncoming() == 0):
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ it.increment()
+ if(count != 1):
+ winner = None
+ break
+ if(winner != None):
+ # check whether this edge was part of the selection
+ if(winner.getTimeStamp() != GetTimeStampCF()):
+ #print("---", winner.getId().getFirst(), winner.getId().getSecond())
+ # if not, let's check whether it's short enough with
+ # respect to the chain made without staying in the selection
+ #------------------------------------------------------------
+ # Did we compute the prospective chain length already ?
+ if(self._length == 0):
+ #if not, let's do it
+ _it = pyChainSilhouetteGenericIterator(0,0)
+ _it.setBegin(winner)
+ _it.setCurrentEdge(winner)
+ _it.setOrientation(winnerOrientation)
+ _it.init()
+ while(_it.isEnd() == 0):
+ ve = _it.getObject()
+ #print("--------", ve.getId().getFirst(), ve.getId().getSecond())
+ self._length = self._length + ve.getLength2D()
+ _it.increment()
+ if(_it.isBegin() != 0):
+ break;
+ _it.setBegin(winner)
+ _it.setCurrentEdge(winner)
+ _it.setOrientation(winnerOrientation)
+ if(_it.isBegin() == 0):
+ _it.decrement()
+ while ((_it.isEnd() == 0) and (_it.isBegin() == 0)):
+ ve = _it.getObject()
+ #print("--------", ve.getId().getFirst(), ve.getId().getSecond())
+ self._length = self._length + ve.getLength2D()
+ _it.decrement()
+
+ # let's do the comparison:
+ # nw let's compute the length of this connex non selected part:
+ connexl = 0
+ _cit = pyChainSilhouetteGenericIterator(0,0)
+ _cit.setBegin(winner)
+ _cit.setCurrentEdge(winner)
+ _cit.setOrientation(winnerOrientation)
+ _cit.init()
+ while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())):
+ ve = _cit.getObject()
+ #print("-------- --------", ve.getId().getFirst(), ve.getId().getSecond())
+ connexl = connexl + ve.getLength2D()
+ _cit.increment()
+ if(connexl > self._percent * self._length):
+ winner = None
+ return winner
+
+## Chaining iterator that fills small occlusions
+## size
+## The max length of the occluded part
+## expressed in pixels
+class pyFillOcclusionsAbsoluteChainingIterator(ChainingIterator):
+ def __init__(self, length):
+ ChainingIterator.__init__(self, 0, 1,None,1)
+ self._length = float(length)
+ def getExactTypeName(self):
+ return "pySmallFillOcclusionsChainingIterator"
+ def init(self):
+ pass
+ def traverse(self, iter):
+ winner = None
+ winnerOrientation = 0
+ #print(self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond())
+ it = AdjacencyIterator(iter)
+ tvertex = self.getVertex()
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.mate(self.getCurrentEdge())
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getId() == mateVE.getId() ):
+ winner = ve
+ if(it.isIncoming() == 0):
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for nat in natures:
+ if(self.getCurrentEdge().getNature() & nat != 0):
+ count=0
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getNature() & nat != 0):
+ count = count+1
+ winner = ve
+ if(it.isIncoming() == 0):
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ it.increment()
+ if(count != 1):
+ winner = None
+ break
+ if(winner != None):
+ # check whether this edge was part of the selection
+ if(winner.getTimeStamp() != GetTimeStampCF()):
+ #print("---", winner.getId().getFirst(), winner.getId().getSecond())
+ # nw let's compute the length of this connex non selected part:
+ connexl = 0
+ _cit = pyChainSilhouetteGenericIterator(0,0)
+ _cit.setBegin(winner)
+ _cit.setCurrentEdge(winner)
+ _cit.setOrientation(winnerOrientation)
+ _cit.init()
+ while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())):
+ ve = _cit.getObject()
+ #print("-------- --------", ve.getId().getFirst(), ve.getId().getSecond())
+ connexl = connexl + ve.getLength2D()
+ _cit.increment()
+ if(connexl > self._length):
+ winner = None
+ return winner
+
+
+## Chaining iterator that fills small occlusions
+## percent
+## The max length of the occluded part
+## expressed in % of the total chain length
+class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator):
+ def __init__(self, percent, l):
+ ChainingIterator.__init__(self, 0, 1,None,1)
+ self._length = 0
+ self._absLength = l
+ self._percent = float(percent)
+ def getExactTypeName(self):
+ return "pyFillOcclusionsChainingIterator"
+ def init(self):
+ # each time we're evaluating a chain length
+ # we try to do it once. Thus we reinit
+ # the chain length here:
+ self._length = 0
+ def traverse(self, iter):
+ winner = None
+ winnerOrientation = 0
+ print(self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond())
+ it = AdjacencyIterator(iter)
+ tvertex = self.getVertex()
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.mate(self.getCurrentEdge())
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getId() == mateVE.getId() ):
+ winner = ve
+ if(it.isIncoming() == 0):
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for nat in natures:
+ if(self.getCurrentEdge().getNature() & nat != 0):
+ count=0
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getNature() & nat != 0):
+ count = count+1
+ winner = ve
+ if(it.isIncoming() == 0):
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ it.increment()
+ if(count != 1):
+ winner = None
+ break
+ if(winner != None):
+ # check whether this edge was part of the selection
+ if(winner.getTimeStamp() != GetTimeStampCF()):
+ #print("---", winner.getId().getFirst(), winner.getId().getSecond())
+ # if not, let's check whether it's short enough with
+ # respect to the chain made without staying in the selection
+ #------------------------------------------------------------
+ # Did we compute the prospective chain length already ?
+ if(self._length == 0):
+ #if not, let's do it
+ _it = pyChainSilhouetteGenericIterator(0,0)
+ _it.setBegin(winner)
+ _it.setCurrentEdge(winner)
+ _it.setOrientation(winnerOrientation)
+ _it.init()
+ while(_it.isEnd() == 0):
+ ve = _it.getObject()
+ #print("--------", ve.getId().getFirst(), ve.getId().getSecond())
+ self._length = self._length + ve.getLength2D()
+ _it.increment()
+ if(_it.isBegin() != 0):
+ break;
+ _it.setBegin(winner)
+ _it.setCurrentEdge(winner)
+ _it.setOrientation(winnerOrientation)
+ if(_it.isBegin() == 0):
+ _it.decrement()
+ while ((_it.isEnd() == 0) and (_it.isBegin() == 0)):
+ ve = _it.getObject()
+ #print("--------", ve.getId().getFirst(), ve.getId().getSecond())
+ self._length = self._length + ve.getLength2D()
+ _it.decrement()
+
+ # let's do the comparison:
+ # nw let's compute the length of this connex non selected part:
+ connexl = 0
+ _cit = pyChainSilhouetteGenericIterator(0,0)
+ _cit.setBegin(winner)
+ _cit.setCurrentEdge(winner)
+ _cit.setOrientation(winnerOrientation)
+ _cit.init()
+ while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())):
+ ve = _cit.getObject()
+ #print("-------- --------", ve.getId().getFirst(), ve.getId().getSecond())
+ connexl = connexl + ve.getLength2D()
+ _cit.increment()
+ if((connexl > self._percent * self._length) or (connexl > self._absLength)):
+ winner = None
+ return winner
+
+## Chaining iterator that fills small occlusions without caring about the
+## actual selection
+## percent
+## The max length of the occluded part
+## expressed in % of the total chain length
+class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator):
+ def __init__(self, percent, l):
+ ChainingIterator.__init__(self, 0, 1,None,1)
+ self._length = 0
+ self._absLength = l
+ self._percent = float(percent)
+ def getExactTypeName(self):
+ return "pyFillOcclusionsChainingIterator"
+ def init(self):
+ # each time we're evaluating a chain length
+ # we try to do it once. Thus we reinit
+ # the chain length here:
+ self._length = 0
+ def traverse(self, iter):
+ winner = None
+ winnerOrientation = 0
+ print(self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond())
+ it = AdjacencyIterator(iter)
+ tvertex = self.getVertex()
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.mate(self.getCurrentEdge())
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getId() == mateVE.getId() ):
+ winner = ve
+ if(it.isIncoming() == 0):
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for nat in natures:
+ if(self.getCurrentEdge().getNature() & nat != 0):
+ count=0
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ if(ve.getNature() & nat != 0):
+ count = count+1
+ winner = ve
+ if(it.isIncoming() == 0):
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ it.increment()
+ if(count != 1):
+ winner = None
+ break
+ if(winner != None):
+ # check whether this edge was part of the selection
+ if(winner.qi() != 0):
+ #print("---", winner.getId().getFirst(), winner.getId().getSecond())
+ # if not, let's check whether it's short enough with
+ # respect to the chain made without staying in the selection
+ #------------------------------------------------------------
+ # Did we compute the prospective chain length already ?
+ if(self._length == 0):
+ #if not, let's do it
+ _it = pyChainSilhouetteGenericIterator(0,0)
+ _it.setBegin(winner)
+ _it.setCurrentEdge(winner)
+ _it.setOrientation(winnerOrientation)
+ _it.init()
+ while(_it.isEnd() == 0):
+ ve = _it.getObject()
+ #print("--------", ve.getId().getFirst(), ve.getId().getSecond())
+ self._length = self._length + ve.getLength2D()
+ _it.increment()
+ if(_it.isBegin() != 0):
+ break;
+ _it.setBegin(winner)
+ _it.setCurrentEdge(winner)
+ _it.setOrientation(winnerOrientation)
+ if(_it.isBegin() == 0):
+ _it.decrement()
+ while ((_it.isEnd() == 0) and (_it.isBegin() == 0)):
+ ve = _it.getObject()
+ #print("--------", ve.getId().getFirst(), ve.getId().getSecond())
+ self._length = self._length + ve.getLength2D()
+ _it.decrement()
+
+ # let's do the comparison:
+ # nw let's compute the length of this connex non selected part:
+ connexl = 0
+ _cit = pyChainSilhouetteGenericIterator(0,0)
+ _cit.setBegin(winner)
+ _cit.setCurrentEdge(winner)
+ _cit.setOrientation(winnerOrientation)
+ _cit.init()
+ while((_cit.isEnd() == 0) and (_cit.getObject().qi() != 0)):
+ ve = _cit.getObject()
+ #print("-------- --------", ve.getId().getFirst(), ve.getId().getSecond())
+ connexl = connexl + ve.getLength2D()
+ _cit.increment()
+ if((connexl > self._percent * self._length) or (connexl > self._absLength)):
+ winner = None
+ return winner
+
+
+## the natural chaining iterator
+## It follows the edges of same nature on the same
+## objects with preseance on silhouettes, then borders,
+## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
+## You can specify whether to stay in the selection or not.
+class pyNoIdChainSilhouetteIterator(ChainingIterator):
+ def __init__(self, stayInSelection=1):
+ ChainingIterator.__init__(self, stayInSelection, 1,None,1)
+ def getExactTypeName(self):
+ return "pyChainSilhouetteIterator"
+ def init(self):
+ pass
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ tvertex = self.getVertex()
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.mate(self.getCurrentEdge())
+ while(it.isEnd() == 0):
+ ve = it.getObject()
+ feB = self.getCurrentEdge().fedgeB()
+ feA = ve.fedgeA()
+ vB = feB.vertexB()
+ vA = feA.vertexA()
+ if vA.getId().getFirst() == vB.getId().getFirst():
+ winner = ve
+ break
+ feA = self.getCurrentEdge().fedgeA()
+ feB = ve.fedgeB()
+ vB = feB.vertexB()
+ vA = feA.vertexA()
+ if vA.getId().getFirst() == vB.getId().getFirst():
+ winner = ve
+ break
+ feA = self.getCurrentEdge().fedgeB()
+ feB = ve.fedgeB()
+ vB = feB.vertexB()
+ vA = feA.vertexB()
+ if vA.getId().getFirst() == vB.getId().getFirst():
+ winner = ve
+ break
+ feA = self.getCurrentEdge().fedgeA()
+ feB = ve.fedgeA()
+ vB = feB.vertexA()
+ vA = feA.vertexA()
+ if vA.getId().getFirst() == vB.getId().getFirst():
+ winner = ve
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for i in range(len(natures)):
+ currentNature = self.getCurrentEdge().getNature()
+ if(natures[i] & currentNature):
+ count=0
+ while(it.isEnd() == 0):
+ visitNext = 0
+ oNature = it.getObject().getNature()
+ if(oNature & natures[i] != 0):
+ if(natures[i] != oNature):
+ for j in range(i):
+ if(natures[j] & oNature != 0):
+ visitNext = 1
+ break
+ if(visitNext != 0):
+ break
+ count = count+1
+ winner = it.getObject()
+ it.increment()
+ if(count != 1):
+ winner = None
+ break
+ return winner
+
diff --git a/release/scripts/freestyle/style_modules/Functions0D.py b/release/scripts/freestyle/style_modules/Functions0D.py
new file mode 100755
index 00000000000..38dd4b770a6
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/Functions0D.py
@@ -0,0 +1,92 @@
+from freestyle_init import *
+
+class CurveMaterialF0D(UnaryFunction0DMaterial):
+ # A replacement of the built-in MaterialF0D for stroke creation.
+ # MaterialF0D does not work with Curves and Strokes.
+ def getName(self):
+ return "CurveMaterialF0D"
+ def __call__(self, inter):
+ cp = inter.getObject()
+ assert(isinstance(cp, CurvePoint))
+ fe = cp.A().getFEdge(cp.B())
+ assert(fe is not None)
+ return fe.material() if fe.isSmooth() else fe.bMaterial()
+
+class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble):
+ def getName(self):
+ return "InverseCurvature2DAngleF0D"
+
+ def __call__(self, inter):
+ func = Curvature2DAngleF0D()
+ c = func(inter)
+ return (3.1415 - c)
+
+class pyCurvilinearLengthF0D(UnaryFunction0DDouble):
+ def getName(self):
+ return "CurvilinearLengthF0D"
+
+ def __call__(self, inter):
+ i0d = inter.getObject()
+ s = i0d.getExactTypeName()
+ if (string.find(s, "CurvePoint") == -1):
+ print("CurvilinearLengthF0D: not implemented yet for", s)
+ return -1
+ cp = castToCurvePoint(i0d)
+ return cp.t2d()
+
+## estimate anisotropy of density
+class pyDensityAnisotropyF0D(UnaryFunction0DDouble):
+ def __init__(self,level):
+ UnaryFunction0DDouble.__init__(self)
+ self.IsoDensity = ReadCompleteViewMapPixelF0D(level)
+ self.d0Density = ReadSteerableViewMapPixelF0D(0, level)
+ self.d1Density = ReadSteerableViewMapPixelF0D(1, level)
+ self.d2Density = ReadSteerableViewMapPixelF0D(2, level)
+ self.d3Density = ReadSteerableViewMapPixelF0D(3, level)
+ def getName(self):
+ return "pyDensityAnisotropyF0D"
+ def __call__(self, inter):
+ c_iso = self.IsoDensity(inter)
+ c_0 = self.d0Density(inter)
+ c_1 = self.d1Density(inter)
+ c_2 = self.d2Density(inter)
+ c_3 = self.d3Density(inter)
+ cMax = max( max(c_0,c_1), max(c_2,c_3))
+ cMin = min( min(c_0,c_1), min(c_2,c_3))
+ if ( c_iso == 0 ):
+ v = 0
+ else:
+ v = (cMax-cMin)/c_iso
+ return (v)
+
+## Returns the gradient vector for a pixel
+## l
+## the level at which one wants to compute the gradient
+class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f):
+ def __init__(self, l):
+ UnaryFunction0DVec2f.__init__(self)
+ self._l = l
+ self._step = pow(2,self._l)
+ def getName(self):
+ return "pyViewMapGradientVectorF0D"
+ def __call__(self, iter):
+ p = iter.getObject().getPoint2D()
+ gx = ReadCompleteViewMapPixelCF(self._l, int(p.x()+self._step), int(p.y()))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()))
+ gy = ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()+self._step))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()))
+ return Vector([gx, gy])
+
+class pyViewMapGradientNormF0D(UnaryFunction0DDouble):
+ def __init__(self, l):
+ UnaryFunction0DDouble.__init__(self)
+ self._l = l
+ self._step = pow(2,self._l)
+ def getName(self):
+ return "pyViewMapGradientNormF0D"
+ def __call__(self, iter):
+ p = iter.getObject().getPoint2D()
+ gx = ReadCompleteViewMapPixelCF(self._l, int(p.x()+self._step), int(p.y()))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()))
+ gy = ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()+self._step))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()))
+ grad = Vector([gx, gy])
+ return grad.length
+
+
diff --git a/release/scripts/freestyle/style_modules/Functions1D.py b/release/scripts/freestyle/style_modules/Functions1D.py
new file mode 100755
index 00000000000..aaf115356cb
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/Functions1D.py
@@ -0,0 +1,45 @@
+from freestyle_init import *
+from Functions0D import *
+import string
+
+class pyGetInverseProjectedZF1D(UnaryFunction1DDouble):
+ def getName(self):
+ return "pyGetInverseProjectedZF1D"
+
+ def __call__(self, inter):
+ func = GetProjectedZF1D()
+ z = func(inter)
+ return (1.0 - z)
+
+class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble):
+ def getName(self):
+ return "pyGetInverseProjectedZF1D"
+
+ def __call__(self, inter):
+ func = GetProjectedZF1D()
+ z = func(inter)
+ return (1.0 - z*z)
+
+class pyDensityAnisotropyF1D(UnaryFunction1DDouble):
+ def __init__(self,level, integrationType=IntegrationType.MEAN, sampling=2.0):
+ UnaryFunction1DDouble.__init__(self, integrationType)
+ self._func = pyDensityAnisotropyF0D(level)
+ self._integration = integrationType
+ self._sampling = sampling
+ def getName(self):
+ return "pyDensityAnisotropyF1D"
+ def __call__(self, inter):
+ v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration)
+ return v
+
+class pyViewMapGradientNormF1D(UnaryFunction1DDouble):
+ def __init__(self,l, integrationType, sampling=2.0):
+ UnaryFunction1DDouble.__init__(self, integrationType)
+ self._func = pyViewMapGradientNormF0D(l)
+ self._integration = integrationType
+ self._sampling = sampling
+ def getName(self):
+ return "pyViewMapGradientNormF1D"
+ def __call__(self, inter):
+ v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration)
+ return v
diff --git a/release/scripts/freestyle/style_modules/PredicatesB1D.py b/release/scripts/freestyle/style_modules/PredicatesB1D.py
new file mode 100755
index 00000000000..3b7d21039df
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/PredicatesB1D.py
@@ -0,0 +1,70 @@
+from freestyle_init import *
+from Functions1D import *
+from random import *
+
+class pyZBP1D(BinaryPredicate1D):
+ def getName(self):
+ return "pyZBP1D"
+
+ def __call__(self, i1, i2):
+ func = GetZF1D()
+ return (func(i1) > func(i2))
+
+class pyZDiscontinuityBP1D(BinaryPredicate1D):
+ def __init__(self, iType = IntegrationType.MEAN):
+ BinaryPredicate1D.__init__(self)
+ self._GetZDiscontinuity = ZDiscontinuityF1D(iType)
+
+ def getName(self):
+ return "pyZDiscontinuityBP1D"
+
+ def __call__(self, i1, i2):
+ return (self._GetZDiscontinuity(i1) > self._GetZDiscontinuity(i2))
+
+class pyLengthBP1D(BinaryPredicate1D):
+ def getName(self):
+ return "LengthBP1D"
+
+ def __call__(self, i1, i2):
+ return (i1.getLength2D() > i2.getLength2D())
+
+class pySilhouetteFirstBP1D(BinaryPredicate1D):
+ def getName(self):
+ return "SilhouetteFirstBP1D"
+
+ def __call__(self, inter1, inter2):
+ bpred = SameShapeIdBP1D()
+ if (bpred(inter1, inter2) != 1):
+ return 0
+ if (inter1.getNature() & Nature.SILHOUETTE):
+ return (inter2.getNature() & Nature.SILHOUETTE)
+ return (inter1.getNature() == inter2.getNature())
+
+class pyNatureBP1D(BinaryPredicate1D):
+ def getName(self):
+ return "NatureBP1D"
+
+ def __call__(self, inter1, inter2):
+ return (inter1.getNature() & inter2.getNature())
+
+class pyViewMapGradientNormBP1D(BinaryPredicate1D):
+ def __init__(self,l, sampling=2.0):
+ BinaryPredicate1D.__init__(self)
+ self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
+ def getName(self):
+ return "pyViewMapGradientNormBP1D"
+ def __call__(self, i1,i2):
+ print("compare gradient")
+ return (self._GetGradient(i1) > self._GetGradient(i2))
+
+class pyShuffleBP1D(BinaryPredicate1D):
+ def __init__(self):
+ BinaryPredicate1D.__init__(self)
+ seed(1)
+ def getName(self):
+ return "pyNearAndContourFirstBP1D"
+
+ def __call__(self, inter1, inter2):
+ r1 = uniform(0,1)
+ r2 = uniform(0,1)
+ return (r1<r2)
diff --git a/release/scripts/freestyle/style_modules/PredicatesU0D.py b/release/scripts/freestyle/style_modules/PredicatesU0D.py
new file mode 100755
index 00000000000..162254f17ed
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/PredicatesU0D.py
@@ -0,0 +1,103 @@
+from freestyle_init import *
+from Functions0D import *
+
+class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
+ def __init__(self,a):
+ UnaryPredicate0D.__init__(self)
+ self._a = a
+
+ def getName(self):
+ return "HigherCurvature2DAngleUP0D"
+
+ def __call__(self, inter):
+ func = Curvature2DAngleF0D()
+ a = func(inter)
+ return ( a > self._a)
+
+class pyUEqualsUP0D(UnaryPredicate0D):
+ def __init__(self,u, w):
+ UnaryPredicate0D.__init__(self)
+ self._u = u
+ self._w = w
+
+ def getName(self):
+ return "UEqualsUP0D"
+
+ def __call__(self, inter):
+ func = pyCurvilinearLengthF0D()
+ u = func(inter)
+ return ( ( u > (self._u-self._w) ) and ( u < (self._u+self._w) ) )
+
+class pyVertexNatureUP0D(UnaryPredicate0D):
+ def __init__(self,nature):
+ UnaryPredicate0D.__init__(self)
+ self._nature = nature
+
+ def getName(self):
+ return "pyVertexNatureUP0D"
+
+ def __call__(self, inter):
+ v = inter.getObject()
+ nat = v.getNature()
+ if(nat & self._nature):
+ return 1;
+ return 0
+
+## check whether an Interface0DIterator
+## is a TVertex and is the one that is
+## hidden (inferred from the context)
+class pyBackTVertexUP0D(UnaryPredicate0D):
+ def __init__(self):
+ UnaryPredicate0D.__init__(self)
+ self._getQI = QuantitativeInvisibilityF0D()
+ def getName(self):
+ return "pyBackTVertexUP0D"
+ def __call__(self, iter):
+ v = iter.getObject()
+ nat = v.getNature()
+ if(nat & Nature.T_VERTEX == 0):
+ return 0
+ next = iter
+ if(next.isEnd()):
+ return 0
+ if(self._getQI(next) != 0):
+ return 1
+ return 0
+
+class pyParameterUP0DGoodOne(UnaryPredicate0D):
+ def __init__(self,pmin,pmax):
+ UnaryPredicate0D.__init__(self)
+ self._m = pmin
+ self._M = pmax
+ #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D()
+
+ def getName(self):
+ return "pyCurvilinearAbscissaHigherThanUP0D"
+
+ def __call__(self, inter):
+ #s = self.getCurvilinearAbscissa(inter)
+ u = inter.u()
+ #print(u)
+ return ((u>=self._m) and (u<=self._M))
+
+class pyParameterUP0D(UnaryPredicate0D):
+ def __init__(self,pmin,pmax):
+ UnaryPredicate0D.__init__(self)
+ self._m = pmin
+ self._M = pmax
+ #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D()
+
+ def getName(self):
+ return "pyCurvilinearAbscissaHigherThanUP0D"
+
+ def __call__(self, inter):
+ func = Curvature2DAngleF0D()
+ c = func(inter)
+ b1 = (c>0.1)
+ #s = self.getCurvilinearAbscissa(inter)
+ u = inter.u()
+ #print(u)
+ b = ((u>=self._m) and (u<=self._M))
+ return b and b1
+
+
diff --git a/release/scripts/freestyle/style_modules/PredicatesU1D.py b/release/scripts/freestyle/style_modules/PredicatesU1D.py
new file mode 100755
index 00000000000..3529ca8b4e3
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/PredicatesU1D.py
@@ -0,0 +1,381 @@
+from freestyle_init import *
+from Functions1D import *
+
+count = 0
+class pyNFirstUP1D(UnaryPredicate1D):
+ def __init__(self, n):
+ UnaryPredicate1D.__init__(self)
+ self.__n = n
+ def __call__(self, inter):
+ global count
+ count = count + 1
+ if count <= self.__n:
+ return 1
+ return 0
+
+class pyHigherLengthUP1D(UnaryPredicate1D):
+ def __init__(self,l):
+ UnaryPredicate1D.__init__(self)
+ self._l = l
+
+ def getName(self):
+ return "HigherLengthUP1D"
+
+ def __call__(self, inter):
+ return (inter.getLength2D() > self._l)
+
+class pyNatureUP1D(UnaryPredicate1D):
+ def __init__(self,nature):
+ UnaryPredicate1D.__init__(self)
+ self._nature = nature
+ self._getNature = CurveNatureF1D()
+
+ def getName(self):
+ return "pyNatureUP1D"
+
+ def __call__(self, inter):
+ if(self._getNature(inter) & self._nature):
+ return 1
+ return 0
+
+class pyHigherNumberOfTurnsUP1D(UnaryPredicate1D):
+ def __init__(self,n,a):
+ UnaryPredicate1D.__init__(self)
+ self._n = n
+ self._a = a
+
+ def getName(self):
+ return "HigherNumberOfTurnsUP1D"
+
+ def __call__(self, inter):
+ count = 0
+ func = Curvature2DAngleF0D()
+ it = inter.verticesBegin()
+ while(it.isEnd() == 0):
+ if(func(it) > self._a):
+ count = count+1
+ if(count > self._n):
+ return 1
+ it.increment()
+ return 0
+
+class pyDensityUP1D(UnaryPredicate1D):
+ def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._wsize = wsize
+ self._threshold = threshold
+ self._integration = integration
+ self._func = DensityF1D(self._wsize, self._integration, sampling)
+
+ def getName(self):
+ return "pyDensityUP1D"
+
+ def __call__(self, inter):
+ if(self._func(inter) < self._threshold):
+ return 1
+ return 0
+
+class pyLowSteerableViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, level,integration = IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._level = level
+ self._integration = integration
+
+ def getName(self):
+ return "pyLowSteerableViewMapDensityUP1D"
+
+ def __call__(self, inter):
+ func = GetSteerableViewMapDensityF1D(self._level, self._integration)
+ v = func(inter)
+ print(v)
+ if(v < self._threshold):
+ return 1
+ return 0
+
+class pyLowDirectionalViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._orientation = orientation
+ self._level = level
+ self._integration = integration
+
+ def getName(self):
+ return "pyLowDirectionalViewMapDensityUP1D"
+
+ def __call__(self, inter):
+ func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration)
+ v = func(inter)
+ #print(v)
+ if(v < self._threshold):
+ return 1
+ return 0
+
+class pyHighSteerableViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, level,integration = IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._level = level
+ self._integration = integration
+ self._func = GetSteerableViewMapDensityF1D(self._level, self._integration)
+ def getName(self):
+ return "pyHighSteerableViewMapDensityUP1D"
+
+ def __call__(self, inter):
+
+ v = self._func(inter)
+ if(v > self._threshold):
+ return 1
+ return 0
+
+class pyHighDirectionalViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._orientation = orientation
+ self._level = level
+ self._integration = integration
+ self._sampling = sampling
+ def getName(self):
+ return "pyLowDirectionalViewMapDensityUP1D"
+
+ def __call__(self, inter):
+ func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration, self._sampling)
+ v = func(inter)
+ if(v > self._threshold):
+ return 1
+ return 0
+
+class pyHighViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, level,integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._level = level
+ self._integration = integration
+ self._sampling = sampling
+ self._func = GetCompleteViewMapDensityF1D(self._level, self._integration, self._sampling) # 2.0 is the smpling
+
+ def getName(self):
+ return "pyHighViewMapDensityUP1D"
+
+ def __call__(self, inter):
+ #print("toto")
+ #print(func.getName())
+ #print(inter.getExactTypeName())
+ v= self._func(inter)
+ if(v > self._threshold):
+ return 1
+ return 0
+
+class pyDensityFunctorUP1D(UnaryPredicate1D):
+ def __init__(self,wsize,threshold, functor, funcmin=0.0, funcmax=1.0, integration = IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._wsize = wsize
+ self._threshold = float(threshold)
+ self._functor = functor
+ self._funcmin = float(funcmin)
+ self._funcmax = float(funcmax)
+ self._integration = integration
+
+ def getName(self):
+ return "pyDensityFunctorUP1D"
+
+ def __call__(self, inter):
+ func = DensityF1D(self._wsize, self._integration)
+ res = self._functor(inter)
+ k = (res-self._funcmin)/(self._funcmax-self._funcmin)
+ if(func(inter) < self._threshold*k):
+ return 1
+ return 0
+
+class pyZSmallerUP1D(UnaryPredicate1D):
+ def __init__(self,z, integration=IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._z = z
+ self._integration = integration
+ def getName(self):
+ return "pyZSmallerUP1D"
+
+ def __call__(self, inter):
+ func = GetProjectedZF1D(self._integration)
+ if(func(inter) < self._z):
+ return 1
+ return 0
+
+class pyIsOccludedByUP1D(UnaryPredicate1D):
+ def __init__(self,id):
+ UnaryPredicate1D.__init__(self)
+ self._id = id
+ def getName(self):
+ return "pyIsOccludedByUP1D"
+ def __call__(self, inter):
+ func = GetShapeF1D()
+ shapes = func(inter)
+ for s in shapes:
+ if(s.getId() == self._id):
+ return 0
+ it = inter.verticesBegin()
+ itlast = inter.verticesEnd()
+ itlast.decrement()
+ v = it.getObject()
+ vlast = itlast.getObject()
+ tvertex = v.viewvertex()
+ if type(tvertex) is TVertex:
+ print("TVertex: [ ", tvertex.getId().getFirst(), ",", tvertex.getId().getSecond()," ]")
+ eit = tvertex.edgesBegin()
+ while(eit.isEnd() == 0):
+ ve, incoming = eit.getObject()
+ if(ve.getId() == self._id):
+ return 1
+ print("-------", ve.getId().getFirst(), "-", ve.getId().getSecond())
+ eit.increment()
+ tvertex = vlast.viewvertex()
+ if type(tvertex) is TVertex:
+ print("TVertex: [ ", tvertex.getId().getFirst(), ",", tvertex.getId().getSecond()," ]")
+ eit = tvertex.edgesBegin()
+ while(eit.isEnd() == 0):
+ ve, incoming = eit.getObject()
+ if(ve.getId() == self._id):
+ return 1
+ print("-------", ve.getId().getFirst(), "-", ve.getId().getSecond())
+ eit.increment()
+ return 0
+
+class pyIsInOccludersListUP1D(UnaryPredicate1D):
+ def __init__(self,id):
+ UnaryPredicate1D.__init__(self)
+ self._id = id
+ def getName(self):
+ return "pyIsInOccludersListUP1D"
+ def __call__(self, inter):
+ func = GetOccludersF1D()
+ occluders = func(inter)
+ for a in occluders:
+ if(a.getId() == self._id):
+ return 1
+ return 0
+
+class pyIsOccludedByItselfUP1D(UnaryPredicate1D):
+ def __init__(self):
+ UnaryPredicate1D.__init__(self)
+ self.__func1 = GetOccludersF1D()
+ self.__func2 = GetShapeF1D()
+ def getName(self):
+ return "pyIsOccludedByItselfUP1D"
+ def __call__(self, inter):
+ lst1 = self.__func1(inter)
+ lst2 = self.__func2(inter)
+ for vs1 in lst1:
+ for vs2 in lst2:
+ if vs1.getId() == vs2.getId():
+ return 1
+ return 0
+
+class pyIsOccludedByIdListUP1D(UnaryPredicate1D):
+ def __init__(self, idlist):
+ UnaryPredicate1D.__init__(self)
+ self._idlist = idlist
+ self.__func1 = GetOccludersF1D()
+ def getName(self):
+ return "pyIsOccludedByIdListUP1D"
+ def __call__(self, inter):
+ lst1 = self.__func1(inter)
+ for vs1 in lst1:
+ for id in self._idlist:
+ if vs1.getId() == id:
+ return 1
+ return 0
+
+class pyShapeIdListUP1D(UnaryPredicate1D):
+ def __init__(self,idlist):
+ UnaryPredicate1D.__init__(self)
+ self._idlist = idlist
+ self._funcs = []
+ for id in idlist :
+ self._funcs.append(ShapeUP1D(id.getFirst(), id.getSecond()))
+
+ def getName(self):
+ return "pyShapeIdUP1D"
+ def __call__(self, inter):
+ for func in self._funcs :
+ if(func(inter) == 1) :
+ return 1
+ return 0
+
+## deprecated
+class pyShapeIdUP1D(UnaryPredicate1D):
+ def __init__(self,id):
+ UnaryPredicate1D.__init__(self)
+ self._id = id
+ def getName(self):
+ return "pyShapeIdUP1D"
+ def __call__(self, inter):
+ func = GetShapeF1D()
+ shapes = func(inter)
+ for a in shapes:
+ if(a.getId() == self._id):
+ return 1
+ return 0
+
+class pyHighDensityAnisotropyUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, level, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._l = threshold
+ self.func = pyDensityAnisotropyF1D(level, IntegrationType.MEAN, sampling)
+ def getName(self):
+ return "pyHighDensityAnisotropyUP1D"
+ def __call__(self, inter):
+ return (self.func(inter) > self._l)
+
+class pyHighViewMapGradientNormUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, l, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
+ def getName(self):
+ return "pyHighViewMapGradientNormUP1D"
+ def __call__(self, inter):
+ gn = self._GetGradient(inter)
+ #print(gn)
+ return (gn > self._threshold)
+
+class pyDensityVariableSigmaUP1D(UnaryPredicate1D):
+ def __init__(self,functor, sigmaMin,sigmaMax, lmin, lmax, tmin, tmax, integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._functor = functor
+ self._sigmaMin = float(sigmaMin)
+ self._sigmaMax = float(sigmaMax)
+ self._lmin = float(lmin)
+ self._lmax = float(lmax)
+ self._tmin = tmin
+ self._tmax = tmax
+ self._integration = integration
+ self._sampling = sampling
+
+ def getName(self):
+ return "pyDensityUP1D"
+
+ def __call__(self, inter):
+ sigma = (self._sigmaMax-self._sigmaMin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._sigmaMin
+ t = (self._tmax-self._tmin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._tmin
+ if(sigma<self._sigmaMin):
+ sigma = self._sigmaMin
+ self._func = DensityF1D(sigma, self._integration, self._sampling)
+ d = self._func(inter)
+ if(d<t):
+ return 1
+ return 0
+
+class pyClosedCurveUP1D(UnaryPredicate1D):
+ def __call__(self, inter):
+ it = inter.verticesBegin()
+ itlast = inter.verticesEnd()
+ itlast.decrement()
+ vlast = itlast.getObject()
+ v = it.getObject()
+ print(v.getId().getFirst(), v.getId().getSecond())
+ print(vlast.getId().getFirst(), vlast.getId().getSecond())
+ if(v.getId() == vlast.getId()):
+ return 1
+ return 0
diff --git a/release/scripts/freestyle/style_modules/anisotropic_diffusion.py b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py
new file mode 100755
index 00000000000..7e7ebf647bd
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py
@@ -0,0 +1,74 @@
+#
+# Filename : anisotropic_diffusion.py
+# Author : Fredo Durand
+# Date : 12/08/2004
+# Purpose : Smoothes lines using an anisotropic diffusion scheme
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+from PredicatesU0D import *
+from math import *
+
+## thickness modifiers
+
+normalInfo=Normal2DF0D()
+curvatureInfo=Curvature2DAngleF0D()
+
+def edgestopping(x, sigma):
+ return exp(- x*x/(2*sigma*sigma))
+
+class pyDiffusion2Shader(StrokeShader):
+ def __init__(self, lambda1, nbIter):
+ StrokeShader.__init__(self)
+ self._lambda = lambda1
+ self._nbIter = nbIter
+ def getName(self):
+ return "pyDiffusionShader"
+ def shade(self, stroke):
+ for i in range (1, self._nbIter):
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ v=it.getObject()
+ p1 = v.getPoint()
+ p2 = normalInfo(it.castToInterface0DIterator())*self._lambda*curvatureInfo(it.castToInterface0DIterator())
+ v.setPoint(p1+p2)
+ it.increment()
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select( upred )
+bpred = TrueBP1D();
+Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred) )
+shaders_list = [
+ ConstantThicknessShader(4),
+ StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0),
+ SamplingShader(2),
+ pyDiffusion2Shader(-0.03, 30),
+ IncreasingColorShader(1.0,0.0,0.0,1, 0, 1, 0, 1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
+
+
+
diff --git a/release/scripts/freestyle/style_modules/apriori_and_causal_density.py b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py
new file mode 100755
index 00000000000..7cdd4b2fd66
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py
@@ -0,0 +1,45 @@
+#
+# Filename : apriori_and_causal_density.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Selects the lines with high a priori density and
+# subjects them to the causal density so as to avoid
+# cluttering
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.3, IntegrationType.LAST))
+Operators.select(upred)
+bpred = TrueBP1D()
+Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ ConstantThicknessShader(2),
+ ConstantColorShader(0.0, 0.0, 0.0,1)
+ ]
+Operators.create(pyDensityUP1D(1,0.1, IntegrationType.MEAN), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/apriori_density.py b/release/scripts/freestyle/style_modules/apriori_density.py
new file mode 100755
index 00000000000..5ff6c58e77f
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/apriori_density.py
@@ -0,0 +1,43 @@
+#
+# Filename : apriori_density.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws lines having a high a priori density
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+
+Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.1,5)))
+bpred = TrueBP1D()
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.0007,5))
+Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ ConstantThicknessShader(2),
+ ConstantColorShader(0.0, 0.0, 0.0,1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/backbone_stretcher.py b/release/scripts/freestyle/style_modules/backbone_stretcher.py
new file mode 100755
index 00000000000..8a6b9d71a66
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/backbone_stretcher.py
@@ -0,0 +1,36 @@
+#
+# Filename : backbone_stretcher.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Stretches the geometry of visible lines
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [TextureAssignerShader(4), ConstantColorShader(0.5, 0.5, 0.5), BackboneStretcherShader(20)]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/blueprint_circles.py b/release/scripts/freestyle/style_modules/blueprint_circles.py
new file mode 100755
index 00000000000..7f3a7564cfe
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/blueprint_circles.py
@@ -0,0 +1,46 @@
+#
+# Filename : blueprint_circles.py
+# Author : Emmanuel Turquin
+# Date : 04/08/2005
+# Purpose : Produces a blueprint using circular contour strokes
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
+bpred = SameShapeIdBP1D()
+Operators.select(upred)
+Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred))
+Operators.select(pyHigherLengthUP1D(200))
+shaders_list = [
+ ConstantThicknessShader(5),
+ pyBluePrintCirclesShader(3),
+ pyPerlinNoise1DShader(0.1, 15, 8),
+ TextureAssignerShader(4),
+ IncreasingColorShader(0.8, 0.8, 0.3, 0.4, 0.3, 0.3, 0.3, 0.1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/blueprint_ellipses.py b/release/scripts/freestyle/style_modules/blueprint_ellipses.py
new file mode 100755
index 00000000000..a5cfe4ec30b
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/blueprint_ellipses.py
@@ -0,0 +1,46 @@
+#
+# Filename : blueprint_ellipses.py
+# Author : Emmanuel Turquin
+# Date : 04/08/2005
+# Purpose : Produces a blueprint using elliptic contour strokes
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
+bpred = SameShapeIdBP1D()
+Operators.select(upred)
+Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred))
+Operators.select(pyHigherLengthUP1D(200))
+shaders_list = [
+ ConstantThicknessShader(5),
+ pyBluePrintEllipsesShader(3),
+ pyPerlinNoise1DShader(0.1, 10, 8),
+ TextureAssignerShader(4),
+ IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.3, 0.3, 0.3, 0.1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/blueprint_squares.py b/release/scripts/freestyle/style_modules/blueprint_squares.py
new file mode 100755
index 00000000000..7798acc7d47
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/blueprint_squares.py
@@ -0,0 +1,45 @@
+# Filename : blueprint_squares.py
+# Author : Emmanuel Turquin
+# Date : 04/08/2005
+# Purpose : Produces a blueprint using square contour strokes
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
+bpred = SameShapeIdBP1D()
+Operators.select(upred)
+Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred))
+Operators.select(pyHigherLengthUP1D(200))
+shaders_list = [
+ ConstantThicknessShader(8),
+ pyBluePrintSquaresShader(2, 20),
+ pyPerlinNoise1DShader(0.07, 10, 8),
+ TextureAssignerShader(4),
+ IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.6, 0.3, 0.3, 0.3),
+ ConstantThicknessShader(4)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/cartoon.py b/release/scripts/freestyle/style_modules/cartoon.py
new file mode 100755
index 00000000000..6ace7e0585a
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/cartoon.py
@@ -0,0 +1,42 @@
+#
+# Filename : cartoon.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws colored lines. The color is automatically
+# infered from each object's material in a cartoon-like
+# fashion.
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ BezierCurveShader(3),
+ ConstantThicknessShader(4),
+ pyMaterialColorShader(0.8)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/contour.py b/release/scripts/freestyle/style_modules/contour.py
new file mode 100755
index 00000000000..c4b3a0f0827
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/contour.py
@@ -0,0 +1,42 @@
+#
+# Filename : contour.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws each object's visible contour
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+
+Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D() ) )
+bpred = SameShapeIdBP1D();
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
+Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ ConstantThicknessShader(5.0),
+ IncreasingColorShader(0.8,0,0,1,0.1,0,0,1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/curvature2d.py b/release/scripts/freestyle/style_modules/curvature2d.py
new file mode 100755
index 00000000000..fc2bcab4946
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/curvature2d.py
@@ -0,0 +1,60 @@
+#
+# Filename : curvature2d.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The stroke points are colored in gray levels and depending
+# on the 2d curvature value
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+
+class py2DCurvatureColorShader(StrokeShader):
+ def getName(self):
+ return "py2DCurvatureColorShader"
+
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ func = Curvature2DAngleF0D()
+ while it.isEnd() == 0:
+ it0D = it.castToInterface0DIterator()
+ sv = it.getObject()
+ att = sv.attribute()
+ c = func(it0D)
+ if (c<0):
+ print("negative 2D curvature")
+ color = 10.0 * c/3.1415
+ att.setColor(color,color,color);
+ it.increment()
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0),
+ ConstantThicknessShader(5),
+ py2DCurvatureColorShader()
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/external_contour.py b/release/scripts/freestyle/style_modules/external_contour.py
new file mode 100755
index 00000000000..2a39b79a410
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/external_contour.py
@@ -0,0 +1,43 @@
+#
+# Filename : external_contour.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the external contour of the scene
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from ChainingIterators import *
+from shaders import *
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred )
+bpred = TrueBP1D();
+Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
+shaders_list = [
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.0, 0.0, 0.0,1)
+ ]
+Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/external_contour_sketchy.py b/release/scripts/freestyle/style_modules/external_contour_sketchy.py
new file mode 100755
index 00000000000..8a4c570b279
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/external_contour_sketchy.py
@@ -0,0 +1,48 @@
+#
+# Filename : external_contour_sketchy.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the external contour of the scene using a sketchy
+# chaining iterator (in particular each ViewEdge can be drawn
+# several times
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred)
+Operators.bidirectionalChain(pySketchyChainingIterator(), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(4),
+ SpatialNoiseShader(10, 150, 2, 1, 1),
+ IncreasingThicknessShader(4, 10),
+ SmoothingShader(400, 0.1, 0, 0.2, 0, 0, 0, 1),
+ IncreasingColorShader(1,0,0,1,0,1,0,1),
+ TextureAssignerShader(4)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/external_contour_smooth.py b/release/scripts/freestyle/style_modules/external_contour_smooth.py
new file mode 100755
index 00000000000..201dc271388
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/external_contour_smooth.py
@@ -0,0 +1,44 @@
+#
+# Filename : external_contour_smooth.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws a smooth external contour
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+from ChainingIterators import *
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred)
+bpred = TrueBP1D();
+Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(2),
+ IncreasingThicknessShader(4,20),
+ IncreasingColorShader(1.0, 0.0, 0.5,1, 0.5,1, 0.3, 1),
+ SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/extra-lines.sml b/release/scripts/freestyle/style_modules/extra-lines.sml
new file mode 100755
index 00000000000..c63cd40945d
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/extra-lines.sml
@@ -0,0 +1,3 @@
+1suggestive.py
+1ridges.py
+1nor_suggestive_or_ridges.py
diff --git a/release/scripts/freestyle/style_modules/freestyle_init.py b/release/scripts/freestyle/style_modules/freestyle_init.py
new file mode 100644
index 00000000000..9eb8b2d6340
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/freestyle_init.py
@@ -0,0 +1,2 @@
+from Freestyle import *
+from mathutils import Vector
diff --git a/release/scripts/freestyle/style_modules/haloing.py b/release/scripts/freestyle/style_modules/haloing.py
new file mode 100755
index 00000000000..afa46173d54
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/haloing.py
@@ -0,0 +1,50 @@
+#
+# Filename : haloing.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : This style module selects the lines that
+# are connected (in the image) to a specific
+# object and trims them in order to produce
+# a haloing effect around the target shape
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesU1D import *
+from PredicatesB1D import *
+from shaders import *
+
+# id corresponds to the id of the target object
+# (accessed by SHIFT+click)
+id = Id(3,0)
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0) , pyIsOccludedByUP1D(id))
+Operators.select(upred)
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ IncreasingThicknessShader(3, 5),
+ IncreasingColorShader(1,0,0, 1,0,1,0,1),
+ SamplingShader(1.0),
+ pyTVertexRemoverShader(),
+ TipRemoverShader(3.0)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/ignore_small_occlusions.py b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py
new file mode 100755
index 00000000000..ff6efa89ade
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py
@@ -0,0 +1,41 @@
+#
+# Filename : ignore_small_oclusions.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The strokes are drawn through small occlusions
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+#Operators.bidirectionalChain(pyFillOcclusionsChainingIterator(0.1))
+Operators.bidirectionalChain(pyFillOcclusionsAbsoluteChainingIterator(12))
+shaders_list = [
+ SamplingShader(5.0),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.0,0.0,0.0),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/invisible_lines.py b/release/scripts/freestyle/style_modules/invisible_lines.py
new file mode 100755
index 00000000000..ea509463bfd
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/invisible_lines.py
@@ -0,0 +1,42 @@
+#
+# Filename : invisible_lines.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws all lines whose Quantitative Invisibility
+# is different from 0
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+upred = NotUP1D(QuantitativeInvisibilityUP1D(0))
+Operators.select(upred)
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(5.0),
+ ConstantThicknessShader(3.0),
+ ConstantColorShader(0.7,0.7,0.7)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/japanese_bigbrush.py b/release/scripts/freestyle/style_modules/japanese_bigbrush.py
new file mode 100755
index 00000000000..7f109598aaa
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/japanese_bigbrush.py
@@ -0,0 +1,60 @@
+#
+# Filename : japanese_bigbrush.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Simulates a big brush fr oriental painting
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesU1D import *
+from PredicatesB1D import *
+from Functions0D import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0)))
+## Splits strokes at points of highest 2D curavture
+## when there are too many abrupt turns in it
+func = pyInverseCurvature2DAngleF0D()
+Operators.recursiveSplit(func, pyParameterUP0D(0.2,0.8), NotUP1D(pyHigherNumberOfTurnsUP1D(3, 0.5)), 2)
+## Keeps only long enough strokes
+Operators.select(pyHigherLengthUP1D(100))
+## Sorts so as to draw the longest strokes first
+## (this will be done using the causal density)
+Operators.sort(pyLengthBP1D())
+shaders_list = [
+ pySamplingShader(10),
+ BezierCurveShader(30),
+ SamplingShader(50),
+ ConstantThicknessShader(10),
+ pyNonLinearVaryingThicknessShader(4,25, 0.6),
+ TextureAssignerShader(6),
+ ConstantColorShader(0.2, 0.2, 0.2,1.0),
+ TipRemoverShader(10)
+ ]
+
+## Use the causal density to avoid cluttering
+Operators.create(pyDensityUP1D(8,0.4, IntegrationType.MEAN), shaders_list)
+
+
diff --git a/release/scripts/freestyle/style_modules/logical_operators.py b/release/scripts/freestyle/style_modules/logical_operators.py
new file mode 100755
index 00000000000..0ecf6623697
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/logical_operators.py
@@ -0,0 +1,36 @@
+from freestyle_init import *
+
+class AndUP1D(UnaryPredicate1D):
+ def __init__(self, pred1, pred2):
+ UnaryPredicate1D.__init__(self)
+ self.__pred1 = pred1
+ self.__pred2 = pred2
+
+ def getName(self):
+ return "AndUP1D"
+
+ def __call__(self, inter):
+ return self.__pred1(inter) and self.__pred2(inter)
+
+class OrUP1D(UnaryPredicate1D):
+ def __init__(self, pred1, pred2):
+ UnaryPredicate1D.__init__(self)
+ self.__pred1 = pred1
+ self.__pred2 = pred2
+
+ def getName(self):
+ return "OrUP1D"
+
+ def __call__(self, inter):
+ return self.__pred1(inter) or self.__pred2(inter)
+
+class NotUP1D(UnaryPredicate1D):
+ def __init__(self, pred):
+ UnaryPredicate1D.__init__(self)
+ self.__pred = pred
+
+ def getName(self):
+ return "NotUP1D"
+
+ def __call__(self, inter):
+ return self.__pred(inter) == 0
diff --git a/release/scripts/freestyle/style_modules/long_anisotropically_dense.py b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py
new file mode 100755
index 00000000000..155ee489680
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py
@@ -0,0 +1,81 @@
+#
+# Filename : long_anisotropically_dense.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Selects the lines that are long and have a high anisotropic
+# a priori density and uses causal density
+# to draw without cluttering. Ideally, half of the
+# selected lines are culled using the causal density.
+#
+# ********************* WARNING *************************************
+# ******** The Directional a priori density maps must ******
+# ******** have been computed prior to using this style module ******
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesU1D import *
+from PredicatesU0D import *
+from PredicatesB1D import *
+from Functions0D import *
+from Functions1D import *
+from shaders import *
+
+## custom density predicate
+class pyDensityUP1D(UnaryPredicate1D):
+ def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._wsize = wsize
+ self._threshold = threshold
+ self._integration = integration
+ self._func = DensityF1D(self._wsize, self._integration, sampling)
+ self._func2 = DensityF1D(self._wsize, IntegrationType.MAX, sampling)
+
+ def getName(self):
+ return "pyDensityUP1D"
+
+ def __call__(self, inter):
+ c = self._func(inter)
+ m = self._func2(inter)
+ if(c < self._threshold):
+ return 1
+ if( m > 4* c ):
+ if ( c < 1.5*self._threshold ):
+ return 1
+ return 0
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0)))
+Operators.select(pyHigherLengthUP1D(40))
+## selects lines having a high anisotropic a priori density
+Operators.select(pyHighDensityAnisotropyUP1D(0.3,4))
+Operators.sort(pyLengthBP1D())
+shaders_list = [
+ SamplingShader(2.0),
+ ConstantThicknessShader(2),
+ ConstantColorShader(0.2,0.2,0.25,1),
+ ]
+## uniform culling
+Operators.create(pyDensityUP1D(3.0,2.0e-2, IntegrationType.MEAN, 0.1), shaders_list)
+
+
diff --git a/release/scripts/freestyle/style_modules/multiple_parameterization.py b/release/scripts/freestyle/style_modules/multiple_parameterization.py
new file mode 100755
index 00000000000..3f0409db5fa
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/multiple_parameterization.py
@@ -0,0 +1,51 @@
+#
+# Filename : multiple_parameterization.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The thickness and the color of the strokes vary continuously
+# independently from occlusions although only
+# visible lines are actually drawn. This is equivalent
+# to assigning the thickness using a parameterization covering
+# the complete silhouette (visible+invisible) and drawing
+# the strokes using a second parameterization that only
+# covers the visible portions.
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+## Chain following the same nature, but without the restriction
+## of staying inside the selection (0).
+Operators.bidirectionalChain(ChainSilhouetteIterator(0))
+shaders_list = [
+ SamplingShader(20),
+ IncreasingThicknessShader(1.5, 30),
+ ConstantColorShader(0.0,0.0,0.0),
+ IncreasingColorShader(1,0,0,1,0,1,0,1),
+ TextureAssignerShader(-1),
+ pyHLRShader() ## this shader draws only visible portions
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/nature.py b/release/scripts/freestyle/style_modules/nature.py
new file mode 100755
index 00000000000..b5481a8e519
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/nature.py
@@ -0,0 +1,43 @@
+#
+# Filename : nature.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Uses the NatureUP1D predicate to select the lines
+# of a given type (among Nature.SILHOUETTE, Nature.CREASE, Nature.SUGGESTIVE_CONTOURS,
+# Nature.BORDERS).
+# The suggestive contours must have been enabled in the
+# options dialog to appear in the View Map.
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+
+Operators.select(pyNatureUP1D(Nature.SILHOUETTE))
+Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D( pyNatureUP1D( Nature.SILHOUETTE) ) )
+shaders_list = [
+ IncreasingThicknessShader(3, 10),
+ IncreasingColorShader(0.0,0.0,0.0, 1, 0.8,0,0,1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/near_lines.py b/release/scripts/freestyle/style_modules/near_lines.py
new file mode 100755
index 00000000000..565bca1fe1f
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/near_lines.py
@@ -0,0 +1,44 @@
+#
+# Filename : near_lines.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the lines that are "closer" than a threshold
+# (between 0 and 1)
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyZSmallerUP1D(0.5, IntegrationType.MEAN))
+Operators.select(upred)
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ TextureAssignerShader(-1),
+ ConstantThicknessShader(5),
+ ConstantColorShader(0.0, 0.0, 0.0)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/occluded_by_specific_object.py b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py
new file mode 100755
index 00000000000..09ce39d5dd6
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py
@@ -0,0 +1,45 @@
+#
+# Filename : occluded_by_specific_object.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws only the lines that are occluded by a given object
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesU1D import *
+from shaders import *
+
+## the id of the occluder (use SHIFT+click on the ViewMap to
+## retrieve ids)
+id = Id(3,0)
+upred = AndUP1D(NotUP1D(QuantitativeInvisibilityUP1D(0)),
+pyIsInOccludersListUP1D(id))
+Operators.select(upred)
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(5),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.3,0.3,0.3,1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/parameter_editor.py b/release/scripts/freestyle/style_modules/parameter_editor.py
new file mode 100644
index 00000000000..e817771732a
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/parameter_editor.py
@@ -0,0 +1,1273 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+import Freestyle
+import math
+import mathutils
+import time
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+class ColorRampModifier(StrokeShader):
+ def __init__(self, blend, influence, ramp):
+ StrokeShader.__init__(self)
+ self.__blend = blend
+ self.__influence = influence
+ self.__ramp = ramp
+ def evaluate(self, t):
+ col = Freestyle.evaluateColorRamp(self.__ramp, t)
+ col = col.xyz # omit alpha
+ return col
+ def blend_ramp(self, a, b):
+ return Freestyle.blendRamp(self.__blend, a, self.__influence, b)
+
+class ScalarBlendModifier(StrokeShader):
+ def __init__(self, blend, influence):
+ StrokeShader.__init__(self)
+ self.__blend = blend
+ self.__influence = influence
+ def blend(self, v1, v2):
+ fac = self.__influence
+ facm = 1.0 - fac
+ if self.__blend == "MIX":
+ v1 = facm * v1 + fac * v2
+ elif self.__blend == "ADD":
+ v1 += fac * v2
+ elif self.__blend == "MULTIPLY":
+ v1 *= facm + fac * v2;
+ elif self.__blend == "SUBTRACT":
+ v1 -= fac * v2
+ elif self.__blend == "DIVIDE":
+ if v2 != 0.0:
+ v1 = facm * v1 + fac * v1 / v2
+ elif self.__blend == "DIFFERENCE":
+ v1 = facm * v1 + fac * abs(v1 - v2)
+ elif self.__blend == "MININUM":
+ tmp = fac * v1
+ if v1 > tmp:
+ v1 = tmp
+ elif self.__blend == "MAXIMUM":
+ tmp = fac * v1
+ if v1 < tmp:
+ v1 = tmp
+ else:
+ raise ValueError("unknown curve blend type: " + self.__blend)
+ return v1
+
+class CurveMappingModifier(ScalarBlendModifier):
+ def __init__(self, blend, influence, mapping, invert, curve):
+ ScalarBlendModifier.__init__(self, blend, influence)
+ assert mapping in ("LINEAR", "CURVE")
+ self.__mapping = getattr(self, mapping)
+ self.__invert = invert
+ self.__curve = curve
+ def LINEAR(self, t):
+ if self.__invert:
+ return 1.0 - t
+ return t
+ def CURVE(self, t):
+ return Freestyle.evaluateCurveMappingF(self.__curve, 0, t)
+ def evaluate(self, t):
+ return self.__mapping(t)
+
+class ThicknessModifierMixIn:
+ def __init__(self):
+ scene = Freestyle.getCurrentScene()
+ self.__persp_camera = (scene.camera.data.type == "PERSP")
+ def set_thickness(self, sv, outer, inner):
+ fe = sv.A().getFEdge(sv.B())
+ nature = fe.getNature()
+ if (nature & Nature.BORDER):
+ if self.__persp_camera:
+ point = -sv.getPoint3D()
+ point.normalize()
+ dir = point.dot(fe.normalB())
+ else:
+ dir = fe.normalB().z
+ if dir < 0.0: # the back side is visible
+ outer, inner = inner, outer
+ elif (nature & Nature.SILHOUETTE):
+ if fe.isSmooth(): # TODO more tests needed
+ outer, inner = inner, outer
+ else:
+ outer = inner = (outer + inner) / 2
+ sv.attribute().setThickness(outer, inner)
+
+class ThicknessBlenderMixIn(ThicknessModifierMixIn):
+ def __init__(self, position, ratio):
+ ThicknessModifierMixIn.__init__(self)
+ self.__position = position
+ self.__ratio = ratio
+ def blend_thickness(self, outer, inner, v):
+ if self.__position == "CENTER":
+ outer = self.blend(outer, v / 2)
+ inner = self.blend(inner, v / 2)
+ elif self.__position == "INSIDE":
+ outer = self.blend(outer, 0)
+ inner = self.blend(inner, v)
+ elif self.__position == "OUTSIDE":
+ outer = self.blend(outer, v)
+ inner = self.blend(inner, 0)
+ elif self.__position == "RELATIVE":
+ outer = self.blend(outer, v * self.__ratio)
+ inner = self.blend(inner, v * (1 - self.__ratio))
+ else:
+ raise ValueError("unknown thickness position: " + self.__position)
+ return outer, inner
+
+class BaseColorShader(ConstantColorShader):
+ def getName(self):
+ return "BaseColorShader"
+
+class BaseThicknessShader(StrokeShader, ThicknessModifierMixIn):
+ def __init__(self, thickness, position, ratio):
+ StrokeShader.__init__(self)
+ ThicknessModifierMixIn.__init__(self)
+ if position == "CENTER":
+ self.__outer = thickness / 2
+ self.__inner = thickness / 2
+ elif position == "INSIDE":
+ self.__outer = 0
+ self.__inner = thickness
+ elif position == "OUTSIDE":
+ self.__outer = thickness
+ self.__inner = 0
+ elif position == "RELATIVE":
+ self.__outer = thickness * ratio
+ self.__inner = thickness * (1 - ratio)
+ else:
+ raise ValueError("unknown thickness position: " + self.position)
+ def getName(self):
+ return "BaseThicknessShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ sv = it.getObject()
+ self.set_thickness(sv, self.__outer, self.__inner)
+ it.increment()
+
+# Along Stroke modifiers
+
+def iter_t2d_along_stroke(stroke):
+ total = stroke.getLength2D()
+ distance = 0.0
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ p = it.getObject().getPoint()
+ if not it.isBegin():
+ distance += (prev - p).length
+ prev = p
+ t = min(distance / total, 1.0)
+ yield it, t
+ it.increment()
+
+class ColorAlongStrokeShader(ColorRampModifier):
+ def getName(self):
+ return "ColorAlongStrokeShader"
+ def shade(self, stroke):
+ for it, t in iter_t2d_along_stroke(stroke):
+ attr = it.getObject().attribute()
+ a = attr.getColorRGB()
+ b = self.evaluate(t)
+ c = self.blend_ramp(a, b)
+ attr.setColor(c)
+
+class AlphaAlongStrokeShader(CurveMappingModifier):
+ def getName(self):
+ return "AlphaAlongStrokeShader"
+ def shade(self, stroke):
+ for it, t in iter_t2d_along_stroke(stroke):
+ attr = it.getObject().attribute()
+ a = attr.getAlpha()
+ b = self.evaluate(t)
+ c = self.blend(a, b)
+ attr.setAlpha(c)
+
+class ThicknessAlongStrokeShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__value_min = value_min
+ self.__value_max = value_max
+ def getName(self):
+ return "ThicknessAlongStrokeShader"
+ def shade(self, stroke):
+ for it, t in iter_t2d_along_stroke(stroke):
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
+ b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+
+# Distance from Camera modifiers
+
+def iter_distance_from_camera(stroke, range_min, range_max):
+ normfac = range_max - range_min # normalization factor
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ p = it.getObject().getPoint3D() # in the camera coordinate
+ distance = p.length
+ if distance < range_min:
+ t = 0.0
+ elif distance > range_max:
+ t = 1.0
+ else:
+ t = (distance - range_min) / normfac
+ yield it, t
+ it.increment()
+
+class ColorDistanceFromCameraShader(ColorRampModifier):
+ def __init__(self, blend, influence, ramp, range_min, range_max):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ self.__range_min = range_min
+ self.__range_max = range_max
+ def getName(self):
+ return "ColorDistanceFromCameraShader"
+ def shade(self, stroke):
+ for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
+ attr = it.getObject().attribute()
+ a = attr.getColorRGB()
+ b = self.evaluate(t)
+ c = self.blend_ramp(a, b)
+ attr.setColor(c)
+
+class AlphaDistanceFromCameraShader(CurveMappingModifier):
+ def __init__(self, blend, influence, mapping, invert, curve, range_min, range_max):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__range_min = range_min
+ self.__range_max = range_max
+ def getName(self):
+ return "AlphaDistanceFromCameraShader"
+ def shade(self, stroke):
+ for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
+ attr = it.getObject().attribute()
+ a = attr.getAlpha()
+ b = self.evaluate(t)
+ c = self.blend(a, b)
+ attr.setAlpha(c)
+
+class ThicknessDistanceFromCameraShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, range_min, range_max, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__range_min = range_min
+ self.__range_max = range_max
+ self.__value_min = value_min
+ self.__value_max = value_max
+ def getName(self):
+ return "ThicknessDistanceFromCameraShader"
+ def shade(self, stroke):
+ for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
+ b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+
+# Distance from Object modifiers
+
+def iter_distance_from_object(stroke, object, range_min, range_max):
+ scene = Freestyle.getCurrentScene()
+ mv = scene.camera.matrix_world.copy() # model-view matrix
+ mv.invert()
+ loc = mv * object.location # loc in the camera coordinate
+ normfac = range_max - range_min # normalization factor
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ p = it.getObject().getPoint3D() # in the camera coordinate
+ distance = (p - loc).length
+ if distance < range_min:
+ t = 0.0
+ elif distance > range_max:
+ t = 1.0
+ else:
+ t = (distance - range_min) / normfac
+ yield it, t
+ it.increment()
+
+class ColorDistanceFromObjectShader(ColorRampModifier):
+ def __init__(self, blend, influence, ramp, target, range_min, range_max):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ self.__target = target
+ self.__range_min = range_min
+ self.__range_max = range_max
+ def getName(self):
+ return "ColorDistanceFromObjectShader"
+ def shade(self, stroke):
+ if self.__target is None:
+ return
+ for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
+ attr = it.getObject().attribute()
+ a = attr.getColorRGB()
+ b = self.evaluate(t)
+ c = self.blend_ramp(a, b)
+ attr.setColor(c)
+
+class AlphaDistanceFromObjectShader(CurveMappingModifier):
+ def __init__(self, blend, influence, mapping, invert, curve, target, range_min, range_max):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__target = target
+ self.__range_min = range_min
+ self.__range_max = range_max
+ def getName(self):
+ return "AlphaDistanceFromObjectShader"
+ def shade(self, stroke):
+ if self.__target is None:
+ return
+ for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
+ attr = it.getObject().attribute()
+ a = attr.getAlpha()
+ b = self.evaluate(t)
+ c = self.blend(a, b)
+ attr.setAlpha(c)
+
+class ThicknessDistanceFromObjectShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, target, range_min, range_max, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__target = target
+ self.__range_min = range_min
+ self.__range_max = range_max
+ self.__value_min = value_min
+ self.__value_max = value_max
+ def getName(self):
+ return "ThicknessDistanceFromObjectShader"
+ def shade(self, stroke):
+ if self.__target is None:
+ return
+ for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
+ b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+
+# Material modifiers
+
+def iter_material_color(stroke, material_attr):
+ func = CurveMaterialF0D()
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ material = func(it.castToInterface0DIterator())
+ if material_attr == "DIFF":
+ color = (material.diffuseR(),
+ material.diffuseG(),
+ material.diffuseB())
+ elif material_attr == "SPEC":
+ color = (material.specularR(),
+ material.specularG(),
+ material.specularB())
+ else:
+ raise ValueError("unexpected material attribute: " + material_attr)
+ yield it, color
+ it.increment()
+
+def iter_material_value(stroke, material_attr):
+ func = CurveMaterialF0D()
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ material = func(it.castToInterface0DIterator())
+ if material_attr == "DIFF":
+ r = material.diffuseR()
+ g = material.diffuseG()
+ b = material.diffuseB()
+ t = 0.35 * r + 0.45 * r + 0.2 * b
+ elif material_attr == "DIFF_R":
+ t = material.diffuseR()
+ elif material_attr == "DIFF_G":
+ t = material.diffuseG()
+ elif material_attr == "DIFF_B":
+ t = material.diffuseB()
+ elif material_attr == "SPEC":
+ r = material.specularR()
+ g = material.specularG()
+ b = material.specularB()
+ t = 0.35 * r + 0.45 * r + 0.2 * b
+ elif material_attr == "SPEC_R":
+ t = material.specularR()
+ elif material_attr == "SPEC_G":
+ t = material.specularG()
+ elif material_attr == "SPEC_B":
+ t = material.specularB()
+ elif material_attr == "SPEC_HARDNESS":
+ t = material.shininess()
+ elif material_attr == "ALPHA":
+ t = material.diffuseA()
+ else:
+ raise ValueError("unexpected material attribute: " + material_attr)
+ yield it, t
+ it.increment()
+
+class ColorMaterialShader(ColorRampModifier):
+ def __init__(self, blend, influence, ramp, material_attr, use_ramp):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ self.__material_attr = material_attr
+ self.__use_ramp = use_ramp
+ def getName(self):
+ return "ColorMaterialShader"
+ def shade(self, stroke):
+ if self.__material_attr in ["DIFF", "SPEC"] and not self.__use_ramp:
+ for it, b in iter_material_color(stroke, self.__material_attr):
+ attr = it.getObject().attribute()
+ a = attr.getColorRGB()
+ c = self.blend_ramp(a, b)
+ attr.setColor(c)
+ else:
+ for it, t in iter_material_value(stroke, self.__material_attr):
+ attr = it.getObject().attribute()
+ a = attr.getColorRGB()
+ b = self.evaluate(t)
+ c = self.blend_ramp(a, b)
+ attr.setColor(c)
+
+class AlphaMaterialShader(CurveMappingModifier):
+ def __init__(self, blend, influence, mapping, invert, curve, material_attr):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__material_attr = material_attr
+ def getName(self):
+ return "AlphaMaterialShader"
+ def shade(self, stroke):
+ for it, t in iter_material_value(stroke, self.__material_attr):
+ attr = it.getObject().attribute()
+ a = attr.getAlpha()
+ b = self.evaluate(t)
+ c = self.blend(a, b)
+ attr.setAlpha(c)
+
+class ThicknessMaterialShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, material_attr, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__material_attr = material_attr
+ self.__value_min = value_min
+ self.__value_max = value_max
+ def getName(self):
+ return "ThicknessMaterialShader"
+ def shade(self, stroke):
+ for it, t in iter_material_value(stroke, self.__material_attr):
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
+ b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+
+# Calligraphic thickness modifier
+
+class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, orientation, min_thickness, max_thickness):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ ScalarBlendModifier.__init__(self, blend, influence)
+ rad = orientation / 180.0 * math.pi
+ self.__orientation = mathutils.Vector((math.cos(rad), math.sin(rad)))
+ self.__min_thickness = min_thickness
+ self.__max_thickness = max_thickness
+ def shade(self, stroke):
+ func = VertexOrientation2DF0D()
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ dir = func(it.castToInterface0DIterator())
+ orthDir = mathutils.Vector((-dir.y, dir.x))
+ orthDir.normalize()
+ fac = abs(orthDir * self.__orientation)
+ sv = it.getObject()
+ a = sv.attribute().getThicknessRL()
+ b = self.__min_thickness + fac * (self.__max_thickness - self.__min_thickness)
+ b = max(b, 0.0)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+ it.increment()
+
+# Geometry modifiers
+
+def iter_distance_along_stroke(stroke):
+ distance = 0.0
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ p = it.getObject().getPoint()
+ if not it.isBegin():
+ distance += (prev - p).length
+ prev = p
+ yield it, distance
+ it.increment()
+
+class SinusDisplacementShader(StrokeShader):
+ def __init__(self, wavelength, amplitude, phase):
+ StrokeShader.__init__(self)
+ self._wavelength = wavelength
+ self._amplitude = amplitude
+ self._phase = phase / wavelength * 2 * math.pi
+ self._getNormal = Normal2DF0D()
+ def getName(self):
+ return "SinusDisplacementShader"
+ def shade(self, stroke):
+ for it, distance in iter_distance_along_stroke(stroke):
+ v = it.getObject()
+ n = self._getNormal(it.castToInterface0DIterator())
+ p = v.getPoint()
+ u = v.u()
+ n = n * self._amplitude * math.cos(distance / self._wavelength * 2 * math.pi + self._phase)
+ v.setPoint(p + n)
+ stroke.UpdateLength()
+
+class PerlinNoise1DShader(StrokeShader):
+ def __init__(self, freq = 10, amp = 10, oct = 4, angle = 45, seed = -1):
+ StrokeShader.__init__(self)
+ self.__noise = Noise(seed)
+ self.__freq = freq
+ self.__amp = amp
+ self.__oct = oct
+ theta = pi * angle / 180.0
+ self.__dir = Vector([cos(theta), sin(theta)])
+ def getName(self):
+ return "PerlinNoise1DShader"
+ def shade(self, stroke):
+ length = stroke.getLength2D()
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ v = it.getObject()
+ nres = self.__noise.turbulence1(length * v.u(), self.__freq, self.__amp, self.__oct)
+ v.setPoint(v.getPoint() + nres * self.__dir)
+ it.increment()
+ stroke.UpdateLength()
+
+class PerlinNoise2DShader(StrokeShader):
+ def __init__(self, freq = 10, amp = 10, oct = 4, angle = 45, seed = -1):
+ StrokeShader.__init__(self)
+ self.__noise = Noise(seed)
+ self.__freq = freq
+ self.__amp = amp
+ self.__oct = oct
+ theta = pi * angle / 180.0
+ self.__dir = Vector([cos(theta), sin(theta)])
+ def getName(self):
+ return "PerlinNoise2DShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ v = it.getObject()
+ vec = Vector([v.getProjectedX(), v.getProjectedY()])
+ nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
+ v.setPoint(v.getPoint() + nres * self.__dir)
+ it.increment()
+ stroke.UpdateLength()
+
+class Offset2DShader(StrokeShader):
+ def __init__(self, start, end, x, y):
+ StrokeShader.__init__(self)
+ self.__start = start
+ self.__end = end
+ self.__xy = Vector([x, y])
+ self.__getNormal = Normal2DF0D()
+ def getName(self):
+ return "Offset2DShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ v = it.getObject()
+ u = v.u()
+ a = self.__start + u * (self.__end - self.__start)
+ n = self.__getNormal(it.castToInterface0DIterator())
+ n = n * a
+ p = v.getPoint()
+ v.setPoint(p + n + self.__xy)
+ it.increment()
+ stroke.UpdateLength()
+
+class Transform2DShader(StrokeShader):
+ def __init__(self, pivot, scale_x, scale_y, angle, pivot_u, pivot_x, pivot_y):
+ StrokeShader.__init__(self)
+ self.__pivot = pivot
+ self.__scale_x = scale_x
+ self.__scale_y = scale_y
+ self.__angle = angle
+ self.__pivot_u = pivot_u
+ self.__pivot_x = pivot_x
+ self.__pivot_y = pivot_y
+ def getName(self):
+ return "Transform2DShader"
+ def shade(self, stroke):
+ # determine the pivot of scaling and rotation operations
+ if self.__pivot == "START":
+ it = stroke.strokeVerticesBegin()
+ pivot = it.getObject().getPoint()
+ elif self.__pivot == "END":
+ it = stroke.strokeVerticesEnd()
+ it.decrement()
+ pivot = it.getObject().getPoint()
+ elif self.__pivot == "PARAM":
+ p = None
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ prev = p
+ v = it.getObject()
+ p = v.getPoint()
+ u = v.u()
+ if self.__pivot_u < u:
+ break
+ it.increment()
+ if prev is None:
+ pivot = p
+ else:
+ delta = u - self.__pivot_u
+ pivot = p + delta * (prev - p)
+ elif self.__pivot == "CENTER":
+ pivot = Vector([0.0, 0.0])
+ n = 0
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ p = it.getObject().getPoint()
+ pivot = pivot + p
+ n = n + 1
+ it.increment()
+ pivot.x = pivot.x / n
+ pivot.y = pivot.y / n
+ elif self.__pivot == "ABSOLUTE":
+ pivot = Vector([self.__pivot_x, self.__pivot_y])
+ # apply scaling and rotation operations
+ cos_theta = math.cos(math.pi * self.__angle / 180.0)
+ sin_theta = math.sin(math.pi * self.__angle / 180.0)
+ it = stroke.strokeVerticesBegin()
+ while not it.isEnd():
+ v = it.getObject()
+ p = v.getPoint()
+ p = p - pivot
+ x = p.x * self.__scale_x
+ y = p.y * self.__scale_y
+ p.x = x * cos_theta - y * sin_theta
+ p.y = x * sin_theta + y * cos_theta
+ v.setPoint(p + pivot)
+ it.increment()
+ stroke.UpdateLength()
+
+# Predicates and helper functions
+
+class QuantitativeInvisibilityRangeUP1D(UnaryPredicate1D):
+ def __init__(self, qi_start, qi_end):
+ UnaryPredicate1D.__init__(self)
+ self.__getQI = QuantitativeInvisibilityF1D()
+ self.__qi_start = qi_start
+ self.__qi_end = qi_end
+ def getName(self):
+ return "QuantitativeInvisibilityRangeUP1D"
+ def __call__(self, inter):
+ qi = self.__getQI(inter)
+ return self.__qi_start <= qi <= self.__qi_end
+
+def join_unary_predicates(upred_list, bpred):
+ if not upred_list:
+ return None
+ upred = upred_list[0]
+ for p in upred_list[1:]:
+ upred = bpred(upred, p)
+ return upred
+
+class ObjectNamesUP1D(UnaryPredicate1D):
+ def __init__(self, names, negative):
+ UnaryPredicate1D.__init__(self)
+ self._names = names
+ self._negative = negative
+ def getName(self):
+ return "ObjectNamesUP1D"
+ def __call__(self, viewEdge):
+ found = viewEdge.viewShape().getName() in self._names
+ if self._negative:
+ return not found
+ return found
+
+# Stroke caps
+
+def iter_stroke_vertices(stroke):
+ it = stroke.strokeVerticesBegin()
+ prev_p = None
+ while not it.isEnd():
+ sv = it.getObject()
+ p = sv.getPoint()
+ if prev_p is None or (prev_p - p).length > 1e-6:
+ yield sv
+ prev_p = p
+ it.increment()
+
+class RoundCapShader(StrokeShader):
+ def round_cap_thickness(self, x):
+ x = max(0.0, min(x, 1.0))
+ return math.sqrt(1.0 - (x ** 2))
+ def shade(self, stroke):
+ # save the location and attribute of stroke vertices
+ buffer = []
+ for sv in iter_stroke_vertices(stroke):
+ buffer.append((sv.getPoint(), sv.attribute()))
+ nverts = len(buffer)
+ if nverts < 2:
+ return
+ # calculate the number of additional vertices to form caps
+ R, L = stroke[0].attribute().getThicknessRL()
+ caplen_beg = (R + L) / 2.0
+ nverts_beg = max(5, int(R + L))
+ R, L = stroke[-1].attribute().getThicknessRL()
+ caplen_end = (R + L) / 2.0
+ nverts_end = max(5, int(R + L))
+ # adjust the total number of stroke vertices
+ stroke.Resample(nverts + nverts_beg + nverts_end)
+ # restore the location and attribute of the original vertices
+ for i in range(nverts):
+ p, attr = buffer[i]
+ stroke[nverts_beg + i].setPoint(p)
+ stroke[nverts_beg + i].setAttribute(attr)
+ # reshape the cap at the beginning of the stroke
+ q, attr = buffer[1]
+ p, attr = buffer[0]
+ d = p - q
+ d = d / d.length * caplen_beg
+ n = 1.0 / nverts_beg
+ R, L = attr.getThicknessRL()
+ for i in range(nverts_beg):
+ t = (nverts_beg - i) * n
+ stroke[i].setPoint(p + d * t)
+ r = self.round_cap_thickness((nverts_beg - i + 1) * n)
+ stroke[i].setAttribute(attr)
+ stroke[i].attribute().setThickness(R * r, L * r)
+ # reshape the cap at the end of the stroke
+ q, attr = buffer[-2]
+ p, attr = buffer[-1]
+ d = p - q
+ d = d / d.length * caplen_end
+ n = 1.0 / nverts_end
+ R, L = attr.getThicknessRL()
+ for i in range(nverts_end):
+ t = (nverts_end - i) * n
+ stroke[-i-1].setPoint(p + d * t)
+ r = self.round_cap_thickness((nverts_end - i + 1) * n)
+ stroke[-i-1].setAttribute(attr)
+ stroke[-i-1].attribute().setThickness(R * r, L * r)
+
+class SquareCapShader(StrokeShader):
+ def shade(self, stroke):
+ # save the location and attribute of stroke vertices
+ buffer = []
+ for sv in iter_stroke_vertices(stroke):
+ buffer.append((sv.getPoint(), sv.attribute()))
+ nverts = len(buffer)
+ if nverts < 2:
+ return
+ # calculate the number of additional vertices to form caps
+ R, L = stroke[0].attribute().getThicknessRL()
+ caplen_beg = (R + L) / 2.0
+ nverts_beg = 1
+ R, L = stroke[-1].attribute().getThicknessRL()
+ caplen_end = (R + L) / 2.0
+ nverts_end = 1
+ # adjust the total number of stroke vertices
+ stroke.Resample(nverts + nverts_beg + nverts_end)
+ # restore the location and attribute of the original vertices
+ for i in range(nverts):
+ p, attr = buffer[i]
+ stroke[nverts_beg + i].setPoint(p)
+ stroke[nverts_beg + i].setAttribute(attr)
+ # reshape the cap at the beginning of the stroke
+ q, attr = buffer[1]
+ p, attr = buffer[0]
+ d = p - q
+ stroke[0].setPoint(p + d / d.length * caplen_beg)
+ stroke[0].setAttribute(attr)
+ # reshape the cap at the end of the stroke
+ q, attr = buffer[-2]
+ p, attr = buffer[-1]
+ d = p - q
+ stroke[-1].setPoint(p + d / d.length * caplen_beg)
+ stroke[-1].setAttribute(attr)
+
+# dashed line
+
+class DashedLineStartingUP0D(UnaryPredicate0D):
+ def __init__(self, controller):
+ UnaryPredicate0D.__init__(self)
+ self._controller = controller
+ def __call__(self, inter):
+ return self._controller.start()
+
+class DashedLineStoppingUP0D(UnaryPredicate0D):
+ def __init__(self, controller):
+ UnaryPredicate0D.__init__(self)
+ self._controller = controller
+ def __call__(self, inter):
+ return self._controller.stop()
+
+class DashedLineController:
+ def __init__(self, pattern, sampling):
+ self.sampling = float(sampling)
+ k = len(pattern) // 2
+ n = k * 2
+ self.start_pos = [pattern[i] + pattern[i+1] for i in range(0, n, 2)]
+ self.stop_pos = [pattern[i] for i in range(0, n, 2)]
+ self.init()
+ def init(self):
+ self.start_len = 0.0
+ self.start_idx = 0
+ self.stop_len = self.sampling
+ self.stop_idx = 0
+ def start(self):
+ self.start_len += self.sampling
+ if abs(self.start_len - self.start_pos[self.start_idx]) < self.sampling / 2.0:
+ self.start_len = 0.0
+ self.start_idx = (self.start_idx + 1) % len(self.start_pos)
+ return True
+ return False
+ def stop(self):
+ if self.start_len > 0.0:
+ self.init()
+ self.stop_len += self.sampling
+ if abs(self.stop_len - self.stop_pos[self.stop_idx]) < self.sampling / 2.0:
+ self.stop_len = self.sampling
+ self.stop_idx = (self.stop_idx + 1) % len(self.stop_pos)
+ return True
+ return False
+
+# predicates for chaining
+
+class AngleLargerThanBP1D(BinaryPredicate1D):
+ def __init__(self, angle):
+ BinaryPredicate1D.__init__(self)
+ self._angle = math.pi * angle / 180.0
+ def getName(self):
+ return "AngleLargerThanBP1D"
+ def __call__(self, i1, i2):
+ fe1a = i1.fedgeA()
+ fe1b = i1.fedgeB()
+ fe2a = i2.fedgeA()
+ fe2b = i2.fedgeB()
+ sv1a = fe1a.vertexA().getPoint2D()
+ sv1b = fe1b.vertexB().getPoint2D()
+ sv2a = fe2a.vertexA().getPoint2D()
+ sv2b = fe2b.vertexB().getPoint2D()
+ if (sv1a - sv2a).length < 1e-6:
+ dir1 = sv1a - sv1b
+ dir2 = sv2b - sv2a
+ elif (sv1b - sv2b).length < 1e-6:
+ dir1 = sv1b - sv1a
+ dir2 = sv2a - sv2b
+ elif (sv1a - sv2b).length < 1e-6:
+ dir1 = sv1a - sv1b
+ dir2 = sv2a - sv2b
+ elif (sv1b - sv2a).length < 1e-6:
+ dir1 = sv1b - sv1a
+ dir2 = sv2b - sv2a
+ else:
+ return False
+ denom = dir1.length * dir2.length
+ if denom < 1e-6:
+ return False
+ x = (dir1 * dir2) / denom
+ return math.acos(min(max(x, -1.0), 1.0)) > self._angle
+
+class AndBP1D(BinaryPredicate1D):
+ def __init__(self, pred1, pred2):
+ BinaryPredicate1D.__init__(self)
+ self.__pred1 = pred1
+ self.__pred2 = pred2
+ def getName(self):
+ return "AndBP1D"
+ def __call__(self, i1, i2):
+ return self.__pred1(i1, i2) and self.__pred2(i1, i2)
+
+# predicates for selection
+
+class LengthThresholdUP1D(UnaryPredicate1D):
+ def __init__(self, min_length=None, max_length=None):
+ UnaryPredicate1D.__init__(self)
+ self._min_length = min_length
+ self._max_length = max_length
+ def getName(self):
+ return "LengthThresholdUP1D"
+ def __call__(self, inter):
+ length = inter.getLength2D()
+ if self._min_length is not None and length < self._min_length:
+ return False
+ if self._max_length is not None and length > self._max_length:
+ return False
+ return True
+
+class FaceMarkBothUP1D(UnaryPredicate1D):
+ def __call__(self, inter): # ViewEdge
+ fe = inter.fedgeA()
+ while fe is not None:
+ if fe.isSmooth():
+ if fe.faceMark():
+ return True
+ else:
+ if fe.aFaceMark() and fe.bFaceMark():
+ return True
+ fe = fe.nextEdge()
+ return False
+
+class FaceMarkOneUP1D(UnaryPredicate1D):
+ def __call__(self, inter): # ViewEdge
+ fe = inter.fedgeA()
+ while fe is not None:
+ if fe.isSmooth():
+ if fe.faceMark():
+ return True
+ else:
+ if fe.aFaceMark() or fe.bFaceMark():
+ return True
+ fe = fe.nextEdge()
+ return False
+
+# predicates for splitting
+
+class MaterialBoundaryUP0D(UnaryPredicate0D):
+ def getName(self):
+ return "MaterialBoundaryUP0D"
+ def __call__(self, it):
+ if it.isBegin():
+ return False
+ it_prev = Interface0DIterator(it)
+ it_prev.decrement()
+ v = it.getObject()
+ it.increment()
+ if it.isEnd():
+ return False
+ fe = v.getFEdge(it_prev.getObject())
+ idx1 = fe.materialIndex() if fe.isSmooth() else fe.bMaterialIndex()
+ fe = v.getFEdge(it.getObject())
+ idx2 = fe.materialIndex() if fe.isSmooth() else fe.bMaterialIndex()
+ return idx1 != idx2
+
+class Curvature2DAngleThresholdUP0D(UnaryPredicate0D):
+ def __init__(self, min_angle=None, max_angle=None):
+ UnaryPredicate0D.__init__(self)
+ self._min_angle = min_angle
+ self._max_angle = max_angle
+ self._func = Curvature2DAngleF0D()
+ def getName(self):
+ return "Curvature2DAngleThresholdUP0D"
+ def __call__(self, inter):
+ angle = math.pi - self._func(inter)
+ if self._min_angle is not None and angle < self._min_angle:
+ return True
+ if self._max_angle is not None and angle > self._max_angle:
+ return True
+ return False
+
+class Length2DThresholdUP0D(UnaryPredicate0D):
+ def __init__(self, length_limit):
+ UnaryPredicate0D.__init__(self)
+ self._length_limit = length_limit
+ self._t = 0.0
+ def getName(self):
+ return "Length2DThresholdUP0D"
+ def __call__(self, inter):
+ t = inter.t() # curvilinear abscissa
+ if t < self._t:
+ self._t = 0.0
+ return False
+ if t - self._t < self._length_limit:
+ return False
+ self._t = t
+ return True
+
+# Seed for random number generation
+
+class Seed:
+ def __init__(self):
+ self.t_max = 2 ** 15
+ self.t = int(time.time()) % self.t_max
+ def get(self, seed):
+ if seed < 0:
+ self.t = (self.t + 1) % self.t_max
+ return self.t
+ return seed
+
+_seed = Seed()
+
+# main function for parameter processing
+
+def process(layer_name, lineset_name):
+ scene = Freestyle.getCurrentScene()
+ layer = scene.render.layers[layer_name]
+ lineset = layer.freestyle_settings.linesets[lineset_name]
+ linestyle = lineset.linestyle
+
+ selection_criteria = []
+ # prepare selection criteria by visibility
+ if lineset.select_by_visibility:
+ if lineset.visibility == "VISIBLE":
+ selection_criteria.append(
+ QuantitativeInvisibilityUP1D(0))
+ elif lineset.visibility == "HIDDEN":
+ selection_criteria.append(
+ NotUP1D(QuantitativeInvisibilityUP1D(0)))
+ elif lineset.visibility == "RANGE":
+ selection_criteria.append(
+ QuantitativeInvisibilityRangeUP1D(lineset.qi_start, lineset.qi_end))
+ # prepare selection criteria by edge types
+ if lineset.select_by_edge_types:
+ edge_type_criteria = []
+ if lineset.select_silhouette:
+ upred = pyNatureUP1D(Nature.SILHOUETTE)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_silhouette else upred)
+ if lineset.select_border:
+ upred = pyNatureUP1D(Nature.BORDER)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_border else upred)
+ if lineset.select_crease:
+ upred = pyNatureUP1D(Nature.CREASE)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_crease else upred)
+ if lineset.select_ridge_valley:
+ upred = pyNatureUP1D(Nature.RIDGE)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_ridge_valley else upred)
+ if lineset.select_suggestive_contour:
+ upred = pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_suggestive_contour else upred)
+ if lineset.select_material_boundary:
+ upred = pyNatureUP1D(Nature.MATERIAL_BOUNDARY)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_material_boundary else upred)
+ if lineset.select_edge_mark:
+ upred = pyNatureUP1D(Nature.EDGE_MARK)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_edge_mark else upred)
+ if lineset.select_contour:
+ upred = ContourUP1D()
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_contour else upred)
+ if lineset.select_external_contour:
+ upred = ExternalContourUP1D()
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_external_contour else upred)
+ if lineset.edge_type_combination == "OR":
+ upred = join_unary_predicates(edge_type_criteria, OrUP1D)
+ else:
+ upred = join_unary_predicates(edge_type_criteria, AndUP1D)
+ if upred is not None:
+ if lineset.edge_type_negation == "EXCLUSIVE":
+ upred = NotUP1D(upred)
+ selection_criteria.append(upred)
+ # prepare selection criteria by face marks
+ if lineset.select_by_face_marks:
+ if lineset.face_mark_condition == "BOTH":
+ upred = FaceMarkBothUP1D()
+ else:
+ upred = FaceMarkOneUP1D()
+ if lineset.face_mark_negation == "EXCLUSIVE":
+ upred = NotUP1D(upred)
+ selection_criteria.append(upred)
+ # prepare selection criteria by group of objects
+ if lineset.select_by_group:
+ if lineset.group is not None:
+ names = dict((ob.name, True) for ob in lineset.group.objects)
+ upred = ObjectNamesUP1D(names, lineset.group_negation == 'EXCLUSIVE')
+ selection_criteria.append(upred)
+ # prepare selection criteria by image border
+ if lineset.select_by_image_border:
+ w = scene.render.resolution_x
+ h = scene.render.resolution_y
+ if scene.render.use_border:
+ xmin = scene.render.border_min_x * w
+ xmax = scene.render.border_max_x * w
+ ymin = scene.render.border_min_y * h
+ ymax = scene.render.border_max_y * h
+ else:
+ xmin, xmax = 0.0, float(w)
+ ymin, ymax = 0.0, float(h)
+ upred = WithinImageBoundaryUP1D(xmin, ymin, xmax, ymax)
+ selection_criteria.append(upred)
+ # select feature edges
+ upred = join_unary_predicates(selection_criteria, AndUP1D)
+ if upred is None:
+ upred = TrueUP1D()
+ Operators.select(upred)
+ # join feature edges to form chains
+ if linestyle.use_chaining:
+ if linestyle.chaining == "PLAIN":
+ if linestyle.same_object:
+ Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
+ else:
+ Operators.bidirectionalChain(ChainPredicateIterator(upred, TrueBP1D()), NotUP1D(upred))
+ elif linestyle.chaining == "SKETCHY":
+ if linestyle.same_object:
+ Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(linestyle.rounds))
+ else:
+ Operators.bidirectionalChain(pySketchyChainingIterator(linestyle.rounds))
+ else:
+ Operators.chain(ChainPredicateIterator(FalseUP1D(), FalseBP1D()), NotUP1D(upred))
+ # split chains
+ if linestyle.material_boundary:
+ Operators.sequentialSplit(MaterialBoundaryUP0D())
+ if linestyle.use_min_angle or linestyle.use_max_angle:
+ min_angle = linestyle.min_angle if linestyle.use_min_angle else None
+ max_angle = linestyle.max_angle if linestyle.use_max_angle else None
+ Operators.sequentialSplit(Curvature2DAngleThresholdUP0D(min_angle, max_angle))
+ if linestyle.use_split_length:
+ Operators.sequentialSplit(Length2DThresholdUP0D(linestyle.split_length), 1.0)
+ # select chains
+ if linestyle.use_min_length or linestyle.use_max_length:
+ min_length = linestyle.min_length if linestyle.use_min_length else None
+ max_length = linestyle.max_length if linestyle.use_max_length else None
+ Operators.select(LengthThresholdUP1D(min_length, max_length))
+ # dashed line
+ if linestyle.use_dashed_line:
+ pattern = []
+ if linestyle.dash1 > 0 and linestyle.gap1 > 0:
+ pattern.append(linestyle.dash1)
+ pattern.append(linestyle.gap1)
+ if linestyle.dash2 > 0 and linestyle.gap2 > 0:
+ pattern.append(linestyle.dash2)
+ pattern.append(linestyle.gap2)
+ if linestyle.dash3 > 0 and linestyle.gap3 > 0:
+ pattern.append(linestyle.dash3)
+ pattern.append(linestyle.gap3)
+ if len(pattern) > 0:
+ sampling = 1.0
+ controller = DashedLineController(pattern, sampling)
+ Operators.sequentialSplit(DashedLineStartingUP0D(controller),
+ DashedLineStoppingUP0D(controller),
+ sampling)
+ # prepare a list of stroke shaders
+ shaders_list = []
+ for m in linestyle.geometry_modifiers:
+ if not m.use:
+ continue
+ if m.type == "SAMPLING":
+ shaders_list.append(SamplingShader(
+ m.sampling))
+ elif m.type == "BEZIER_CURVE":
+ shaders_list.append(BezierCurveShader(
+ m.error))
+ elif m.type == "SINUS_DISPLACEMENT":
+ shaders_list.append(SinusDisplacementShader(
+ m.wavelength, m.amplitude, m.phase))
+ elif m.type == "SPATIAL_NOISE":
+ shaders_list.append(SpatialNoiseShader(
+ m.amplitude, m.scale, m.octaves, m.smooth, m.pure_random))
+ elif m.type == "PERLIN_NOISE_1D":
+ shaders_list.append(PerlinNoise1DShader(
+ m.frequency, m.amplitude, m.octaves, m.angle, _seed.get(m.seed)))
+ elif m.type == "PERLIN_NOISE_2D":
+ shaders_list.append(PerlinNoise2DShader(
+ m.frequency, m.amplitude, m.octaves, m.angle, _seed.get(m.seed)))
+ elif m.type == "BACKBONE_STRETCHER":
+ shaders_list.append(BackboneStretcherShader(
+ m.backbone_length))
+ elif m.type == "TIP_REMOVER":
+ shaders_list.append(TipRemoverShader(
+ m.tip_length))
+ elif m.type == "POLYGONIZATION":
+ shaders_list.append(PolygonalizationShader(
+ m.error))
+ elif m.type == "GUIDING_LINES":
+ shaders_list.append(GuidingLinesShader(
+ m.offset))
+ elif m.type == "BLUEPRINT":
+ if m.shape == "CIRCLES":
+ shaders_list.append(pyBluePrintCirclesShader(
+ m.rounds, m.random_radius, m.random_center))
+ elif m.shape == "ELLIPSES":
+ shaders_list.append(pyBluePrintEllipsesShader(
+ m.rounds, m.random_radius, m.random_center))
+ elif m.shape == "SQUARES":
+ shaders_list.append(pyBluePrintSquaresShader(
+ m.rounds, m.backbone_length, m.random_backbone))
+ elif m.type == "2D_OFFSET":
+ shaders_list.append(Offset2DShader(
+ m.start, m.end, m.x, m.y))
+ elif m.type == "2D_TRANSFORM":
+ shaders_list.append(Transform2DShader(
+ m.pivot, m.scale_x, m.scale_y, m.angle, m.pivot_u, m.pivot_x, m.pivot_y))
+ color = linestyle.color
+ if (not linestyle.use_chaining) or (linestyle.chaining == "PLAIN" and linestyle.same_object):
+ thickness_position = linestyle.thickness_position
+ else:
+ thickness_position = "CENTER"
+ print("Warning: Thickness poisition options are applied when chaining is disabled")
+ print(" or the Plain chaining is used with the Same Object option enabled.")
+ shaders_list.append(BaseColorShader(color.r, color.g, color.b, linestyle.alpha))
+ shaders_list.append(BaseThicknessShader(linestyle.thickness, thickness_position,
+ linestyle.thickness_ratio))
+ for m in linestyle.color_modifiers:
+ if not m.use:
+ continue
+ if m.type == "ALONG_STROKE":
+ shaders_list.append(ColorAlongStrokeShader(
+ m.blend, m.influence, m.color_ramp))
+ elif m.type == "DISTANCE_FROM_CAMERA":
+ shaders_list.append(ColorDistanceFromCameraShader(
+ m.blend, m.influence, m.color_ramp,
+ m.range_min, m.range_max))
+ elif m.type == "DISTANCE_FROM_OBJECT":
+ shaders_list.append(ColorDistanceFromObjectShader(
+ m.blend, m.influence, m.color_ramp, m.target,
+ m.range_min, m.range_max))
+ elif m.type == "MATERIAL":
+ shaders_list.append(ColorMaterialShader(
+ m.blend, m.influence, m.color_ramp, m.material_attr,
+ m.use_ramp))
+ for m in linestyle.alpha_modifiers:
+ if not m.use:
+ continue
+ if m.type == "ALONG_STROKE":
+ shaders_list.append(AlphaAlongStrokeShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve))
+ elif m.type == "DISTANCE_FROM_CAMERA":
+ shaders_list.append(AlphaDistanceFromCameraShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.range_min, m.range_max))
+ elif m.type == "DISTANCE_FROM_OBJECT":
+ shaders_list.append(AlphaDistanceFromObjectShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
+ m.range_min, m.range_max))
+ elif m.type == "MATERIAL":
+ shaders_list.append(AlphaMaterialShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.material_attr))
+ for m in linestyle.thickness_modifiers:
+ if not m.use:
+ continue
+ if m.type == "ALONG_STROKE":
+ shaders_list.append(ThicknessAlongStrokeShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.value_min, m.value_max))
+ elif m.type == "DISTANCE_FROM_CAMERA":
+ shaders_list.append(ThicknessDistanceFromCameraShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.range_min, m.range_max, m.value_min, m.value_max))
+ elif m.type == "DISTANCE_FROM_OBJECT":
+ shaders_list.append(ThicknessDistanceFromObjectShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
+ m.range_min, m.range_max, m.value_min, m.value_max))
+ elif m.type == "MATERIAL":
+ shaders_list.append(ThicknessMaterialShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.material_attr, m.value_min, m.value_max))
+ elif m.type == "CALLIGRAPHY":
+ shaders_list.append(CalligraphicThicknessShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence,
+ m.orientation, m.min_thickness, m.max_thickness))
+ if linestyle.caps == "ROUND":
+ shaders_list.append(RoundCapShader())
+ elif linestyle.caps == "SQUARE":
+ shaders_list.append(SquareCapShader())
+ # create strokes using the shaders list
+ Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/polygonalize.py b/release/scripts/freestyle/style_modules/polygonalize.py
new file mode 100755
index 00000000000..4446c4c1dcc
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/polygonalize.py
@@ -0,0 +1,40 @@
+#
+# Filename : polygonalize.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Make the strokes more "polygonal"
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(2.0),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.0,0.0,0.0),
+ PolygonalizationShader(8)
+ ]
+Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/qi0.py b/release/scripts/freestyle/style_modules/qi0.py
new file mode 100755
index 00000000000..d35d23cb7c3
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/qi0.py
@@ -0,0 +1,41 @@
+#
+# Filename : qi0.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the visible lines (chaining follows same nature lines)
+# (most basic style module)
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(5.0),
+ ConstantThicknessShader(4.0),
+ ConstantColorShader(0.0,0.0,0.0)
+ ]
+Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/qi0_not_external_contour.py b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py
new file mode 100755
index 00000000000..eed41af32b4
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py
@@ -0,0 +1,43 @@
+#
+# Filename : qi0_not_external_contour.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the visible lines (chaining follows same nature lines)
+# that do not belong to the external contour of the scene
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred)
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(4),
+ SpatialNoiseShader(4, 150, 2, True, True),
+ IncreasingThicknessShader(2, 5),
+ BackboneStretcherShader(20),
+ IncreasingColorShader(1,0,0,1,0,1,0,1),
+ TextureAssignerShader(4)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/qi1.py b/release/scripts/freestyle/style_modules/qi1.py
new file mode 100755
index 00000000000..8d248376138
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/qi1.py
@@ -0,0 +1,42 @@
+#
+# Filename : qi1.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws lines hidden by one surface.
+# *** Quantitative Invisibility must have been
+# enabled in the options dialog to use this style module ****
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(1))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(1)))
+shaders_list = [
+ SamplingShader(5.0),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.5,0.5,0.5, 1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/qi2.py b/release/scripts/freestyle/style_modules/qi2.py
new file mode 100755
index 00000000000..ba5e97b6982
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/qi2.py
@@ -0,0 +1,42 @@
+#
+# Filename : qi2.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws lines hidden by two surfaces.
+# *** Quantitative Invisibility must have been
+# enabled in the options dialog to use this style module ****
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(2))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(2)))
+shaders_list = [
+ SamplingShader(10),
+ ConstantThicknessShader(1.5),
+ ConstantColorShader(0.7,0.7,0.7, 1)
+ ]
+Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py
new file mode 100755
index 00000000000..53fa03103aa
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py
@@ -0,0 +1,68 @@
+#
+# Filename : sequentialsplit_sketchy.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Use the sequential split with two different
+# predicates to specify respectively the starting and
+# the stopping extremities for strokes
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesU1D import *
+from PredicatesU0D import *
+from Functions0D import *
+
+## Predicate to tell whether a TVertex
+## corresponds to a change from 0 to 1 or not.
+class pyBackTVertexUP0D(UnaryPredicate0D):
+ def __init__(self):
+ UnaryPredicate0D.__init__(self)
+ self._getQI = QuantitativeInvisibilityF0D()
+ def getName(self):
+ return "pyBackTVertexUP0D"
+ def __call__(self, iter):
+ v = iter.getObject()
+ nat = v.getNature()
+ if(nat & Nature.T_VERTEX == 0):
+ return 0
+ if(self._getQI(iter) != 0):
+ return 1
+ return 0
+
+
+upred = QuantitativeInvisibilityUP1D(0)
+Operators.select(upred)
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
+## starting and stopping predicates:
+start = pyVertexNatureUP0D(Nature.NON_T_VERTEX)
+stop = pyBackTVertexUP0D()
+Operators.sequentialSplit(start, stop, 10)
+shaders_list = [
+ SpatialNoiseShader(7, 120, 2, True, True),
+ IncreasingThicknessShader(5, 8),
+ ConstantColorShader(0.2, 0.2, 0.2, 1),
+ TextureAssignerShader(4)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
+
diff --git a/release/scripts/freestyle/style_modules/shaders.py b/release/scripts/freestyle/style_modules/shaders.py
new file mode 100755
index 00000000000..70941477a7b
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/shaders.py
@@ -0,0 +1,1343 @@
+from freestyle_init import *
+from PredicatesU0D import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from logical_operators import *
+from ChainingIterators import *
+from random import *
+from math import *
+
+## thickness modifiers
+######################
+
+class pyDepthDiscontinuityThicknessShader(StrokeShader):
+ def __init__(self, min, max):
+ StrokeShader.__init__(self)
+ self.__min = float(min)
+ self.__max = float(max)
+ self.__func = ZDiscontinuityF0D()
+ def getName(self):
+ return "pyDepthDiscontinuityThicknessShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ z_min=0.0
+ z_max=1.0
+ a = (self.__max - self.__min)/(z_max-z_min)
+ b = (self.__min*z_max-self.__max*z_min)/(z_max-z_min)
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ z = self.__func(it.castToInterface0DIterator())
+ thickness = a*z+b
+ it.getObject().attribute().setThickness(thickness, thickness)
+ it.increment()
+
+class pyConstantThicknessShader(StrokeShader):
+ def __init__(self, thickness):
+ StrokeShader.__init__(self)
+ self._thickness = thickness
+
+ def getName(self):
+ return "pyConstantThicknessShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ t = self._thickness/2.0
+ att.setThickness(t, t)
+ it.increment()
+
+class pyFXSThicknessShader(StrokeShader):
+ def __init__(self, thickness):
+ StrokeShader.__init__(self)
+ self._thickness = thickness
+
+ def getName(self):
+ return "pyFXSThicknessShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ t = self._thickness/2.0
+ att.setThickness(t, t)
+ it.increment()
+
+class pyFXSVaryingThicknessWithDensityShader(StrokeShader):
+ def __init__(self, wsize, threshold_min, threshold_max, thicknessMin, thicknessMax):
+ StrokeShader.__init__(self)
+ self.wsize= wsize
+ self.threshold_min= threshold_min
+ self.threshold_max= threshold_max
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+
+ def getName(self):
+ return "pyVaryingThicknessWithDensityShader"
+ def shade(self, stroke):
+ n = stroke.strokeVerticesSize()
+ i = 0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ func = DensityF0D(self.wsize)
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ toto = it.castToInterface0DIterator()
+ c= func(toto)
+ if (c < self.threshold_min ):
+ c = self.threshold_min
+ if (c > self.threshold_max ):
+ c = self.threshold_max
+## t = (c - self.threshold_min)/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin
+ t = (self.threshold_max - c )/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin
+ att.setThickness(t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+class pyIncreasingThicknessShader(StrokeShader):
+ def __init__(self, thicknessMin, thicknessMax):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+
+ def getName(self):
+ return "pyIncreasingThicknessShader"
+ def shade(self, stroke):
+ n = stroke.strokeVerticesSize()
+ i = 0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ c = float(i)/float(n)
+ if(i < float(n)/2.0):
+ t = (1.0 - c)*self._thicknessMin + c * self._thicknessMax
+ else:
+ t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin
+ att.setThickness(t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+class pyConstrainedIncreasingThicknessShader(StrokeShader):
+ def __init__(self, thicknessMin, thicknessMax, ratio):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+ self._ratio = ratio
+
+ def getName(self):
+ return "pyConstrainedIncreasingThicknessShader"
+ def shade(self, stroke):
+ slength = stroke.getLength2D()
+ tmp = self._ratio*slength
+ maxT = 0.0
+ if(tmp < self._thicknessMax):
+ maxT = tmp
+ else:
+ maxT = self._thicknessMax
+ n = stroke.strokeVerticesSize()
+ i = 0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ c = float(i)/float(n)
+ if(i < float(n)/2.0):
+ t = (1.0 - c)*self._thicknessMin + c * maxT
+ else:
+ t = (1.0 - c)*maxT + c * self._thicknessMin
+ att.setThickness(t/2.0, t/2.0)
+ if(i == n-1):
+ att.setThickness(self._thicknessMin/2.0, self._thicknessMin/2.0)
+ i = i+1
+ it.increment()
+
+class pyDecreasingThicknessShader(StrokeShader):
+ def __init__(self, thicknessMax, thicknessMin):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+
+ def getName(self):
+ return "pyDecreasingThicknessShader"
+ def shade(self, stroke):
+ l = stroke.getLength2D()
+ tMax = self._thicknessMax
+ if(self._thicknessMax > 0.33*l):
+ tMax = 0.33*l
+ tMin = self._thicknessMin
+ if(self._thicknessMin > 0.1*l):
+ tMin = 0.1*l
+ n = stroke.strokeVerticesSize()
+ i = 0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ c = float(i)/float(n)
+ t = (1.0 - c)*tMax +c*tMin
+ att.setThickness(t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+def smoothC( a, exp ):
+ c = pow(float(a),exp)*pow(2.0,exp)
+ return c
+
+class pyNonLinearVaryingThicknessShader(StrokeShader):
+ def __init__(self, thicknessExtremity, thicknessMiddle, exponent):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMiddle
+ self._thicknessMax = thicknessExtremity
+ self._exponent = exponent
+
+ def getName(self):
+ return "pyNonLinearVaryingThicknessShader"
+ def shade(self, stroke):
+ n = stroke.strokeVerticesSize()
+ i = 0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ if(i < float(n)/2.0):
+ c = float(i)/float(n)
+ else:
+ c = float(n-i)/float(n)
+ c = smoothC(c, self._exponent)
+ t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin
+ att.setThickness(t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+## Spherical linear interpolation (cos)
+class pySLERPThicknessShader(StrokeShader):
+ def __init__(self, thicknessMin, thicknessMax, omega=1.2):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+ self._omega = omega
+
+ def getName(self):
+ return "pySLERPThicknessShader"
+ def shade(self, stroke):
+ slength = stroke.getLength2D()
+ tmp = 0.33*slength
+ maxT = self._thicknessMax
+ if(tmp < self._thicknessMax):
+ maxT = tmp
+
+ n = stroke.strokeVerticesSize()
+ i = 0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ c = float(i)/float(n)
+ if(i < float(n)/2.0):
+ t = sin((1-c)*self._omega)/sinh(self._omega)*self._thicknessMin + sin(c*self._omega)/sinh(self._omega) * maxT
+ else:
+ t = sin((1-c)*self._omega)/sinh(self._omega)*maxT + sin(c*self._omega)/sinh(self._omega) * self._thicknessMin
+ att.setThickness(t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+class pyTVertexThickenerShader(StrokeShader): ## FIXME
+ def __init__(self, a=1.5, n=3):
+ StrokeShader.__init__(self)
+ self._a = a
+ self._n = n
+
+ def getName(self):
+ return "pyTVertexThickenerShader"
+
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX)
+ while it.isEnd() == 0:
+ if(predTVertex(it) == 1):
+ it2 = StrokeVertexIterator(it)
+ it2.increment()
+ if not(it.isBegin() or it2.isEnd()):
+ it.increment()
+ continue
+ n = self._n
+ a = self._a
+ if(it.isBegin()):
+ it3 = StrokeVertexIterator(it)
+ count = 0
+ while (it3.isEnd() == 0 and count < n):
+ att = it3.getObject().attribute()
+ tr = att.getThicknessR();
+ tl = att.getThicknessL();
+ r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
+ #r = (1.0-a)/float(n-1)*count + a
+ att.setThickness(r*tr, r*tl)
+ it3.increment()
+ count = count + 1
+ if(it2.isEnd()):
+ it4 = StrokeVertexIterator(it)
+ count = 0
+ while (it4.isBegin() == 0 and count < n):
+ att = it4.getObject().attribute()
+ tr = att.getThicknessR();
+ tl = att.getThicknessL();
+ r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
+ #r = (1.0-a)/float(n-1)*count + a
+ att.setThickness(r*tr, r*tl)
+ it4.decrement()
+ count = count + 1
+ if ((it4.isBegin() == 1)):
+ att = it4.getObject().attribute()
+ tr = att.getThicknessR();
+ tl = att.getThicknessL();
+ r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
+ #r = (1.0-a)/float(n-1)*count + a
+ att.setThickness(r*tr, r*tl)
+ it.increment()
+
+class pyImportance2DThicknessShader(StrokeShader):
+ def __init__(self, x, y, w, kmin, kmax):
+ StrokeShader.__init__(self)
+ self._x = x
+ self._y = y
+ self._w = float(w)
+ self._kmin = float(kmin)
+ self._kmax = float(kmax)
+
+ def getName(self):
+ return "pyImportanceThicknessShader"
+ def shade(self, stroke):
+ origin = Vector([self._x, self._y])
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ v = it.getObject()
+ p = Vector([v.getProjectedX(), v.getProjectedY()])
+ d = (p-origin).length
+ if(d>self._w):
+ k = self._kmin
+ else:
+ k = (self._kmax*(self._w-d) + self._kmin*d)/self._w
+ att = v.attribute()
+ tr = att.getThicknessR()
+ tl = att.getThicknessL()
+ att.setThickness(k*tr/2.0, k*tl/2.0)
+ it.increment()
+
+class pyImportance3DThicknessShader(StrokeShader):
+ def __init__(self, x, y, z, w, kmin, kmax):
+ StrokeShader.__init__(self)
+ self._x = x
+ self._y = y
+ self._z = z
+ self._w = float(w)
+ self._kmin = float(kmin)
+ self._kmax = float(kmax)
+
+ def getName(self):
+ return "pyImportance3DThicknessShader"
+ def shade(self, stroke):
+ origin = Vector([self._x, self._y, self._z])
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ v = it.getObject()
+ p = Vector([v.getX(), v.getY(), v.getZ()])
+ d = (p-origin).length
+ if(d>self._w):
+ k = self._kmin
+ else:
+ k = (self._kmax*(self._w-d) + self._kmin*d)/self._w
+ att = v.attribute()
+ tr = att.getThicknessR()
+ tl = att.getThicknessL()
+ att.setThickness(k*tr/2.0, k*tl/2.0)
+ it.increment()
+
+class pyZDependingThicknessShader(StrokeShader):
+ def __init__(self, min, max):
+ StrokeShader.__init__(self)
+ self.__min = min
+ self.__max = max
+ self.__func = GetProjectedZF0D()
+ def getName(self):
+ return "pyZDependingThicknessShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ z_min = 1
+ z_max = 0
+ while it.isEnd() == 0:
+ z = self.__func(it.castToInterface0DIterator())
+ if z < z_min:
+ z_min = z
+ if z > z_max:
+ z_max = z
+ it.increment()
+ z_diff = 1 / (z_max - z_min)
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ z = (self.__func(it.castToInterface0DIterator()) - z_min) * z_diff
+ thickness = (1 - z) * self.__max + z * self.__min
+ it.getObject().attribute().setThickness(thickness, thickness)
+ it.increment()
+
+
+## color modifiers
+##################
+
+class pyConstantColorShader(StrokeShader):
+ def __init__(self,r,g,b, a = 1):
+ StrokeShader.__init__(self)
+ self._r = r
+ self._g = g
+ self._b = b
+ self._a = a
+ def getName(self):
+ return "pyConstantColorShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ att.setColor(self._r, self._g, self._b)
+ att.setAlpha(self._a)
+ it.increment()
+
+#c1->c2
+class pyIncreasingColorShader(StrokeShader):
+ def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
+ StrokeShader.__init__(self)
+ self._c1 = [r1,g1,b1,a1]
+ self._c2 = [r2,g2,b2,a2]
+ def getName(self):
+ return "pyIncreasingColorShader"
+ def shade(self, stroke):
+ n = stroke.strokeVerticesSize() - 1
+ inc = 0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ c = float(inc)/float(n)
+
+ att.setColor( (1-c)*self._c1[0] + c*self._c2[0],
+ (1-c)*self._c1[1] + c*self._c2[1],
+ (1-c)*self._c1[2] + c*self._c2[2],)
+ att.setAlpha((1-c)*self._c1[3] + c*self._c2[3],)
+ inc = inc+1
+ it.increment()
+
+# c1->c2->c1
+class pyInterpolateColorShader(StrokeShader):
+ def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
+ StrokeShader.__init__(self)
+ self._c1 = [r1,g1,b1,a1]
+ self._c2 = [r2,g2,b2,a2]
+ def getName(self):
+ return "pyInterpolateColorShader"
+ def shade(self, stroke):
+ n = stroke.strokeVerticesSize() - 1
+ inc = 0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ u = float(inc)/float(n)
+ c = 1-2*(fabs(u-0.5))
+ att.setColor( (1-c)*self._c1[0] + c*self._c2[0],
+ (1-c)*self._c1[1] + c*self._c2[1],
+ (1-c)*self._c1[2] + c*self._c2[2],)
+ att.setAlpha((1-c)*self._c1[3] + c*self._c2[3],)
+ inc = inc+1
+ it.increment()
+
+class pyMaterialColorShader(StrokeShader):
+ def __init__(self, threshold=50):
+ StrokeShader.__init__(self)
+ self._threshold = threshold
+
+ def getName(self):
+ return "pyMaterialColorShader"
+
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ func = MaterialF0D()
+ xn = 0.312713
+ yn = 0.329016
+ Yn = 1.0
+ un = 4.* xn/ ( -2.*xn + 12.*yn + 3. )
+ vn= 9.* yn/ ( -2.*xn + 12.*yn +3. )
+ while it.isEnd() == 0:
+ toto = it.castToInterface0DIterator()
+ mat = func(toto)
+
+ r = mat.diffuseR()
+ g = mat.diffuseG()
+ b = mat.diffuseB()
+
+ X = 0.412453*r + 0.35758 *g + 0.180423*b
+ Y = 0.212671*r + 0.71516 *g + 0.072169*b
+ Z = 0.019334*r + 0.119193*g + 0.950227*b
+
+ if((X == 0) and (Y == 0) and (Z == 0)):
+ X = 0.01
+ Y = 0.01
+ Z = 0.01
+ u = 4.*X / (X + 15.*Y + 3.*Z)
+ v = 9.*Y / (X + 15.*Y + 3.*Z)
+
+ L= 116. * pow((Y/Yn),(1./3.)) -16
+ U = 13. * L * (u - un)
+ V = 13. * L * (v - vn)
+
+ if (L > self._threshold):
+ L = L/1.3
+ U = U+10
+ else:
+ L = L +2.5*(100-L)/5.
+ U = U/3.0
+ V = V/3.0
+ u = U / (13. * L) + un
+ v = V / (13. * L) + vn
+
+ Y = Yn * pow( ((L+16.)/116.), 3.)
+ X = -9. * Y * u / ((u - 4.)* v - u * v)
+ Z = (9. * Y - 15*v*Y - v*X) /( 3. * v)
+
+ r = 3.240479 * X - 1.53715 * Y - 0.498535 * Z
+ g = -0.969256 * X + 1.875991 * Y + 0.041556 * Z
+ b = 0.055648 * X - 0.204043 * Y + 1.057311 * Z
+
+ r = max(0,r)
+ g = max(0,g)
+ b = max(0,b)
+
+ att = it.getObject().attribute()
+ att.setColor(r, g, b)
+ it.increment()
+
+class pyRandomColorShader(StrokeShader):
+ def getName(self):
+ return "pyRandomColorShader"
+ def __init__(self, s=1):
+ StrokeShader.__init__(self)
+ seed(s)
+ def shade(self, stroke):
+ ## pick a random color
+ c0 = float(uniform(15,75))/100.0
+ c1 = float(uniform(15,75))/100.0
+ c2 = float(uniform(15,75))/100.0
+ print(c0, c1, c2)
+ it = stroke.strokeVerticesBegin()
+ while(it.isEnd() == 0):
+ it.getObject().attribute().setColor(c0,c1,c2)
+ it.increment()
+
+class py2DCurvatureColorShader(StrokeShader):
+ def getName(self):
+ return "py2DCurvatureColorShader"
+
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ func = Curvature2DAngleF0D()
+ while it.isEnd() == 0:
+ toto = it.castToInterface0DIterator()
+ sv = it.getObject()
+ att = sv.attribute()
+ c = func(toto)
+ if (c<0):
+ print("negative 2D curvature")
+ color = 10.0 * c/3.1415
+ print(color)
+ att.setColor(color,color,color);
+ it.increment()
+
+class pyTimeColorShader(StrokeShader):
+ def __init__(self, step=0.01):
+ StrokeShader.__init__(self)
+ self._t = 0
+ self._step = step
+ def shade(self, stroke):
+ c = self._t*1.0
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ att = it.getObject().attribute()
+ att.setColor(c,c,c)
+ it.increment()
+ self._t = self._t+self._step
+
+## geometry modifiers
+
+class pySamplingShader(StrokeShader):
+ def __init__(self, sampling):
+ StrokeShader.__init__(self)
+ self._sampling = sampling
+ def getName(self):
+ return "pySamplingShader"
+ def shade(self, stroke):
+ stroke.Resample(float(self._sampling))
+
+class pyBackboneStretcherShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def getName(self):
+ return "pyBackboneStretcherShader"
+ def shade(self, stroke):
+ it0 = stroke.strokeVerticesBegin()
+ it1 = StrokeVertexIterator(it0)
+ it1.increment()
+ itn = stroke.strokeVerticesEnd()
+ itn.decrement()
+ itn_1 = StrokeVertexIterator(itn)
+ itn_1.decrement()
+ v0 = it0.getObject()
+ v1 = it1.getObject()
+ vn_1 = itn_1.getObject()
+ vn = itn.getObject()
+ p0 = Vector([v0.getProjectedX(), v0.getProjectedY()])
+ pn = Vector([vn.getProjectedX(), vn.getProjectedY()])
+ p1 = Vector([v1.getProjectedX(), v1.getProjectedY()])
+ pn_1 = Vector([vn_1.getProjectedX(), vn_1.getProjectedY()])
+ d1 = p0-p1
+ d1.normalize()
+ dn = pn-pn_1
+ dn.normalize()
+ newFirst = p0+d1*float(self._l)
+ newLast = pn+dn*float(self._l)
+ v0.setPoint(newFirst)
+ vn.setPoint(newLast)
+ stroke.UpdateLength()
+
+class pyLengthDependingBackboneStretcherShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def getName(self):
+ return "pyBackboneStretcherShader"
+ def shade(self, stroke):
+ l = stroke.getLength2D()
+ stretch = self._l*l
+ it0 = stroke.strokeVerticesBegin()
+ it1 = StrokeVertexIterator(it0)
+ it1.increment()
+ itn = stroke.strokeVerticesEnd()
+ itn.decrement()
+ itn_1 = StrokeVertexIterator(itn)
+ itn_1.decrement()
+ v0 = it0.getObject()
+ v1 = it1.getObject()
+ vn_1 = itn_1.getObject()
+ vn = itn.getObject()
+ p0 = Vector([v0.getProjectedX(), v0.getProjectedY()])
+ pn = Vector([vn.getProjectedX(), vn.getProjectedY()])
+ p1 = Vector([v1.getProjectedX(), v1.getProjectedY()])
+ pn_1 = Vector([vn_1.getProjectedX(), vn_1.getProjectedY()])
+ d1 = p0-p1
+ d1.normalize()
+ dn = pn-pn_1
+ dn.normalize()
+ newFirst = p0+d1*float(stretch)
+ newLast = pn+dn*float(stretch)
+ v0.setPoint(newFirst)
+ vn.setPoint(newLast)
+ stroke.UpdateLength()
+
+
+## Shader to replace a stroke by its corresponding tangent
+class pyGuidingLineShader(StrokeShader):
+ def getName(self):
+ return "pyGuidingLineShader"
+ ## shading method
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin() ## get the first vertex
+ itlast = stroke.strokeVerticesEnd() ##
+ itlast.decrement() ## get the last one
+ t = itlast.getObject().getPoint() - it.getObject().getPoint() ## tangent direction
+ itmiddle = StrokeVertexIterator(it) ##
+ while(itmiddle.getObject().u()<0.5): ## look for the stroke middle vertex
+ itmiddle.increment() ##
+ it = StrokeVertexIterator(itmiddle)
+ it.increment()
+ while(it.isEnd() == 0): ## position all the vertices along the tangent for the right part
+ it.getObject().setPoint(itmiddle.getObject().getPoint() \
+ +t*(it.getObject().u()-itmiddle.getObject().u()))
+ it.increment()
+ it = StrokeVertexIterator(itmiddle)
+ it.decrement()
+ while(it.isBegin() == 0): ## position all the vertices along the tangent for the left part
+ it.getObject().setPoint(itmiddle.getObject().getPoint() \
+ -t*(itmiddle.getObject().u()-it.getObject().u()))
+ it.decrement()
+ it.getObject().setPoint(itmiddle.getObject().getPoint()-t*(itmiddle.getObject().u())) ## first vertex
+ stroke.UpdateLength()
+
+
+class pyBackboneStretcherNoCuspShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def getName(self):
+ return "pyBackboneStretcherNoCuspShader"
+ def shade(self, stroke):
+ it0 = stroke.strokeVerticesBegin()
+ it1 = StrokeVertexIterator(it0)
+ it1.increment()
+ itn = stroke.strokeVerticesEnd()
+ itn.decrement()
+ itn_1 = StrokeVertexIterator(itn)
+ itn_1.decrement()
+ v0 = it0.getObject()
+ v1 = it1.getObject()
+ if((v0.getNature() & Nature.CUSP == 0) and (v1.getNature() & Nature.CUSP == 0)):
+ p0 = v0.getPoint()
+ p1 = v1.getPoint()
+ d1 = p0-p1
+ d1.normalize()
+ newFirst = p0+d1*float(self._l)
+ v0.setPoint(newFirst)
+ vn_1 = itn_1.getObject()
+ vn = itn.getObject()
+ if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)):
+ pn = vn.getPoint()
+ pn_1 = vn_1.getPoint()
+ dn = pn-pn_1
+ dn.normalize()
+ newLast = pn+dn*float(self._l)
+ vn.setPoint(newLast)
+ stroke.UpdateLength()
+
+normalInfo=Normal2DF0D()
+curvatureInfo=Curvature2DAngleF0D()
+
+def edgestopping(x, sigma):
+ return exp(- x*x/(2*sigma*sigma))
+
+class pyDiffusion2Shader(StrokeShader):
+ def __init__(self, lambda1, nbIter):
+ StrokeShader.__init__(self)
+ self._lambda = lambda1
+ self._nbIter = nbIter
+ self._normalInfo = Normal2DF0D()
+ self._curvatureInfo = Curvature2DAngleF0D()
+ def getName(self):
+ return "pyDiffusionShader"
+ def shade(self, stroke):
+ for i in range (1, self._nbIter):
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ v=it.getObject()
+ p1 = v.getPoint()
+ p2 = self._normalInfo(it.castToInterface0DIterator())*self._lambda*self._curvatureInfo(it.castToInterface0DIterator())
+ v.setPoint(p1+p2)
+ it.increment()
+ stroke.UpdateLength()
+
+class pyTipRemoverShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def getName(self):
+ return "pyTipRemoverShader"
+ def shade(self, stroke):
+ originalSize = stroke.strokeVerticesSize()
+ if(originalSize<4):
+ return
+ verticesToRemove = []
+ oldAttributes = []
+ it = stroke.strokeVerticesBegin()
+ while(it.isEnd() == 0):
+ v = it.getObject()
+ if((v.curvilinearAbscissa() < self._l) or (v.strokeLength()-v.curvilinearAbscissa() < self._l)):
+ verticesToRemove.append(v)
+ oldAttributes.append(StrokeAttribute(v.attribute()))
+ it.increment()
+ if(originalSize-len(verticesToRemove) < 2):
+ return
+ for sv in verticesToRemove:
+ stroke.RemoveVertex(sv)
+ stroke.Resample(originalSize)
+ if(stroke.strokeVerticesSize() != originalSize):
+ print("pyTipRemover: Warning: resampling problem")
+ it = stroke.strokeVerticesBegin()
+ for a in oldAttributes:
+ if(it.isEnd() == 1):
+ break
+ v = it.getObject()
+ v.setAttribute(a)
+ it.increment()
+ stroke.UpdateLength()
+
+class pyTVertexRemoverShader(StrokeShader):
+ def getName(self):
+ return "pyTVertexRemoverShader"
+ def shade(self, stroke):
+ if(stroke.strokeVerticesSize() <= 3 ):
+ return
+ predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX)
+ it = stroke.strokeVerticesBegin()
+ itlast = stroke.strokeVerticesEnd()
+ itlast.decrement()
+ if(predTVertex(it) == 1):
+ stroke.RemoveVertex(it.getObject())
+ if(predTVertex(itlast) == 1):
+ stroke.RemoveVertex(itlast.getObject())
+ stroke.UpdateLength()
+
+class pyExtremitiesOrientationShader(StrokeShader):
+ def __init__(self, x1,y1,x2=0,y2=0):
+ StrokeShader.__init__(self)
+ self._v1 = Vector([x1,y1])
+ self._v2 = Vector([x2,y2])
+ def getName(self):
+ return "pyExtremitiesOrientationShader"
+ def shade(self, stroke):
+ print(self._v1.x,self._v1.y)
+ stroke.setBeginningOrientation(self._v1.x,self._v1.y)
+ stroke.setEndingOrientation(self._v2.x,self._v2.y)
+
+def getFEdge(it1, it2):
+ return it1.getFEdge(it2)
+
+class pyHLRShader(StrokeShader):
+ def getName(self):
+ return "pyHLRShader"
+ def shade(self, stroke):
+ originalSize = stroke.strokeVerticesSize()
+ if(originalSize<4):
+ return
+ it = stroke.strokeVerticesBegin()
+ invisible = 0
+ it2 = StrokeVertexIterator(it)
+ it2.increment()
+ fe = getFEdge(it.getObject(), it2.getObject())
+ if(fe.viewedge().qi() != 0):
+ invisible = 1
+ while(it2.isEnd() == 0):
+ v = it.getObject()
+ vnext = it2.getObject()
+ if(v.getNature() & Nature.VIEW_VERTEX):
+ #if(v.getNature() & Nature.T_VERTEX):
+ fe = getFEdge(v,vnext)
+ qi = fe.viewedge().qi()
+ if(qi != 0):
+ invisible = 1
+ else:
+ invisible = 0
+ if(invisible == 1):
+ v.attribute().setVisible(0)
+ it.increment()
+ it2.increment()
+
+class pyTVertexOrientationShader(StrokeShader):
+ def __init__(self):
+ StrokeShader.__init__(self)
+ self._Get2dDirection = Orientation2DF1D()
+ def getName(self):
+ return "pyTVertexOrientationShader"
+ ## finds the TVertex orientation from the TVertex and
+ ## the previous or next edge
+ def findOrientation(self, tv, ve):
+ mateVE = tv.mate(ve)
+ if((ve.qi() != 0) or (mateVE.qi() != 0)):
+ ait = AdjacencyIterator(tv,1,0)
+ winner = None
+ incoming = 1
+ while(ait.isEnd() == 0):
+ ave = ait.getObject()
+ if((ave.getId() != ve.getId()) and (ave.getId() != mateVE.getId())):
+ winner = ait.getObject()
+ if(ait.isIncoming() == 0):
+ incoming = 0
+ break
+ ait.increment()
+ if(winner != None):
+ if(incoming != 0):
+ direction = self._Get2dDirection(winner.fedgeB())
+ else:
+ direction = self._Get2dDirection(winner.fedgeA())
+ return direction
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ it2 = StrokeVertexIterator(it)
+ it2.increment()
+ ## case where the first vertex is a TVertex
+ v = it.getObject()
+ if(v.getNature() & Nature.T_VERTEX):
+ tv = v.castToTVertex()
+ ve = getFEdge(v, it2.getObject()).viewedge()
+ if(tv != None):
+ dir = self.findOrientation(tv, ve)
+ #print(dir.x, dir.y)
+ v.attribute().setAttributeVec2f("orientation", dir)
+ while(it2.isEnd() == 0):
+ vprevious = it.getObject()
+ v = it2.getObject()
+ if(v.getNature() & Nature.T_VERTEX):
+ tv = v.castToTVertex()
+ ve = getFEdge(vprevious, v).viewedge()
+ if(tv != None):
+ dir = self.findOrientation(tv, ve)
+ #print(dir.x, dir.y)
+ v.attribute().setAttributeVec2f("orientation", dir)
+ it.increment()
+ it2.increment()
+ ## case where the last vertex is a TVertex
+ v = it.getObject()
+ if(v.getNature() & Nature.T_VERTEX):
+ itPrevious = StrokeVertexIterator(it)
+ itPrevious.decrement()
+ tv = v.castToTVertex()
+ ve = getFEdge(itPrevious.getObject(), v).viewedge()
+ if(tv != None):
+ dir = self.findOrientation(tv, ve)
+ #print(dir.x, dir.y)
+ v.attribute().setAttributeVec2f("orientation", dir)
+
+class pySinusDisplacementShader(StrokeShader):
+ def __init__(self, f, a):
+ StrokeShader.__init__(self)
+ self._f = f
+ self._a = a
+ self._getNormal = Normal2DF0D()
+
+ def getName(self):
+ return "pySinusDisplacementShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ v = it.getObject()
+ #print(self._getNormal.getName())
+ n = self._getNormal(it.castToInterface0DIterator())
+ p = v.getPoint()
+ u = v.u()
+ a = self._a*(1-2*(fabs(u-0.5)))
+ n = n*a*cos(self._f*u*6.28)
+ #print(n.x, n.y)
+ v.setPoint(p+n)
+ #v.setPoint(v.getPoint()+n*a*cos(f*v.u()))
+ it.increment()
+ stroke.UpdateLength()
+
+class pyPerlinNoise1DShader(StrokeShader):
+ def __init__(self, freq = 10, amp = 10, oct = 4, seed = -1):
+ StrokeShader.__init__(self)
+ self.__noise = Noise(seed)
+ self.__freq = freq
+ self.__amp = amp
+ self.__oct = oct
+ def getName(self):
+ return "pyPerlinNoise1DShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ v = it.getObject()
+ i = v.getProjectedX() + v.getProjectedY()
+ nres = self.__noise.turbulence1(i, self.__freq, self.__amp, self.__oct)
+ v.setPoint(v.getProjectedX() + nres, v.getProjectedY() + nres)
+ it.increment()
+ stroke.UpdateLength()
+
+class pyPerlinNoise2DShader(StrokeShader):
+ def __init__(self, freq = 10, amp = 10, oct = 4, seed = -1):
+ StrokeShader.__init__(self)
+ self.__noise = Noise(seed)
+ self.__freq = freq
+ self.__amp = amp
+ self.__oct = oct
+ def getName(self):
+ return "pyPerlinNoise2DShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ v = it.getObject()
+ vec = Vector([v.getProjectedX(), v.getProjectedY()])
+ nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
+ v.setPoint(v.getProjectedX() + nres, v.getProjectedY() + nres)
+ it.increment()
+ stroke.UpdateLength()
+
+class pyBluePrintCirclesShader(StrokeShader):
+ def __init__(self, turns = 1, random_radius = 3, random_center = 5):
+ StrokeShader.__init__(self)
+ self.__turns = turns
+ self.__random_center = random_center
+ self.__random_radius = random_radius
+ def getName(self):
+ return "pyBluePrintCirclesShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ if it.isEnd():
+ return
+ p_min = it.getObject().getPoint()
+ p_max = it.getObject().getPoint()
+ while it.isEnd() == 0:
+ p = it.getObject().getPoint()
+ if (p.x < p_min.x):
+ p_min.x = p.x
+ if (p.x > p_max.x):
+ p_max.x = p.x
+ if (p.y < p_min.y):
+ p_min.y = p.y
+ if (p.y > p_max.y):
+ p_max.y = p.y
+ it.increment()
+ stroke.Resample(32 * self.__turns)
+ sv_nb = stroke.strokeVerticesSize()
+# print("min :", p_min.x, p_min.y) # DEBUG
+# print("mean :", p_sum.x, p_sum.y) # DEBUG
+# print("max :", p_max.x, p_max.y) # DEBUG
+# print("----------------------") # DEBUG
+#######################################################
+ sv_nb = sv_nb // self.__turns
+ center = (p_min + p_max) / 2
+ radius = (center.x - p_min.x + center.y - p_min.y) / 2
+ p_new = Vector([0, 0])
+#######################################################
+ R = self.__random_radius
+ C = self.__random_center
+ i = 0
+ it = stroke.strokeVerticesBegin()
+ for j in range(self.__turns):
+ prev_radius = radius
+ prev_center = center
+ radius = radius + randint(-R, R)
+ center = center + Vector([randint(-C, C), randint(-C, C)])
+ while i < sv_nb and it.isEnd() == 0:
+ t = float(i) / float(sv_nb - 1)
+ r = prev_radius + (radius - prev_radius) * t
+ c = prev_center + (center - prev_center) * t
+ p_new.x = c.x + r * cos(2 * pi * t)
+ p_new.y = c.y + r * sin(2 * pi * t)
+ it.getObject().setPoint(p_new)
+ i = i + 1
+ it.increment()
+ i = 1
+ verticesToRemove = []
+ while it.isEnd() == 0:
+ verticesToRemove.append(it.getObject())
+ it.increment()
+ for sv in verticesToRemove:
+ stroke.RemoveVertex(sv)
+ stroke.UpdateLength()
+
+class pyBluePrintEllipsesShader(StrokeShader):
+ def __init__(self, turns = 1, random_radius = 3, random_center = 5):
+ StrokeShader.__init__(self)
+ self.__turns = turns
+ self.__random_center = random_center
+ self.__random_radius = random_radius
+ def getName(self):
+ return "pyBluePrintEllipsesShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ if it.isEnd():
+ return
+ p_min = it.getObject().getPoint()
+ p_max = it.getObject().getPoint()
+ while it.isEnd() == 0:
+ p = it.getObject().getPoint()
+ if (p.x < p_min.x):
+ p_min.x = p.x
+ if (p.x > p_max.x):
+ p_max.x = p.x
+ if (p.y < p_min.y):
+ p_min.y = p.y
+ if (p.y > p_max.y):
+ p_max.y = p.y
+ it.increment()
+ stroke.Resample(32 * self.__turns)
+ sv_nb = stroke.strokeVerticesSize()
+ sv_nb = sv_nb // self.__turns
+ center = (p_min + p_max) / 2
+ radius = center - p_min
+ p_new = Vector([0, 0])
+#######################################################
+ R = self.__random_radius
+ C = self.__random_center
+ i = 0
+ it = stroke.strokeVerticesBegin()
+ for j in range(self.__turns):
+ prev_radius = radius
+ prev_center = center
+ radius = radius + Vector([randint(-R, R), randint(-R, R)])
+ center = center + Vector([randint(-C, C), randint(-C, C)])
+ while i < sv_nb and it.isEnd() == 0:
+ t = float(i) / float(sv_nb - 1)
+ r = prev_radius + (radius - prev_radius) * t
+ c = prev_center + (center - prev_center) * t
+ p_new.x = c.x + r.x * cos(2 * pi * t)
+ p_new.y = c.y + r.y * sin(2 * pi * t)
+ it.getObject().setPoint(p_new)
+ i = i + 1
+ it.increment()
+ i = 1
+ verticesToRemove = []
+ while it.isEnd() == 0:
+ verticesToRemove.append(it.getObject())
+ it.increment()
+ for sv in verticesToRemove:
+ stroke.RemoveVertex(sv)
+ stroke.UpdateLength()
+
+
+class pyBluePrintSquaresShader(StrokeShader):
+ def __init__(self, turns = 1, bb_len = 10, bb_rand = 0):
+ StrokeShader.__init__(self)
+ self.__turns = turns
+ self.__bb_len = bb_len
+ self.__bb_rand = bb_rand
+
+ def getName(self):
+ return "pyBluePrintSquaresShader"
+
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ if it.isEnd():
+ return
+ p_min = it.getObject().getPoint()
+ p_max = it.getObject().getPoint()
+ while it.isEnd() == 0:
+ p = it.getObject().getPoint()
+ if (p.x < p_min.x):
+ p_min.x = p.x
+ if (p.x > p_max.x):
+ p_max.x = p.x
+ if (p.y < p_min.y):
+ p_min.y = p.y
+ if (p.y > p_max.y):
+ p_max.y = p.y
+ it.increment()
+ stroke.Resample(32 * self.__turns)
+ sv_nb = stroke.strokeVerticesSize()
+#######################################################
+ sv_nb = sv_nb // self.__turns
+ first = sv_nb // 4
+ second = 2 * first
+ third = 3 * first
+ fourth = sv_nb
+ p_first = Vector([p_min.x - self.__bb_len, p_min.y])
+ p_first_end = Vector([p_max.x + self.__bb_len, p_min.y])
+ p_second = Vector([p_max.x, p_min.y - self.__bb_len])
+ p_second_end = Vector([p_max.x, p_max.y + self.__bb_len])
+ p_third = Vector([p_max.x + self.__bb_len, p_max.y])
+ p_third_end = Vector([p_min.x - self.__bb_len, p_max.y])
+ p_fourth = Vector([p_min.x, p_max.y + self.__bb_len])
+ p_fourth_end = Vector([p_min.x, p_min.y - self.__bb_len])
+#######################################################
+ R = self.__bb_rand
+ r = self.__bb_rand // 2
+ it = stroke.strokeVerticesBegin()
+ visible = 1
+ for j in range(self.__turns):
+ p_first = p_first + Vector([randint(-R, R), randint(-r, r)])
+ p_first_end = p_first_end + Vector([randint(-R, R), randint(-r, r)])
+ p_second = p_second + Vector([randint(-r, r), randint(-R, R)])
+ p_second_end = p_second_end + Vector([randint(-r, r), randint(-R, R)])
+ p_third = p_third + Vector([randint(-R, R), randint(-r, r)])
+ p_third_end = p_third_end + Vector([randint(-R, R), randint(-r, r)])
+ p_fourth = p_fourth + Vector([randint(-r, r), randint(-R, R)])
+ p_fourth_end = p_fourth_end + Vector([randint(-r, r), randint(-R, R)])
+ vec_first = p_first_end - p_first
+ vec_second = p_second_end - p_second
+ vec_third = p_third_end - p_third
+ vec_fourth = p_fourth_end - p_fourth
+ i = 0
+ while i < sv_nb and it.isEnd() == 0:
+ if i < first:
+ p_new = p_first + vec_first * float(i)/float(first - 1)
+ if i == first - 1:
+ visible = 0
+ elif i < second:
+ p_new = p_second + vec_second * float(i - first)/float(second - first - 1)
+ if i == second - 1:
+ visible = 0
+ elif i < third:
+ p_new = p_third + vec_third * float(i - second)/float(third - second - 1)
+ if i == third - 1:
+ visible = 0
+ else:
+ p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1)
+ if i == fourth - 1:
+ visible = 0
+ if it.getObject() == None:
+ i = i + 1
+ it.increment()
+ if visible == 0:
+ visible = 1
+ continue
+ it.getObject().setPoint(p_new)
+ it.getObject().attribute().setVisible(visible)
+ if visible == 0:
+ visible = 1
+ i = i + 1
+ it.increment()
+ verticesToRemove = []
+ while it.isEnd() == 0:
+ verticesToRemove.append(it.getObject())
+ it.increment()
+ for sv in verticesToRemove:
+ stroke.RemoveVertex(sv)
+ stroke.UpdateLength()
+
+
+class pyBluePrintDirectedSquaresShader(StrokeShader):
+ def __init__(self, turns = 1, bb_len = 10, mult = 1):
+ StrokeShader.__init__(self)
+ self.__mult = mult
+ self.__turns = turns
+ self.__bb_len = 1 + float(bb_len) / 100
+ def getName(self):
+ return "pyBluePrintDirectedSquaresShader"
+ def shade(self, stroke):
+ stroke.Resample(32 * self.__turns)
+ p_mean = Vector([0, 0])
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ p = it.getObject().getPoint()
+ p_mean = p_mean + p
+ it.increment()
+ sv_nb = stroke.strokeVerticesSize()
+ p_mean = p_mean / sv_nb
+ p_var_xx = 0
+ p_var_yy = 0
+ p_var_xy = 0
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ p = it.getObject().getPoint()
+ p_var_xx = p_var_xx + pow(p.x - p_mean.x, 2)
+ p_var_yy = p_var_yy + pow(p.y - p_mean.y, 2)
+ p_var_xy = p_var_xy + (p.x - p_mean.x) * (p.y - p_mean.y)
+ it.increment()
+ p_var_xx = p_var_xx / sv_nb
+ p_var_yy = p_var_yy / sv_nb
+ p_var_xy = p_var_xy / sv_nb
+## print(p_var_xx, p_var_yy, p_var_xy)
+ trace = p_var_xx + p_var_yy
+ det = p_var_xx * p_var_yy - p_var_xy * p_var_xy
+ sqrt_coeff = sqrt(trace * trace - 4 * det)
+ lambda1 = (trace + sqrt_coeff) / 2
+ lambda2 = (trace - sqrt_coeff) / 2
+## print(lambda1, lambda2)
+ theta = atan(2 * p_var_xy / (p_var_xx - p_var_yy)) / 2
+## print(theta)
+ if p_var_yy > p_var_xx:
+ e1 = Vector([cos(theta + pi / 2), sin(theta + pi / 2)]) * sqrt(lambda1) * self.__mult
+ e2 = Vector([cos(theta + pi), sin(theta + pi)]) * sqrt(lambda2) * self.__mult
+ else:
+ e1 = Vector([cos(theta), sin(theta)]) * sqrt(lambda1) * self.__mult
+ e2 = Vector([cos(theta + pi / 2), sin(theta + pi / 2)]) * sqrt(lambda2) * self.__mult
+#######################################################
+ sv_nb = sv_nb // self.__turns
+ first = sv_nb // 4
+ second = 2 * first
+ third = 3 * first
+ fourth = sv_nb
+ bb_len1 = self.__bb_len
+ bb_len2 = 1 + (bb_len1 - 1) * sqrt(lambda1 / lambda2)
+ p_first = p_mean - e1 - e2 * bb_len2
+ p_second = p_mean - e1 * bb_len1 + e2
+ p_third = p_mean + e1 + e2 * bb_len2
+ p_fourth = p_mean + e1 * bb_len1 - e2
+ vec_first = e2 * bb_len2 * 2
+ vec_second = e1 * bb_len1 * 2
+ vec_third = vec_first * -1
+ vec_fourth = vec_second * -1
+#######################################################
+ it = stroke.strokeVerticesBegin()
+ visible = 1
+ for j in range(self.__turns):
+ i = 0
+ while i < sv_nb:
+ if i < first:
+ p_new = p_first + vec_first * float(i)/float(first - 1)
+ if i == first - 1:
+ visible = 0
+ elif i < second:
+ p_new = p_second + vec_second * float(i - first)/float(second - first - 1)
+ if i == second - 1:
+ visible = 0
+ elif i < third:
+ p_new = p_third + vec_third * float(i - second)/float(third - second - 1)
+ if i == third - 1:
+ visible = 0
+ else:
+ p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1)
+ if i == fourth - 1:
+ visible = 0
+ it.getObject().setPoint(p_new)
+ it.getObject().attribute().setVisible(visible)
+ if visible == 0:
+ visible = 1
+ i = i + 1
+ it.increment()
+ verticesToRemove = []
+ while it.isEnd() == 0:
+ verticesToRemove.append(it.getObject())
+ it.increment()
+ for sv in verticesToRemove:
+ stroke.RemoveVertex(sv)
+ stroke.UpdateLength()
+
+class pyModulateAlphaShader(StrokeShader):
+ def __init__(self, min = 0, max = 1):
+ StrokeShader.__init__(self)
+ self.__min = min
+ self.__max = max
+ def getName(self):
+ return "pyModulateAlphaShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ alpha = it.getObject().attribute().getAlpha()
+ p = it.getObject().getPoint()
+ alpha = alpha * p.y / 400
+ if alpha < self.__min:
+ alpha = self.__min
+ elif alpha > self.__max:
+ alpha = self.__max
+ it.getObject().attribute().setAlpha(alpha)
+ it.increment()
+
+
+## various
+class pyDummyShader(StrokeShader):
+ def getName(self):
+ return "pyDummyShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ it_end = stroke.strokeVerticesEnd()
+ while it.isEnd() == 0:
+ toto = it.castToInterface0DIterator()
+ att = it.getObject().attribute()
+ att.setColor(0.3, 0.4, 0.4)
+ att.setThickness(0, 5)
+ it.increment()
+
+class pyDebugShader(StrokeShader):
+ def getName(self):
+ return "pyDebugShader"
+
+ def shade(self, stroke):
+ fe = GetSelectedFEdgeCF()
+ id1=fe.vertexA().getId()
+ id2=fe.vertexB().getId()
+ #print(id1.getFirst(), id1.getSecond())
+ #print(id2.getFirst(), id2.getSecond())
+ it = stroke.strokeVerticesBegin()
+ found = 0
+ foundfirst = 0
+ foundsecond = 0
+ while it.isEnd() == 0:
+ cp = it.getObject()
+ if((cp.A().getId() == id1) or (cp.B().getId() == id1)):
+ foundfirst = 1
+ if((cp.A().getId() == id2) or (cp.B().getId() == id2)):
+ foundsecond = 1
+ if((foundfirst != 0) and (foundsecond != 0)):
+ found = 1
+ break
+ it.increment()
+ if(found != 0):
+ print("The selected Stroke id is: ", stroke.getId().getFirst(), stroke.getId().getSecond())
diff --git a/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py
new file mode 100755
index 00000000000..163c891fa90
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py
@@ -0,0 +1,48 @@
+#
+# Filename : sketchy_multiple_parameterization.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Builds sketchy strokes whose topology relies on a
+# parameterization that covers the complete lines (visible+invisible)
+# whereas only the visible portions are actually drawn
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+## 0: don't restrict to selection
+Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(3,0))
+shaders_list = [
+ SamplingShader(2),
+ SpatialNoiseShader(15, 120, 2, 1, 1),
+ IncreasingThicknessShader(5, 30),
+ SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1),
+ IncreasingColorShader(0,0.2,0,1,0.2,0.7,0.2,1),
+ TextureAssignerShader(6),
+ pyHLRShader()
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/sketchy_topology_broken.py b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py
new file mode 100755
index 00000000000..9ec0cffcfec
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py
@@ -0,0 +1,89 @@
+#
+# Filename : sketchy_topology_broken.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The topology of the strokes is, first, built
+# independantly from the 3D topology of objects,
+# and, second, so as to chain several times the same ViewEdge.
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+## Backbone stretcher that leaves cusps intact to avoid cracks
+class pyBackboneStretcherNoCuspShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def getName(self):
+ return "pyBackboneStretcherNoCuspShader"
+ def shade(self, stroke):
+ it0 = stroke.strokeVerticesBegin()
+ it1 = StrokeVertexIterator(it0)
+ it1.increment()
+ itn = stroke.strokeVerticesEnd()
+ itn.decrement()
+ itn_1 = StrokeVertexIterator(itn)
+ itn_1.decrement()
+ v0 = it0.getObject()
+ v1 = it1.getObject()
+ if((v0.getNature() & Nature.CUSP == 0) and (v1.getNature() & Nature.CUSP == 0)):
+ p0 = v0.getPoint()
+ p1 = v1.getPoint()
+ d1 = p0-p1
+ d1.normalize()
+ newFirst = p0+d1*float(self._l)
+ v0.setPoint(newFirst)
+ else:
+ print("got a v0 cusp")
+ vn_1 = itn_1.getObject()
+ vn = itn.getObject()
+ if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)):
+ pn = vn.getPoint()
+ pn_1 = vn_1.getPoint()
+ dn = pn-pn_1
+ dn.normalize()
+ newLast = pn+dn*float(self._l)
+ vn.setPoint(newLast)
+ else:
+ print("got a vn cusp")
+
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+## Chain 3 times each ViewEdge indpendantly from the
+## initial objects topology
+Operators.bidirectionalChain(pySketchyChainingIterator(3))
+shaders_list = [
+ SamplingShader(4),
+ SpatialNoiseShader(6, 120, 2, 1, 1),
+ IncreasingThicknessShader(4, 10),
+ SmoothingShader(100, 0.1, 0, 0.2, 0, 0, 0, 1),
+ pyBackboneStretcherNoCuspShader(20),
+ #ConstantColorShader(0.0,0.0,0.0)
+ IncreasingColorShader(0.2,0.2,0.2,1,0.5,0.5,0.5,1),
+ #IncreasingColorShader(1,0,0,1,0,1,0,1),
+ TextureAssignerShader(4)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py
new file mode 100755
index 00000000000..85e11af38b9
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py
@@ -0,0 +1,49 @@
+#
+# Filename : sketchy_topology_preserved.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The topology of the strokes is built
+# so as to chain several times the same ViewEdge.
+# The topology of the objects is preserved
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from PredicatesU1D import *
+from shaders import *
+
+upred = QuantitativeInvisibilityUP1D(0)
+Operators.select(upred)
+Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(3,1))
+shaders_list = [
+ SamplingShader(4),
+ SpatialNoiseShader(20, 220, 2, 1, 1),
+ IncreasingThicknessShader(4, 8),
+ SmoothingShader(300, 0.05, 0, 0.2, 0, 0, 0, 0.5),
+ ConstantColorShader(0.6,0.2,0.0),
+ TextureAssignerShader(4),
+ ]
+
+Operators.create(TrueUP1D(), shaders_list)
+
diff --git a/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py
new file mode 100755
index 00000000000..52cc10a9c60
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py
@@ -0,0 +1,41 @@
+#
+# Filename : split_at_highest_2d_curvature.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the visible lines (chaining follows same nature lines)
+# (most basic style module)
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesU0D import *
+from PredicatesU1D import *
+from Functions0D import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+func = pyInverseCurvature2DAngleF0D()
+Operators.recursiveSplit(func, pyParameterUP0D(0.4,0.6), NotUP1D(pyHigherLengthUP1D(100)), 2)
+shaders_list = [ConstantThicknessShader(10), IncreasingColorShader(1,0,0,1,0,1,0,1), TextureAssignerShader(3)]
+Operators.create(TrueUP1D(), shaders_list)
+
diff --git a/release/scripts/freestyle/style_modules/split_at_tvertices.py b/release/scripts/freestyle/style_modules/split_at_tvertices.py
new file mode 100755
index 00000000000..78f781dd290
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/split_at_tvertices.py
@@ -0,0 +1,42 @@
+#
+# Filename : split_at_tvertices.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws strokes that starts and stops at Tvertices (visible or not)
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesU1D import *
+from PredicatesU0D import *
+from Functions0D import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+start = pyVertexNatureUP0D(Nature.T_VERTEX)
+## use the same predicate to decide where to start and where to stop
+## the strokes:
+Operators.sequentialSplit(start, start, 10)
+shaders_list = [ConstantThicknessShader(5), IncreasingColorShader(1,0,0,1,0,1,0,1), TextureAssignerShader(3)]
+Operators.create(TrueUP1D(), shaders_list)
+
diff --git a/release/scripts/freestyle/style_modules/stroke_texture.py b/release/scripts/freestyle/style_modules/stroke_texture.py
new file mode 100755
index 00000000000..afebbe30a90
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/stroke_texture.py
@@ -0,0 +1,43 @@
+#
+# Filename : stroke_texture.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws textured strokes (illustrate the StrokeTextureShader shader)
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+from ChainingIterators import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(3),
+ BezierCurveShader(4),
+ StrokeTextureShader("washbrushAlpha.bmp", Stroke.DRY_MEDIUM, 1),
+ ConstantThicknessShader(40),
+ ConstantColorShader(0,0,0,1),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/suggestive.py b/release/scripts/freestyle/style_modules/suggestive.py
new file mode 100755
index 00000000000..39d8515ed6c
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/suggestive.py
@@ -0,0 +1,43 @@
+#
+# Filename : suggestive.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the suggestive contours.
+# ***** The suggestive contours must be enabled
+# in the options dialog *****
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from PredicatesU1D import *
+from shaders import *
+
+upred = AndUP1D(pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR), QuantitativeInvisibilityUP1D(0))
+Operators.select(upred)
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ IncreasingThicknessShader(1, 3),
+ ConstantColorShader(0.2,0.2,0.2, 1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py
new file mode 100755
index 00000000000..21f6c7bdf35
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py
@@ -0,0 +1,62 @@
+#
+# Filename : thickness_fof_depth_discontinuity.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Assigns to strokes a thickness that depends on the depth discontinuity
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+class pyDepthDiscontinuityThicknessShader(StrokeShader):
+ def __init__(self, min, max):
+ StrokeShader.__init__(self)
+ self.__min = float(min)
+ self.__max = float(max)
+ self.__func = ZDiscontinuityF0D()
+ def getName(self):
+ return "pyDepthDiscontinuityThicknessShader"
+ def shade(self, stroke):
+ it = stroke.strokeVerticesBegin()
+ z_min=0.0
+ z_max=1.0
+ a = (self.__max - self.__min)/(z_max-z_min)
+ b = (self.__min*z_max-self.__max*z_min)/(z_max-z_min)
+ it = stroke.strokeVerticesBegin()
+ while it.isEnd() == 0:
+ z = self.__func(it.castToInterface0DIterator())
+ thickness = a*z+b
+ it.getObject().attribute().setThickness(thickness, thickness)
+ it.increment()
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(1),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.0,0.0,0.0),
+ pyDepthDiscontinuityThicknessShader(0.8, 6)
+ ]
+Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/tipremover.py b/release/scripts/freestyle/style_modules/tipremover.py
new file mode 100755
index 00000000000..3e495b7d332
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/tipremover.py
@@ -0,0 +1,42 @@
+#
+# Filename : tipremover.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Removes strokes extremities
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+
+from freestyle_init import *
+from logical_operators import *
+from ChainingIterators import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(5),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0,0,0),
+ TipRemoverShader(20)
+ ]
+Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/tvertex_remover.py b/release/scripts/freestyle/style_modules/tvertex_remover.py
new file mode 100755
index 00000000000..c328f4c98ec
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/tvertex_remover.py
@@ -0,0 +1,42 @@
+#
+# Filename : tvertex_remover.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Removes TVertices
+#
+#############################################################################
+#
+# Copyright (C) : Please refer to the COPYRIGHT file distributed
+# with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#############################################################################
+
+
+from freestyle_init import *
+from logical_operators import *
+from PredicatesB1D import *
+from shaders import *
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ IncreasingThicknessShader(3, 5),
+ ConstantColorShader(0.2,0.2,0.2, 1),
+ SamplingShader(10.0),
+ pyTVertexRemoverShader()
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/uniformpruning_zsort.py b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py
new file mode 100755
index 00000000000..50a2f6423fd
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py
@@ -0,0 +1,40 @@
+from freestyle_init import *
+from logical_operators import *
+from PredicatesU1D import *
+from PredicatesU0D import *
+from PredicatesB1D import *
+from Functions0D import *
+from Functions1D import *
+from shaders import *
+
+class pyDensityUP1D(UnaryPredicate1D):
+ def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._wsize = wsize
+ self._threshold = threshold
+ self._integration = integration
+ self._func = DensityF1D(self._wsize, self._integration, sampling)
+
+ def getName(self):
+ return "pyDensityUP1D"
+
+ def __call__(self, inter):
+ d = self._func(inter)
+ print("For Chain ", inter.getId().getFirst(), inter.getId().getSecond(), "density is ", d)
+ if(d < self._threshold):
+ return 1
+ return 0
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectionalChain(ChainSilhouetteIterator())
+#Operators.sequentialSplit(pyVertexNatureUP0D(Nature.VIEW_VERTEX), 2)
+Operators.sort(pyZBP1D())
+shaders_list = [
+ StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0),
+ ConstantThicknessShader(3),
+ SamplingShader(5.0),
+ ConstantColorShader(0,0,0,1)
+ ]
+Operators.create(pyDensityUP1D(2,0.05, IntegrationType.MEAN,4), shaders_list)
+#Operators.create(pyDensityFunctorUP1D(8,0.03, pyGetInverseProjectedZF1D(), 0,1, IntegrationType.MEAN), shaders_list)
+
diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py
index ecbbe34dbb4..0ecb0d46c5f 100644
--- a/release/scripts/startup/bl_operators/__init__.py
+++ b/release/scripts/startup/bl_operators/__init__.py
@@ -27,6 +27,7 @@ _modules = (
"anim",
"clip",
"console",
+ "freestyle",
"image",
"mesh",
"node",
diff --git a/release/scripts/startup/bl_operators/freestyle.py b/release/scripts/startup/bl_operators/freestyle.py
new file mode 100644
index 00000000000..49e6249cacd
--- /dev/null
+++ b/release/scripts/startup/bl_operators/freestyle.py
@@ -0,0 +1,133 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+import bpy
+
+from bpy.props import (EnumProperty, StringProperty)
+
+
+class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
+ '''Fill the Range Min/Max entries by the min/max distance between selected mesh objects and the source object (either a user-specified object or the active camera)'''
+ bl_idname = "scene.freestyle_fill_range_by_selection"
+ bl_label = "Fill Range by Selection"
+
+ type = EnumProperty(name="Type", description="Type of the modifier to work on",
+ items=[("COLOR", "Color", "Color modifier type"),
+ ("ALPHA", "Alpha", "Alpha modifier type"),
+ ("THICKNESS", "Thickness", "Thickness modifier type")])
+ name = StringProperty(name="Name", description="Name of the modifier to work on")
+
+ def execute(self, context):
+ rl = context.scene.render.layers.active
+ lineset = rl.freestyle_settings.linesets.active
+ linestyle = lineset.linestyle
+ # Find the modifier to work on
+ if self.type == 'COLOR':
+ m = linestyle.color_modifiers[self.name]
+ elif self.type == 'ALPHA':
+ m = linestyle.alpha_modifiers[self.name]
+ else:
+ m = linestyle.thickness_modifiers[self.name]
+ # Find the source object
+ if m.type == 'DISTANCE_FROM_CAMERA':
+ source = context.scene.camera
+ elif m.type == 'DISTANCE_FROM_OBJECT':
+ if m.target is None:
+ self.report({'ERROR'}, "Target object not specified")
+ return {'CANCELLED'}
+ source = m.target
+ else:
+ self.report({'ERROR'}, "Unexpected modifier type: " + m.type)
+ return {'CANCELLED'}
+ # Find selected mesh objects
+ selection = [ob for ob in context.scene.objects if ob.select and ob.type == 'MESH' and ob.name != source.name]
+ if len(selection) > 0:
+ # Compute the min/max distance between selected mesh objects and the source
+ min_dist = float('inf')
+ max_dist = -min_dist
+ for ob in selection:
+ for vert in ob.data.vertices:
+ dist = (ob.matrix_world * vert.co - source.location).length
+ min_dist = min(dist, min_dist)
+ max_dist = max(dist, max_dist)
+ # Fill the Range Min/Max entries with the computed distances
+ m.range_min = min_dist
+ m.range_max = max_dist
+ return {'FINISHED'}
+
+
+class SCENE_OT_freestyle_add_edge_marks_to_keying_set(bpy.types.Operator):
+ '''Add the data paths to the Freestyle Edge Mark property of selected edges to the active keying set'''
+ bl_idname = "scene.freestyle_add_edge_marks_to_keying_set"
+ bl_label = "Add Edge Marks to Keying Set"
+ bl_options = {'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return (ob and ob.type == 'MESH')
+
+ def execute(self, context):
+ # active keying set
+ scene = context.scene
+ ks = scene.keying_sets.active
+ if ks is None:
+ ks = scene.keying_sets.new(idname="FreestyleEdgeMarkKeyingSet", name="Freestyle Edge Mark Keying Set")
+ ks.bl_description = ""
+ # add data paths to the keying set
+ ob = context.active_object
+ ob_mode = ob.mode
+ mesh = ob.data
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+ for i, edge in enumerate(mesh.edges):
+ if not edge.hide and edge.select:
+ path = 'edges[%d].use_freestyle_edge_mark' % i
+ ks.paths.add(mesh, path, index=0)
+ bpy.ops.object.mode_set(mode=ob_mode, toggle=False)
+ return {'FINISHED'}
+
+
+class SCENE_OT_freestyle_add_face_marks_to_keying_set(bpy.types.Operator):
+ '''Add the data paths to the Freestyle Face Mark property of selected polygons to the active keying set'''
+ bl_idname = "scene.freestyle_add_face_marks_to_keying_set"
+ bl_label = "Add Face Marks to Keying Set"
+ bl_options = {'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return (ob and ob.type == 'MESH')
+
+ def execute(self, context):
+ # active keying set
+ scene = context.scene
+ ks = scene.keying_sets.active
+ if ks is None:
+ ks = scene.keying_sets.new(idname="FreestyleFaceMarkKeyingSet", name="Freestyle Face Mark Keying Set")
+ ks.bl_description = ""
+ # add data paths to the keying set
+ ob = context.active_object
+ ob_mode = ob.mode
+ mesh = ob.data
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+ for i, polygon in enumerate(mesh.polygons):
+ if not polygon.hide and polygon.select:
+ path = 'polygons[%d].use_freestyle_face_mark' % i
+ ks.paths.add(mesh, path, index=0)
+ bpy.ops.object.mode_set(mode=ob_mode, toggle=False)
+ return {'FINISHED'}
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 5f21f78a375..6125540d491 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -316,10 +316,31 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
layout.prop(lay, "name")
+class DATA_PT_customdata(MeshButtonsPanel, Panel):
+ bl_label = "Geometry Data"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ # me = context.mesh
+ col = layout.column()
+ # sticky has no UI access since 2.49 - we may remove
+ '''
+ row = col.row(align=True)
+ row.operator("mesh.customdata_create_sticky")
+ row.operator("mesh.customdata_clear_sticky", icon='X')
+ '''
+ col.operator("mesh.customdata_clear_mask", icon='X')
+ col.operator("mesh.customdata_clear_skin", icon='X')
+
+
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.Mesh
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index dfc75168d2b..8eecbf4b604 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -763,6 +763,7 @@ class MATERIAL_PT_options(MaterialButtonsPanel, Panel):
col.prop(mat, "use_vertex_color_paint")
col.prop(mat, "use_vertex_color_light")
col.prop(mat, "use_object_color")
+ col.prop(mat, "use_uv_project")
if simple_material(base_mat):
col.prop(mat, "pass_index")
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index b777fcddcf2..47689b9be73 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -63,10 +63,10 @@ class RENDER_PT_render(RenderButtonsPanel, Panel):
rd = context.scene.render
- row = layout.row()
- row.operator("render.render", text="Image", icon='RENDER_STILL')
+ row = layout.row(align=True)
+ row.operator("render.render", text="Render", icon='RENDER_STILL')
row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True
- row.operator("render.play_rendered_anim", text="Play", icon='RENDER_ANIMATION')
+ row.operator("render.play_rendered_anim", text="Play", icon='PLAY')
layout.prop(rd, "display_mode", text="Display")
@@ -124,11 +124,12 @@ class RENDER_PT_layers(RenderButtonsPanel, Panel):
col.prop(rl, "use_solid")
col.prop(rl, "use_halo")
col.prop(rl, "use_ztransp")
+ col.prop(rl, "use_sky")
col = split.column()
- col.prop(rl, "use_sky")
col.prop(rl, "use_edge_enhance")
col.prop(rl, "use_strand")
+ col.prop(rl, "use_freestyle")
layout.separator()
@@ -175,6 +176,555 @@ class RENDER_PT_layers(RenderButtonsPanel, Panel):
row.prop(rl, "exclude_refraction", text="")
+class RENDER_MT_lineset_specials(Menu):
+ bl_label = "Lineset Specials"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator("scene.freestyle_lineset_copy", icon='COPYDOWN')
+ layout.operator("scene.freestyle_lineset_paste", icon='PASTEDOWN')
+
+
+class RENDER_PT_freestyle(RenderButtonsPanel, Panel):
+ bl_label = "Freestyle"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ rd = context.scene.render
+ if rd.engine not in cls.COMPAT_ENGINES:
+ return False
+ rl = rd.layers.active
+ return rl and rl.use_freestyle
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+ rl = rd.layers.active
+ freestyle = rl.freestyle_settings
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(freestyle, "raycasting_algorithm", text="Raycasting Algorithm")
+ col.prop(freestyle, "mode", text="Control Mode")
+
+ col.label(text="Edge Detection Options:")
+ col.prop(freestyle, "use_smoothness")
+ col.prop(freestyle, "crease_angle")
+ if freestyle.mode == "SCRIPT":
+ col.prop(freestyle, "use_material_boundaries")
+ col.prop(freestyle, "use_ridges_and_valleys")
+ col.prop(freestyle, "use_suggestive_contours")
+ col.prop(freestyle, "use_advanced_options")
+ if freestyle.use_advanced_options:
+ col.prop(freestyle, "sphere_radius")
+ col.prop(freestyle, "kr_derivative_epsilon")
+
+ if freestyle.mode == "EDITOR":
+
+ lineset = freestyle.linesets.active
+
+ col.label(text="Line Sets:")
+ row = col.row()
+ rows = 2
+ if lineset:
+ rows = 5
+ row.template_list(freestyle, "linesets", freestyle.linesets, "active_index", rows=rows)
+
+ sub = row.column()
+ subsub = sub.column(align=True)
+ subsub.operator("scene.freestyle_lineset_add", icon='ZOOMIN', text="")
+ subsub.operator("scene.freestyle_lineset_remove", icon='ZOOMOUT', text="")
+ subsub.menu("RENDER_MT_lineset_specials", icon='DOWNARROW_HLT', text="")
+ if lineset:
+ sub.separator()
+ subsub = sub.column(align=True)
+ subsub.operator("scene.freestyle_lineset_move", icon='TRIA_UP', text="").direction = 'UP'
+ subsub.operator("scene.freestyle_lineset_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
+ else: # freestyle.mode == "SCRIPT"
+
+ col.separator()
+ col.operator("scene.freestyle_module_add")
+
+ for i, module in enumerate(freestyle.modules):
+ box = layout.box()
+ box.context_pointer_set("freestyle_module", module)
+ row = box.row(align=True)
+ row.prop(module, "use", text="")
+ row.prop(module, "module_path", text="")
+ row.operator("scene.freestyle_module_remove", icon='X', text="")
+ row.operator("scene.freestyle_module_move", icon='TRIA_UP', text="").direction = 'UP'
+ row.operator("scene.freestyle_module_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
+
+class RENDER_PT_freestyle_lineset(RenderButtonsPanel, Panel):
+ bl_label = "Freestyle: Line Set"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ rd = context.scene.render
+ if rd.engine not in cls.COMPAT_ENGINES:
+ return False
+ rl = rd.layers.active
+ if rl and rl.use_freestyle:
+ freestyle = rl.freestyle_settings
+ return freestyle.mode == "EDITOR" and freestyle.linesets.active
+ return False
+
+ def draw_edge_type_buttons(self, box, lineset, edge_type):
+ # property names
+ select_edge_type = "select_" + edge_type
+ exclude_edge_type = "exclude_" + edge_type
+ # draw edge type buttons
+ row = box.row(align=True)
+ row.prop(lineset, select_edge_type)
+ sub = row.column()
+ sub.prop(lineset, exclude_edge_type, text="")
+ sub.enabled = getattr(lineset, select_edge_type)
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+ rl = rd.layers.active
+ freestyle = rl.freestyle_settings
+ lineset = freestyle.linesets.active
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(lineset, "name")
+
+ col.prop(lineset, "select_by_visibility")
+ if lineset.select_by_visibility:
+ sub = col.row(align=True)
+ sub.prop(lineset, "visibility", expand=True)
+ if lineset.visibility == "RANGE":
+ sub = col.row(align=True)
+ sub.prop(lineset, "qi_start")
+ sub.prop(lineset, "qi_end")
+ col.separator() # XXX
+
+ col.prop(lineset, "select_by_edge_types")
+ if lineset.select_by_edge_types:
+ row = col.row()
+ row.prop(lineset, "edge_type_negation", expand=True)
+ row = col.row()
+ row.prop(lineset, "edge_type_combination", expand=True)
+
+ row = col.row()
+ sub = row.column()
+ self.draw_edge_type_buttons(sub, lineset, "silhouette")
+ self.draw_edge_type_buttons(sub, lineset, "border")
+ self.draw_edge_type_buttons(sub, lineset, "contour")
+ self.draw_edge_type_buttons(sub, lineset, "suggestive_contour")
+ self.draw_edge_type_buttons(sub, lineset, "ridge_valley")
+ sub = row.column()
+ self.draw_edge_type_buttons(sub, lineset, "crease")
+ self.draw_edge_type_buttons(sub, lineset, "edge_mark")
+ self.draw_edge_type_buttons(sub, lineset, "external_contour")
+ self.draw_edge_type_buttons(sub, lineset, "material_boundary")
+ col.separator() # XXX
+
+ col.prop(lineset, "select_by_face_marks")
+ if lineset.select_by_face_marks:
+ row = col.row()
+ row.prop(lineset, "face_mark_negation", expand=True)
+ row = col.row()
+ row.prop(lineset, "face_mark_condition", expand=True)
+ col.separator() # XXX
+
+ col.prop(lineset, "select_by_group")
+ if lineset.select_by_group:
+ col.prop(lineset, "group")
+ row = col.row()
+ row.prop(lineset, "group_negation", expand=True)
+ col.separator() # XXX
+
+ col.prop(lineset, "select_by_image_border")
+
+
+class RENDER_PT_freestyle_linestyle(RenderButtonsPanel, Panel):
+ bl_label = "Freestyle: Line Style"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ rd = context.scene.render
+ if rd.engine not in cls.COMPAT_ENGINES:
+ return False
+ rl = rd.layers.active
+ if rl and rl.use_freestyle:
+ freestyle = rl.freestyle_settings
+ return freestyle.mode == "EDITOR" and freestyle.linesets.active
+ return False
+
+ def draw_modifier_box_header(self, box, modifier):
+ row = box.row()
+ row.context_pointer_set("modifier", modifier)
+ if modifier.expanded:
+ icon = "TRIA_DOWN"
+ else:
+ icon = "TRIA_RIGHT"
+ row.prop(modifier, "expanded", text="", icon=icon, emboss=False)
+ row.label(text=modifier.rna_type.name)
+ row.prop(modifier, "name", text="")
+ row.prop(modifier, "use", text="")
+ row.operator("scene.freestyle_modifier_copy", icon='NONE', text="Copy")
+ sub = row.row(align=True)
+ sub.operator("scene.freestyle_modifier_move", icon='TRIA_UP', text="").direction = 'UP'
+ sub.operator("scene.freestyle_modifier_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+ row.operator("scene.freestyle_modifier_remove", icon='X', text="")
+
+ def draw_modifier_common(self, box, modifier):
+ row = box.row()
+ row.prop(modifier, "blend", text="")
+ row.prop(modifier, "influence")
+
+ def draw_modifier_color_ramp_common(self, box, modifier, has_range):
+ box.template_color_ramp(modifier, "color_ramp", expand=True)
+ if has_range:
+ row = box.row(align=True)
+ row.prop(modifier, "range_min")
+ row.prop(modifier, "range_max")
+
+ def draw_modifier_curve_common(self, box, modifier, has_range, has_value):
+ row = box.row()
+ row.prop(modifier, "mapping", text="")
+ sub = row.column()
+ sub.prop(modifier, "invert")
+ if modifier.mapping == "CURVE":
+ sub.enabled = False
+ box.template_curve_mapping(modifier, "curve")
+ if has_range:
+ row = box.row(align=True)
+ row.prop(modifier, "range_min")
+ row.prop(modifier, "range_max")
+ if has_value:
+ row = box.row(align=True)
+ row.prop(modifier, "value_min")
+ row.prop(modifier, "value_max")
+
+ def draw_color_modifier(self, context, modifier):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ self.draw_modifier_box_header(col.box(), modifier)
+ if modifier.expanded:
+ box = col.box()
+ self.draw_modifier_common(box, modifier)
+
+ if modifier.type == "ALONG_STROKE":
+ self.draw_modifier_color_ramp_common(box, modifier, False)
+
+ elif modifier.type == "DISTANCE_FROM_OBJECT":
+ box.prop(modifier, "target")
+ self.draw_modifier_color_ramp_common(box, modifier, True)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'COLOR'
+ prop.name = modifier.name
+
+ elif modifier.type == "DISTANCE_FROM_CAMERA":
+ self.draw_modifier_color_ramp_common(box, modifier, True)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'COLOR'
+ prop.name = modifier.name
+
+ elif modifier.type == "MATERIAL":
+ row = box.row()
+ row.prop(modifier, "material_attr", text="")
+ sub = row.column()
+ sub.prop(modifier, "use_ramp")
+ if modifier.material_attr in ["DIFF", "SPEC"]:
+ sub.enabled = True
+ show_ramp = modifier.use_ramp
+ else:
+ sub.enabled = False
+ show_ramp = True
+ if show_ramp:
+ self.draw_modifier_color_ramp_common(box, modifier, False)
+
+ def draw_alpha_modifier(self, context, modifier):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ self.draw_modifier_box_header(col.box(), modifier)
+ if modifier.expanded:
+ box = col.box()
+ self.draw_modifier_common(box, modifier)
+
+ if modifier.type == "ALONG_STROKE":
+ self.draw_modifier_curve_common(box, modifier, False, False)
+
+ elif modifier.type == "DISTANCE_FROM_OBJECT":
+ box.prop(modifier, "target")
+ self.draw_modifier_curve_common(box, modifier, True, False)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'ALPHA'
+ prop.name = modifier.name
+
+ elif modifier.type == "DISTANCE_FROM_CAMERA":
+ self.draw_modifier_curve_common(box, modifier, True, False)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'ALPHA'
+ prop.name = modifier.name
+
+ elif modifier.type == "MATERIAL":
+ box.prop(modifier, "material_attr", text="")
+ self.draw_modifier_curve_common(box, modifier, False, False)
+
+ def draw_thickness_modifier(self, context, modifier):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ self.draw_modifier_box_header(col.box(), modifier)
+ if modifier.expanded:
+ box = col.box()
+ self.draw_modifier_common(box, modifier)
+
+ if modifier.type == "ALONG_STROKE":
+ self.draw_modifier_curve_common(box, modifier, False, True)
+
+ elif modifier.type == "DISTANCE_FROM_OBJECT":
+ box.prop(modifier, "target")
+ self.draw_modifier_curve_common(box, modifier, True, True)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'THICKNESS'
+ prop.name = modifier.name
+
+ elif modifier.type == "DISTANCE_FROM_CAMERA":
+ self.draw_modifier_curve_common(box, modifier, True, True)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'THICKNESS'
+ prop.name = modifier.name
+
+ elif modifier.type == "MATERIAL":
+ box.prop(modifier, "material_attr", text="")
+ self.draw_modifier_curve_common(box, modifier, False, True)
+
+ elif modifier.type == "CALLIGRAPHY":
+ col = box.column()
+ col.prop(modifier, "orientation")
+ col.prop(modifier, "min_thickness")
+ col.prop(modifier, "max_thickness")
+
+ def draw_geometry_modifier(self, context, modifier):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ self.draw_modifier_box_header(col.box(), modifier)
+ if modifier.expanded:
+ box = col.box()
+
+ if modifier.type == "SAMPLING":
+ box.prop(modifier, "sampling")
+
+ elif modifier.type == "BEZIER_CURVE":
+ box.prop(modifier, "error")
+
+ elif modifier.type == "SINUS_DISPLACEMENT":
+ box.prop(modifier, "wavelength")
+ box.prop(modifier, "amplitude")
+ box.prop(modifier, "phase")
+
+ elif modifier.type == "SPATIAL_NOISE":
+ box.prop(modifier, "amplitude")
+ box.prop(modifier, "scale")
+ box.prop(modifier, "octaves")
+ sub = box.row()
+ sub.prop(modifier, "smooth")
+ sub.prop(modifier, "pure_random")
+
+ elif modifier.type == "PERLIN_NOISE_1D":
+ box.prop(modifier, "frequency")
+ box.prop(modifier, "amplitude")
+ box.prop(modifier, "octaves")
+ box.prop(modifier, "angle")
+ box.prop(modifier, "seed")
+
+ elif modifier.type == "PERLIN_NOISE_2D":
+ box.prop(modifier, "frequency")
+ box.prop(modifier, "amplitude")
+ box.prop(modifier, "octaves")
+ box.prop(modifier, "angle")
+ box.prop(modifier, "seed")
+
+ elif modifier.type == "BACKBONE_STRETCHER":
+ box.prop(modifier, "backbone_length")
+
+ elif modifier.type == "TIP_REMOVER":
+ box.prop(modifier, "tip_length")
+
+ elif modifier.type == "POLYGONIZATION":
+ box.prop(modifier, "error")
+
+ elif modifier.type == "GUIDING_LINES":
+ box.prop(modifier, "offset")
+
+ elif modifier.type == "BLUEPRINT":
+ row = box.row()
+ row.prop(modifier, "shape", expand=True)
+ box.prop(modifier, "rounds")
+ if modifier.shape in ["CIRCLES", "ELLIPSES"]:
+ box.prop(modifier, "random_radius")
+ box.prop(modifier, "random_center")
+ elif modifier.shape == "SQUARES":
+ box.prop(modifier, "backbone_length")
+ box.prop(modifier, "random_backbone")
+
+ elif modifier.type == "2D_OFFSET":
+ row = box.row(align=True)
+ row.prop(modifier, "start")
+ row.prop(modifier, "end")
+ row = box.row(align=True)
+ row.prop(modifier, "x")
+ row.prop(modifier, "y")
+
+ elif modifier.type == "2D_TRANSFORM":
+ box.prop(modifier, "pivot")
+ if modifier.pivot == "PARAM":
+ box.prop(modifier, "pivot_u")
+ elif modifier.pivot == "ABSOLUTE":
+ row = box.row(align=True)
+ row.prop(modifier, "pivot_x")
+ row.prop(modifier, "pivot_y")
+ row = box.row(align=True)
+ row.prop(modifier, "scale_x")
+ row.prop(modifier, "scale_y")
+ box.prop(modifier, "angle")
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+ rl = rd.layers.active
+ lineset = rl.freestyle_settings.linesets.active
+ linestyle = lineset.linestyle
+
+ layout.template_ID(lineset, "linestyle", new="scene.freestyle_linestyle_new")
+ row = layout.row(align=True)
+ row.prop(linestyle, "panel", expand=True)
+ if linestyle.panel == "STROKES":
+ # Chaining
+ col = layout.column()
+ col.prop(linestyle, "use_chaining", text="Chaining:")
+ sub = col.column()
+ sub.enabled = linestyle.use_chaining
+ sub.prop(linestyle, "chaining", text="")
+ if linestyle.chaining == "PLAIN":
+ sub.prop(linestyle, "same_object")
+ elif linestyle.chaining == "SKETCHY":
+ subsub = sub.row()
+ subsub.prop(linestyle, "same_object")
+ subsub.prop(linestyle, "rounds")
+ # Splitting
+ col = layout.column()
+ col.label(text="Splitting:")
+ row = col.row()
+ row.prop(linestyle, "material_boundary")
+ row = col.row()
+ sub = row.column()
+ sub.prop(linestyle, "use_min_angle", text="Min 2D Angle")
+ subsub = sub.split()
+ subsub.prop(linestyle, "min_angle", text="")
+ subsub.enabled = linestyle.use_min_angle
+ sub = row.column()
+ sub.prop(linestyle, "use_max_angle", text="Max 2D Angle")
+ subsub = sub.split()
+ subsub.prop(linestyle, "max_angle", text="")
+ subsub.enabled = linestyle.use_max_angle
+ col.prop(linestyle, "use_split_length", text="2D Length")
+ row = col.row()
+ row.prop(linestyle, "split_length", text="")
+ row.enabled = linestyle.use_split_length
+ # Selection
+ col = layout.column()
+ col.label(text="Selection:")
+ sub = col.row()
+ subcol = sub.column()
+ subcol.prop(linestyle, "use_min_length", text="Min 2D Length")
+ subsub = subcol.split()
+ subsub.prop(linestyle, "min_length", text="")
+ subsub.enabled = linestyle.use_min_length
+ subcol = sub.column()
+ subcol.prop(linestyle, "use_max_length", text="Max 2D Length")
+ subsub = subcol.split()
+ subsub.prop(linestyle, "max_length", text="")
+ subsub.enabled = linestyle.use_max_length
+ # Caps
+ col = layout.column()
+ col.label(text="Caps:")
+ row = col.row(align=True)
+ row.prop(linestyle, "caps", expand=True)
+ col = layout.column()
+ col.prop(linestyle, "use_dashed_line")
+ split = col.split()
+ split.enabled = linestyle.use_dashed_line
+ sub = split.column()
+ sub.label(text="Dash")
+ sub.prop(linestyle, "dash1", text="")
+ sub = split.column()
+ sub.label(text="Gap")
+ sub.prop(linestyle, "gap1", text="")
+ sub = split.column()
+ sub.label(text="Dash")
+ sub.prop(linestyle, "dash2", text="")
+ sub = split.column()
+ sub.label(text="Gap")
+ sub.prop(linestyle, "gap2", text="")
+ sub = split.column()
+ sub.label(text="Dash")
+ sub.prop(linestyle, "dash3", text="")
+ sub = split.column()
+ sub.label(text="Gap")
+ sub.prop(linestyle, "gap3", text="")
+ elif linestyle.panel == "COLOR":
+ col = layout.column()
+ col.label(text="Base Color:")
+ col.prop(linestyle, "color", text="")
+ col = layout.column()
+ col.label(text="Modifiers:")
+ col.operator_menu_enum("scene.freestyle_color_modifier_add", "type", text="Add Modifier")
+ for modifier in linestyle.color_modifiers:
+ self.draw_color_modifier(context, modifier)
+ elif linestyle.panel == "ALPHA":
+ col = layout.column()
+ col.label(text="Base Transparency:")
+ col.prop(linestyle, "alpha")
+ col = layout.column()
+ col.label(text="Modifiers:")
+ col.operator_menu_enum("scene.freestyle_alpha_modifier_add", "type", text="Add Modifier")
+ for modifier in linestyle.alpha_modifiers:
+ self.draw_alpha_modifier(context, modifier)
+ elif linestyle.panel == "THICKNESS":
+ col = layout.column()
+ col.label(text="Base Thickness:")
+ col.prop(linestyle, "thickness")
+ col = layout.column()
+ row = col.row()
+ row.prop(linestyle, "thickness_position", expand=True)
+ row = col.row()
+ row.prop(linestyle, "thickness_ratio")
+ row.enabled = linestyle.thickness_position == "RELATIVE"
+ col = layout.column()
+ col.label(text="Modifiers:")
+ col.operator_menu_enum("scene.freestyle_thickness_modifier_add", "type", text="Add Modifier")
+ for modifier in linestyle.thickness_modifiers:
+ self.draw_thickness_modifier(context, modifier)
+ elif linestyle.panel == "GEOMETRY":
+ col = layout.column()
+ col.label(text="Modifiers:")
+ col.operator_menu_enum("scene.freestyle_geometry_modifier_add", "type", text="Add Modifier")
+ for modifier in linestyle.geometry_modifiers:
+ self.draw_geometry_modifier(context, modifier)
+ elif linestyle.panel == "MISC":
+ pass
+
+
class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
bl_label = "Dimensions"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -399,6 +949,20 @@ class RENDER_PT_post_processing(RenderButtonsPanel, Panel):
sub.prop(rd, "edge_threshold", text="Threshold", slider=True)
sub.prop(rd, "edge_color", text="")
+ layout.separator()
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rd, "use_freestyle", text="Freestyle")
+ sub = col.column()
+ sub.label(text="Line Thickness:")
+ sub.active = rd.use_freestyle
+ sub.row().prop(rd, "line_thickness_mode", expand=True)
+ subrow = sub.row()
+ subrow.active = (rd.line_thickness_mode == "ABSOLUTE")
+ subrow.prop(rd, "unit_line_thickness")
+
class RENDER_PT_stamp(RenderButtonsPanel, Panel):
bl_label = "Stamp"
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 39c892930f4..4a418698e26 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -83,11 +83,11 @@ class SEQUENCER_HT_header(Header):
layout.separator()
layout.operator("sequencer.refresh_all")
- elif st.view_type == 'SEQUENCER_PREVIEW':
- layout.separator()
- layout.operator("sequencer.refresh_all")
- layout.prop(st, "display_channel", text="Channel")
else:
+ if st.view_type == 'SEQUENCER_PREVIEW':
+ layout.separator()
+ layout.operator("sequencer.refresh_all")
+
layout.prop(st, "display_channel", text="Channel")
ed = context.scene.sequence_editor
@@ -101,12 +101,12 @@ class SEQUENCER_HT_header(Header):
row = layout.row()
row.prop(st, "overlay_type", text="")
- row = layout.row(align=True)
- props = row.operator("render.opengl", text="", icon='RENDER_STILL')
- props.sequencer = True
- props = row.operator("render.opengl", text="", icon='RENDER_ANIMATION')
- props.animation = True
- props.sequencer = True
+ row = layout.row(align=True)
+ props = row.operator("render.opengl", text="", icon='RENDER_STILL')
+ props.sequencer = True
+ props = row.operator("render.opengl", text="", icon='RENDER_ANIMATION')
+ props.animation = True
+ props.sequencer = True
layout.template_running_jobs()
@@ -130,12 +130,19 @@ class SEQUENCER_MT_view(Menu):
st = context.space_data
+ if st.view_type in {'PREVIEW'}:
+ # Specifying the REGION_PREVIEW context is needed in preview-only
+ # mode, else the lookup for the shortcut will fail in
+ # wm_keymap_item_find_props() (see #32595).
+ layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.operator("sequencer.properties", icon='MENU_PANEL')
+ layout.operator_context = 'INVOKE_DEFAULT'
layout.separator()
if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
layout.operator("sequencer.view_all", text="View all Sequences")
+ layout.operator("sequencer.view_selected")
if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.operator("sequencer.view_all_preview", text="Fit preview in window")
@@ -145,19 +152,21 @@ class SEQUENCER_MT_view(Menu):
# # XXX, invokes in the header view
# layout.operator("sequencer.view_ghost_border", text="Overlay Border")
- layout.operator("sequencer.view_selected")
-
- layout.prop(st, "show_seconds")
+ if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ layout.prop(st, "show_seconds")
+ layout.prop(st, "show_frame_indicator")
- layout.prop(st, "show_frame_indicator")
- if st.display_mode == 'IMAGE':
- layout.prop(st, "show_safe_margin")
- if st.display_mode == 'WAVEFORM':
- layout.prop(st, "show_separate_color")
+ if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ if st.display_mode == 'IMAGE':
+ layout.prop(st, "show_safe_margin")
+ elif st.display_mode == 'WAVEFORM':
+ layout.prop(st, "show_separate_color")
layout.separator()
- layout.prop(st, "use_marker_sync")
- layout.separator()
+
+ if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ layout.prop(st, "use_marker_sync")
+ layout.separator()
layout.operator("screen.area_dupli")
layout.operator("screen.screen_full_area")
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 5db103466a9..92255275966 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -583,7 +583,7 @@ class VIEW3D_MT_select_edit_mesh(Menu):
if context.scene.tool_settings.mesh_select_mode[2] == False:
layout.operator("mesh.select_non_manifold", text="Non Manifold")
layout.operator("mesh.select_loose_verts", text="Loose Verts/Edges")
- layout.operator("mesh.select_similar", text="Similar")
+ layout.operator_menu_enum("mesh.select_similar", "type", text="Similar")
layout.separator()
@@ -722,6 +722,7 @@ class VIEW3D_MT_select_edit_armature(Menu):
props.extend = True
props.direction = 'CHILD'
+ layout.operator_menu_enum("armature.select_similar", "type", text="Similar")
layout.operator("object.select_pattern", text="Select Pattern...")
@@ -1826,6 +1827,11 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.separator()
+ layout.operator("mesh.mark_freestyle_edge").clear = False
+ layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
+
+ layout.separator()
+
layout.operator("mesh.edge_rotate", text="Rotate Edge CW").direction = 'CW'
layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").direction = 'CCW'
@@ -1866,6 +1872,11 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.separator()
+ layout.operator("mesh.mark_freestyle_face").clear = False
+ layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True
+
+ layout.separator()
+
layout.operator("mesh.quads_convert_to_tris")
layout.operator("mesh.tris_convert_to_quads")
@@ -2469,6 +2480,8 @@ class VIEW3D_PT_view3d_meshdisplay(Panel):
col.prop(mesh, "show_edge_bevel_weight", text="Bevel Weights")
col.prop(mesh, "show_edge_seams", text="Seams")
col.prop(mesh, "show_edge_sharp", text="Sharp")
+ col.prop(mesh, "show_freestyle_edge_marks", text="Freestyle Edge Marks")
+ col.prop(mesh, "show_freestyle_face_marks", text="Freestyle Face Marks")
col.separator()
col.label(text="Normals:")
diff --git a/release/text/readme.html b/release/text/readme.html
index 512ba32bac0..40ea9035835 100644
--- a/release/text/readme.html
+++ b/release/text/readme.html
@@ -20,7 +20,7 @@
<p class="body">For more information, visit <a href="http://www.blender.org">blender.org</a>.</p>
<p><br></p>
<p class="header"><b>2.64</b></p>
-<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.64. This release is the fifth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. <a href="http://www.blender.org/development/release-logs/blender-263/">More information about this release</a>.</p>
+<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.64. This release is the fifth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. <a href="http://www.blender.org/development/release-logs/blender-264/">More information about this release</a>.</p>
<p><br></p>
<p class="header"><b>Bugs</b></p>
<p class="body">Although Blender 2.64 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
diff --git a/release/windows/contrib/vfapi/vfapi-plugin.c b/release/windows/contrib/vfapi/vfapi-plugin.c
index 81547b8bb1a..8e1bfb0f247 100644
--- a/release/windows/contrib/vfapi/vfapi-plugin.c
+++ b/release/windows/contrib/vfapi/vfapi-plugin.c
@@ -157,7 +157,8 @@ static int my_gets(SOCKET sock, char * line, int maxlen)
line++;
*line = 0;
break;
- } else {
+ }
+ else {
line++;
maxlen--;
}
@@ -251,15 +252,20 @@ HRESULT __stdcall VF_OpenFileFunc_Blen(
if (strcmp(key, "width") == 0) {
rval->width = atoi(val);
- } else if (strcmp(key, "height") == 0) {
+ }
+ else if (strcmp(key, "height") == 0) {
rval->height = atoi(val);
- } else if (strcmp(key, "start") == 0) {
+ }
+ else if (strcmp(key, "start") == 0) {
rval->start = atoi(val);
- } else if (strcmp(key, "end") == 0) {
+ }
+ else if (strcmp(key, "end") == 0) {
rval->end = atoi(val);
- } else if (strcmp(key, "rate") == 0) {
+ }
+ else if (strcmp(key, "rate") == 0) {
rval->rate = atoi(val);
- } else if (strcmp(key, "ratescale") == 0) {
+ }
+ else if (strcmp(key, "ratescale") == 0) {
rval->ratescale = atoi(val);
}
}
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 92785804b01..611a920b7f1 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -51,6 +51,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_key_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lamp_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lattice_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_linestyle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_listBase.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_material_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_mesh_types.h
@@ -106,6 +107,7 @@ add_subdirectory(nodes)
add_subdirectory(modifiers)
add_subdirectory(makesdna)
add_subdirectory(makesrna)
+ADD_SUBDIRECTORY(freestyle)
if(WITH_COMPOSITOR)
add_subdirectory(opencl) # later on this may be used more generally
diff --git a/source/blender/SConscript b/source/blender/SConscript
index e1f81f9aaba..8fb160ba09a 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -9,6 +9,7 @@ SConscript(['avi/SConscript',
'blenloader/SConscript',
'gpu/SConscript',
'editors/SConscript',
+ 'freestyle/SConscript',
'imbuf/SConscript',
'makesdna/SConscript',
'render/SConscript',
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 02b66993c0a..1900efa2dbc 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -174,7 +174,7 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len)
blf_font_ensure_ascii_table(font);
- while (str[i] && i < len) {
+ while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
if (c == BLI_UTF8_ERR)
@@ -430,8 +430,8 @@ void blf_font_width_and_height(FontBLF *font, const char *str, float *width, flo
}
blf_font_boundbox(font, str, &box);
- *width = (BLI_RCT_SIZE_X(&box) * xa);
- *height = (BLI_RCT_SIZE_Y(&box) * ya);
+ *width = (BLI_rctf_size_x(&box) * xa);
+ *height = (BLI_rctf_size_y(&box) * ya);
}
float blf_font_width(FontBLF *font, const char *str)
@@ -445,7 +445,7 @@ float blf_font_width(FontBLF *font, const char *str)
xa = 1.0f;
blf_font_boundbox(font, str, &box);
- return BLI_RCT_SIZE_X(&box) * xa;
+ return BLI_rctf_size_x(&box) * xa;
}
float blf_font_height(FontBLF *font, const char *str)
@@ -459,7 +459,7 @@ float blf_font_height(FontBLF *font, const char *str)
ya = 1.0f;
blf_font_boundbox(font, str, &box);
- return BLI_RCT_SIZE_Y(&box) * ya;
+ return BLI_rctf_size_y(&box) * ya;
}
float blf_font_fixed_width(FontBLF *font)
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 63225651e5b..91ecded88be 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -415,7 +415,7 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
g->uv[1][1] = ((float)(g->yoff + g->height)) / ((float)gc->p2_height);
/* update the x offset for the next glyph. */
- gc->x_offs += (int)(BLI_RCT_SIZE_X(&g->box) + gc->pad);
+ gc->x_offs += (int)(BLI_rctf_size_x(&g->box) + gc->pad);
gc->rem_glyphs--;
g->build_tex = 1;
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index fed82d7e93d..db1139c9c7b 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 263
-#define BLENDER_SUBVERSION 19
+#define BLENDER_SUBVERSION 21
/* 262 was the last editmesh release but its has compatibility code for bmesh data,
* so set the minversion to 2.61 */
@@ -53,7 +53,7 @@ extern "C" {
/* can be left blank, otherwise a,b,c... etc with no quotes */
#define BLENDER_VERSION_CHAR a
/* alpha/beta/rc/release, docs use this */
-#define BLENDER_VERSION_CYCLE beta
+#define BLENDER_VERSION_CYCLE rc
extern char versionstr[]; /* from blender.c */
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index cd67059ea8c..728f88b3c16 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -61,7 +61,7 @@ void curvemapping_set_black_white(struct CurveMapping *cumap, con
#define CURVEMAP_SLOPE_NEGATIVE 0
#define CURVEMAP_SLOPE_POSITIVE 1
-void curvemap_reset(struct CurveMap *cuma, struct rctf *clipr, int preset, int slope);
+void curvemap_reset(struct CurveMap *cuma, const struct rctf *clipr, int preset, int slope);
void curvemap_remove(struct CurveMap *cuma, const short flag);
void curvemap_remove_point(struct CurveMap *cuma, struct CurveMapPoint *cmp);
struct CurveMapPoint *curvemap_insert(struct CurveMap *cuma, float x, float y);
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index a845ac10c9d..e6161cebf54 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -93,6 +93,8 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float
/* ** Nurbs ** */
+int BKE_nurbList_index_get_co(struct ListBase *editnurb, const int index, float r_co[3]);
+
int BKE_nurbList_verts_count(struct ListBase *nurb);
int BKE_nurbList_verts_count_without_handles(struct ListBase *nurb);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 67cdee9fa07..3e9803a908b 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -52,10 +52,6 @@ int group_is_animated(struct Object *parent, struct Group *group);
void group_tag_recalc(struct Group *group);
void group_handle_recalc_and_update(struct Scene *scene, struct Object *parent, struct Group *group);
-#if 0 /* UNUSED */
-struct Object *group_get_member_with_action(struct Group *group, struct bAction *act);
-void group_relink_nla_objects(struct Object *ob);
-#endif
#endif
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index 1ad451b0937..01baf8feb2a 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -47,13 +47,13 @@ struct Mesh;
extern "C" {
#endif
-void BKE_key_free(struct Key *sc);
-void free_key_nolib(struct Key *key);
-struct Key *add_key(struct ID *id);
+void BKE_key_free(struct Key *sc);
+void BKE_key_free_nolib(struct Key *key);
+struct Key *BKE_key_add(struct ID *id);
struct Key *BKE_key_copy(struct Key *key);
-struct Key *copy_key_nolib(struct Key *key);
-void BKE_key_make_local(struct Key *key);
-void sort_keys(struct Key *key);
+struct Key *BKE_key_copy_nolib(struct Key *key);
+void BKE_key_make_local(struct Key *key);
+void BKE_key_sort(struct Key *key);
void key_curve_position_weights(float t, float data[4], int type);
void key_curve_tangent_weights(float t, float data[4], int type);
@@ -61,27 +61,29 @@ void key_curve_normal_weights(float t, float data[4], int type);
float *do_ob_key(struct Scene *scene, struct Object *ob);
-struct Key *ob_get_key(struct Object *ob);
-struct KeyBlock *add_keyblock(struct Key *key, const char *name);
-struct KeyBlock *add_keyblock_ctime(struct Key *key, const char *name, const short do_force);
-struct KeyBlock *ob_get_keyblock(struct Object *ob);
-struct KeyBlock *ob_get_reference_keyblock(struct Object *ob);
-struct KeyBlock *key_get_keyblock(struct Key *key, int index);
-struct KeyBlock *key_get_named_keyblock(struct Key *key, const char name[]);
-char *key_get_curValue_rnaPath(struct Key *key, struct KeyBlock *kb);
+struct Key *BKE_key_from_object(struct Object *ob);
+struct KeyBlock *BKE_keyblock_from_object(struct Object *ob);
+struct KeyBlock *BKE_keyblock_from_object_reference(struct Object *ob);
+
+struct KeyBlock *BKE_keyblock_add(struct Key *key, const char *name);
+struct KeyBlock *BKE_keyblock_add_ctime(struct Key *key, const char *name, const short do_force);
+struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index);
+struct KeyBlock *BKE_keyblock_find_name(struct Key *key, const char name[]);
+void BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock *kb_src);
+char *BKE_keyblock_curval_rnapath_get(struct Key *key, struct KeyBlock *kb);
// needed for the GE
-void do_rel_key(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, const int mode);
+void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, const int mode);
/* conversion functions */
-void key_to_mesh(struct KeyBlock *kb, struct Mesh *me);
-void mesh_to_key(struct Mesh *me, struct KeyBlock *kb);
-void key_to_latt(struct KeyBlock *kb, struct Lattice *lt);
-void latt_to_key(struct Lattice *lt, struct KeyBlock *kb);
-void key_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb);
-void curve_to_key(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb);
-float (*key_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3];
-void vertcos_to_key(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]);
-void offset_to_key(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]);
+void BKE_key_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me);
+void BKE_key_convert_from_mesh(struct Mesh *me, struct KeyBlock *kb);
+void BKE_key_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt);
+void BKE_key_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb);
+void BKE_key_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb);
+void BKE_key_convert_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb);
+float (*BKE_key_convert_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3];
+void BKE_key_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]);
+void BKE_key_convert_from_offset(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]);
/* key.c */
extern int slurph_opt;
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
new file mode 100644
index 00000000000..bb763f4e6b3
--- /dev/null
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -0,0 +1,74 @@
+/* BKE_linestyle.h
+ *
+ *
+ * $Id: BKE_particle.h 29187 2010-06-03 15:39:02Z kjym3 $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_LINESTYLE_H
+#define BKE_LINESTYLE_H
+
+#include "DNA_linestyle_types.h"
+
+#define LS_MODIFIER_TYPE_COLOR 1
+#define LS_MODIFIER_TYPE_ALPHA 2
+#define LS_MODIFIER_TYPE_THICKNESS 3
+#define LS_MODIFIER_TYPE_GEOMETRY 4
+
+struct Main;
+struct Object;
+
+FreestyleLineStyle *FRS_new_linestyle(char *name, struct Main *main);
+void FRS_free_linestyle(FreestyleLineStyle *linestyle);
+FreestyleLineStyle *FRS_copy_linestyle(FreestyleLineStyle *linestyle);
+
+LineStyleModifier *FRS_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, int type);
+LineStyleModifier *FRS_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, int type);
+LineStyleModifier *FRS_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, int type);
+LineStyleModifier *FRS_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, int type);
+
+LineStyleModifier *FRS_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+LineStyleModifier *FRS_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+LineStyleModifier *FRS_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+LineStyleModifier *FRS_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+
+void FRS_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+void FRS_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+void FRS_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+void FRS_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+
+void FRS_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void FRS_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void FRS_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void FRS_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+
+void FRS_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase);
+char *FRS_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp);
+
+void FRS_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob);
+
+#endif
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 3074e1c0e63..ad5541a5a2f 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -87,6 +87,7 @@ typedef struct Main {
ListBase gpencil;
ListBase movieclip;
ListBase mask;
+ ListBase linestyle;
char id_tag_update[256];
} Main;
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 31642dad60d..269d96d5c38 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -93,6 +93,7 @@ void BKE_object_to_mat3(struct Object *ob, float mat[][3]);
void BKE_object_to_mat4(struct Object *ob, float mat[][4]);
void BKE_object_apply_mat4(struct Object *ob, float mat[][4], const short use_compat, const short use_parent);
+int BKE_object_pose_context_check(struct Object *ob);
struct Object *BKE_object_pose_armature_get(struct Object *ob);
void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h
index a29dc0e7be4..e0eb8c04b60 100644
--- a/source/blender/blenkernel/BKE_property.h
+++ b/source/blender/blenkernel/BKE_property.h
@@ -35,19 +35,18 @@ struct bProperty;
struct ListBase;
struct Object;
-void free_property(struct bProperty *prop);
-void free_properties(struct ListBase *lb);
-struct bProperty *copy_property(struct bProperty *prop);
-void copy_properties(struct ListBase *lbn, struct ListBase *lbo);
-void init_property(struct bProperty *prop);
-struct bProperty *new_property(int type);
-void unique_property(struct bProperty *first, struct bProperty *prop, int force);
-struct bProperty *get_ob_property(struct Object *ob, const char *name);
-void set_ob_property(struct Object *ob, struct bProperty *propc);
-int compare_property(struct bProperty *prop, const char *str);
-void set_property(struct bProperty *prop, const char *str);
-void add_property(struct bProperty *prop, const char *str);
-void set_property_valstr(struct bProperty *prop, char *str);
-void cp_property(struct bProperty *prop1, struct bProperty *prop2);
+void BKE_bproperty_free(struct bProperty *prop);
+void BKE_bproperty_free_list(struct ListBase *lb);
+struct bProperty *BKE_bproperty_copy(struct bProperty *prop);
+void BKE_bproperty_copy_list(struct ListBase *lbn, struct ListBase *lbo);
+void BKE_bproperty_init(struct bProperty *prop);
+struct bProperty *BKE_bproperty_new(int type);
+void BKE_bproperty_unique(struct bProperty *first, struct bProperty *prop, int force);
+struct bProperty *BKE_bproperty_object_get(struct Object *ob, const char *name);
+void BKE_bproperty_object_set(struct Object *ob, struct bProperty *propc);
+// int BKE_bproperty_cmp(struct bProperty *prop, const char *str);
+void BKE_bproperty_set(struct bProperty *prop, const char *str);
+void BKE_bproperty_add(struct bProperty *prop, const char *str);
+void BKE_bproperty_set_valstr(struct bProperty *prop, char *str);
#endif
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index 22b44511195..d598a26fdf9 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -74,5 +74,7 @@ void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_u
void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up);
void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up);
+const char *sca_state_name_get(Object *ob, short bit);
+
#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index efdb80433c6..9a24a3ca4e0 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
../blenfont
../blenlib
../blenloader
+ ../freestyle
../gpu
../ikplugin
../imbuf
@@ -102,8 +103,8 @@ set(SRC
intern/lamp.c
intern/lattice.c
intern/library.c
- intern/mask_evaluate.c
- intern/mask_rasterize.c
+ intern/linestyle.c
+ intern/mask_evaluate.c intern/mask_rasterize.c
intern/mask.c
intern/material.c
intern/mball.c
@@ -194,6 +195,7 @@ set(SRC
BKE_lamp.h
BKE_lattice.h
BKE_library.h
+ BKE_linestyle.h
BKE_mask.h
BKE_main.h
BKE_material.h
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index d1a35b122e8..8a656c735f6 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -12,7 +12,7 @@ incs = '. #/intern/guardedalloc #/intern/memutil'
incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager'
incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna'
incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers'
-incs += ' #/intern/iksolver/extern ../blenloader'
+incs += ' #/intern/iksolver/extern ../blenloader ../freestyle'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/opennl/extern #/intern/bsp/extern'
incs += ' ../gpu #/extern/glew/include'
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 387d4775ad4..82ac0736b07 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -1397,7 +1397,7 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss)
return eCCGError_None;
}
-#define VERT_getNo(e, lvl) _vert_getNo(e, lvl, vertDataSize, normalDataOffset)
+#define VERT_getNo(e, lvl) _vert_getNo(v, lvl, vertDataSize, normalDataOffset)
#define EDGE_getNo(e, lvl, x) _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset)
#define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
@@ -1491,7 +1491,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
/* XXX can I reduce the number of normalisations here? */
for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) {
CCGVert *v = (CCGVert *) effectedV[ptrIdx];
- float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset);
+ float length, *no = VERT_getNo(v, lvl);
NormZero(no);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 07d14513bd0..5e13fe78a43 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -808,7 +808,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob,
if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL;
if (build_shapekey_layers && me->key && (kb = BLI_findlink(&me->key->block, ob->shapenr - 1))) {
- key_to_mesh(kb, me);
+ BKE_key_convert_to_mesh(kb, me);
}
if (mti->type == eModifierTypeType_OnlyDeform) {
@@ -878,7 +878,7 @@ static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free
* by a more flexible customdata system, but not simple */
if (!em) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
- KeyBlock *kb = key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest);
+ KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest);
if (kb->data)
return kb->data;
@@ -1276,7 +1276,7 @@ static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape
}
if (!kb) {
- kb = add_keyblock(me->key, layer->name);
+ kb = BKE_keyblock_add(me->key, layer->name);
kb->uid = layer->uid;
}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 06bf5211abb..925658b84f4 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1214,475 +1214,3 @@ void what_does_obaction(Object *ob, Object *workob, bPose *pose, bAction *act, c
}
}
-/* ********** NLA with non-poses works with ipo channels ********** */
-
-#if 0 // XXX OLD ANIMATION SYSTEM (TO BE REMOVED)
-
-/* ************************ Blending with NLA *************** */
-
-static void blend_pose_strides(bPose *dst, bPose *src, float srcweight, short mode)
-{
- float dstweight;
-
- switch (mode) {
- case ACTSTRIPMODE_BLEND:
- dstweight = 1.0F - srcweight;
- break;
- case ACTSTRIPMODE_ADD:
- dstweight = 1.0F;
- break;
- default:
- dstweight = 1.0F;
- }
-
- interp_v3_v3v3(dst->stride_offset, dst->stride_offset, src->stride_offset, srcweight);
-}
-
-
-/*
- * bone matching diagram, strips A and B
- *
- * .------------------------.
- * | A |
- * '------------------------'
- * . . b2
- * . .-------------v----------.
- * . | B . |
- * . '------------------------'
- * . . .
- * . . .
- * offset: . 0 . A-B . A-b2+B
- * . . .
- *
- * */
-
-
-static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src, float srcweight, short mode)
-{
- /* matching offset bones */
- /* take dst offset, and put src on on that location */
-
- if (strip->offs_bone[0] == 0)
- return;
-
- /* are we also blending with matching bones? */
- if (strip->prev && strip->start >= strip->prev->start) {
- bPoseChannel *dpchan = BKE_pose_channel_find_name(dst, strip->offs_bone);
- if (dpchan) {
- bPoseChannel *spchan = BKE_pose_channel_find_name(src, strip->offs_bone);
- if (spchan) {
- float vec[3];
-
- /* dst->ctime has the internal strip->prev action time */
- /* map this time to nla time */
-
- float ctime = get_actionstrip_frame(strip, src->ctime, 1);
-
- if (ctime > strip->prev->end) {
- bActionChannel *achan;
-
- /* add src to dest, minus the position of src on strip->prev->end */
-
- ctime = get_actionstrip_frame(strip, strip->prev->end, 0);
-
- achan = get_action_channel(strip->act, strip->offs_bone);
- if (achan && achan->ipo) {
- bPoseChannel pchan;
- /* Evaluates and sets the internal ipo value */
- calc_ipo(achan->ipo, ctime);
- /* This call also sets the pchan flags */
- execute_action_ipo(achan, &pchan);
-
- /* store offset that moves src to location of pchan */
- sub_v3_v3v3(vec, dpchan->loc, pchan.loc);
-
- mul_mat3_m4_v3(dpchan->bone->arm_mat, vec);
- }
- }
- else {
- /* store offset that moves src to location of dst */
-
- sub_v3_v3v3(vec, dpchan->loc, spchan->loc);
- mul_mat3_m4_v3(dpchan->bone->arm_mat, vec);
- }
-
- /* if blending, we only add with factor scrweight */
- mul_v3_fl(vec, srcweight);
-
- add_v3_v3(dst->cyclic_offset, vec);
- }
- }
- }
-
- add_v3_v3(dst->cyclic_offset, src->cyclic_offset);
-}
-
-/* added "sizecorr" here, to allow armatures to be scaled and still have striding.
- * Only works for uniform scaling. In general I'd advise against scaling armatures ever though! (ton)
- */
-static float stridechannel_frame(Object *ob, float sizecorr, bActionStrip *strip, Path *path, float pathdist, float *stride_offset)
-{
- bAction *act = strip->act;
- const char *name = strip->stridechannel;
- bActionChannel *achan = get_action_channel(act, name);
- int stride_axis = strip->stride_axis;
-
- if (achan && achan->ipo) {
- IpoCurve *icu = NULL;
- float minx = 0.0f, maxx = 0.0f, miny = 0.0f, maxy = 0.0f;
- int foundvert = 0;
-
- if (stride_axis == 0) stride_axis = AC_LOC_X;
- else if (stride_axis == 1) stride_axis = AC_LOC_Y;
- else stride_axis = AC_LOC_Z;
-
- /* calculate the min/max */
- for (icu = achan->ipo->curve.first; icu; icu = icu->next) {
- if (icu->adrcode == stride_axis) {
- if (icu->totvert > 1) {
- foundvert = 1;
- minx = icu->bezt[0].vec[1][0];
- maxx = icu->bezt[icu->totvert - 1].vec[1][0];
-
- miny = icu->bezt[0].vec[1][1];
- maxy = icu->bezt[icu->totvert - 1].vec[1][1];
- }
- break;
- }
- }
-
- if (foundvert && miny != maxy) {
- float stridelen = sizecorr * fabs(maxy - miny), striptime;
- float actiondist, pdist, pdistNewNormalized, offs;
- float vec1[4], vec2[4], dir[3];
-
- /* internal cycling, actoffs is in frames */
- offs = stridelen * strip->actoffs / (maxx - minx);
-
- /* amount path moves object */
- pdist = (float)fmod(pathdist + offs, stridelen);
- striptime = pdist / stridelen;
-
- /* amount stride bone moves */
- actiondist = sizecorr * eval_icu(icu, minx + striptime * (maxx - minx)) - miny;
-
- pdist = fabs(actiondist) - pdist;
- pdistNewNormalized = (pathdist + pdist) / path->totdist;
-
- /* now we need to go pdist further (or less) on cu path */
- where_on_path(ob, (pathdist) / path->totdist, vec1, dir); /* vec needs size 4 */
- if (pdistNewNormalized <= 1) {
- /* search for correction in positive path-direction */
- where_on_path(ob, pdistNewNormalized, vec2, dir); /* vec needs size 4 */
- sub_v3_v3v3(stride_offset, vec2, vec1);
- }
- else {
- /* we reached the end of the path, search backwards instead */
- where_on_path(ob, (pathdist - pdist) / path->totdist, vec2, dir); /* vec needs size 4 */
- sub_v3_v3v3(stride_offset, vec1, vec2);
- }
- mul_mat3_m4_v3(ob->obmat, stride_offset);
- return striptime;
- }
- }
- return 0.0f;
-}
-
-static void cyclic_offs_bone(Object *ob, bPose *pose, bActionStrip *strip, float time)
-{
- /* only called when strip has cyclic, so >= 1.0f works... */
- if (time >= 1.0f) {
- bActionChannel *achan = get_action_channel(strip->act, strip->offs_bone);
-
- if (achan && achan->ipo) {
- IpoCurve *icu = NULL;
- Bone *bone;
- float min[3] = {0.0f, 0.0f, 0.0f}, max[3] = {0.0f, 0.0f, 0.0f};
- int index = 0, foundvert = 0;
-
- /* calculate the min/max */
- for (icu = achan->ipo->curve.first; icu; icu = icu->next) {
- if (icu->totvert > 1) {
-
- if (icu->adrcode == AC_LOC_X)
- index = 0;
- else if (icu->adrcode == AC_LOC_Y)
- index = 1;
- else if (icu->adrcode == AC_LOC_Z)
- index = 2;
- else
- continue;
-
- foundvert = 1;
- min[index] = icu->bezt[0].vec[1][1];
- max[index] = icu->bezt[icu->totvert - 1].vec[1][1];
- }
- }
- if (foundvert) {
- /* bring it into armature space */
- sub_v3_v3v3(min, max, min);
- bone = BKE_armature_find_bone_name(ob->data, strip->offs_bone); /* weak */
- if (bone) {
- mul_mat3_m4_v3(bone->arm_mat, min);
-
- /* dominant motion, cyclic_offset was cleared in BKE_pose_rest */
- if (strip->flag & (ACTSTRIP_CYCLIC_USEX | ACTSTRIP_CYCLIC_USEY | ACTSTRIP_CYCLIC_USEZ)) {
- if (strip->flag & ACTSTRIP_CYCLIC_USEX) pose->cyclic_offset[0] = time * min[0];
- if (strip->flag & ACTSTRIP_CYCLIC_USEY) pose->cyclic_offset[1] = time * min[1];
- if (strip->flag & ACTSTRIP_CYCLIC_USEZ) pose->cyclic_offset[2] = time * min[2];
- }
- else {
- if (fabsf(min[0]) >= fabsf(min[1]) && fabsf(min[0]) >= fabsf(min[2]))
- pose->cyclic_offset[0] = time * min[0];
- else if (fabsf(min[1]) >= fabsf(min[0]) && fabsf(min[1]) >= fabsf(min[2]))
- pose->cyclic_offset[1] = time * min[1];
- else
- pose->cyclic_offset[2] = time * min[2];
- }
- }
- }
- }
- }
-}
-
-/* simple case for now; only the curve path with constraint value > 0.5 */
-/* blending we might do later... */
-static Object *get_parent_path(Object *ob)
-{
- bConstraint *con;
-
- if (ob->parent && ob->parent->type == OB_CURVE)
- return ob->parent;
-
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
- if (con->enforce > 0.5f) {
- bFollowPathConstraint *data = con->data;
- return data->tar;
- }
- }
- }
- return NULL;
-}
-
-/* ************** do the action ************ */
-
-/* ----- nla, etc. --------- */
-
-static void do_nla(Scene *scene, Object *ob, int blocktype)
-{
- bPose *tpose = NULL;
- Key *key = NULL;
- ListBase tchanbase = {NULL, NULL}, chanbase = {NULL, NULL};
- bActionStrip *strip, *striplast = NULL, *stripfirst = NULL;
- float striptime, frametime, length, actlength;
- float blendfac, stripframe;
- float scene_cfra = BKE_scene_frame_get(scene);
- int doit, dostride;
-
- if (blocktype == ID_AR) {
- BKE_pose_copy_data(&tpose, ob->pose, 1);
- BKE_pose_rest(ob->pose); // potentially destroying current not-keyed pose
- }
- else {
- key = ob_get_key(ob);
- }
-
- /* check on extend to left or right, when no strip is hit by 'cfra' */
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- /* escape loop on a hit */
- if (scene_cfra >= strip->start && scene_cfra <= strip->end + 0.1f) /* note 0.1 comes back below */
- break;
- if (scene_cfra < strip->start) {
- if (stripfirst == NULL)
- stripfirst = strip;
- else if (stripfirst->start > strip->start)
- stripfirst = strip;
- }
- else if (scene_cfra > strip->end) {
- if (striplast == NULL)
- striplast = strip;
- else if (striplast->end < strip->end)
- striplast = strip;
- }
- }
- if (strip == NULL) { /* extend */
- if (striplast)
- scene_cfra = striplast->end;
- else if (stripfirst)
- scene_cfra = stripfirst->start;
- }
-
- /* and now go over all strips */
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- doit = dostride = 0;
-
- if (strip->act && !(strip->flag & ACTSTRIP_MUTE)) { /* so theres an action */
-
- /* Determine if the current frame is within the strip's range */
- length = strip->end - strip->start;
- actlength = strip->actend - strip->actstart;
- striptime = (scene_cfra - strip->start) / length;
- stripframe = (scene_cfra - strip->start);
-
- if (striptime >= 0.0) {
-
- if (blocktype == ID_AR)
- BKE_pose_rest(tpose);
-
- /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */
- if (striptime < 1.0f + 0.1f / length) {
-
- /* Handle path */
- if ((strip->flag & ACTSTRIP_USESTRIDE) && (blocktype == ID_AR) && (ob->ipoflag & OB_DISABLE_PATH) == 0) {
- Object *parent = get_parent_path(ob);
-
- if (parent) {
- Curve *cu = parent->data;
- float ctime, pdist;
-
- if (cu->flag & CU_PATH) {
- /* Ensure we have a valid path */
- if (cu->path == NULL || cu->path->data == NULL) makeDispListCurveTypes(scene, parent, 0);
- if (cu->path) {
-
- /* Find the position on the path */
- ctime = bsystem_time(scene, ob, scene_cfra, 0.0);
-
- if (calc_ipo_spec(cu->ipo, CU_SPEED, &ctime) == 0) {
- /* correct for actions not starting on zero */
- ctime = (ctime - strip->actstart) / cu->pathlen;
- CLAMP(ctime, 0.0, 1.0);
- }
- pdist = ctime * cu->path->totdist;
-
- if (tpose && strip->stridechannel[0]) {
- striptime = stridechannel_frame(parent, ob->size[0], strip, cu->path, pdist, tpose->stride_offset);
- }
- else {
- if (strip->stridelen) {
- striptime = pdist / strip->stridelen;
- striptime = (float)fmod(striptime + strip->actoffs, 1.0);
- }
- else
- striptime = 0;
- }
-
- frametime = (striptime * actlength) + strip->actstart;
- frametime = bsystem_time(scene, ob, frametime, 0.0);
-
- if (blocktype == ID_AR) {
- extract_pose_from_action(tpose, strip->act, frametime);
- }
- else if (blocktype == ID_OB) {
- extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime);
- if (key)
- extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime);
- }
- doit = dostride = 1;
- }
- }
- }
- }
- /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */
- else {
-
- /* Mod to repeat */
- if (strip->repeat != 1.0f) {
- float cycle = striptime * strip->repeat;
-
- striptime = (float)fmod(cycle, 1.0f + 0.1f / length);
- cycle -= striptime;
-
- if (blocktype == ID_AR)
- cyclic_offs_bone(ob, tpose, strip, cycle);
- }
-
- frametime = (striptime * actlength) + strip->actstart;
- frametime = nla_time(scene, frametime, (float)strip->repeat);
-
- if (blocktype == ID_AR) {
- extract_pose_from_action(tpose, strip->act, frametime);
- }
- else if (blocktype == ID_OB) {
- extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime);
- if (key)
- extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime);
- }
-
- doit = 1;
- }
- }
- /* Handle extend */
- else {
- if (strip->flag & ACTSTRIP_HOLDLASTFRAME) {
- /* we want the strip to hold on the exact fraction of the repeat value */
-
- frametime = actlength * (strip->repeat - (int)strip->repeat);
- if (frametime <= 0.000001f) frametime = actlength; /* rounding errors... */
- frametime = bsystem_time(scene, ob, frametime + strip->actstart, 0.0);
-
- if (blocktype == ID_AR)
- extract_pose_from_action(tpose, strip->act, frametime);
- else if (blocktype == ID_OB) {
- extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime);
- if (key)
- extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime);
- }
-
- /* handle cycle hold */
- if (strip->repeat != 1.0f) {
- if (blocktype == ID_AR)
- cyclic_offs_bone(ob, tpose, strip, strip->repeat - 1.0f);
- }
-
- doit = 1;
- }
- }
-
- /* Handle blendin & blendout */
- if (doit) {
- /* Handle blendin */
-
- if (strip->blendin > 0.0 && stripframe <= strip->blendin && scene_cfra >= strip->start) {
- blendfac = stripframe / strip->blendin;
- }
- else if (strip->blendout > 0.0 && stripframe >= (length - strip->blendout) && scene_cfra <= strip->end) {
- blendfac = (length - stripframe) / (strip->blendout);
- }
- else
- blendfac = 1;
-
- if (blocktype == ID_AR) { /* Blend this pose with the accumulated pose */
- /* offset bone, for matching cycles */
- blend_pose_offset_bone(strip, ob->pose, tpose, blendfac, strip->mode);
-
- blend_poses(ob->pose, tpose, blendfac, strip->mode);
- if (dostride)
- blend_pose_strides(ob->pose, tpose, blendfac, strip->mode);
- }
- else {
- blend_ipochannels(&chanbase, &tchanbase, blendfac, strip->mode);
- BLI_freelistN(&tchanbase);
- }
- }
- }
- }
- }
-
- if (blocktype == ID_OB) {
- execute_ipochannels(&chanbase);
- }
- else if (blocktype == ID_AR) {
- /* apply stride offset to object */
- add_v3_v3(ob->obmat[3], ob->pose->stride_offset);
- }
-
- /* free */
- if (tpose)
- BKE_pose_free(tpose);
- if (chanbase.first)
- BLI_freelistN(&chanbase);
-}
-
-#endif // XXX OLD ANIMATION SYSTEM (TO BE REMOVED)
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 6a3dae93639..cf785a4bb42 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -86,6 +86,7 @@ short id_type_can_have_animdata(ID *id)
case ID_PA:
case ID_MA: case ID_TE: case ID_NT:
case ID_LA: case ID_CA: case ID_WO:
+ case ID_LS:
case ID_SPK:
case ID_SCE:
case ID_MC:
@@ -761,7 +762,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
AnimData *adt = BKE_animdata_from_id(id); \
if (adt) func(id, adt, user_data); \
} (void)0
-
+
/* "embedded" nodetree cases (i.e. scene/material/texture->nodetree) */
#define ANIMDATA_NODETREE_IDS_CB(first, NtId_Type) \
for (id = first; id; id = id->next) { \
@@ -773,13 +774,13 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
} \
if (adt) func(id, adt, user_data); \
} (void)0
-
+
/* nodes */
ANIMDATA_IDS_CB(mainptr->nodetree.first);
-
+
/* textures */
ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex);
-
+
/* lamps */
ANIMDATA_IDS_CB(mainptr->lamp.first);
@@ -827,7 +828,10 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
/* scenes */
ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene);
-}
+
+ /* line styles */
+ ANIMDATA_IDS_CB(mainptr->linestyle.first);
+ }
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
* NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
@@ -912,10 +916,13 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha
/* worlds */
RENAMEFIX_ANIM_IDS(mainptr->world.first);
+ /* linestyles */
+ RENAMEFIX_ANIM_IDS(mainptr->linestyle.first);
+
/* scenes */
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene);
-}
-
+ }
+
/* *********************************** */
/* KeyingSet API */
@@ -2398,6 +2405,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
/* movie clips */
EVAL_ANIM_IDS(main->movieclip.first, ADT_RECALC_ANIM);
+ /* linestyles */
+ EVAL_ANIM_IDS(main->linestyle.first, ADT_RECALC_ANIM);
+
/* objects */
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
* this tagged by Depsgraph on framechange. This optimization means that objects
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index af9bb971d05..6631afcddaf 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -161,8 +161,6 @@ void bvhtree_update_from_mvert(BVHTree * bvhtree, MFace *faces, int numfaces, MV
/***********************************
Collision modifier code end
***********************************/
-#define mySWAP(a, b) do { double tmp = b ; b = a ; a = tmp ; } while (0)
-
// w3 is not perfect
static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 )
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 19c8c2cd632..b66bd1fd32b 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -262,7 +262,7 @@ CurveMapPoint *curvemap_insert(CurveMap *cuma, float x, float y)
return newcmp;
}
-void curvemap_reset(CurveMap *cuma, rctf *clipr, int preset, int slope)
+void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
{
if (cuma->curve)
MEM_freeN(cuma->curve);
@@ -481,7 +481,7 @@ static float curvemap_calc_extend(const CurveMap *cuma, float x, const float fir
}
/* only creates a table for a single channel in CurveMapping */
-static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
+static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
{
CurveMapPoint *cmp = cuma->curve;
BezTriple *bezt;
@@ -679,7 +679,7 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles)
CurveMap *cuma = cumap->cm + cumap->cur;
CurveMapPoint *cmp = cuma->curve;
rctf *clipr = &cumap->clipr;
- float thresh = 0.01f * BLI_RCT_SIZE_X(clipr);
+ float thresh = 0.01f * BLI_rctf_size_x(clipr);
float dx = 0.0f, dy = 0.0f;
int a;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 6b9e0921c3b..e3f7ae1b1c7 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1030,7 +1030,6 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
if (VALID_CONS_TARGET(ct)) {
float size[3], vec[3];
float totmat[3][3];
- float tmat[4][4];
/* Get size property, since ob->size is only the object's own relative size, not its global one */
mat4_to_size(size, cob->matrix);
@@ -1053,9 +1052,8 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
vectomat(vec, ct->matrix[2],
(short)data->reserved1, (short)data->reserved2,
data->flags, totmat);
-
- copy_m4_m4(tmat, cob->matrix);
- mul_m4_m3m4(cob->matrix, totmat, tmat);
+
+ mul_m4_m3m4(cob->matrix, totmat, cob->matrix);
}
}
@@ -2281,7 +2279,6 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
float totmat[3][3];
float tmpmat[3][3];
float invmat[3][3];
- float tmat[4][4];
float mdet;
/* Vector object -> target */
@@ -2509,8 +2506,6 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
totmat[1][0] = tmpmat[1][0]; totmat[1][1] = tmpmat[1][1]; totmat[1][2] = tmpmat[1][2];
totmat[2][0] = tmpmat[2][0]; totmat[2][1] = tmpmat[2][1]; totmat[2][2] = tmpmat[2][2];
- copy_m4_m4(tmat, cob->matrix);
-
mdet = determinant_m3(totmat[0][0], totmat[0][1], totmat[0][2],
totmat[1][0], totmat[1][1], totmat[1][2],
totmat[2][0], totmat[2][1], totmat[2][2]);
@@ -2519,7 +2514,7 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
}
/* apply out transformaton to the object */
- mul_m4_m3m4(cob->matrix, totmat, tmat);
+ mul_m4_m3m4(cob->matrix, totmat, cob->matrix);
}
}
@@ -2717,7 +2712,6 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
if (VALID_CONS_TARGET(ct)) {
float size[3], scale[3], vec[3], xx[3], zz[3], orth[3];
float totmat[3][3];
- float tmat[4][4];
float dist;
/* store scaling before destroying obmat */
@@ -2815,9 +2809,8 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
normalize_v3_v3(totmat[2], zz);
break;
} /* switch (data->plane) */
-
- copy_m4_m4(tmat, cob->matrix);
- mul_m4_m3m4(cob->matrix, totmat, tmat);
+
+ mul_m4_m3m4(cob->matrix, totmat, cob->matrix);
}
}
@@ -4061,32 +4054,36 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
copy_v3_v3(cob->matrix[3], disp);
}
- if (data->depth_ob && data->depth_ob->derivedFinal) {
+ if (data->depth_ob) {
Object *depth_ob = data->depth_ob;
- BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
- BVHTreeRayHit hit;
- float ray_start[3], ray_end[3], ray_nor[3], imat[4][4];
- int result;
+ DerivedMesh *target = object_get_derived_final(depth_ob);
+ if (target) {
+ BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
+ BVHTreeRayHit hit;
+ float ray_start[3], ray_end[3], ray_nor[3], imat[4][4];
+ int result;
- invert_m4_m4(imat, depth_ob->obmat);
+ invert_m4_m4(imat, depth_ob->obmat);
- mul_v3_m4v3(ray_start, imat, camob->obmat[3]);
- mul_v3_m4v3(ray_end, imat, cob->matrix[3]);
+ mul_v3_m4v3(ray_start, imat, camob->obmat[3]);
+ mul_v3_m4v3(ray_end, imat, cob->matrix[3]);
- sub_v3_v3v3(ray_nor, ray_end, ray_start);
+ sub_v3_v3v3(ray_nor, ray_end, ray_start);
- bvhtree_from_mesh_faces(&treeData, depth_ob->derivedFinal, 0.0f, 4, 6);
+ bvhtree_from_mesh_faces(&treeData, target, 0.0f, 4, 6);
- hit.dist = FLT_MAX;
- hit.index = -1;
+ hit.dist = FLT_MAX;
+ hit.index = -1;
- result = BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData);
+ result = BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData);
- if (result != -1) {
- mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co);
- }
+ if (result != -1) {
+ mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co);
+ }
- free_bvhtree_from_mesh(&treeData);
+ free_bvhtree_from_mesh(&treeData);
+ target->release(target);
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index a2f88781cbb..09ca0df0680 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -429,6 +429,33 @@ void BKE_curve_texspace_calc(Curve *cu)
}
}
+int BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
+{
+ Nurb *nu;
+ int tot = 0;
+
+ for (nu = nurb->first; nu; nu = nu->next) {
+ int tot_nu;
+ if (nu->type == CU_BEZIER) {
+ tot_nu = nu->pntsu;
+ if (index - tot < tot_nu) {
+ copy_v3_v3(r_co, nu->bezt[index - tot].vec[1]);
+ return TRUE;
+ }
+ }
+ else {
+ tot_nu = nu->pntsu * nu->pntsv;
+ if (index - tot < tot_nu) {
+ copy_v3_v3(r_co, nu->bp[index - tot].vec);
+ return TRUE;
+ }
+ }
+ tot += tot_nu;
+ }
+
+ return FALSE;
+}
+
int BKE_nurbList_verts_count(ListBase *nurb)
{
Nurb *nu;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 342ee5bba41..ba859cadf92 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -271,28 +271,6 @@ static void layerInterp_mdeformvert(void **sources, const float *weights,
BLI_linklist_free(dest_dw, linklist_free_simple);
}
-
-static void layerInterp_msticky(void **sources, const float *weights,
- const float *UNUSED(sub_weights), int count, void *dest)
-{
- float co[2], w;
- MSticky *mst;
- int i;
-
- co[0] = co[1] = 0.0f;
- for (i = 0; i < count; i++) {
- w = weights ? weights[i] : 1.0f;
- mst = (MSticky *)sources[i];
-
- madd_v2_v2fl(co, mst->co, w);
- }
-
- /* delay writing to the destination incase dest is in sources */
- mst = (MSticky *)dest;
- copy_v2_v2(mst->co, co);
-}
-
-
static void layerCopy_tface(const void *source, void *dest, int count)
{
const MTFace *source_tf = (const MTFace *)source;
@@ -1055,8 +1033,8 @@ static void layerInterp_mvert_skin(void **sources, const float *weights,
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
- /* 1: CD_MSTICKY */
- {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL,
+ /* 1: CD_MSTICKY */ /* DEPRECATED */
+ {sizeof(float) * 2, "", 1, NULL, NULL, NULL, NULL, NULL,
NULL},
/* 2: CD_MDEFORMVERT */
{sizeof(MDeformVert), "MDeformVert", 1, NULL, layerCopy_mdeformvert,
@@ -1155,7 +1133,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(GridPaintMask), "GridPaintMask", 1, NULL, layerCopy_grid_paint_mask,
layerFree_grid_paint_mask, NULL, NULL, NULL},
/* 36: CD_SKIN_NODE */
- {sizeof(MVertSkin), "MVertSkin", 1, "Skin", NULL, NULL,
+ {sizeof(MVertSkin), "MVertSkin", 1, NULL, NULL, NULL,
layerInterp_mvert_skin, NULL, layerDefault_mvert_skin}
};
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index b8d5294eabc..31a6f768f89 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -501,7 +501,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if (ob->adt)
dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation
- key = ob_get_key(ob);
+ key = BKE_key_from_object(ob);
if (key && key->adt)
dag_add_driver_relation(key->adt, dag, node, 1);
@@ -2650,7 +2650,7 @@ static void dag_id_flush_update(Scene *sce, ID *id)
/* set flags based on ShapeKey */
if (idtype == ID_KE) {
for (obt = bmain->object.first; obt; obt = obt->id.next) {
- Key *key = ob_get_key(obt);
+ Key *key = BKE_key_from_object(obt);
if (!(ob && obt == ob) && ((ID *)key == id)) {
obt->flag |= (OB_RECALC_OB | OB_RECALC_DATA);
lib_id_recalc_tag(bmain, &obt->id);
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index befec1907da..8d430eb58b5 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -152,7 +152,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
/* don't consider two-edged faces */
- if (efa->len < 3) {
+ if (UNLIKELY(efa->len < 3)) {
/* do nothing */
}
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 538d2469a93..68321076398 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -48,10 +48,6 @@
#include "BKE_fcurve.h"
#include "BKE_idprop.h"
-
-#define SMALL -1.0e-10
-#define SELECT 1
-
/* ******************************** F-Modifiers ********************************* */
/* Info ------------------------------- */
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 500df1b7b75..3392f6f109b 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -79,6 +79,7 @@ void BKE_group_unlink(Group *group)
Object *ob;
Scene *sce;
SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
ParticleSystem *psys;
for (ma = bmain->mat.first; ma; ma = ma->id.next) {
@@ -103,6 +104,11 @@ void BKE_group_unlink(Group *group)
for (srl = sce->r.layers.first; srl; srl = srl->next) {
if (srl->light_override == group)
srl->light_override = NULL;
+
+ for(lineset= srl->freestyleConfig.linesets.first; lineset; lineset= lineset->next) {
+ if (lineset->group == group)
+ lineset->group= NULL;
+ }
}
}
@@ -110,16 +116,6 @@ void BKE_group_unlink(Group *group)
if (ob->dup_group == group) {
ob->dup_group = NULL;
-#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
- {
- bActionStrip *strip;
- /* duplicator strips use a group object, we remove it */
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->object)
- strip->object = NULL;
- }
- }
-#endif
}
for (psys = ob->particlesystem.first; psys; psys = psys->next) {
@@ -383,57 +379,3 @@ void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group
}
}
}
-
-#if 0
-Object *group_get_member_with_action(Group *group, bAction *act)
-{
- GroupObject *go;
-
- if (group == NULL || act == NULL) return NULL;
-
- for (go = group->gobject.first; go; go = go->next) {
- if (go->ob) {
- if (go->ob->action == act)
- return go->ob;
- if (go->ob->nlastrips.first) {
- bActionStrip *strip;
-
- for (strip = go->ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->act == act)
- return go->ob;
- }
- }
- }
- }
- return NULL;
-}
-
-/* if group has NLA, we try to map the used objects in NLA to group members */
-/* this assuming that object has received a new group link */
-void group_relink_nla_objects(Object *ob)
-{
- Group *group;
- GroupObject *go;
- bActionStrip *strip;
-
- if (ob == NULL || ob->dup_group == NULL) return;
- group = ob->dup_group;
-
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->object) {
- for (go = group->gobject.first; go; go = go->next) {
- if (go->ob) {
- if (strcmp(go->ob->id.name, strip->object->id.name) == 0)
- break;
- }
- }
- if (go)
- strip->object = go->ob;
- else
- strip->object = NULL;
- }
-
- }
-}
-
-#endif
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 8a49cba7649..d8c3e260399 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -65,7 +65,7 @@ static void icon_free(void *val)
Icon *icon = val;
if (icon) {
- if (icon->drawinfo_free) {
+ if (icon->drawinfo_free) {
icon->drawinfo_free(icon->drawinfo);
}
else if (icon->drawinfo) {
@@ -255,7 +255,7 @@ void BKE_icon_changed(int id)
prv->changed_timestamp[i]++;
}
}
- }
+ }
}
int BKE_icon_getid(struct ID *id)
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 30427a81c4b..828f752eaa5 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -61,6 +61,7 @@ static IDType idtypes[] = {
{ ID_KE, "Key", "shape_keys", 0},
{ ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE},
{ ID_LI, "Library", "libraries", 0},
+ { ID_LS, "FreestyleLineStyle", "linestyles", IDTYPE_FLAGS_ISLINKABLE},
{ ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE},
{ ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE},
{ ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE},
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 8229df28ab8..8ceaab56f83 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -484,7 +484,7 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
BLI_remlink(&group->data.group, loop);
IDP_FreeProperty(loop);
- MEM_freeN(loop);
+ MEM_freeN(loop);
}
else {
group->len++;
@@ -679,7 +679,7 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
case IDP_DOUBLE:
prop = MEM_callocN(sizeof(IDProperty), "IDProperty float");
*(double *)&prop->data.val = val->d;
- break;
+ break;
case IDP_ARRAY:
{
/* for now, we only support float and int and double arrays */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index d514a0a7dd0..d620fc50e86 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -603,7 +603,8 @@ Image *BKE_image_load_exists(const char *filepath)
return BKE_image_load(filepath);
}
-static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, float color[4])
+static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type,
+ float color[4], ColorManagedColorspaceSettings *colorspace_settings)
{
ImBuf *ibuf;
unsigned char *rect = NULL;
@@ -612,10 +613,24 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
if (floatbuf) {
ibuf = IMB_allocImBuf(width, height, depth, IB_rectfloat);
rect_float = ibuf->rect_float;
+
+ if (colorspace_settings->name[0] == '\0') {
+ const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_FLOAT);
+
+ BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name));
+ }
}
else {
ibuf = IMB_allocImBuf(width, height, depth, IB_rect);
rect = (unsigned char *)ibuf->rect;
+
+ if (colorspace_settings->name[0] == '\0') {
+ const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
+
+ BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name));
+ }
+
+ IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace_settings->name);
}
BLI_strncpy(ibuf->name, name, sizeof(ibuf->name));
@@ -650,7 +665,7 @@ Image *BKE_image_add_generated(unsigned int width, unsigned int height, const ch
ima->gen_type = gen_type;
ima->gen_flag |= (floatbuf ? IMA_GEN_FLOAT : 0);
- ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color);
+ ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings);
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
ima->ok = IMA_OK_LOADED;
@@ -1227,6 +1242,9 @@ void BKE_imformat_defaults(ImageFormatData *im_format)
im_format->imtype = R_IMF_IMTYPE_PNG;
im_format->quality = 90;
im_format->compress = 90;
+
+ BKE_color_managed_display_settings_init(&im_format->display_settings);
+ BKE_color_managed_view_settings_init(&im_format->view_settings);
}
void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *imbuf)
@@ -2201,8 +2219,10 @@ void BKE_image_backup_render(Scene *scene, Image *ima)
/* in that case we have to build a render-result */
static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
{
+ const char *colorspace = ima->colorspace_settings.name;
+ int predivide = ima->flag & IMA_CM_PREDIVIDE;
- ima->rr = RE_MultilayerConvert(ibuf->userdata, ibuf->x, ibuf->y);
+ ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y);
#ifdef WITH_OPENEXR
IMB_exr_close(ibuf->userdata);
@@ -2585,7 +2605,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
/* invalidate color managed buffers if render result changed */
BLI_lock_thread(LOCK_COLORMANAGE);
- if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) {
+ if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf)
+ {
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
@@ -2778,7 +2799,8 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
/* UV testgrid or black or solid etc */
if (ima->gen_x == 0) ima->gen_x = 1024;
if (ima->gen_y == 0) ima->gen_y = 1024;
- ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, color);
+ ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type,
+ color, &ima->colorspace_settings);
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
ima->ok = IMA_OK_LOADED;
}
@@ -2994,5 +3016,8 @@ void BKE_image_get_aspect(Image *image, float *aspx, float *aspy)
*aspx = 1.0;
/* x is always 1 */
- *aspy = image->aspy / image->aspx;
+ if (image)
+ *aspy = image->aspy / image->aspx;
+ else
+ *aspy = 1.0f;
}
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index fcc8b4322a0..ebb95a6561e 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -48,7 +48,9 @@
#include "BKE_global.h"
-#define CLOTH_OPENMP_LIMIT 512
+#ifdef _OPENMP
+# define CLOTH_OPENMP_LIMIT 512
+#endif
#if 0 /* debug timing */
#ifdef _WIN32
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index b79608342dd..5b05ce02104 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -94,7 +94,7 @@ void BKE_key_free(Key *key)
}
-void free_key_nolib(Key *key)
+void BKE_key_free_nolib(Key *key)
{
KeyBlock *kb;
@@ -121,7 +121,7 @@ void free_key_nolib(Key *key)
/* from misc_util: flip the bytes from x */
/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
-Key *add_key(ID *id) /* common function */
+Key *BKE_key_add(ID *id) /* common function */
{
Key *key;
char *el;
@@ -196,7 +196,7 @@ Key *BKE_key_copy(Key *key)
}
-Key *copy_key_nolib(Key *key)
+Key *BKE_key_copy_nolib(Key *key)
{
Key *keyn;
KeyBlock *kbn, *kb;
@@ -241,7 +241,7 @@ void BKE_key_make_local(Key *key)
* currently being called.
*/
-void sort_keys(Key *key)
+void BKE_key_sort(Key *key)
{
KeyBlock *kb;
KeyBlock *kb2;
@@ -711,7 +711,7 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const
}
}
-void do_rel_key(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode)
+void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode)
{
KeyBlock *kb;
int *ofsp, ofs[3], elemsize, b;
@@ -1071,7 +1071,7 @@ static float *get_weights_array(Object *ob, char *vgroup)
static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
{
- KeyBlock *k[4], *actkb = ob_get_keyblock(ob);
+ KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag = 0;
@@ -1106,7 +1106,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int
kb->weights = get_weights_array(ob, kb->vgroup);
}
- do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY);
+ BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY);
for (kb = key->block.first; kb; kb = kb->next) {
if (kb->weights) MEM_freeN(kb->weights);
@@ -1154,11 +1154,11 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const
for (a = 0, nu = cu->nurb.first; nu; nu = nu->next, a += step) {
if (nu->bp) {
step = nu->pntsu * nu->pntsv;
- do_rel_key(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT);
+ BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT);
}
else if (nu->bezt) {
step = 3 * nu->pntsu;
- do_rel_key(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE);
+ BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE);
}
else {
step = 0;
@@ -1169,7 +1169,7 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const
static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
{
Curve *cu = ob->data;
- KeyBlock *k[4], *actkb = ob_get_keyblock(ob);
+ KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag = 0;
@@ -1251,7 +1251,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const in
static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
{
Lattice *lt = ob->data;
- KeyBlock *k[4], *actkb = ob_get_keyblock(ob);
+ KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
float t[4];
int flag;
@@ -1277,7 +1277,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int
for (kb = key->block.first; kb; kb = kb->next)
kb->weights = get_weights_array(ob, kb->vgroup);
- do_rel_key(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY);
+ BKE_key_evaluate_relative(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY);
for (kb = key->block.first; kb; kb = kb->next) {
if (kb->weights) MEM_freeN(kb->weights);
@@ -1302,8 +1302,8 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int
/* returns key coordinates (+ tilt) when key applied, NULL otherwise */
float *do_ob_key(Scene *scene, Object *ob)
{
- Key *key = ob_get_key(ob);
- KeyBlock *actkb = ob_get_keyblock(ob);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *actkb = BKE_keyblock_from_object(ob);
char *out;
int tot = 0, size = 0;
@@ -1386,7 +1386,7 @@ float *do_ob_key(Scene *scene, Object *ob)
return (float *)out;
}
-Key *ob_get_key(Object *ob)
+Key *BKE_key_from_object(Object *ob)
{
if (ob == NULL) return NULL;
@@ -1405,7 +1405,7 @@ Key *ob_get_key(Object *ob)
return NULL;
}
-KeyBlock *add_keyblock(Key *key, const char *name)
+KeyBlock *BKE_keyblock_add(Key *key, const char *name)
{
KeyBlock *kb;
float curpos = -0.1;
@@ -1439,7 +1439,7 @@ KeyBlock *add_keyblock(Key *key, const char *name)
/**
* \note caller may want to set this to current time, but don't do it here since we need to sort
- * which could cause problems in some cases, see #add_keyblock_ctime */
+ * which could cause problems in some cases, see #BKE_keyblock_add_ctime */
kb->pos = curpos + 0.1f; /* only used for absolute shape keys */
return kb;
@@ -1453,22 +1453,22 @@ KeyBlock *add_keyblock(Key *key, const char *name)
* \param name Optional name for the new keyblock.
* \param do_force always use ctime even for relative keys.
*/
-KeyBlock *add_keyblock_ctime(Key *key, const char *name, const short do_force)
+KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const short do_force)
{
- KeyBlock *kb = add_keyblock(key, name);
+ KeyBlock *kb = BKE_keyblock_add(key, name);
if (do_force || (key->type != KEY_RELATIVE)) {
kb->pos = key->ctime / 100.0f;
- sort_keys(key);
+ BKE_key_sort(key);
}
return kb;
}
/* only the active keyblock */
-KeyBlock *ob_get_keyblock(Object *ob)
+KeyBlock *BKE_keyblock_from_object(Object *ob)
{
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
if (key) {
KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1);
@@ -1478,9 +1478,9 @@ KeyBlock *ob_get_keyblock(Object *ob)
return NULL;
}
-KeyBlock *ob_get_reference_keyblock(Object *ob)
+KeyBlock *BKE_keyblock_from_object_reference(Object *ob)
{
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
if (key)
return key->refkey;
@@ -1489,7 +1489,7 @@ KeyBlock *ob_get_reference_keyblock(Object *ob)
}
/* get the appropriate KeyBlock given an index */
-KeyBlock *key_get_keyblock(Key *key, int index)
+KeyBlock *BKE_keyblock_from_key(Key *key, int index)
{
KeyBlock *kb;
int i;
@@ -1509,18 +1509,29 @@ KeyBlock *key_get_keyblock(Key *key, int index)
}
/* get the appropriate KeyBlock given a name to search for */
-KeyBlock *key_get_named_keyblock(Key *key, const char name[])
+KeyBlock *BKE_keyblock_find_name(Key *key, const char name[])
{
- if (key && name)
- return BLI_findstring(&key->block, name, offsetof(KeyBlock, name));
-
- return NULL;
+ return BLI_findstring(&key->block, name, offsetof(KeyBlock, name));
+}
+
+/**
+ * \brief copy shape-key attributes, but not key data.or name/uid
+ */
+void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src)
+{
+ kb_dst->pos = kb_src->pos;
+ kb_dst->curval = kb_src->curval;
+ kb_dst->type = kb_src->type;
+ kb_dst->relative = kb_src->relative;
+ BLI_strncpy(kb_dst->vgroup, kb_src->vgroup, sizeof(kb_dst->vgroup));
+ kb_dst->slidermin = kb_src->slidermin;
+ kb_dst->slidermax = kb_src->slidermax;
}
/* Get RNA-Path for 'value' setting of the given ShapeKey
* NOTE: the user needs to free the returned string once they're finish with it
*/
-char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb)
+char *BKE_keyblock_curval_rnapath_get(Key *key, KeyBlock *kb)
{
PointerRNA ptr;
PropertyRNA *prop;
@@ -1542,7 +1553,7 @@ char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb)
/* conversion functions */
/************************* Lattice ************************/
-void latt_to_key(Lattice *lt, KeyBlock *kb)
+void BKE_key_convert_from_lattice(Lattice *lt, KeyBlock *kb)
{
BPoint *bp;
float *fp;
@@ -1563,7 +1574,7 @@ void latt_to_key(Lattice *lt, KeyBlock *kb)
}
}
-void key_to_latt(KeyBlock *kb, Lattice *lt)
+void BKE_key_convert_to_lattice(KeyBlock *kb, Lattice *lt)
{
BPoint *bp;
float *fp;
@@ -1581,7 +1592,7 @@ void key_to_latt(KeyBlock *kb, Lattice *lt)
}
/************************* Curve ************************/
-void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
+void BKE_key_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb)
{
Nurb *nu;
BezTriple *bezt;
@@ -1632,7 +1643,7 @@ void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
}
}
-void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
+void BKE_key_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
{
Nurb *nu;
BezTriple *bezt;
@@ -1683,7 +1694,7 @@ void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
}
/************************* Mesh ************************/
-void mesh_to_key(Mesh *me, KeyBlock *kb)
+void BKE_key_convert_from_mesh(Mesh *me, KeyBlock *kb)
{
MVert *mvert;
float *fp;
@@ -1704,7 +1715,7 @@ void mesh_to_key(Mesh *me, KeyBlock *kb)
}
}
-void key_to_mesh(KeyBlock *kb, Mesh *me)
+void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me)
{
MVert *mvert;
float *fp;
@@ -1721,7 +1732,7 @@ void key_to_mesh(KeyBlock *kb, Mesh *me)
}
/************************* vert coords ************************/
-float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3]
+float (*BKE_key_convert_to_vertcos(Object * ob, KeyBlock * kb))[3]
{
float (*vertCos)[3], *co;
float *fp = kb->data;
@@ -1743,7 +1754,7 @@ float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3]
if (tot == 0) return NULL;
- vertCos = MEM_callocN(tot * sizeof(*vertCos), "key_to_vertcos vertCos");
+ vertCos = MEM_callocN(tot * sizeof(*vertCos), "BKE_key_convert_to_vertcos vertCos");
/* Copy coords to array */
co = (float *)vertCos;
@@ -1797,7 +1808,7 @@ float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3]
return vertCos;
}
-void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
+void BKE_key_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
{
float *co = (float *)vertCos, *fp;
int tot = 0, a, elemsize;
@@ -1826,7 +1837,7 @@ void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
return;
}
- fp = kb->data = MEM_callocN(tot * elemsize, "key_to_vertcos vertCos");
+ fp = kb->data = MEM_callocN(tot * elemsize, "BKE_key_convert_to_vertcos vertCos");
/* Copy coords to keyblock */
@@ -1877,7 +1888,7 @@ void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
}
}
-void offset_to_key(Object *ob, KeyBlock *kb, float (*ofs)[3])
+void BKE_key_convert_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3])
{
int a;
float *co = (float *)ofs, *fp = kb->data;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 45364f5aafa..f6e86bdbb5a 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -109,6 +109,7 @@
#include "BKE_speaker.h"
#include "BKE_movieclip.h"
#include "BKE_mask.h"
+#include "BKE_linestyle.h"
#include "RNA_access.h"
@@ -268,6 +269,8 @@ int id_make_local(ID *id, int test)
return 0; /* can't be linked */
case ID_GD:
return 0; /* not implemented */
+ case ID_LS:
+ return 0; /* not implemented */
}
return 0;
@@ -362,6 +365,9 @@ int id_copy(ID *id, ID **newid, int test)
case ID_MSK:
if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id);
return 1;
+ case ID_LS:
+ if(!test) *newid= (ID*)FRS_copy_linestyle((FreestyleLineStyle*)id);
+ return 1;
}
return 0;
@@ -492,6 +498,8 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->movieclip);
case ID_MSK:
return &(mainlib->mask);
+ case ID_LS:
+ return &(mainlib->linestyle);
}
return NULL;
}
@@ -576,6 +584,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[a++] = &(main->wm);
lb[a++] = &(main->movieclip);
lb[a++] = &(main->mask);
+ lb[a++] = &(main->linestyle);
lb[a] = NULL;
@@ -690,6 +699,9 @@ static ID *alloc_libblock_notest(short type)
case ID_MSK:
id = MEM_callocN(sizeof(Mask), "Mask");
break;
+ case ID_LS:
+ id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style");
+ break;
}
return id;
}
@@ -902,6 +914,9 @@ void BKE_libblock_free(ListBase *lb, void *idv)
case ID_MSK:
BKE_mask_free(bmain, (Mask *)id);
break;
+ case ID_LS:
+ FRS_free_linestyle((FreestyleLineStyle *)id);
+ break;
}
if (id->properties) {
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
new file mode 100644
index 00000000000..0ed1b02d3c9
--- /dev/null
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -0,0 +1,1005 @@
+/* linestyle.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_material_types.h" /* for ramp blend */
+#include "DNA_texture_types.h"
+
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_linestyle.h"
+#include "BKE_main.h"
+#include "BKE_texture.h"
+#include "BKE_colortools.h"
+#include "BKE_animsys.h"
+
+#include "BLI_blenlib.h"
+
+static char *modifier_name[LS_MODIFIER_NUM] = {
+ NULL,
+ "Along Stroke",
+ "Distance from Camera",
+ "Distance from Object",
+ "Material",
+ "Sampling",
+ "Bezier Curve",
+ "Sinus Displacement",
+ "Spatial Noise",
+ "Perlin Noise 1D",
+ "Perlin Noise 2D",
+ "Backbone Stretcher",
+ "Tip Remover",
+ "Calligraphy",
+ "Polygonalization",
+ "Guiding Lines",
+ "Blueprint",
+ "2D Offset",
+ "2D Transform"};
+
+static void default_linestyle_settings(FreestyleLineStyle *linestyle)
+{
+ linestyle->panel = LS_PANEL_STROKES;
+ linestyle->r = linestyle->g = linestyle->b = 0.0;
+ linestyle->alpha = 1.0;
+ linestyle->thickness = 1.0;
+ linestyle->thickness_position = LS_THICKNESS_CENTER;
+ linestyle->thickness_ratio = 0.5f;
+ linestyle->chaining = LS_CHAINING_PLAIN;
+ linestyle->rounds = 3;
+ linestyle->min_angle = 0.0f;
+ linestyle->max_angle = 0.0f;
+ linestyle->min_length = 0.0f;
+ linestyle->max_length = 10000.0f;
+ linestyle->split_length = 100;
+
+ linestyle->color_modifiers.first = linestyle->color_modifiers.last = NULL;
+ linestyle->alpha_modifiers.first = linestyle->alpha_modifiers.last = NULL;
+ linestyle->thickness_modifiers.first = linestyle->thickness_modifiers.last = NULL;
+ linestyle->geometry_modifiers.first = linestyle->geometry_modifiers.last = NULL;
+
+ FRS_add_linestyle_geometry_modifier(linestyle, LS_MODIFIER_SAMPLING);
+
+ linestyle->caps = LS_CAPS_BUTT;
+}
+
+FreestyleLineStyle *FRS_new_linestyle(char *name, struct Main *main)
+{
+ FreestyleLineStyle *linestyle;
+
+ if (!main)
+ main = G.main;
+
+ linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(&main->linestyle, ID_LS, name);
+
+ default_linestyle_settings(linestyle);
+
+ return linestyle;
+}
+
+void FRS_free_linestyle(FreestyleLineStyle *linestyle)
+{
+ LineStyleModifier *m;
+
+ BKE_free_animdata(&linestyle->id);
+ while ((m = (LineStyleModifier *)linestyle->color_modifiers.first))
+ FRS_remove_linestyle_color_modifier(linestyle, m);
+ while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first))
+ FRS_remove_linestyle_alpha_modifier(linestyle, m);
+ while ((m = (LineStyleModifier *)linestyle->thickness_modifiers.first))
+ FRS_remove_linestyle_thickness_modifier(linestyle, m);
+ while ((m = (LineStyleModifier *)linestyle->geometry_modifiers.first))
+ FRS_remove_linestyle_geometry_modifier(linestyle, m);
+}
+
+FreestyleLineStyle *FRS_copy_linestyle(FreestyleLineStyle *linestyle)
+{
+ FreestyleLineStyle *new_linestyle;
+ LineStyleModifier *m;
+
+ new_linestyle = FRS_new_linestyle(linestyle->id.name+2, NULL);
+ FRS_free_linestyle(new_linestyle);
+
+ new_linestyle->r = linestyle->r;
+ new_linestyle->g = linestyle->g;
+ new_linestyle->b = linestyle->b;
+ new_linestyle->alpha = linestyle->alpha;
+ new_linestyle->thickness = linestyle->thickness;
+ new_linestyle->thickness_position = linestyle->thickness_position;
+ new_linestyle->thickness_ratio = linestyle->thickness_ratio;
+ new_linestyle->flag = linestyle->flag;
+ new_linestyle->caps = linestyle->caps;
+ new_linestyle->chaining = linestyle->chaining;
+ new_linestyle->rounds = linestyle->rounds;
+ new_linestyle->min_angle = linestyle->min_angle;
+ new_linestyle->max_angle = linestyle->max_angle;
+ new_linestyle->min_length = linestyle->min_length;
+ new_linestyle->max_length = linestyle->max_length;
+ new_linestyle->split_length = linestyle->split_length;
+ new_linestyle->dash1 = linestyle->dash1;
+ new_linestyle->gap1 = linestyle->gap1;
+ new_linestyle->dash2 = linestyle->dash2;
+ new_linestyle->gap2 = linestyle->gap2;
+ new_linestyle->dash3 = linestyle->dash3;
+ new_linestyle->gap3 = linestyle->gap3;
+ new_linestyle->panel = linestyle->panel;
+ for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next)
+ FRS_copy_linestyle_color_modifier(new_linestyle, m);
+ for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next)
+ FRS_copy_linestyle_alpha_modifier(new_linestyle, m);
+ for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next)
+ FRS_copy_linestyle_thickness_modifier(new_linestyle, m);
+ for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next)
+ FRS_copy_linestyle_geometry_modifier(new_linestyle, m);
+ return new_linestyle;
+}
+
+static LineStyleModifier *new_modifier(int type, size_t size)
+{
+ LineStyleModifier *m;
+
+ m = (LineStyleModifier *)MEM_callocN(size, "line style modifier");
+ if (m) {
+ m->type = type;
+ strcpy(m->name, modifier_name[type]);
+ m->influence = 1.0f;
+ m->flags = LS_MODIFIER_ENABLED | LS_MODIFIER_EXPANDED;
+ }
+ return m;
+}
+
+static void add_to_modifier_list(ListBase *lb, LineStyleModifier *m)
+{
+ BLI_addtail(lb, (void *)m);
+ BLI_uniquename(lb, m, modifier_name[m->type], '.', offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+static LineStyleModifier *alloc_color_modifier(int type)
+{
+ size_t size;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ size = sizeof(LineStyleColorModifier_AlongStroke);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ size = sizeof(LineStyleColorModifier_DistanceFromCamera);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ size = sizeof(LineStyleColorModifier_DistanceFromObject);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ size = sizeof(LineStyleColorModifier_Material);
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ return new_modifier(type, size);
+}
+
+LineStyleModifier *FRS_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, int type)
+{
+ LineStyleModifier *m;
+
+ m = alloc_color_modifier(type);
+ if (!m)
+ return NULL;
+ m->blend = MA_RAMP_BLEND;
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ ((LineStyleColorModifier_AlongStroke *)m)->color_ramp = add_colorband(1);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_DistanceFromCamera *)m)->range_min = 0.0f;
+ ((LineStyleColorModifier_DistanceFromCamera *)m)->range_max = 10000.0f;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ ((LineStyleColorModifier_DistanceFromObject *)m)->target = NULL;
+ ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_DistanceFromObject *)m)->range_min = 0.0f;
+ ((LineStyleColorModifier_DistanceFromObject *)m)->range_max = 10000.0f;
+ break;
+ case LS_MODIFIER_MATERIAL:
+ ((LineStyleColorModifier_Material *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_Material *)m)->mat_attr = LS_MODIFIER_MATERIAL_DIFF;
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->color_modifiers, m);
+
+ return m;
+}
+
+LineStyleModifier *FRS_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ LineStyleModifier *new_m;
+
+ new_m = alloc_color_modifier(m->type);
+ if (!new_m)
+ return NULL;
+ new_m->influence = m->influence;
+ new_m->flags = m->flags;
+ new_m->blend = m->blend;
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleColorModifier_AlongStroke *p = (LineStyleColorModifier_AlongStroke *)m;
+ ((LineStyleColorModifier_AlongStroke *)new_m)->color_ramp = MEM_dupallocN(p->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleColorModifier_DistanceFromCamera *p = (LineStyleColorModifier_DistanceFromCamera *)m;
+ ((LineStyleColorModifier_DistanceFromCamera *)new_m)->color_ramp = MEM_dupallocN(p->color_ramp);
+ ((LineStyleColorModifier_DistanceFromCamera *)new_m)->range_min = p->range_min;
+ ((LineStyleColorModifier_DistanceFromCamera *)new_m)->range_max = p->range_max;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)m;
+ if (p->target)
+ p->target->id.us++;
+ ((LineStyleColorModifier_DistanceFromObject *)new_m)->target = p->target;
+ ((LineStyleColorModifier_DistanceFromObject *)new_m)->color_ramp = MEM_dupallocN(p->color_ramp);
+ ((LineStyleColorModifier_DistanceFromObject *)new_m)->range_min = p->range_min;
+ ((LineStyleColorModifier_DistanceFromObject *)new_m)->range_max = p->range_max;
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleColorModifier_Material *p = (LineStyleColorModifier_Material *)m;
+ ((LineStyleColorModifier_Material *)new_m)->color_ramp = MEM_dupallocN(p->color_ramp);
+ ((LineStyleColorModifier_Material *)new_m)->mat_attr = p->mat_attr;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->color_modifiers, new_m);
+
+ return new_m;
+}
+
+void FRS_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ MEM_freeN(((LineStyleColorModifier_AlongStroke *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ MEM_freeN(((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ MEM_freeN(((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ MEM_freeN(((LineStyleColorModifier_Material *)m)->color_ramp);
+ break;
+ }
+ BLI_freelinkN(&linestyle->color_modifiers, m);
+}
+
+static LineStyleModifier *alloc_alpha_modifier(int type)
+{
+ size_t size;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ size = sizeof(LineStyleAlphaModifier_AlongStroke);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ size = sizeof(LineStyleAlphaModifier_DistanceFromCamera);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ size = sizeof(LineStyleAlphaModifier_DistanceFromObject);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ size = sizeof(LineStyleAlphaModifier_Material);
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ return new_modifier(type, size);
+}
+
+LineStyleModifier *FRS_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, int type)
+{
+ LineStyleModifier *m;
+
+ m = alloc_alpha_modifier(type);
+ if (!m)
+ return NULL;
+ m->blend = LS_VALUE_BLEND;
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ ((LineStyleAlphaModifier_AlongStroke *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ ((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleAlphaModifier_DistanceFromCamera *)m)->range_min = 0.0f;
+ ((LineStyleAlphaModifier_DistanceFromCamera *)m)->range_max = 10000.0f;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ ((LineStyleAlphaModifier_DistanceFromObject *)m)->target = NULL;
+ ((LineStyleAlphaModifier_DistanceFromObject *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleAlphaModifier_DistanceFromObject *)m)->range_min = 0.0f;
+ ((LineStyleAlphaModifier_DistanceFromObject *)m)->range_max = 10000.0f;
+ break;
+ case LS_MODIFIER_MATERIAL:
+ ((LineStyleAlphaModifier_Material *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleAlphaModifier_Material *)m)->mat_attr = LS_MODIFIER_MATERIAL_DIFF;
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->alpha_modifiers, m);
+
+ return m;
+}
+
+LineStyleModifier *FRS_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ LineStyleModifier *new_m;
+
+ new_m = alloc_alpha_modifier(m->type);
+ if (!new_m)
+ return NULL;
+ new_m->influence = m->influence;
+ new_m->flags = m->flags;
+ new_m->blend = m->blend;
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleAlphaModifier_AlongStroke *p = (LineStyleAlphaModifier_AlongStroke *)m;
+ ((LineStyleAlphaModifier_AlongStroke *)new_m)->curve = curvemapping_copy(p->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleAlphaModifier_DistanceFromCamera *p = (LineStyleAlphaModifier_DistanceFromCamera *)m;
+ ((LineStyleAlphaModifier_DistanceFromCamera *)new_m)->curve = curvemapping_copy(p->curve);
+ ((LineStyleAlphaModifier_DistanceFromCamera *)new_m)->range_min = p->range_min;
+ ((LineStyleAlphaModifier_DistanceFromCamera *)new_m)->range_max = p->range_max;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)m;
+ if (p->target)
+ p->target->id.us++;
+ ((LineStyleAlphaModifier_DistanceFromObject *)new_m)->target = p->target;
+ ((LineStyleAlphaModifier_DistanceFromObject *)new_m)->curve = curvemapping_copy(p->curve);
+ ((LineStyleAlphaModifier_DistanceFromObject *)new_m)->range_min = p->range_min;
+ ((LineStyleAlphaModifier_DistanceFromObject *)new_m)->range_max = p->range_max;
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleAlphaModifier_Material *p = (LineStyleAlphaModifier_Material *)m;
+ ((LineStyleAlphaModifier_Material *)new_m)->curve = curvemapping_copy(p->curve);
+ ((LineStyleAlphaModifier_Material *)new_m)->mat_attr = p->mat_attr;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->alpha_modifiers, new_m);
+
+ return new_m;
+}
+
+void FRS_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ curvemapping_free(((LineStyleAlphaModifier_AlongStroke *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ curvemapping_free(((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ curvemapping_free(((LineStyleAlphaModifier_DistanceFromObject *)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ curvemapping_free(((LineStyleAlphaModifier_Material *)m)->curve);
+ break;
+ }
+ BLI_freelinkN(&linestyle->alpha_modifiers, m);
+}
+
+static LineStyleModifier *alloc_thickness_modifier(int type)
+{
+ size_t size;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ size = sizeof(LineStyleThicknessModifier_AlongStroke);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ size = sizeof(LineStyleThicknessModifier_DistanceFromCamera);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ size = sizeof(LineStyleThicknessModifier_DistanceFromObject);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ size = sizeof(LineStyleThicknessModifier_Material);
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ size = sizeof(LineStyleThicknessModifier_Calligraphy);
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ return new_modifier(type, size);
+}
+
+LineStyleModifier *FRS_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, int type)
+{
+ LineStyleModifier *m;
+
+ m = alloc_thickness_modifier(type);
+ if (!m)
+ return NULL;
+ m->blend = LS_VALUE_BLEND;
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ ((LineStyleThicknessModifier_AlongStroke *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleThicknessModifier_AlongStroke *)m)->value_min = 0.0f;
+ ((LineStyleThicknessModifier_AlongStroke *)m)->value_max = 1.0f;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ ((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleThicknessModifier_DistanceFromCamera *)m)->range_min = 0.0f;
+ ((LineStyleThicknessModifier_DistanceFromCamera *)m)->range_max = 1000.0f;
+ ((LineStyleThicknessModifier_DistanceFromCamera *)m)->value_min = 0.0f;
+ ((LineStyleThicknessModifier_DistanceFromCamera *)m)->value_max = 1.0f;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ ((LineStyleThicknessModifier_DistanceFromObject *)m)->target = NULL;
+ ((LineStyleThicknessModifier_DistanceFromObject *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleThicknessModifier_DistanceFromObject *)m)->range_min = 0.0f;
+ ((LineStyleThicknessModifier_DistanceFromObject *)m)->range_max = 1000.0f;
+ ((LineStyleThicknessModifier_DistanceFromObject *)m)->value_min = 0.0f;
+ ((LineStyleThicknessModifier_DistanceFromObject *)m)->value_max = 1.0f;
+ break;
+ case LS_MODIFIER_MATERIAL:
+ ((LineStyleThicknessModifier_Material *)m)->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ ((LineStyleThicknessModifier_Material *)m)->mat_attr = LS_MODIFIER_MATERIAL_DIFF;
+ ((LineStyleThicknessModifier_Material *)m)->value_min = 0.0f;
+ ((LineStyleThicknessModifier_Material *)m)->value_max = 1.0f;
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ ((LineStyleThicknessModifier_Calligraphy *)m)->min_thickness = 1.0f;
+ ((LineStyleThicknessModifier_Calligraphy *)m)->max_thickness = 10.0f;
+ ((LineStyleThicknessModifier_Calligraphy *)m)->orientation = 60.0f;
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->thickness_modifiers, m);
+
+ return m;
+}
+
+LineStyleModifier *FRS_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ LineStyleModifier *new_m;
+
+ new_m = alloc_thickness_modifier(m->type);
+ if (!new_m)
+ return NULL;
+ new_m->influence = m->influence;
+ new_m->flags = m->flags;
+ new_m->blend = m->blend;
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleThicknessModifier_AlongStroke *p = (LineStyleThicknessModifier_AlongStroke *)m;
+ ((LineStyleThicknessModifier_AlongStroke *)new_m)->curve = curvemapping_copy(p->curve);
+ ((LineStyleThicknessModifier_AlongStroke *)new_m)->value_min = p->value_min;
+ ((LineStyleThicknessModifier_AlongStroke *)new_m)->value_max = p->value_max;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleThicknessModifier_DistanceFromCamera *p = (LineStyleThicknessModifier_DistanceFromCamera *)m;
+ ((LineStyleThicknessModifier_DistanceFromCamera *)new_m)->curve = curvemapping_copy(p->curve);
+ ((LineStyleThicknessModifier_DistanceFromCamera *)new_m)->range_min = p->range_min;
+ ((LineStyleThicknessModifier_DistanceFromCamera *)new_m)->range_max = p->range_max;
+ ((LineStyleThicknessModifier_DistanceFromCamera *)new_m)->value_min = p->value_min;
+ ((LineStyleThicknessModifier_DistanceFromCamera *)new_m)->value_max = p->value_max;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)m;
+ if (p->target)
+ p->target->id.us++;
+ ((LineStyleThicknessModifier_DistanceFromObject *)new_m)->target = p->target;
+ ((LineStyleThicknessModifier_DistanceFromObject *)new_m)->curve = curvemapping_copy(p->curve);
+ ((LineStyleThicknessModifier_DistanceFromObject *)new_m)->range_min = p->range_min;
+ ((LineStyleThicknessModifier_DistanceFromObject *)new_m)->range_max = p->range_max;
+ ((LineStyleThicknessModifier_DistanceFromObject *)new_m)->value_min = p->value_min;
+ ((LineStyleThicknessModifier_DistanceFromObject *)new_m)->value_max = p->value_max;
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleThicknessModifier_Material *p = (LineStyleThicknessModifier_Material *)m;
+ ((LineStyleThicknessModifier_Material *)new_m)->curve = curvemapping_copy(p->curve);
+ ((LineStyleThicknessModifier_Material *)new_m)->mat_attr = p->mat_attr;
+ ((LineStyleThicknessModifier_Material *)new_m)->value_min = p->value_min;
+ ((LineStyleThicknessModifier_Material *)new_m)->value_max = p->value_max;
+ }
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ {
+ LineStyleThicknessModifier_Calligraphy *p = (LineStyleThicknessModifier_Calligraphy *)m;
+ ((LineStyleThicknessModifier_Calligraphy *)new_m)->min_thickness = p->min_thickness;
+ ((LineStyleThicknessModifier_Calligraphy *)new_m)->max_thickness = p->max_thickness;
+ ((LineStyleThicknessModifier_Calligraphy *)new_m)->orientation = p->orientation;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->thickness_modifiers, new_m);
+
+ return new_m;
+}
+
+void FRS_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ curvemapping_free(((LineStyleThicknessModifier_AlongStroke *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ curvemapping_free(((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ curvemapping_free(((LineStyleThicknessModifier_DistanceFromObject *)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ curvemapping_free(((LineStyleThicknessModifier_Material *)m)->curve);
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ break;
+ }
+ BLI_freelinkN(&linestyle->thickness_modifiers, m);
+}
+
+static LineStyleModifier *alloc_geometry_modifier(int type)
+{
+ size_t size;
+
+ switch (type) {
+ case LS_MODIFIER_SAMPLING:
+ size = sizeof(LineStyleGeometryModifier_Sampling);
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ size = sizeof(LineStyleGeometryModifier_BezierCurve);
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ size = sizeof(LineStyleGeometryModifier_SinusDisplacement);
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ size = sizeof(LineStyleGeometryModifier_SpatialNoise);
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ size = sizeof(LineStyleGeometryModifier_PerlinNoise1D);
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ size = sizeof(LineStyleGeometryModifier_PerlinNoise2D);
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ size = sizeof(LineStyleGeometryModifier_BackboneStretcher);
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ size = sizeof(LineStyleGeometryModifier_TipRemover);
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ size = sizeof(LineStyleGeometryModifier_Polygonalization);
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ size = sizeof(LineStyleGeometryModifier_GuidingLines);
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ size = sizeof(LineStyleGeometryModifier_Blueprint);
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ size = sizeof(LineStyleGeometryModifier_2DOffset);
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ size = sizeof(LineStyleGeometryModifier_2DTransform);
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ return new_modifier(type, size);
+}
+
+LineStyleModifier *FRS_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, int type)
+{
+ LineStyleModifier *m;
+
+ m = alloc_geometry_modifier(type);
+ if (!m)
+ return NULL;
+ switch (type) {
+ case LS_MODIFIER_SAMPLING:
+ ((LineStyleGeometryModifier_Sampling *)m)->sampling = 10.0;
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ ((LineStyleGeometryModifier_BezierCurve *)m)->error = 10.0;
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ ((LineStyleGeometryModifier_SinusDisplacement *)m)->wavelength = 20.0;
+ ((LineStyleGeometryModifier_SinusDisplacement *)m)->amplitude = 5.0;
+ ((LineStyleGeometryModifier_SinusDisplacement *)m)->phase = 0.0;
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ ((LineStyleGeometryModifier_SpatialNoise *)m)->amplitude = 5.0;
+ ((LineStyleGeometryModifier_SpatialNoise *)m)->scale = 20.0;
+ ((LineStyleGeometryModifier_SpatialNoise *)m)->octaves = 4;
+ ((LineStyleGeometryModifier_SpatialNoise *)m)->flags = LS_MODIFIER_SPATIAL_NOISE_SMOOTH | LS_MODIFIER_SPATIAL_NOISE_PURERANDOM;
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ ((LineStyleGeometryModifier_PerlinNoise1D *)m)->frequency = 10.0;
+ ((LineStyleGeometryModifier_PerlinNoise1D *)m)->amplitude = 10.0;
+ ((LineStyleGeometryModifier_PerlinNoise1D *)m)->octaves = 4;
+ ((LineStyleGeometryModifier_PerlinNoise1D *)m)->angle = 45.0;
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ ((LineStyleGeometryModifier_PerlinNoise2D *)m)->frequency = 10.0;
+ ((LineStyleGeometryModifier_PerlinNoise2D *)m)->amplitude = 10.0;
+ ((LineStyleGeometryModifier_PerlinNoise2D *)m)->octaves = 4;
+ ((LineStyleGeometryModifier_PerlinNoise2D *)m)->angle = 45.0;
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ ((LineStyleGeometryModifier_BackboneStretcher *)m)->backbone_length = 10.0;
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ ((LineStyleGeometryModifier_TipRemover *)m)->tip_length = 10.0;
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ ((LineStyleGeometryModifier_Polygonalization *)m)->error = 10.0;
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ ((LineStyleGeometryModifier_GuidingLines *)m)->offset = 0.0;
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ ((LineStyleGeometryModifier_Blueprint *)m)->flags = LS_MODIFIER_BLUEPRINT_CIRCLES;
+ ((LineStyleGeometryModifier_Blueprint *)m)->rounds = 1;
+ ((LineStyleGeometryModifier_Blueprint *)m)->backbone_length = 10.f;
+ ((LineStyleGeometryModifier_Blueprint *)m)->random_radius = 3;
+ ((LineStyleGeometryModifier_Blueprint *)m)->random_center = 5;
+ ((LineStyleGeometryModifier_Blueprint *)m)->random_backbone = 5;
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ ((LineStyleGeometryModifier_2DOffset *)m)->start = 0.f;
+ ((LineStyleGeometryModifier_2DOffset *)m)->end = 0.f;
+ ((LineStyleGeometryModifier_2DOffset *)m)->x = 0.f;
+ ((LineStyleGeometryModifier_2DOffset *)m)->y = 0.f;
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ ((LineStyleGeometryModifier_2DTransform *)m)->pivot = LS_MODIFIER_2D_TRANSFORM_PIVOT_CENTER;
+ ((LineStyleGeometryModifier_2DTransform *)m)->scale_x = 1.f;
+ ((LineStyleGeometryModifier_2DTransform *)m)->scale_y = 1.f;
+ ((LineStyleGeometryModifier_2DTransform *)m)->angle = 0.f;
+ ((LineStyleGeometryModifier_2DTransform *)m)->pivot_u = 0.5f;
+ ((LineStyleGeometryModifier_2DTransform *)m)->pivot_x = 0.f;
+ ((LineStyleGeometryModifier_2DTransform *)m)->pivot_y = 0.f;
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->geometry_modifiers, m);
+
+ return m;
+}
+
+LineStyleModifier *FRS_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ LineStyleModifier *new_m;
+
+ new_m = alloc_geometry_modifier(m->type);
+ if (!new_m)
+ return NULL;
+ new_m->flags = m->flags;
+ switch (m->type) {
+ case LS_MODIFIER_SAMPLING:
+ {
+ LineStyleGeometryModifier_Sampling *p = (LineStyleGeometryModifier_Sampling *)m;
+ ((LineStyleGeometryModifier_Sampling *)new_m)->sampling = p->sampling;
+ }
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ {
+ LineStyleGeometryModifier_BezierCurve *p = (LineStyleGeometryModifier_BezierCurve *)m;
+ ((LineStyleGeometryModifier_BezierCurve *)new_m)->error = p->error;
+ }
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ {
+ LineStyleGeometryModifier_SinusDisplacement *p = (LineStyleGeometryModifier_SinusDisplacement *)m;
+ ((LineStyleGeometryModifier_SinusDisplacement *)new_m)->wavelength = p->wavelength;
+ ((LineStyleGeometryModifier_SinusDisplacement *)new_m)->amplitude = p->amplitude;
+ ((LineStyleGeometryModifier_SinusDisplacement *)new_m)->phase = p->phase;
+ }
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ {
+ LineStyleGeometryModifier_SpatialNoise *p = (LineStyleGeometryModifier_SpatialNoise *)m;
+ ((LineStyleGeometryModifier_SpatialNoise *)new_m)->amplitude = p->amplitude;
+ ((LineStyleGeometryModifier_SpatialNoise *)new_m)->scale = p->scale;
+ ((LineStyleGeometryModifier_SpatialNoise *)new_m)->octaves = p->octaves;
+ ((LineStyleGeometryModifier_SpatialNoise *)new_m)->flags = p->flags;
+ }
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ {
+ LineStyleGeometryModifier_PerlinNoise1D *p = (LineStyleGeometryModifier_PerlinNoise1D *)m;
+ ((LineStyleGeometryModifier_PerlinNoise1D *)new_m)->frequency = p->frequency;
+ ((LineStyleGeometryModifier_PerlinNoise1D *)new_m)->amplitude = p->amplitude;
+ ((LineStyleGeometryModifier_PerlinNoise1D *)new_m)->octaves = p->octaves;
+ ((LineStyleGeometryModifier_PerlinNoise1D *)new_m)->angle = p->angle;
+ }
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ {
+ LineStyleGeometryModifier_PerlinNoise2D *p = (LineStyleGeometryModifier_PerlinNoise2D *)m;
+ ((LineStyleGeometryModifier_PerlinNoise2D *)new_m)->frequency = p->frequency;
+ ((LineStyleGeometryModifier_PerlinNoise2D *)new_m)->amplitude = p->amplitude;
+ ((LineStyleGeometryModifier_PerlinNoise2D *)new_m)->octaves = p->octaves;
+ ((LineStyleGeometryModifier_PerlinNoise2D *)new_m)->angle = p->angle;
+ }
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ {
+ LineStyleGeometryModifier_BackboneStretcher *p = (LineStyleGeometryModifier_BackboneStretcher *)m;
+ ((LineStyleGeometryModifier_BackboneStretcher *)new_m)->backbone_length = p->backbone_length;
+ }
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ {
+ LineStyleGeometryModifier_TipRemover *p = (LineStyleGeometryModifier_TipRemover *)m;
+ ((LineStyleGeometryModifier_TipRemover *)new_m)->tip_length = p->tip_length;
+ }
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ {
+ LineStyleGeometryModifier_Polygonalization *p = (LineStyleGeometryModifier_Polygonalization *)m;
+ ((LineStyleGeometryModifier_Polygonalization *)new_m)->error = p->error;
+ }
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ {
+ LineStyleGeometryModifier_GuidingLines *p = (LineStyleGeometryModifier_GuidingLines *)m;
+ ((LineStyleGeometryModifier_GuidingLines *)new_m)->offset = p->offset;
+ }
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ {
+ LineStyleGeometryModifier_Blueprint *p = (LineStyleGeometryModifier_Blueprint *)m;
+ ((LineStyleGeometryModifier_Blueprint *)new_m)->flags = p->flags;
+ ((LineStyleGeometryModifier_Blueprint *)new_m)->rounds = p->rounds;
+ ((LineStyleGeometryModifier_Blueprint *)new_m)->backbone_length = p->backbone_length;
+ ((LineStyleGeometryModifier_Blueprint *)new_m)->random_radius = p->random_radius;
+ ((LineStyleGeometryModifier_Blueprint *)new_m)->random_center = p->random_center;
+ ((LineStyleGeometryModifier_Blueprint *)new_m)->random_backbone = p->random_backbone;
+ }
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ {
+ LineStyleGeometryModifier_2DOffset *p = (LineStyleGeometryModifier_2DOffset *)m;
+ ((LineStyleGeometryModifier_2DOffset *)new_m)->start = p->start;
+ ((LineStyleGeometryModifier_2DOffset *)new_m)->end = p->end;
+ ((LineStyleGeometryModifier_2DOffset *)new_m)->x = p->x;
+ ((LineStyleGeometryModifier_2DOffset *)new_m)->y = p->y;
+ }
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ {
+ LineStyleGeometryModifier_2DTransform *p = (LineStyleGeometryModifier_2DTransform *)m;
+ ((LineStyleGeometryModifier_2DTransform *)new_m)->pivot = p->pivot;
+ ((LineStyleGeometryModifier_2DTransform *)new_m)->scale_x = p->scale_x;
+ ((LineStyleGeometryModifier_2DTransform *)new_m)->scale_y = p->scale_y;
+ ((LineStyleGeometryModifier_2DTransform *)new_m)->angle = p->angle;
+ ((LineStyleGeometryModifier_2DTransform *)new_m)->pivot_u = p->pivot_u;
+ ((LineStyleGeometryModifier_2DTransform *)new_m)->pivot_x = p->pivot_x;
+ ((LineStyleGeometryModifier_2DTransform *)new_m)->pivot_y = p->pivot_y;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->geometry_modifiers, new_m);
+
+ return new_m;
+}
+
+void FRS_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ switch (m->type) {
+ case LS_MODIFIER_SAMPLING:
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ break;
+ }
+ BLI_freelinkN(&linestyle->geometry_modifiers, m);
+}
+
+static void move_modifier(ListBase *lb, LineStyleModifier *modifier, int direction)
+{
+ BLI_remlink(lb, modifier);
+ if (direction > 0)
+ BLI_insertlinkbefore(lb, modifier->prev, modifier);
+ else
+ BLI_insertlinkafter(lb, modifier->next, modifier);
+}
+
+void FRS_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+{
+ move_modifier(&linestyle->color_modifiers, modifier, direction);
+}
+
+void FRS_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+{
+ move_modifier(&linestyle->alpha_modifiers, modifier, direction);
+}
+
+void FRS_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+{
+ move_modifier(&linestyle->thickness_modifiers, modifier, direction);
+}
+
+void FRS_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+{
+ move_modifier(&linestyle->geometry_modifiers, modifier, direction);
+}
+
+void FRS_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase)
+{
+ LineStyleModifier *m;
+ ColorBand *color_ramp;
+ LinkData *link;
+
+ listbase->first = listbase->last = NULL;
+ for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ color_ramp = ((LineStyleColorModifier_AlongStroke *)m)->color_ramp;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ color_ramp = ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ color_ramp = ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp;
+ break;
+ case LS_MODIFIER_MATERIAL:
+ color_ramp = ((LineStyleColorModifier_Material *)m)->color_ramp;
+ break;
+ default:
+ continue;
+ }
+ link = (LinkData *) MEM_callocN( sizeof(LinkData), "link to color ramp");
+ link->data = color_ramp;
+ BLI_addtail(listbase, link);
+ }
+}
+
+char *FRS_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp)
+{
+ LineStyleModifier *m;
+
+ for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ if (color_ramp == ((LineStyleColorModifier_AlongStroke *)m)->color_ramp)
+ goto found;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ if (color_ramp == ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp)
+ goto found;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ if (color_ramp == ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp)
+ goto found;
+ break;
+ case LS_MODIFIER_MATERIAL:
+ if (color_ramp == ((LineStyleColorModifier_Material *)m)->color_ramp)
+ goto found;
+ break;
+ }
+ }
+ printf("FRS_path_from_ID_to_color_ramp: No color ramps correspond to the given pointer.\n");
+ return NULL;
+
+found:
+ return BLI_sprintfN("color_modifiers[\"%s\"].color_ramp", m->name);
+}
+
+void FRS_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob)
+{
+ LineStyleModifier *m;
+
+ for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) {
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ if (((LineStyleColorModifier_DistanceFromObject *)m)->target == ob) {
+ ((LineStyleColorModifier_DistanceFromObject *)m)->target = NULL;
+ }
+ }
+ }
+ for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next) {
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ if (((LineStyleAlphaModifier_DistanceFromObject *)m)->target == ob) {
+ ((LineStyleAlphaModifier_DistanceFromObject *)m)->target = NULL;
+ }
+ }
+ }
+ for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next) {
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ if (((LineStyleThicknessModifier_DistanceFromObject *)m)->target == ob) {
+ ((LineStyleThicknessModifier_DistanceFromObject *)m)->target = NULL;
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 00898b0fe10..1a9ac9dc0af 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -410,8 +410,8 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size)
{
MemArena *arena = BLI_memarena_new(1 << 16, __func__);
- const float bucket_dim_x = BLI_RCT_SIZE_X(&layer->bounds);
- const float bucket_dim_y = BLI_RCT_SIZE_Y(&layer->bounds);
+ const float bucket_dim_x = BLI_rctf_size_x(&layer->bounds);
+ const float bucket_dim_y = BLI_rctf_size_y(&layer->bounds);
layer->buckets_x = (bucket_dim_x / pixel_size) / (float)BUCKET_PIXELS_PER_CELL;
layer->buckets_y = (bucket_dim_y / pixel_size) / (float)BUCKET_PIXELS_PER_CELL;
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 7523c59a879..3408e2393c9 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -153,6 +153,7 @@ void init_material(Material *ma)
ma->tx_limit = 0.0;
ma->tx_falloff = 1.0;
ma->shad_alpha = 1.0f;
+ ma->vcol_alpha = 0;
ma->gloss_mir = ma->gloss_tra = 1.0;
ma->samp_gloss_mir = ma->samp_gloss_tra = 18;
@@ -941,7 +942,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
if (ma->texco & (TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM | TEXCO_STRAND | TEXCO_STRESS)) needuv = 1;
else if (ma->texco & (TEXCO_GLOB | TEXCO_UV | TEXCO_OBJECT | TEXCO_SPEED)) needuv = 1;
- else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW | TEXCO_STICKY)) needuv = 1;
+ else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW)) needuv = 1;
if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT))
needtang = 1;
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 3925c3cc858..2030ab0f552 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -186,7 +186,7 @@ void BKE_mball_unlink(MetaBall *mb)
/* do not free mball itself */
void BKE_mball_free(MetaBall *mb)
{
- BKE_mball_unlink(mb);
+ BKE_mball_unlink(mb);
if (mb->adt) {
BKE_free_animdata((ID *)mb);
@@ -562,7 +562,7 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis)
basis = ob;
basisnr = obnr;
}
- }
+ }
}
}
@@ -691,7 +691,7 @@ static float densfunc(MetaElem *ball, float x, float y, float z)
/* *** end deprecated *** */
}
- dist2 = 1.0f - (len_v3(dvec) / ball->rad2);
+ dist2 = 1.0f - (len_squared_v3(dvec) / ball->rad2);
if ((ball->flag & MB_NEGATIVE) == 0) {
return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f;
@@ -732,7 +732,7 @@ static octal_node *find_metaball_octal_node(octal_node *node, float x, float y,
return find_metaball_octal_node(node->nodes[2], x, y, z, depth--);
else
return node;
- }
+ }
}
}
else {
@@ -762,7 +762,7 @@ static octal_node *find_metaball_octal_node(octal_node *node, float x, float y,
return find_metaball_octal_node(node->nodes[6], x, y, z, depth--);
else
return node;
- }
+ }
}
}
@@ -861,7 +861,7 @@ static void *new_pgn_element(int size)
}
BLI_freelistN(&lb);
- return NULL;
+ return NULL;
}
size = 4 * ( (size + 3) / 4);
@@ -1628,7 +1628,7 @@ static void polygonize(PROCESS *mbproc, MetaBall *mb)
for (a = 0; a < G_mb.totelem; a++) {
/* try to find 8 points on the surface for each MetaElem */
- find_first_points(mbproc, mb, a);
+ find_first_points(mbproc, mb, a);
}
/* polygonize all MetaElems of current MetaBall */
@@ -2038,7 +2038,7 @@ static void subdivide_metaball_octal_node(octal_node *node, float size_x, float
}
- /* ml belongs to the (4)5th node too */
+ /* ml belongs to the (4)5th node too */
if (ml->bb->vec[6][2] >= z) {
fill_metaball_octal_node(node, ml, 4);
}
@@ -2226,7 +2226,7 @@ static void init_metaball_octal_tree(int depth)
}
}
- /* size of first node */
+ /* size of first node */
size[0] = node->x_max - node->x_min;
size[1] = node->y_max - node->y_min;
size[2] = node->z_max - node->z_min;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 8c3ec7e2e40..206d80a6ff0 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -367,7 +367,6 @@ void mesh_update_customdata_pointers(Mesh *me, const short do_ensure_tess_cd)
me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
- me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY);
me->medge = CustomData_get_layer(&me->edata, CD_MEDGE);
@@ -1944,8 +1943,9 @@ void BKE_mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpo
MVert *mv = &mverts[i];
float *no = tnorms[i];
- if (normalize_v3(no) == 0.0f)
+ if (UNLIKELY(normalize_v3(no) == 0.0f)) {
normalize_v3_v3(no, mv->co);
+ }
normal_float_to_short_v3(mv->no, no);
}
@@ -1981,8 +1981,9 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces,
MVert *mv = &mverts[i];
float *no = tnorms[i];
- if (normalize_v3(no) == 0.0f)
+ if (UNLIKELY(normalize_v3(no) == 0.0f)) {
normalize_v3_v3(no, mv->co);
+ }
normal_float_to_short_v3(mv->no, no);
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 65538e5bea2..28de80a7157 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -482,7 +482,7 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
}
/* shape key modifier, not yet for curves */
- if (ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) {
+ if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) {
if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
else
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 5ba56a85c72..6fd7a55dd0a 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -115,6 +115,8 @@
#include "GPU_material.h"
+#include "FRS_freestyle.h"
+
/* Local function protos */
float originmat[3][3]; /* after BKE_object_where_is_calc(), can be used in other functions (bad!) */
@@ -340,7 +342,7 @@ void BKE_object_free(Object *ob)
BKE_pose_free(ob->pose);
if (ob->mpath)
animviz_free_motionpath(ob->mpath);
- free_properties(&ob->prop);
+ BKE_bproperty_free_list(&ob->prop);
BKE_object_free_modifiers(ob);
free_sensors(&ob->sensors);
@@ -630,6 +632,14 @@ void BKE_object_unlink(Object *ob)
}
SEQ_END
}
+
+ {
+ SceneRenderLayer *srl;
+
+ for (srl= sce->r.layers.first; srl; srl= srl->next) {
+ FRS_unlink_target_object(&srl->freestyleConfig, ob);
+ }
+ }
}
sce = sce->id.next;
@@ -1079,12 +1089,12 @@ static void copy_object_pose(Object *obn, Object *ob)
}
}
-static int object_pose_context(Object *ob)
+int BKE_object_pose_context_check(Object *ob)
{
- if ( (ob) &&
- (ob->type == OB_ARMATURE) &&
- (ob->pose) &&
- (ob->mode & OB_MODE_POSE))
+ if ((ob) &&
+ (ob->type == OB_ARMATURE) &&
+ (ob->pose) &&
+ (ob->mode & OB_MODE_POSE))
{
return 1;
}
@@ -1098,12 +1108,12 @@ Object *BKE_object_pose_armature_get(Object *ob)
if (ob == NULL)
return NULL;
- if (object_pose_context(ob))
+ if (BKE_object_pose_context_check(ob))
return ob;
ob = modifiers_isDeformedByArmature(ob);
- if (object_pose_context(ob))
+ if (BKE_object_pose_context_check(ob))
return ob;
return NULL;
@@ -1147,7 +1157,7 @@ Object *BKE_object_copy(Object *ob)
}
obn->prop.first = obn->prop.last = NULL;
- copy_properties(&obn->prop, &ob->prop);
+ BKE_bproperty_copy_list(&obn->prop, &ob->prop);
copy_sensors(&obn->sensors, &ob->sensors);
copy_controllers(&obn->controllers, &ob->controllers);
@@ -1766,7 +1776,6 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4])
static void give_parvert(Object *par, int nr, float vec[3])
{
BMEditMesh *em;
- int a, count;
zero_v3(vec);
@@ -1795,18 +1804,28 @@ static void give_parvert(Object *par, int nr, float vec[3])
dm = (em) ? em->derivedFinal : par->derivedFinal;
if (dm) {
- MVert *mvert = dm->getVertArray(dm);
- int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
- int i, vindex, numVerts = dm->getNumVerts(dm);
-
- /* get the average of all verts with (original index == nr) */
- count = 0;
- for (i = 0; i < numVerts; i++) {
- vindex = (index) ? index[i] : i;
-
- if (vindex == nr) {
- add_v3_v3(vec, mvert[i].co);
- count++;
+ int count = 0;
+ int numVerts = dm->getNumVerts(dm);
+
+ if (nr < numVerts) {
+ MVert *mvert = dm->getVertArray(dm);
+ int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
+ int i;
+
+ /* get the average of all verts with (original index == nr) */
+ if (index) {
+ for (i = 0; i < numVerts; i++) {
+ if (index[i] == nr) {
+ add_v3_v3(vec, mvert[i].co);
+ count++;
+ }
+ }
+ }
+ else {
+ if (nr < numVerts) {
+ add_v3_v3(vec, mvert[nr].co);
+ count++;
+ }
}
}
@@ -1828,71 +1847,31 @@ static void give_parvert(Object *par, int nr, float vec[3])
}
}
else if (ELEM(par->type, OB_CURVE, OB_SURF)) {
- Nurb *nu;
- Curve *cu;
- BPoint *bp;
- BezTriple *bezt;
- int found = 0;
- ListBase *nurbs;
-
- cu = par->data;
- nurbs = BKE_curve_nurbs_get(cu);
- nu = nurbs->first;
-
- count = 0;
- while (nu && !found) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (count == nr) {
- found = 1;
- copy_v3_v3(vec, bezt->vec[1]);
- break;
- }
- count++;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (count == nr) {
- found = 1;
- copy_v3_v3(vec, bp->vec);
- break;
- }
- count++;
- bp++;
- }
- }
- nu = nu->next;
- }
+ Curve *cu = par->data;
+ ListBase *nurb = BKE_curve_nurbs_get(cu);;
+ BKE_nurbList_index_get_co(nurb, nr, vec);
}
else if (par->type == OB_LATTICE) {
- Lattice *latt = par->data;
- BPoint *bp;
- DispList *dl = BKE_displist_find(&par->disp, DL_VERTS);
- float *co = dl ? dl->verts : NULL;
-
+ Lattice *latt = par->data;
+ DispList *dl = BKE_displist_find(&par->disp, DL_VERTS);
+ float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL;
+ int tot;
+
if (latt->editlatt) latt = latt->editlatt->latt;
-
- a = latt->pntsu * latt->pntsv * latt->pntsw;
- count = 0;
- bp = latt->def;
- while (a--) {
- if (count == nr) {
- if (co)
- copy_v3_v3(vec, co);
- else
- copy_v3_v3(vec, bp->vec);
- break;
+
+ tot = latt->pntsu * latt->pntsv * latt->pntsw;
+
+ /* ensure dl is correct size */
+ BLI_assert(dl == NULL || dl->nr == tot);
+
+ if (nr < tot) {
+ if (co) {
+ copy_v3_v3(vec, co[nr]);
+ }
+ else {
+ copy_v3_v3(vec, latt->def[nr].vec);
}
- count++;
- if (co) co += 3;
- else bp++;
}
}
}
@@ -2899,22 +2878,22 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int
int newkey = 0;
if (key == NULL) {
- key = me->key = add_key((ID *)me);
+ key = me->key = BKE_key_add((ID *)me);
key->type = KEY_RELATIVE;
newkey = 1;
}
if (newkey || from_mix == FALSE) {
/* create from mesh */
- kb = add_keyblock_ctime(key, name, FALSE);
- mesh_to_key(me, kb);
+ kb = BKE_keyblock_add_ctime(key, name, FALSE);
+ BKE_key_convert_from_mesh(me, kb);
}
else {
/* copy from current values */
float *data = do_ob_key(scene, ob);
/* create new block with prepared data */
- kb = add_keyblock_ctime(key, name, FALSE);
+ kb = BKE_keyblock_add_ctime(key, name, FALSE);
kb->data = data;
kb->totelem = me->totvert;
}
@@ -2930,20 +2909,20 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int
int newkey = 0;
if (key == NULL) {
- key = lt->key = add_key((ID *)lt);
+ key = lt->key = BKE_key_add((ID *)lt);
key->type = KEY_RELATIVE;
newkey = 1;
}
if (newkey || from_mix == FALSE) {
- kb = add_keyblock_ctime(key, name, FALSE);
+ kb = BKE_keyblock_add_ctime(key, name, FALSE);
if (!newkey) {
KeyBlock *basekb = (KeyBlock *)key->block.first;
kb->data = MEM_dupallocN(basekb->data);
kb->totelem = basekb->totelem;
}
else {
- latt_to_key(lt, kb);
+ BKE_key_convert_from_lattice(lt, kb);
}
}
else {
@@ -2951,7 +2930,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int
float *data = do_ob_key(scene, ob);
/* create new block with prepared data */
- kb = add_keyblock_ctime(key, name, FALSE);
+ kb = BKE_keyblock_add_ctime(key, name, FALSE);
kb->totelem = lt->pntsu * lt->pntsv * lt->pntsw;
kb->data = data;
}
@@ -2968,21 +2947,21 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int
int newkey = 0;
if (key == NULL) {
- key = cu->key = add_key((ID *)cu);
+ key = cu->key = BKE_key_add((ID *)cu);
key->type = KEY_RELATIVE;
newkey = 1;
}
if (newkey || from_mix == FALSE) {
/* create from curve */
- kb = add_keyblock_ctime(key, name, FALSE);
+ kb = BKE_keyblock_add_ctime(key, name, FALSE);
if (!newkey) {
KeyBlock *basekb = (KeyBlock *)key->block.first;
kb->data = MEM_dupallocN(basekb->data);
kb->totelem = basekb->totelem;
}
else {
- curve_to_key(cu, kb, lb);
+ BKE_key_convert_from_curve(cu, kb, lb);
}
}
else {
@@ -2990,7 +2969,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int
float *data = do_ob_key(scene, ob);
/* create new block with prepared data */
- kb = add_keyblock_ctime(key, name, FALSE);
+ kb = BKE_keyblock_add_ctime(key, name, FALSE);
kb->totelem = BKE_nurbList_verts_count(lb);
kb->data = data;
}
@@ -3020,7 +2999,7 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
{
int flag = 0;
- if (ob_get_key(ob)) {
+ if (BKE_key_from_object(ob)) {
flag |= eModifierMode_Render;
}
else {
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 26952db8fba..ef03db7ed8f 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -4539,8 +4539,8 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
/* can happen with bad pointcache or physics calculation
* since this becomes geometry, nan's and inf's crash raytrace code.
* better not allow this. */
- if (!finite(bb->vec[0]) || !finite(bb->vec[1]) || !finite(bb->vec[2]) ||
- !finite(bb->vel[0]) || !finite(bb->vel[1]) || !finite(bb->vel[2]) )
+ if ((!finite(bb->vec[0])) || (!finite(bb->vec[1])) || (!finite(bb->vec[2])) ||
+ (!finite(bb->vel[0])) || (!finite(bb->vel[1])) || (!finite(bb->vel[2])) )
{
zero_v3(bb->vec);
zero_v3(bb->vel);
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index 46ddce4b51b..8da4f11fed3 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -27,9 +27,12 @@
/** \file blender/blenkernel/intern/property.c
* \ingroup bke
+ *
+ * This module deals with bProperty only,
+ * they are used on blender objects in the game engine
+ * (where they get converted into C++ classes - CValue and subclasses)
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
@@ -45,7 +48,7 @@
#include "BKE_property.h"
-void free_property(bProperty *prop)
+void BKE_bproperty_free(bProperty *prop)
{
if (prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin);
@@ -53,17 +56,17 @@ void free_property(bProperty *prop)
}
-void free_properties(ListBase *lb)
+void BKE_bproperty_free_list(ListBase *lb)
{
bProperty *prop;
while ( (prop = lb->first) ) {
BLI_remlink(lb, prop);
- free_property(prop);
+ BKE_bproperty_free(prop);
}
}
-bProperty *copy_property(bProperty *prop)
+bProperty *BKE_bproperty_copy(bProperty *prop)
{
bProperty *propn;
@@ -76,13 +79,13 @@ bProperty *copy_property(bProperty *prop)
return propn;
}
-void copy_properties(ListBase *lbn, ListBase *lbo)
+void BKE_bproperty_copy_list(ListBase *lbn, ListBase *lbo)
{
bProperty *prop, *propn;
- free_properties(lbn); /* in case we are copying to an object with props */
+ BKE_bproperty_free_list(lbn); /* in case we are copying to an object with props */
prop = lbo->first;
while (prop) {
- propn = copy_property(prop);
+ propn = BKE_bproperty_copy(prop);
BLI_addtail(lbn, propn);
prop = prop->next;
}
@@ -90,7 +93,7 @@ void copy_properties(ListBase *lbn, ListBase *lbo)
}
-void init_property(bProperty *prop)
+void BKE_bproperty_init(bProperty *prop)
{
/* also use when property changes type */
@@ -113,22 +116,22 @@ void init_property(bProperty *prop)
}
-bProperty *new_property(int type)
+bProperty *BKE_bproperty_new(int type)
{
bProperty *prop;
prop = MEM_callocN(sizeof(bProperty), "property");
prop->type = type;
- init_property(prop);
+ BKE_bproperty_init(prop);
strcpy(prop->name, "prop");
return prop;
}
-/* used by unique_property() only */
-static bProperty *get_property__internal(bProperty *first, bProperty *self, const char *name)
+/* used by BKE_bproperty_unique() only */
+static bProperty *bproperty_get(bProperty *first, bProperty *self, const char *name)
{
bProperty *p;
for (p = first; p; p = p->next) {
@@ -137,7 +140,7 @@ static bProperty *get_property__internal(bProperty *first, bProperty *self, cons
}
return NULL;
}
-void unique_property(bProperty *first, bProperty *prop, int force)
+void BKE_bproperty_unique(bProperty *first, bProperty *prop, int force)
{
bProperty *p;
@@ -151,13 +154,13 @@ void unique_property(bProperty *first, bProperty *prop, int force)
if (force) {
/* change other names to make them unique */
- while ((p = get_property__internal(first, prop, prop->name))) {
- unique_property(first, p, 0);
+ while ((p = bproperty_get(first, prop, prop->name))) {
+ BKE_bproperty_unique(first, p, 0);
}
}
else {
/* change our own name until its unique */
- if (get_property__internal(first, prop, prop->name)) {
+ if (bproperty_get(first, prop, prop->name)) {
/* there is a collision */
char new_name[sizeof(prop->name)];
char base_name[sizeof(prop->name)];
@@ -175,33 +178,34 @@ void unique_property(bProperty *first, bProperty *prop, int force)
BLI_snprintf(num, sizeof(num), "%d", i++);
BLI_strncpy(new_name, base_name, sizeof(prop->name) - strlen(num));
strcat(new_name, num);
- } while (get_property__internal(first, prop, new_name));
+ } while (bproperty_get(first, prop, new_name));
BLI_strncpy(prop->name, new_name, sizeof(prop->name));
}
}
}
-bProperty *get_ob_property(Object *ob, const char *name)
+bProperty *BKE_bproperty_object_get(Object *ob, const char *name)
{
return BLI_findstring(&ob->prop, name, offsetof(bProperty, name));
}
-void set_ob_property(Object *ob, bProperty *propc)
+void BKE_bproperty_object_set(Object *ob, bProperty *propc)
{
bProperty *prop;
- prop = get_ob_property(ob, propc->name);
+ prop = BKE_bproperty_object_get(ob, propc->name);
if (prop) {
- free_property(prop);
+ BKE_bproperty_free(prop);
BLI_remlink(&ob->prop, prop);
}
- BLI_addtail(&ob->prop, copy_property(propc));
+ BLI_addtail(&ob->prop, BKE_bproperty_copy(propc));
}
/* negative: prop is smaller
* positive: prop is larger
*/
-int compare_property(bProperty *prop, const char *str)
+#if 0 /* UNUSED */
+int BKE_bproperty_cmp(bProperty *prop, const char *str)
{
// extern int Gdfra; /* sector.c */
float fvalue, ftest;
@@ -237,8 +241,9 @@ int compare_property(bProperty *prop, const char *str)
return 0;
}
+#endif
-void set_property(bProperty *prop, const char *str)
+void BKE_bproperty_set(bProperty *prop, const char *str)
{
// extern int Gdfra; /* sector.c */
@@ -262,7 +267,7 @@ void set_property(bProperty *prop, const char *str)
}
-void add_property(bProperty *prop, const char *str)
+void BKE_bproperty_add(bProperty *prop, const char *str)
{
// extern int Gdfra; /* sector.c */
@@ -282,7 +287,7 @@ void add_property(bProperty *prop, const char *str)
}
/* reads value of property, sets it in chars in str */
-void set_property_valstr(bProperty *prop, char *str)
+void BKE_bproperty_set_valstr(bProperty *prop, char *str)
{
// extern int Gdfra; /* sector.c */
@@ -303,11 +308,13 @@ void set_property_valstr(bProperty *prop, char *str)
}
}
+#if 0 /* UNUSED */
void cp_property(bProperty *prop1, bProperty *prop2)
{
char str[128];
- set_property_valstr(prop2, str);
+ BKE_bproperty_set_valstr(prop2, str);
- set_property(prop1, str);
+ BKE_bproperty_set(prop1, str);
}
+#endif
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 7d9d2f02c06..6c1fbbfa9a0 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -210,7 +210,7 @@ void unlink_controllers(ListBase *lb)
bController *cont;
for (cont= lb->first; cont; cont= cont->next)
- unlink_controller(cont);
+ unlink_controller(cont);
}
void free_controller(bController *cont)
@@ -536,7 +536,7 @@ void clear_sca_new_poins(void)
ob= G.main->object.first;
while (ob) {
clear_sca_new_poins_ob(ob);
- ob= ob->id.next;
+ ob= ob->id.next;
}
}
@@ -624,7 +624,7 @@ void set_sca_new_poins(void)
ob= G.main->object.first;
while (ob) {
set_sca_new_poins_ob(ob);
- ob= ob->id.next;
+ ob= ob->id.next;
}
}
@@ -696,7 +696,7 @@ void sca_remove_ob_poin(Object *obt, Object *ob)
if (sta->target == ob) sta->target = NULL;
}
act= act->next;
- }
+ }
}
/* ******************** INTERFACE ******************* */
@@ -875,3 +875,20 @@ void unlink_logicbricks(void **poin, void ***ppoin, short *tot)
return;
}
}
+
+const char *sca_state_name_get(Object *ob, short bit)
+{
+ bController *cont;
+ unsigned int mask;
+
+ mask = (1<<bit);
+ cont = ob->controllers.first;
+ while (cont) {
+ if (cont->state_mask & mask) {
+ return cont->name;
+ }
+ cont = cont->next;
+ }
+ return NULL;
+}
+
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 2dec72560a2..0c0396ea758 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -82,6 +82,8 @@
//XXX #include "BIF_previewrender.h"
//XXX #include "BIF_editseq.h"
+#include "FRS_freestyle_config.h"
+
#ifdef WIN32
#else
#include <sys/time.h>
@@ -135,8 +137,6 @@ Scene *BKE_scene_copy(Scene *sce, int type)
MEM_freeN(scen->toolsettings);
}
else {
- ImageFormatData *im_format, *im_formatn;
-
scen = BKE_libblock_copy(&sce->id);
BLI_duplicatelist(&(scen->base), &(sce->base));
@@ -174,11 +174,9 @@ Scene *BKE_scene_copy(Scene *sce, int type)
}
/* copy color management settings */
- im_format = &sce->r.im_format;
- im_formatn = &scen->r.im_format;
-
BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings);
BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings);
+ BKE_color_managed_view_settings_copy(&scen->r.im_format.view_settings, &sce->r.im_format.view_settings);
}
/* tool settings */
@@ -261,7 +259,8 @@ Scene *BKE_scene_copy(Scene *sce, int type)
void BKE_scene_free(Scene *sce)
{
Base *base;
-
+ SceneRenderLayer *srl;
+
base = sce->base.first;
while (base) {
base->object->id.us--;
@@ -301,6 +300,10 @@ void BKE_scene_free(Scene *sce)
sce->r.ffcodecdata.properties = NULL;
}
+ for(srl= sce->r.layers.first; srl; srl= srl->next) {
+ FRS_free_freestyle_config(srl);
+ }
+
BLI_freelistN(&sce->markers);
BLI_freelistN(&sce->transform_spaces);
BLI_freelistN(&sce->r.layers);
@@ -1140,6 +1143,7 @@ SceneRenderLayer *BKE_scene_add_render_layer(Scene *sce, const char *name)
srl->lay = (1 << 20) - 1;
srl->layflag = 0x7FFF; /* solid ztra halo edge strand */
srl->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
+ FRS_add_freestyle_config( srl );
return srl;
}
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 4a88bfbfdad..4c28fe01895 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -143,7 +143,9 @@ typedef struct SB_thread_context {
} SB_thread_context;
#define NLF_BUILD 1
-#define NLF_SOLVE 2
+#if 0
+# define NLF_SOLVE 2
+#endif
#define MID_PRESERVE 1
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index f340bcb5b1e..385d1bb6fc5 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -792,7 +792,6 @@ void sound_stop_scene(struct Scene *UNUSED(scene)) {}
void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; }
int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; }
-int sound_read_sound_buffer(struct bSound *UNUSED(sound), float *UNUSED(buffer), int UNUSED(length), float UNUSED(start), float UNUSED(end)) { return 0; }
void sound_read_waveform(struct bSound *sound) { (void)sound; }
void sound_init_main(struct Main *bmain) { (void)bmain; }
void sound_set_cfra(int cfra) { (void)cfra; }
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 555ed5890c8..facf0793f87 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -513,10 +513,14 @@ static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
w2 = (1.0f - fx + fac2 * fx * -fac) * (fy);
w4 = (fx) * (1.0f - fy + -fac2 * fy * fac);
- fac2 = 1.0f - (w1 + w2 + w4);
- fac2 = fac2 / (float)(faceLen - 3);
- for (j = 0; j < faceLen; j++)
- w[j] = fac2;
+ /* these values aren't used for tri's and cause divide by zero */
+ if (faceLen > 3) {
+ fac2 = 1.0f - (w1 + w2 + w4);
+ fac2 = fac2 / (float)(faceLen - 3);
+ for (j = 0; j < faceLen; j++) {
+ w[j] = fac2;
+ }
+ }
w[i] = w1;
w[(i - 1 + faceLen) % faceLen] = w2;
@@ -960,7 +964,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
edgeFlag = (ccgdm->edgeFlags) ? &ccgdm->edgeFlags[i] : NULL;
if (edgeFlag)
- flags |= (*edgeFlag & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER;
+ flags |= (*edgeFlag & (ME_SEAM | ME_SHARP | ME_FREESTYLE_EDGE)) | ME_EDGEDRAW | ME_EDGERENDER;
else
flags |= ME_EDGEDRAW | ME_EDGERENDER;
@@ -1224,7 +1228,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
if (edgeFlags) {
if (edgeIdx != -1) {
- flags |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER);
+ flags |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP | ME_FREESTYLE_EDGE)) | ME_EDGEDRAW | ME_EDGERENDER);
}
}
else {
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 3c89fdba13a..1f1d609ae42 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -1919,6 +1919,7 @@ static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, s
break;
case 4: /* 32-bit unicode symbol */
unicode = txt_undo_read_uint32(undo_buf, undo_pos);
+ break;
default:
/* should never happen */
BLI_assert(0);
@@ -1970,6 +1971,7 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s
break;
case 4: /* 32-bit unicode symbol */
unicode = txt_undo_read_uint32(undo_buf, undo_pos);
+ break;
default:
/* should never happen */
BLI_assert(0);
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 97ebc3a90ba..337f1b5d248 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -856,7 +856,7 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height
}
/* TODO: add an option to control whether AA is enabled or not */
- PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE);
+ PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height);
MEM_freeN(mask_points);
}
@@ -1043,14 +1043,6 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event)
}
}
}
- else if (event == CLAMP_SEARCH_DIM) {
- float dim[2];
- sub_v2_v2v2(dim, pat_max, pat_min);
- for (a = 0; a < 2; a++) {
- marker->search_min[a] = pat_min[a];
- marker->search_max[a] = pat_max[a];
- }
- }
}
MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr)
@@ -2029,7 +2021,7 @@ static void track_context_free(void *customdata)
{
TrackContext *track_context = (TrackContext *)customdata;
-#if WITH_LIBMV
+#ifdef WITH_LIBMV
if (track_context->search_area)
MEM_freeN(track_context->search_area);
@@ -2289,9 +2281,9 @@ static ImBuf *tracking_context_get_reference_ibuf(MovieTrackingContext *context,
return ibuf;
}
-static void track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context,
- MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra,
- int frame_width, int frame_height)
+static int track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context,
+ MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra,
+ int frame_width, int frame_height)
{
MovieTrackingMarker *marker_keyed = NULL;
ImBuf *reference_ibuf = NULL;
@@ -2299,6 +2291,10 @@ static void track_context_update_reference(MovieTrackingContext *context, TrackC
/* calculate patch for keyframed position */
reference_ibuf = tracking_context_get_reference_ibuf(context, track, marker, curfra, &marker_keyed);
+
+ if (!reference_ibuf)
+ return FALSE;
+
track_context->marker = *marker_keyed;
if (track_context->search_area) {
@@ -2317,6 +2313,8 @@ static void track_context_update_reference(MovieTrackingContext *context, TrackC
}
IMB_freeImBuf(reference_ibuf);
+
+ return TRUE;
}
static void tracking_configure_tracker(TrackContext *track_context, MovieTrackingTrack *track,
@@ -2481,8 +2479,12 @@ int BKE_tracking_context_step(MovieTrackingContext *context)
float *patch_new;
if (need_readjust) {
- track_context_update_reference(context, track_context, track, marker,
- curfra, frame_width, frame_height);
+ if (track_context_update_reference(context, track_context, track, marker,
+ curfra, frame_width, frame_height) == FALSE)
+ {
+ /* happens when reference frame fails to be loaded */
+ continue;
+ }
}
/* for now track to the same search area dimension as marker has got for current frame
@@ -2776,7 +2778,7 @@ static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, L
int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size)
{
-#if WITH_LIBMV
+#ifdef WITH_LIBMV
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) {
diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h
index 3b7f2d6bbaf..833c416c1c1 100644
--- a/source/blender/blenlib/BLI_dynstr.h
+++ b/source/blender/blenlib/BLI_dynstr.h
@@ -80,7 +80,11 @@ void BLI_dynstr_appendf(DynStr *ds, const char *format, ...)
__attribute__ ((format(printf, 2, 3)))
#endif
;
-void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args);
+void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args)
+#ifdef __GNUC__
+__attribute__ ((format(printf, 2, 0)))
+#endif
+;
/**
* Find the length of a DynStr.
@@ -107,7 +111,6 @@ char *BLI_dynstr_get_cstring(DynStr *ds);
*
* \param ds The DynStr of interest.
* \param str The string to fill.
- * \return The contents of \a ds as a c-string.
*/
void BLI_dynstr_get_cstring_ex(DynStr *ds, char *str);
diff --git a/source/blender/blenlib/BLI_endian_switch.h b/source/blender/blenlib/BLI_endian_switch.h
index 7017e7ba789..7cb2790525d 100644
--- a/source/blender/blenlib/BLI_endian_switch.h
+++ b/source/blender/blenlib/BLI_endian_switch.h
@@ -27,16 +27,36 @@
* \ingroup bli
*/
-#include "BLI_endian_switch_inline.h"
+#ifdef __GNUC__
+# define ATTR_ENDIAN_SWITCH \
+ __attribute__((nonnull(1))) \
+ __attribute__((pure))
+#else
+# define ATTR_ENDIAN_SWITCH
+#endif
+
+/* BLI_endian_switch_inline.h */
+BLI_INLINE void BLI_endian_switch_int16(short *val) ATTR_ENDIAN_SWITCH;
+BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) ATTR_ENDIAN_SWITCH;
+BLI_INLINE void BLI_endian_switch_int32(int *val) ATTR_ENDIAN_SWITCH;
+BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) ATTR_ENDIAN_SWITCH;
+BLI_INLINE void BLI_endian_switch_float(float *val) ATTR_ENDIAN_SWITCH;
+BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ATTR_ENDIAN_SWITCH;
+BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_ENDIAN_SWITCH;
+BLI_INLINE void BLI_endian_switch_double(double *val) ATTR_ENDIAN_SWITCH;
/* endian_switch.c */
-void BLI_endian_switch_int16_array(short *val, const int size);
-void BLI_endian_switch_uint16_array(unsigned short *val, const int size);
-void BLI_endian_switch_int32_array(int *val, const int size);
-void BLI_endian_switch_uint32_array(unsigned int *val, const int size);
-void BLI_endian_switch_float_array(float *val, const int size);
-void BLI_endian_switch_int64_array(int64_t *val, const int size);
-void BLI_endian_switch_uint64_array(uint64_t *val, const int size);
-void BLI_endian_switch_double_array(double *val, const int size);
+void BLI_endian_switch_int16_array(short *val, const int size) ATTR_ENDIAN_SWITCH;
+void BLI_endian_switch_uint16_array(unsigned short *val, const int size) ATTR_ENDIAN_SWITCH;
+void BLI_endian_switch_int32_array(int *val, const int size) ATTR_ENDIAN_SWITCH;
+void BLI_endian_switch_uint32_array(unsigned int *val, const int size) ATTR_ENDIAN_SWITCH;
+void BLI_endian_switch_float_array(float *val, const int size) ATTR_ENDIAN_SWITCH;
+void BLI_endian_switch_int64_array(int64_t *val, const int size) ATTR_ENDIAN_SWITCH;
+void BLI_endian_switch_uint64_array(uint64_t *val, const int size) ATTR_ENDIAN_SWITCH;
+void BLI_endian_switch_double_array(double *val, const int size) ATTR_ENDIAN_SWITCH;
+
+#include "BLI_endian_switch_inline.h"
+
+#undef ATTR_ENDIAN_SWITCH
#endif /* __BLI_ENDIAN_SWITCH_H__ */
diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h
index a19909a8f26..1c6463eb6ea 100644
--- a/source/blender/blenlib/BLI_fileops_types.h
+++ b/source/blender/blenlib/BLI_fileops_types.h
@@ -46,7 +46,7 @@ struct direntry {
mode_t type;
char *relname;
char *path;
-#if (defined(WIN32) || defined(WIN64)) && (_MSC_VER >= 1500)
+#if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW32__) && (_MSC_VER >= 1500)
struct _stat64 s;
#elif defined(__MINGW32__)
struct _stati64 s;
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 886ed6f495d..6ee1498c855 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -30,8 +30,8 @@
* \ingroup bli
*/
-#ifdef WIN32
-#define _USE_MATH_DEFINES
+#ifdef _MSC_VER
+# define _USE_MATH_DEFINES
#endif
#include <math.h>
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index 6fe5d48d06e..7c8bf88943d 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -115,6 +115,8 @@ void rgba_float_to_uchar(unsigned char col_r[4], const float col_f[4]);
void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b);
+MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3], const int limit);
+
/***************** lift/gamma/gain / ASC-CDL conversion *****************/
void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 6c81ca3f0a9..de1d423bfad 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -173,6 +173,7 @@ MINLINE int is_one_v3(const float a[3]);
MINLINE int equals_v2v2(const float v1[2], const float v2[2]);
MINLINE int equals_v3v3(const float a[3], const float b[3]);
+MINLINE int compare_v2v2(const float a[3], const float b[3], const float limit);
MINLINE int compare_v3v3(const float a[3], const float b[3], const float limit);
MINLINE int compare_len_v3v3(const float a[3], const float b[3], const float limit);
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index eb9915d6c9b..de4c2cf3a86 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -55,6 +55,8 @@ void BLI_rcti_resize(struct rcti *rect, int x, int y);
void BLI_rctf_resize(struct rctf *rect, float x, float y);
void BLI_rctf_interp(struct rctf *rect, const struct rctf *rect_a, const struct rctf *rect_b, const float fac);
//void BLI_rcti_interp(struct rctf *rect, struct rctf *rect_a, struct rctf *rect_b, float fac);
+int BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]);
+int BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]);
int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit);
int BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b);
int BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest);
@@ -75,14 +77,28 @@ void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src);
void print_rctf(const char *str, const struct rctf *rect);
void print_rcti(const char *str, const struct rcti *rect);
-#define BLI_RCT_SIZE_X(rct) ((rct)->xmax - (rct)->xmin)
-#define BLI_RCT_SIZE_Y(rct) ((rct)->ymax - (rct)->ymin)
+/* hrmf, we need to work out this inline stuff */
+#if defined(_MSC_VER)
+# define BLI_INLINE static __forceinline
+#elif defined(__GNUC__)
+# define BLI_INLINE static inline __attribute((always_inline))
+#else
+/* #warning "MSC/GNUC defines not found, inline non-functional" */
+# define BLI_INLINE static
+#endif
-#define BLI_RCT_CENTER_X(rct) (((rct)->xmin + (rct)->xmax) / 2)
-#define BLI_RCT_CENTER_Y(rct) (((rct)->ymin + (rct)->ymax) / 2)
+#include "DNA_vec_types.h"
+BLI_INLINE float BLI_rcti_cent_x_fl(const struct rcti *rct) { return (float)(rct->xmin + rct->xmax) / 2.0f; }
+BLI_INLINE float BLI_rcti_cent_y_fl(const struct rcti *rct) { return (float)(rct->ymin + rct->ymax) / 2.0f; }
+BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct) { return (rct->xmin + rct->xmax) / 2; }
+BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct) { return (rct->ymin + rct->ymax) / 2; }
+BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct) { return (rct->xmin + rct->xmax) / 2.0f; }
+BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct) { return (rct->ymin + rct->ymax) / 2.0f; }
-#define BLI_RCT_CENTER_X_FL(rct) ((float)((rct)->xmin + (rct)->xmax) / 2.0f)
-#define BLI_RCT_CENTER_Y_FL(rct) ((float)((rct)->ymin + (rct)->ymax) / 2.0f)
+BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct) { return (rct->xmax - rct->xmin); }
+BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct) { return (rct->ymax - rct->ymin); }
+BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct) { return (rct->xmax - rct->xmin); }
+BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct) { return (rct->ymax - rct->ymin); }
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index b3d0df04eb1..666c74ca36f 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -144,7 +144,11 @@ __attribute__((nonnull))
/*
* Replacement for vsnprintf
*/
-size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg);
+size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg)
+#ifdef __GNUC__
+__attribute__ ((format(printf, 3, 0)))
+#endif
+;
/*
* Print formatted string into a newly mallocN'd string
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 2836174be73..eef0a72d3b2 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC
set(INC_SYS
${ZLIB_INCLUDE_DIRS}
${FREETYPE_INCLUDE_DIRS}
+ ${ZLIB_INC}
)
set(SRC
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index c1175192434..ee7d93ea1a9 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -58,7 +58,7 @@ struct Heap {
#define HEAP_LEFT(i) ((i << 1) + 1)
#define HEAP_RIGHT(i) ((i << 1) + 2)
#define HEAP_COMPARE(a, b) (a->value < b->value)
-#define HEAP_EQUALS(a, b) (a->value == b->value)
+// #define HEAP_EQUALS(a, b) (a->value == b->value) // UNUSED
#define HEAP_SWAP(heap, i, j) \
{ \
SWAP(int, heap->tree[i]->index, heap->tree[j]->index); \
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 2b3c314131b..167797946bc 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -42,7 +42,6 @@
#endif
#define MAX_TREETYPE 32
-#define DEFAULT_FIND_NEAREST_HEAP_SIZE 1024
typedef struct BVHNode {
struct BVHNode **children;
@@ -114,6 +113,8 @@ static float KDOP_AXES[13][3] = {
{0, 1.0, -1.0}
};
+#if 0
+
/*
* Generic push and pop heap
*/
@@ -153,7 +154,6 @@ static float KDOP_AXES[13][3] = {
heap[parent] = element; \
} (void)0
-#if 0
static int ADJUST_MEMORY(void *local_memblock, void **memblock, int new_size, int *max_size, int size_per_item)
{
int new_max_size = *max_size * 2;
@@ -1167,8 +1167,6 @@ typedef struct NodeDistance {
} NodeDistance;
-#define NodeDistance_priority(a, b) ( (a).dist < (b).dist)
-
// TODO: use a priority queue to reduce the number of nodes looked on
static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
{
@@ -1211,6 +1209,11 @@ static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node)
#if 0
+
+#define DEFAULT_FIND_NEAREST_HEAP_SIZE 1024
+
+#define NodeDistance_priority(a, b) ( (a).dist < (b).dist)
+
static void NodeDistance_push_heap(NodeDistance *heap, int heap_size)
PUSH_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size)
diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c
index 5da719cd500..1c70a612c4f 100644
--- a/source/blender/blenlib/intern/boxpack2d.c
+++ b/source/blender/blenlib/intern/boxpack2d.c
@@ -73,7 +73,9 @@ typedef struct BoxVert {
((b)->v[BR]->x = (b)->v[TR]->x)
#define UPDATE_V34Y(b) ((b)->v[TL]->y = (b)->v[TR]->y); \
((b)->v[BR]->y = (b)->v[BL]->y)
-#define UPDATE_V34(b) UPDATE_V34X(b); UPDATE_V34Y(b)
+
+/* UNUSED */
+// #define UPDATE_V34(b) UPDATE_V34X(b); UPDATE_V34Y(b)
#define SET_BOXLEFT(b, f) (b)->v[TR]->x = f + (b)->w; \
(b)->v[BL]->x = f; \
@@ -93,8 +95,8 @@ typedef struct BoxVert {
BOXRIGHT(b1) - EPSILON <= BOXLEFT(b2) || \
BOXTOP(b1) - EPSILON <= BOXBOTTOM(b2))
-#define MIN2(x, y) ((x) < (y) ? (x) : (y))
-#define MAX2(x, y) ((x) > (y) ? (x) : (y))
+/* compiler should inline */
+static float maxf(const float a, const float b) { return b > a ? b : a; }
#if 0
#define BOXDEBUG(b) \
@@ -131,8 +133,8 @@ static int vertex_sort(const void *p1, const void *p2)
v1 = vertarray + ((int *)p1)[0];
v2 = vertarray + ((int *)p2)[0];
- a1 = MAX2(v1->x + box_width, v1->y + box_height);
- a2 = MAX2(v2->x + box_width, v2->y + box_height);
+ a1 = maxf(v1->x + box_width, v1->y + box_height);
+ a2 = maxf(v2->x + box_width, v2->y + box_height);
/* sort largest to smallest */
if (a1 > a2) return 1;
@@ -312,8 +314,8 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float *
if (!isect) {
/* maintain the total width and height */
- (*tot_width) = MAX2(BOXRIGHT(box), (*tot_width));
- (*tot_height) = MAX2(BOXTOP(box), (*tot_height));
+ (*tot_width) = maxf(BOXRIGHT(box), (*tot_width));
+ (*tot_height) = maxf(BOXTOP(box), (*tot_height));
/* Place the box */
vert->free &= ~quad_flags[j];
diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c
index be1f4eb3a35..5bafb75d9c0 100644
--- a/source/blender/blenlib/intern/bpath.c
+++ b/source/blender/blenlib/intern/bpath.c
@@ -68,6 +68,7 @@
#include "DNA_vfont_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
+#include "DNA_freestyle_types.h"
#include "BLI_blenlib.h"
#include "BLI_bpath.h"
@@ -504,6 +505,7 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
case ID_SCE:
{
Scene *scene = (Scene *)id;
+ SceneRenderLayer *srl= scene->r.layers.first;
if (scene->ed) {
Sequence *seq;
@@ -539,6 +541,12 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
}
SEQ_END
}
+ for(; srl; srl= srl->next) {
+ FreestyleModuleConfig* module= srl->freestyleConfig.modules.first;
+ for (; module; module= module->next) {
+ rewrite_path_fixed(module->module_path, visit_cb, absbase, bpath_user_data);
+ }
+ }
}
break;
case ID_ME:
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index f3107b565b9..c2f0c38247a 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -341,7 +341,7 @@ void BLI_dir_create_recursive(const char *dirname)
{
char *lslash;
char tmp[MAXPATHLEN];
-
+
/* First remove possible slash at the end of the dirname.
* This routine otherwise tries to create
* blah1/blah2/ (with slash) after creating
@@ -349,23 +349,29 @@ void BLI_dir_create_recursive(const char *dirname)
BLI_strncpy(tmp, dirname, sizeof(tmp));
lslash = BLI_last_slash(tmp);
-
- if (lslash == tmp + strlen(tmp) - 1) {
- *lslash = 0;
+
+ if (lslash && (*(lslash + 1) == '\0')) {
+ *lslash = '\0';
}
-
+
+ /* check special case "c:\foo", don't try create "c:", harmless but prints an error below */
+ if (isalpha(tmp[0]) && (tmp[1] == ':') && tmp[2] == '\0') return;
+
if (BLI_exists(tmp)) return;
lslash = BLI_last_slash(tmp);
+
if (lslash) {
/* Split about the last slash and recurse */
*lslash = 0;
BLI_dir_create_recursive(tmp);
}
-
- if (dirname[0]) /* patch, this recursive loop tries to create a nameless directory */
- if (umkdir(dirname) == -1)
+
+ if (dirname[0]) { /* patch, this recursive loop tries to create a nameless directory */
+ if (umkdir(dirname) == -1) {
printf("Unable to create directory %s\n", dirname);
+ }
+ }
}
int BLI_rename(const char *from, const char *to)
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index 597a645eb9c..85239270541 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -58,9 +58,6 @@
#include "DNA_packedFile_types.h"
#include "DNA_curve_types.h"
-#define myMIN_ASCII 32
-#define myMAX_ASCII 255
-
/* local variables */
static FT_Library library;
static FT_Error err;
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index 6b90cbfe9c3..f520b2318e5 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -273,5 +273,20 @@ MINLINE float rgb_to_luma_y(const float rgb[3])
return 0.212671f * rgb[0] + 0.71516f * rgb[1] + 0.072169f * rgb[2];
}
+MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit)
+{
+ int r = (int)col_a[0] - (int)col_b[0];
+ if (ABS(r) < limit) {
+ int g = (int)col_a[1] - (int)col_b[1];
+ if (ABS(g) < limit) {
+ int b = (int)col_a[2] - (int)col_b[2];
+ if (ABS(b) < limit) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
#endif /* __MATH_COLOR_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 3fb3d2b58ff..1f61b37a1af 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -195,7 +195,7 @@ void mul_m3_m3m3(float m1[][3], float m3_[][3], float m2_[][3])
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
}
-void mul_m4_m4m3(float (*m1)[4], float (*m3_)[4], float (*m2_)[3])
+void mul_m4_m4m3(float m1[][4], float m3_[][4], float m2_[][3])
{
float m2[3][3], m3[4][4];
@@ -215,8 +215,14 @@ void mul_m4_m4m3(float (*m1)[4], float (*m3_)[4], float (*m2_)[3])
}
/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */
-void mult_m3_m3m4(float m1[][3], float m3[][4], float m2[][3])
+void mult_m3_m3m4(float m1[][3], float m3_[][4], float m2_[][3])
{
+ float m2[3][3], m3[4][4];
+
+ /* copy so it works when m1 is the same pointer as m2 or m3 */
+ copy_m3_m3(m2, m2_);
+ copy_m4_m4(m3, m3_);
+
/* m1[i][j] = m2[i][k] * m3[k][j] */
m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
@@ -231,8 +237,14 @@ void mult_m3_m3m4(float m1[][3], float m3[][4], float m2[][3])
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
}
-void mul_m4_m3m4(float (*m1)[4], float (*m3)[3], float (*m2)[4])
+void mul_m4_m3m4(float m1[][4], float m3_[][3], float m2_[][4])
{
+ float m2[4][4], m3[3][3];
+
+ /* copy so it works when m1 is the same pointer as m2 or m3 */
+ copy_m4_m4(m2, m2_);
+ copy_m3_m3(m3, m3_);
+
m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2];
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index f0ed23aabc9..e10b0b3298c 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -35,7 +35,9 @@
/******************************** Quaternions ********************************/
/* used to test is a quat is not normalized (only used for debug prints) */
-#define QUAT_EPSILON 0.0001
+#ifdef DEBUG
+# define QUAT_EPSILON 0.0001
+#endif
/* convenience, avoids setting Y axis everywhere */
void unit_axis_angle(float axis[3], float *angle)
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 0a8f57214d7..c409e536b45 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -724,6 +724,15 @@ MINLINE int equals_v4v4(const float v1[4], const float v2[4])
return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3]));
}
+MINLINE int compare_v2v2(const float v1[2], const float v2[2], const float limit)
+{
+ if (fabsf(v1[0] - v2[0]) < limit)
+ if (fabsf(v1[1] - v2[1]) < limit)
+ return 1;
+
+ return 0;
+}
+
MINLINE int compare_v3v3(const float v1[3], const float v2[3], const float limit)
{
if (fabsf(v1[0] - v2[0]) < limit)
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index bd83c5e018c..792bf929182 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -45,7 +45,8 @@ static float noise3_perlin(float vec[3]);
//static float turbulence_perlin(float *point, float lofreq, float hifreq);
//static float turbulencep(float noisesize, float x, float y, float z, int nr);
-#define HASHVEC(x, y, z) hashvectf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255]
+/* UNUSED */
+// #define HASHVEC(x, y, z) hashvectf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255]
/* needed for voronoi */
#define HASHPNT(x, y, z) hashpntf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255]
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index a7a66718445..cc482e2d3d8 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1368,7 +1368,7 @@ int BLI_testextensie(const char *str, const char *ext)
retval = 0;
}
else if (BLI_strcasecmp(ext, str + a - b)) {
- retval = 0;
+ retval = 0;
}
else {
retval = 1;
diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c
index d3d8d371f60..0bd9e68cb71 100644
--- a/source/blender/blenlib/intern/pbvh.c
+++ b/source/blender/blenlib/intern/pbvh.c
@@ -1169,10 +1169,14 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
break;
case PBVH_FACES:
GPU_update_mesh_buffers(node->draw_buffers,
+ bvh->faces,
+ node->prim_indices,
+ node->totprim,
bvh->verts,
node->vert_indices,
node->uniq_verts +
node->face_verts,
+ node->face_vert_indices,
CustomData_get_layer(bvh->vdata,
CD_PAINT_MASK));
break;
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index 225ede8a8ef..cab383b60f3 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -252,8 +252,8 @@ void BLI_rctf_translate(rctf *rect, float x, float y)
/* change width & height around the central location */
void BLI_rcti_resize(rcti *rect, int x, int y)
{
- rect->xmin = rect->xmax = BLI_RCT_CENTER_X(rect);
- rect->ymin = rect->ymax = BLI_RCT_CENTER_Y(rect);
+ rect->xmin = rect->xmax = BLI_rcti_cent_x(rect);
+ rect->ymin = rect->ymax = BLI_rcti_cent_y(rect);
rect->xmin -= x / 2;
rect->ymin -= y / 2;
rect->xmax = rect->xmin + x;
@@ -262,8 +262,8 @@ void BLI_rcti_resize(rcti *rect, int x, int y)
void BLI_rctf_resize(rctf *rect, float x, float y)
{
- rect->xmin = rect->xmax = BLI_RCT_CENTER_X(rect);
- rect->ymin = rect->ymax = BLI_RCT_CENTER_Y(rect);
+ rect->xmin = rect->xmax = BLI_rctf_cent_x(rect);
+ rect->ymin = rect->ymax = BLI_rctf_cent_y(rect);
rect->xmin -= x * 0.5f;
rect->ymin -= y * 0.5f;
rect->xmax = rect->xmin + x;
@@ -281,6 +281,27 @@ void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const f
/* BLI_rcti_interp() not needed yet */
+
+int BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2])
+{
+ int change = 0;
+ if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = 1; }
+ if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = 1; }
+ if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = 1; }
+ if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = 1; }
+ return change;
+}
+
+int BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2])
+{
+ int change = 0;
+ if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = 1; }
+ if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = 1; }
+ if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = 1; }
+ if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = 1; }
+ return change;
+}
+
int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit)
{
if (fabsf(rect_a->xmin - rect_b->xmin) < limit)
@@ -366,9 +387,9 @@ int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest)
void BLI_rcti_rctf_copy(rcti *dst, const rctf *src)
{
dst->xmin = floorf(src->xmin + 0.5f);
- dst->xmax = dst->xmin + floorf(BLI_RCT_SIZE_X(src) + 0.5f);
+ dst->xmax = dst->xmin + floorf(BLI_rctf_size_x(src) + 0.5f);
dst->ymin = floorf(src->ymin + 0.5f);
- dst->ymax = dst->ymin + floorf(BLI_RCT_SIZE_Y(src) + 0.5f);
+ dst->ymax = dst->ymin + floorf(BLI_rctf_size_y(src) + 0.5f);
}
void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
@@ -382,11 +403,11 @@ void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
void print_rctf(const char *str, const rctf *rect)
{
printf("%s: xmin %.3f, xmax %.3f, ymin %.3f, ymax %.3f (%.3fx%.3f)\n", str,
- rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect));
+ rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_rctf_size_x(rect), BLI_rctf_size_y(rect));
}
void print_rcti(const char *str, const rcti *rect)
{
printf("%s: xmin %d, xmax %d, ymin %d, ymax %d (%dx%d)\n", str,
- rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect));
+ rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
}
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 32afaba2b5c..7ae27b83e67 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -211,7 +211,7 @@ ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
copy_v3_v3(eve->co, vec);
- return eve;
+ return eve;
}
ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2)
@@ -521,7 +521,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf)
while (eve) {
printf("vert: %x co: %f %f\n", eve, eve->xy[0], eve->xy[1]);
eve = eve->next;
- }
+ }
eed = sf_ctx->filledgebase.first;
while (eed) {
printf("edge: %x verts: %x %x\n", eed, eed->v1, eed->v2);
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 0fccd91fc02..0d3f6aee30f 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -34,7 +34,7 @@
#include <sys/types.h>
#include <stdio.h>
-#include <stdlib.h>
+#include <stdlib.h>
#ifndef WIN32
#include <dirent.h>
diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c
index 422a600e51c..bab144266a4 100644
--- a/source/blender/blenlib/intern/string_cursor_utf8.c
+++ b/source/blender/blenlib/intern/string_cursor_utf8.c
@@ -147,7 +147,7 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
int *pos, strCursorJumpDirection direction,
strCursorJumpType jump)
{
- const short pos_prev = *pos;
+ const int pos_prev = *pos;
if (direction == STRCUR_DIR_NEXT) {
BLI_str_cursor_step_next_utf8(str, maxlen, pos);
diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c
index 1b59dc6a3f5..05ebc9500a1 100644
--- a/source/blender/blenlib/intern/uvproject.c
+++ b/source/blender/blenlib/intern/uvproject.c
@@ -105,7 +105,7 @@ void BLI_uvproject_from_view(float target[2], float source[3], float persmat[4][
/* rotmat is the object matrix in this case */
mul_m4_v4(rotmat, pv4);
- /* almost project_short */
+ /* almost ED_view3d_project_short */
mul_m4_v4(persmat, pv4);
if (fabsf(pv4[3]) > 0.00001f) { /* avoid division by zero */
target[0] = winx / 2.0f + (winx / 2.0f) * pv4[0] / pv4[3];
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index c6483442b00..9a2a09a98ae 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -70,6 +70,7 @@
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_lamp_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_meta_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
@@ -133,7 +134,7 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "BKE_property.h" // for get_ob_property
+#include "BKE_property.h" // for BKE_bproperty_object_get
#include "BKE_report.h"
#include "BKE_sca.h" // for init_actuator
#include "BKE_scene.h"
@@ -248,6 +249,12 @@ static void convert_tface_mt(FileData *fd, Main *main);
* bit kludge but better then doubling up on prints,
* we could alternatively have a versions of a report function which forces printing - campbell
*/
+
+static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
+#ifdef __GNUC__
+__attribute__ ((format(printf, 3, 4)))
+#endif
+;
static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
{
char fixed_buf[1024]; /* should be long enough */
@@ -2711,6 +2718,16 @@ static void direct_link_lamp(FileData *fd, Lamp *la)
/* ************ READ keys ***************** */
+static void do_versions_key_uidgen(Key *key)
+{
+ KeyBlock *block;
+
+ key->uidgen = 1;
+ for (block = key->block.first; block; block = block->next) {
+ block->uid = key->uidgen++;
+ }
+}
+
static void lib_link_key(FileData *fd, Main *main)
{
Key *key;
@@ -2718,12 +2735,7 @@ static void lib_link_key(FileData *fd, Main *main)
for (key = main->key.first; key; key = key->id.next) {
/*check if we need to generate unique ids for the shapekeys*/
if (!key->uidgen) {
- KeyBlock *block;
-
- key->uidgen = 1;
- for (block=key->block.first; block; block=block->next) {
- block->uid = key->uidgen++;
- }
+ do_versions_key_uidgen(key);
}
if (key->id.flag & LIB_NEED_LINK) {
@@ -3810,7 +3822,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->tface = newdataadr(fd, mesh->tface);
mesh->mtface = newdataadr(fd, mesh->mtface);
mesh->mcol = newdataadr(fd, mesh->mcol);
- mesh->msticky = newdataadr(fd, mesh->msticky);
mesh->dvert = newdataadr(fd, mesh->dvert);
mesh->mloopcol = newdataadr(fd, mesh->mloopcol);
mesh->mloopuv = newdataadr(fd, mesh->mloopuv);
@@ -4741,6 +4752,7 @@ static void lib_link_scene(FileData *fd, Main *main)
Base *base, *next;
Sequence *seq;
SceneRenderLayer *srl;
+ FreestyleLineSet *fls;
TimeMarker *marker;
for (sce = main->scene.first; sce; sce = sce->id.next) {
@@ -4845,6 +4857,10 @@ static void lib_link_scene(FileData *fd, Main *main)
for (srl = sce->r.layers.first; srl; srl = srl->next) {
srl->mat_override = newlibadr_us(fd, sce->id.lib, srl->mat_override);
srl->light_override = newlibadr_us(fd, sce->id.lib, srl->light_override);
+ for(fls=srl->freestyleConfig.linesets.first; fls; fls= fls->next) {
+ fls->linestyle= newlibadr_us(fd, sce->id.lib, fls->linestyle);
+ fls->group= newlibadr_us(fd, sce->id.lib, fls->group);
+ }
}
/*Game Settings: Dome Warp Text*/
sce->gm.dome.warptext = newlibadr(fd, sce->id.lib, sce->gm.dome.warptext);
@@ -4913,6 +4929,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
Editing *ed;
Sequence *seq;
MetaStack *ms;
+ SceneRenderLayer *srl;
sce->theDag = NULL;
sce->dagisvalid = 0;
@@ -5081,6 +5098,13 @@ static void direct_link_scene(FileData *fd, Scene *sce)
link_list(fd, &(sce->markers));
link_list(fd, &(sce->transform_spaces));
link_list(fd, &(sce->r.layers));
+
+ for(srl = sce->r.layers.first; srl; srl = srl->next) {
+ link_list(fd, &(srl->freestyleConfig.modules));
+ }
+ for(srl = sce->r.layers.first; srl; srl = srl->next) {
+ link_list(fd, &(srl->freestyleConfig.linesets));
+ }
sce->nodetree = newdataadr(fd, sce->nodetree);
if (sce->nodetree)
@@ -6283,6 +6307,14 @@ static void direct_link_mask(FileData *fd, Mask *mask)
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
masklay_shape->data = newdataadr(fd, masklay_shape->data);
+
+ if (masklay_shape->tot_vert) {
+ if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ BLI_endian_switch_float_array(masklay_shape->data,
+ masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE);
+
+ }
+ }
}
masklay->act_spline = newdataadr(fd, masklay->act_spline);
@@ -6332,6 +6364,177 @@ static void lib_link_mask(FileData *fd, Main *main)
}
}
+/* ************ READ LINE STYLE ***************** */
+
+static void lib_link_linestyle(FileData *fd, Main *main)
+{
+ FreestyleLineStyle *linestyle;
+ LineStyleModifier *m;
+
+ linestyle = main->linestyle.first;
+ while (linestyle) {
+ if (linestyle->id.flag & LIB_NEED_LINK) {
+ linestyle->id.flag -= LIB_NEED_LINK;
+
+ if (linestyle->id.properties) IDP_LibLinkProperty(linestyle->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ if (linestyle->adt) lib_link_animdata(fd, &linestyle->id, linestyle->adt);
+ for (m = linestyle->color_modifiers.first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleColorModifier_DistanceFromObject *cm = (LineStyleColorModifier_DistanceFromObject *)m;
+ cm->target = newlibadr(fd, linestyle->id.lib, cm->target);
+ }
+ break;
+ }
+ }
+ for (m = linestyle->alpha_modifiers.first; m; m = m->next){
+ switch (m->type) {
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleAlphaModifier_DistanceFromObject *am = (LineStyleAlphaModifier_DistanceFromObject *)m;
+ am->target = newlibadr(fd, linestyle->id.lib, am->target);
+ }
+ break;
+ }
+ }
+ for (m = linestyle->thickness_modifiers.first; m; m = m->next){
+ switch (m->type) {
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleThicknessModifier_DistanceFromObject *tm = (LineStyleThicknessModifier_DistanceFromObject *)m;
+ tm->target = newlibadr(fd, linestyle->id.lib, tm->target);
+ }
+ break;
+ }
+ }
+ }
+ linestyle = linestyle->id.next;
+ }
+}
+
+static void direct_link_linestyle_color_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+ switch (modifier->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleColorModifier_AlongStroke *m = (LineStyleColorModifier_AlongStroke *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleColorModifier_DistanceFromCamera *m = (LineStyleColorModifier_DistanceFromCamera *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleColorModifier_DistanceFromObject *m = (LineStyleColorModifier_DistanceFromObject *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleColorModifier_Material *m = (LineStyleColorModifier_Material *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ }
+}
+
+static void direct_link_linestyle_alpha_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+ switch (modifier->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleAlphaModifier_AlongStroke *m = (LineStyleAlphaModifier_AlongStroke *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleAlphaModifier_DistanceFromCamera *m = (LineStyleAlphaModifier_DistanceFromCamera *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleAlphaModifier_DistanceFromObject *m = (LineStyleAlphaModifier_DistanceFromObject *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleAlphaModifier_Material *m = (LineStyleAlphaModifier_Material *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ }
+}
+
+static void direct_link_linestyle_thickness_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+ switch (modifier->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleThicknessModifier_AlongStroke *m = (LineStyleThicknessModifier_AlongStroke *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleThicknessModifier_DistanceFromCamera *m = (LineStyleThicknessModifier_DistanceFromCamera *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleThicknessModifier_DistanceFromObject *m = (LineStyleThicknessModifier_DistanceFromObject *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleThicknessModifier_Material *m = (LineStyleThicknessModifier_Material *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ }
+}
+
+static void direct_link_linestyle_geometry_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+}
+
+static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
+{
+ LineStyleModifier *modifier;
+
+ linestyle->adt= newdataadr(fd, linestyle->adt);
+ direct_link_animdata(fd, linestyle->adt);
+ link_list(fd, &linestyle->color_modifiers);
+ for(modifier=linestyle->color_modifiers.first; modifier; modifier= modifier->next)
+ direct_link_linestyle_color_modifier(fd, modifier);
+ link_list(fd, &linestyle->alpha_modifiers);
+ for(modifier=linestyle->alpha_modifiers.first; modifier; modifier= modifier->next)
+ direct_link_linestyle_alpha_modifier(fd, modifier);
+ link_list(fd, &linestyle->thickness_modifiers);
+ for(modifier=linestyle->thickness_modifiers.first; modifier; modifier= modifier->next)
+ direct_link_linestyle_thickness_modifier(fd, modifier);
+ link_list(fd, &linestyle->geometry_modifiers);
+ for(modifier=linestyle->geometry_modifiers.first; modifier; modifier= modifier->next)
+ direct_link_linestyle_geometry_modifier(fd, modifier);
+}
+
/* ************** GENERAL & MAIN ******************** */
@@ -6366,6 +6569,7 @@ static const char *dataname(short id_code)
case ID_PA: return "Data from PA";
case ID_GD: return "Data from GD";
case ID_MC: return "Data from MC";
+ case ID_LS: return "Data from LS";
}
return "Data from Lib Block";
@@ -6540,6 +6744,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_MSK:
direct_link_mask(fd, (Mask *)id);
break;
+ case ID_LS:
+ direct_link_linestyle(fd, (FreestyleLineStyle *)id);
+ break;
}
/*link direct data of ID properties*/
@@ -7368,7 +7575,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
for (ob= main->object.first; ob; ob= ob->id.next) {
if (ob->type == OB_FONT) {
- prop = get_ob_property(ob, "Text");
+ prop = BKE_bproperty_object_get(ob, "Text");
if (prop) {
BKE_reportf_wrap(fd->reports, RPT_WARNING,
"Game property name conflict in object: \"%s\".\nText objects reserve the "
@@ -7960,6 +8167,65 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 20)) {
+ Key *key;
+ for (key = main->key.first; key; key = key->id.next) {
+ do_versions_key_uidgen(key);
+ }
+ }
+
+ /* remove texco */
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 21)) {
+ Material *ma;
+ for (ma = main->mat.first; ma; ma = ma->id.next) {
+ int a;
+ for (a = 0; a < MAX_MTEX; a++) {
+ if (ma->mtex[a]) {
+ if (ma->mtex[a]->texco == TEXCO_STICKY_) {
+ ma->mtex[a]->texco = TEXCO_UV;
+ }
+ }
+ }
+ }
+
+ {
+ Mesh *me;
+ for (me = main->mesh.first; me; me = me->id.next) {
+ CustomData_free_layers(&me->vdata, CD_MSTICKY, me->totvert);
+ }
+ }
+ }
+
+ /* default values in Freestyle settings */
+ {
+ Scene *sce;
+ SceneRenderLayer *srl;
+ FreestyleLineStyle *linestyle;
+
+ for(sce = main->scene.first; sce; sce = sce->id.next) {
+ if (sce->r.line_thickness_mode == 0) {
+ sce->r.line_thickness_mode= R_LINE_THICKNESS_ABSOLUTE;
+ sce->r.unit_line_thickness= 1.f;
+ }
+ for(srl= sce->r.layers.first; srl; srl= srl->next) {
+ if (srl->freestyleConfig.mode == 0)
+ srl->freestyleConfig.mode= FREESTYLE_CONTROL_EDITOR_MODE;
+ if (srl->freestyleConfig.raycasting_algorithm == 0)
+ srl->freestyleConfig.raycasting_algorithm= FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE;
+ }
+ }
+ for(linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+ if (linestyle->thickness_position == 0) {
+ linestyle->thickness_position= LS_THICKNESS_CENTER;
+ linestyle->thickness_ratio= 0.5f;
+ }
+ if (linestyle->chaining == 0)
+ linestyle->chaining= LS_CHAINING_PLAIN;
+ if (linestyle->rounds == 0)
+ linestyle->rounds= 3;
+ }
+ }
+
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
@@ -8006,6 +8272,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_particlesettings(fd, main);
lib_link_movieclip(fd, main);
lib_link_mask(fd, main);
+ lib_link_linestyle(fd, main);
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
@@ -8920,6 +9187,7 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
{
Base *base;
SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
for (base = sce->base.first; base; base = base->next) {
expand_doit(fd, mainvar, base->object);
@@ -8940,6 +9208,12 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
for (srl = sce->r.layers.first; srl; srl = srl->next) {
expand_doit(fd, mainvar, srl->mat_override);
expand_doit(fd, mainvar, srl->light_override);
+
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->group)
+ expand_doit(fd, mainvar, lineset->group);
+ expand_doit(fd, mainvar, lineset->linestyle);
+ }
}
if (sce->r.dometext)
@@ -9033,6 +9307,26 @@ static void expand_mask(FileData *fd, Main *mainvar, Mask *mask)
}
}
+static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *linestyle)
+{
+ LineStyleModifier *m;
+
+ if (linestyle->adt)
+ expand_animdata(fd, mainvar, linestyle->adt);
+ for (m = linestyle->color_modifiers.first; m; m = m->next) {
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+ expand_doit(fd, mainvar, ((LineStyleColorModifier_DistanceFromObject *)m)->target);
+ }
+ for (m = linestyle->alpha_modifiers.first; m; m = m->next){
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+ expand_doit(fd, mainvar, ((LineStyleAlphaModifier_DistanceFromObject *)m)->target);
+ }
+ for (m = linestyle->thickness_modifiers.first; m; m = m->next){
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+ expand_doit(fd, mainvar, ((LineStyleThicknessModifier_DistanceFromObject *)m)->target);
+ }
+}
+
static void expand_main(FileData *fd, Main *mainvar)
{
ListBase *lbarray[MAX_LIBARRAY];
@@ -9119,6 +9413,9 @@ static void expand_main(FileData *fd, Main *mainvar)
case ID_MSK:
expand_mask(fd, mainvar, (Mask *)id);
break;
+ case ID_LS:
+ expand_linestyle(fd, mainvar, (FreestyleLineStyle *)id);
+ break;
}
do_it = TRUE;
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 1cc0d4180ab..d8333e7c8f4 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -92,7 +92,7 @@
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "BKE_property.h" // for get_ob_property
+#include "BKE_property.h" // for BKE_bproperty_object_get
#include "BKE_scene.h"
#include "BKE_sequencer.h"
@@ -387,8 +387,6 @@ static void customdata_version_242(Mesh *me)
if (!me->vdata.totlayer) {
CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, me->mvert, me->totvert);
- if (me->msticky)
- CustomData_add_layer(&me->vdata, CD_MSTICKY, CD_ASSIGN, me->msticky, me->totvert);
if (me->dvert)
CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_ASSIGN, me->dvert, me->totvert);
}
@@ -945,7 +943,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
while (act) {
if (act->type == ACT_IPO) {
ia = act->data;
- prop = get_ob_property(ob, ia->name);
+ prop = BKE_bproperty_object_get(ob, ia->name);
if (prop) {
ia->type = ACT_IPO_FROM_PROP;
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index b8d63b3c5d5..6fb7faae69c 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -108,6 +108,7 @@ Any case: direct data is ALWAYS after the lib block
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_lamp_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -2137,6 +2138,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
TimeMarker *marker;
TransformOrientation *ts;
SceneRenderLayer *srl;
+ FreestyleModuleConfig *fmc;
+ FreestyleLineSet *fls;
ToolSettings *tos;
sce= scebase->first;
@@ -2261,8 +2264,18 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
for (ts = sce->transform_spaces.first; ts; ts = ts->next)
writestruct(wd, DATA, "TransformOrientation", 1, ts);
- for (srl= sce->r.layers.first; srl; srl= srl->next)
+ for (srl= sce->r.layers.first; srl; srl= srl->next) {
writestruct(wd, DATA, "SceneRenderLayer", 1, srl);
+
+ for(fmc= srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ writestruct(wd, DATA, "FreestyleModuleConfig", 1, fmc);
+ }
+
+ for(fls= srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ writestruct(wd, DATA, "FreestyleLineSet", 1, fls);
+ }
+
+ }
if (sce->nodetree) {
writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree);
@@ -2846,6 +2859,205 @@ static void write_masks(WriteData *wd, ListBase *idbase)
mywrite(wd, MYWRITE_FLUSH, 0);
}
+static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers)
+{
+ LineStyleModifier *m;
+ char *struct_name;
+
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ struct_name = "LineStyleColorModifier_AlongStroke";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ struct_name = "LineStyleColorModifier_DistanceFromCamera";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ struct_name = "LineStyleColorModifier_DistanceFromObject";
+ break;
+ case LS_MODIFIER_MATERIAL:
+ struct_name = "LineStyleColorModifier_Material";
+ break;
+ default:
+ struct_name = "LineStyleColorModifier"; // this should not happen
+ }
+ writestruct(wd, DATA, struct_name, 1, m);
+ }
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_AlongStroke *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Material *)m)->color_ramp);
+ break;
+ }
+ }
+}
+
+static void write_linestyle_alpha_modifiers(WriteData *wd, ListBase *modifiers)
+{
+ LineStyleModifier *m;
+ char *struct_name;
+
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ struct_name = "LineStyleAlphaModifier_AlongStroke";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ struct_name = "LineStyleAlphaModifier_DistanceFromCamera";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ struct_name = "LineStyleAlphaModifier_DistanceFromObject";
+ break;
+ case LS_MODIFIER_MATERIAL:
+ struct_name = "LineStyleAlphaModifier_Material";
+ break;
+ default:
+ struct_name = "LineStyleAlphaModifier"; // this should not happen
+ }
+ writestruct(wd, DATA, struct_name, 1, m);
+ }
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_AlongStroke *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_DistanceFromObject *)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_Material *)m)->curve);
+ break;
+ }
+ }
+}
+
+static void write_linestyle_thickness_modifiers(WriteData *wd, ListBase *modifiers)
+{
+ LineStyleModifier *m;
+ char *struct_name;
+
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ struct_name = "LineStyleThicknessModifier_AlongStroke";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ struct_name = "LineStyleThicknessModifier_DistanceFromCamera";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ struct_name = "LineStyleThicknessModifier_DistanceFromObject";
+ break;
+ case LS_MODIFIER_MATERIAL:
+ struct_name = "LineStyleThicknessModifier_Material";
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ struct_name = "LineStyleThicknessModifier_Calligraphy";
+ break;
+ default:
+ struct_name = "LineStyleThicknessModifier"; // this should not happen
+ }
+ writestruct(wd, DATA, struct_name, 1, m);
+ }
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_AlongStroke *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_DistanceFromObject *)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_Material *)m)->curve);
+ break;
+ }
+ }
+}
+
+static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifiers)
+{
+ LineStyleModifier *m;
+ char *struct_name;
+
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_SAMPLING:
+ struct_name = "LineStyleGeometryModifier_Sampling";
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ struct_name = "LineStyleGeometryModifier_BezierCurve";
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ struct_name = "LineStyleGeometryModifier_SinusDisplacement";
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ struct_name = "LineStyleGeometryModifier_SpatialNoise";
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ struct_name = "LineStyleGeometryModifier_PerlinNoise1D";
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ struct_name = "LineStyleGeometryModifier_PerlinNoise2D";
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ struct_name = "LineStyleGeometryModifier_BackboneStretcher";
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ struct_name = "LineStyleGeometryModifier_TipRemover";
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ struct_name = "LineStyleGeometryModifier_Polygonalization";
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ struct_name = "LineStyleGeometryModifier_GuidingLines";
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ struct_name = "LineStyleGeometryModifier_Blueprint";
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ struct_name = "LineStyleGeometryModifier_2DOffset";
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ struct_name = "LineStyleGeometryModifier_2DTransform";
+ break;
+ default:
+ struct_name = "LineStyleGeometryModifier"; // this should not happen
+ }
+ writestruct(wd, DATA, struct_name, 1, m);
+ }
+}
+
+static void write_linestyles(WriteData *wd, ListBase *idbase)
+{
+ FreestyleLineStyle *linestyle;
+
+ for(linestyle=idbase->first; linestyle; linestyle= linestyle->id.next) {
+ if(linestyle->id.us>0 || wd->current) {
+ writestruct(wd, ID_LS, "FreestyleLineStyle", 1, linestyle);
+ if (linestyle->id.properties) IDP_WriteProperty(linestyle->id.properties, wd);
+ if (linestyle->adt) write_animdata(wd, linestyle->adt);
+ write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
+ write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
+ write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
+ write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
+ }
+ }
+}
+
/* context is usually defined by WM, two cases where no WM is available:
* - for forward compatibility, curscreen has to be saved
* - for undofile, curscene needs to be saved */
@@ -2956,6 +3168,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_brushes (wd, &mainvar->brush);
write_scripts (wd, &mainvar->script);
write_gpencils (wd, &mainvar->gpencil);
+ write_linestyles(wd, &mainvar->linestyle);
write_libraries(wd, mainvar->next);
if (write_user_block) {
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 3bd99b748f6..998407c82ba 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -228,6 +228,7 @@ enum {
/* we have 1 spare flag which is awesome but since we're limited to 8
* only add new flags with care! - campbell */
/* BM_ELEM_SPARE = (1 << 6), */
+ BM_ELEM_FREESTYLE = (1 << 6), /* used for Freestyle faces and edges */
BM_ELEM_INTERNAL_TAG = (1 << 7) /* for low level internal API tagging,
* since tools may want to tag verts and
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 4740140187d..691465388e9 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -380,7 +380,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n
}
sub_v3_v3v3(far_vec, far, cent);
- far_dist = len_v3(far_vec); /* real dist */
+ // far_dist = len_v3(far_vec); /* real dist */ /* UNUSED */
/* --- */
@@ -975,14 +975,16 @@ char BM_edge_flag_from_mflag(const short meflag)
((meflag & ME_SEAM) ? BM_ELEM_SEAM : 0) |
((meflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
((meflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */
- ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)
+ ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0) |
+ ((meflag & ME_FREESTYLE_EDGE) ? BM_ELEM_FREESTYLE : 0)
);
}
char BM_face_flag_from_mflag(const char meflag)
{
return ( ((meflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) |
((meflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) |
- ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)
+ ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0) |
+ ((meflag & ME_FREESTYLE_FACE) ? BM_ELEM_FREESTYLE : 0)
);
}
@@ -1005,6 +1007,7 @@ short BM_edge_flag_to_mflag(BMEdge *eed)
((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) |
((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) |
+ ((hflag & BM_ELEM_FREESTYLE) ? ME_FREESTYLE_EDGE : 0) |
((BM_edge_is_wire(eed)) ? ME_LOOSEEDGE : 0) | /* not typical */
ME_EDGERENDER
);
@@ -1015,6 +1018,7 @@ char BM_face_flag_to_mflag(BMFace *efa)
return ( ((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) |
- ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0)
+ ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) |
+ ((hflag & BM_ELEM_FREESTYLE) ? ME_FREESTYLE_FACE : 0)
);
}
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index f03ce9b8543..ccbbb6f170b 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -836,8 +836,6 @@ static void bm_elements_systag_disable(void *veles, int tot, int flag)
}
}
-#define FACE_MARK (1 << 10)
-
static int count_flagged_radial(BMesh *bm, BMLoop *l, int flag)
{
BMLoop *l2 = l;
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 9033436d1b2..12fcd51c069 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -424,7 +424,7 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *target, BMFace *source)
float axis_x[3], axis_y[3];
/* ignore 2-edged faces */
- if (target->f->len < 3)
+ if (UNLIKELY(target->f->len < 3))
return;
if (!CustomData_has_layer(&bm->ldata, CD_MDISPS))
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index c0439311104..e4a838fe893 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -672,7 +672,7 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
* we cant make a crossvec from a vec thats the same as the vec
* unlikely but possible, so make sure if the normal is (0, 0, 1)
* that vec isn't the same or in the same direction even. */
- if (efa->len < 3) {
+ if (UNLIKELY(efa->len < 3)) {
/* crappy fallback method */
if (efa->no[0] < 0.5f) vec[0] = 1.0f;
else if (efa->no[1] < 0.5f) vec[1] = 1.0f;
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index cf593627e8d..734f08142b1 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -282,7 +282,7 @@ void BM_mesh_normals_update(BMesh *bm, const short skip_hidden)
if (skip_hidden && BM_elem_flag_test(v, BM_ELEM_HIDDEN))
continue;
- if (normalize_v3(v->no) == 0.0f) {
+ if (UNLIKELY(normalize_v3(v->no) == 0.0f)) {
normalize_v3_v3(v->no, v->co);
}
}
@@ -356,7 +356,7 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), int UNUSED(type_flag))
* (loop cuts, edge subdivides, etc) are not reflected in the higher levels of
* the mesh at all, which doesn't seem right. Turning off completely for now,
* until this is shown to be better for certain types of mesh edits. */
-#if BMOP_UNTAN_MULTIRES_ENABLED
+#ifdef BMOP_UNTAN_MULTIRES_ENABLED
/* switch multires data out of tangent space */
if ((type_flag & BMO_OP_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
bmesh_mdisps_space_set(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE);
@@ -374,7 +374,7 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), int UNUSED(type_flag))
void bmesh_edit_end(BMesh *bm, int UNUSED(flag))
{
/* BMO_OP_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */
-#if BMOP_UNTAN_MULTIRES_ENABLED
+#ifdef BMOP_UNTAN_MULTIRES_ENABLED
/* switch multires data into tangent space */
if ((flag & BMO_OP_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
/* set normals to their previous winding */
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 51c8b5d3bd8..e6827b1f2cd 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -758,7 +758,7 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
}
if (!currkey) {
- currkey = add_keyblock(me->key, bm->vdata.layers[i].name);
+ currkey = BKE_keyblock_add(me->key, bm->vdata.layers[i].name);
currkey->uid = bm->vdata.layers[i].uid;
}
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 73e2d83520c..3195899ef01 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -558,7 +558,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
/* cant kill data we loop on, build a list and remove those */
BLI_array_empty(bad_faces);
BM_ITER_ELEM (f, &fiter, verts[i], BM_FACES_OF_VERT) {
- if (f->len < 3) {
+ if (UNLIKELY(f->len < 3)) {
BLI_array_append(bad_faces, f);
}
}
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 53b95c97c8b..2100cd2bd0b 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -1253,7 +1253,7 @@ int BMO_error_occurred(BMesh *bm)
return bm->errorstack.first != NULL;
}
-/* returns error code or 0 if no erro */
+/* returns error code or 0 if no error */
int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op)
{
BMOpError *err = bm->errorstack.first;
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index b1da8ecb275..05113576ca4 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -53,7 +53,8 @@ enum {
SIMFACE_AREA,
SIMFACE_PERIMETER,
SIMFACE_NORMAL,
- SIMFACE_COPLANAR
+ SIMFACE_COPLANAR,
+ SIMFACE_FREESTYLE
};
/* similar edge selection slot values */
@@ -65,7 +66,8 @@ enum {
SIMEDGE_CREASE,
SIMEDGE_BEVEL,
SIMEDGE_SEAM,
- SIMEDGE_SHARP
+ SIMEDGE_SHARP,
+ SIMEDGE_FREESTYLE
};
/* similar vertex selection slot values */
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index 4723b631c5f..1567455e354 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -364,8 +364,6 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
/* BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); */ /* UNUSE */
int i;
-#define SIGN(n) ((n) < 0.0f)
-
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
BMIter eiter;
float no[3], cent[3];
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 4d4d7e30a4e..32270007a0b 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -37,7 +37,7 @@
#define DUPE_INPUT 1 /* input from operator */
#define DUPE_NEW 2
#define DUPE_DONE 4
-#define DUPE_MAPPED 8
+// #define DUPE_MAPPED 8 // UNUSED
/**
* COPY VERTEX
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index d780e309118..0d8b397110e 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -37,11 +37,6 @@
#include "intern/bmesh_operators_private.h" /* own include */
-/* Bitflags for edges */
-#define T2QDELETE 1
-#define T2QCOMPLEX 2
-#define T2QJOIN 4
-
/* assumes edges are validated before reaching this poin */
static float measure_facepair(BMVert *v1, BMVert *v2,
BMVert *v3, BMVert *v4, float limit)
@@ -110,93 +105,73 @@ static float measure_facepair(BMVert *v1, BMVert *v2,
#define T2QUV_LIMIT 0.005f
#define T2QCOL_LIMIT 3
-static int compareFaceAttribs(BMesh *bm, BMEdge *e, int douvs, int dovcols)
+static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do_tf, const int do_vcol)
{
- MTexPoly *tp1, *tp2;
- MLoopCol *lcol1, *lcol2, *lcol3, *lcol4;
- MLoopUV *luv1, *luv2, *luv3, *luv4;
- BMLoop *l1, *l2, *l3, *l4;
- int mergeok_uvs = !douvs, mergeok_vcols = !dovcols;
-
- l1 = e->l;
- l3 = e->l->radial_next;
+ /* first get loops */
+ BMLoop *l[4];
+
+ l[0] = e->l;
+ l[2] = e->l->radial_next;
- /* match up loops on each side of an edge corresponding to each ver */
- if (l1->v == l3->v) {
- l2 = l1->next;
- l4 = l2->next;
+ /* match up loops on each side of an edge corresponding to each vert */
+ if (l[0]->v == l[2]->v) {
+ l[1] = l[0]->next;
+ l[3] = l[1]->next;
}
else {
- l2 = l1->next;
+ l[1] = l[0]->next;
- l4 = l3;
- l3 = l4->next;
+ l[3] = l[2];
+ l[2] = l[3]->next;
}
- lcol1 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL);
- lcol2 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL);
- lcol3 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL);
- lcol4 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL);
-
- luv1 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV);
- luv2 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV);
- luv3 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV);
- luv4 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV);
-
- tp1 = CustomData_bmesh_get(&bm->pdata, l1->f->head.data, CD_MTEXPOLY);
- tp2 = CustomData_bmesh_get(&bm->pdata, l2->f->head.data, CD_MTEXPOLY);
-
- if (!lcol1)
- mergeok_vcols = 1;
-
- if (!luv1)
- mergeok_uvs = 1;
-
- /* compare faceedges for each face attribute. Additional per face attributes can be added late */
-
- /* do VCOL */
- if (lcol1 && dovcols) {
- char *cols[4] = {(char *)lcol1, (char *)lcol2, (char *)lcol3, (char *)lcol4};
- int i;
-
- for (i = 0; i < 3; i++) {
- if (cols[0][i] + T2QCOL_LIMIT < cols[2][i] - T2QCOL_LIMIT)
- break;
- if (cols[1][i] + T2QCOL_LIMIT < cols[3][i] - T2QCOL_LIMIT)
- break;
+ /* Test UV's */
+ if (do_uv) {
+ const MLoopUV *luv[4] = {
+ CustomData_bmesh_get(&bm->ldata, l[0]->head.data, CD_MLOOPUV),
+ CustomData_bmesh_get(&bm->ldata, l[1]->head.data, CD_MLOOPUV),
+ CustomData_bmesh_get(&bm->ldata, l[2]->head.data, CD_MLOOPUV),
+ CustomData_bmesh_get(&bm->ldata, l[3]->head.data, CD_MLOOPUV),
+ };
+
+ /* do UV */
+ if (luv[0] && (!compare_v2v2(luv[0]->uv, luv[2]->uv, T2QUV_LIMIT) ||
+ !compare_v2v2(luv[1]->uv, luv[3]->uv, T2QUV_LIMIT)))
+ {
+ return FALSE;
}
-
- if (i == 3)
- mergeok_vcols = 1;
}
- /* do UV */
- if (luv1 && douvs) {
- if (tp1->tpage != tp2->tpage) {
- /* do nothing */
- }
- else {
- int i;
+ if (do_tf) {
+ const MTexPoly *tp[2] = {
+ CustomData_bmesh_get(&bm->pdata, l[0]->f->head.data, CD_MTEXPOLY),
+ CustomData_bmesh_get(&bm->pdata, l[1]->f->head.data, CD_MTEXPOLY),
+ };
- for (i = 0; i < 2; i++) {
- if (luv1->uv[0] + T2QUV_LIMIT > luv3->uv[0] && luv1->uv[0] - T2QUV_LIMIT < luv3->uv[0] &&
- luv1->uv[1] + T2QUV_LIMIT > luv3->uv[1] && luv1->uv[1] - T2QUV_LIMIT < luv3->uv[1])
- {
- if (luv2->uv[0] + T2QUV_LIMIT > luv4->uv[0] && luv2->uv[0] - T2QUV_LIMIT < luv4->uv[0] &&
- luv2->uv[1] + T2QUV_LIMIT > luv4->uv[1] && luv2->uv[1] - T2QUV_LIMIT < luv4->uv[1])
- {
- mergeok_uvs = 1;
- }
- }
- }
+ if (tp[0] && (tp[0]->tpage != tp[1]->tpage)) {
+ return FALSE;
}
}
- if (douvs == mergeok_uvs && dovcols == mergeok_vcols) {
- return TRUE;
+ /* Test Vertex Colors */
+ if (do_vcol) {
+ const MLoopCol *lcol[4] = {
+ CustomData_bmesh_get(&bm->ldata, l[0]->head.data, CD_MLOOPCOL),
+ CustomData_bmesh_get(&bm->ldata, l[1]->head.data, CD_MLOOPCOL),
+ CustomData_bmesh_get(&bm->ldata, l[2]->head.data, CD_MLOOPCOL),
+ CustomData_bmesh_get(&bm->ldata, l[3]->head.data, CD_MLOOPCOL),
+ };
+
+ if (lcol[0]) {
+ if (!compare_rgb_uchar((unsigned char*)&lcol[0]->r, (unsigned char*)&lcol[2]->r, T2QCOL_LIMIT) ||
+ !compare_rgb_uchar((unsigned char*)&lcol[1]->r, (unsigned char*)&lcol[3]->r, T2QCOL_LIMIT))
+ {
+ return FALSE;
+ }
+ }
}
- return FALSE;
+ return TRUE;
}
typedef struct JoinEdge {
@@ -229,11 +204,12 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BMEdge *e;
BLI_array_declare(jedges);
JoinEdge *jedges = NULL;
- int dosharp = BMO_slot_bool_get(op, "cmp_sharp");
- int douvs = BMO_slot_bool_get(op, "cmp_uvs");
- int dovcols = BMO_slot_bool_get(op, "cmp_vcols");
- int domat = BMO_slot_bool_get(op, "cmp_materials");
- float limit = BMO_slot_float_get(op, "limit");
+ int do_sharp = BMO_slot_bool_get(op, "cmp_sharp");
+ int do_uv = BMO_slot_bool_get(op, "cmp_uvs");
+ int do_tf = do_uv; /* texture face, make make its own option eventually */
+ int do_vcol = BMO_slot_bool_get(op, "cmp_vcols");
+ int do_mat = BMO_slot_bool_get(op, "cmp_materials");
+ float limit = BMO_slot_float_get(op, "limit");
int i, totedge;
/* flag all edges of all input face */
@@ -282,13 +258,13 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
v3 = e->l->next->v;
v4 = e->l->radial_next->prev->v;
- if (dosharp && !BM_elem_flag_test(e, BM_ELEM_SMOOTH))
+ if (do_sharp && !BM_elem_flag_test(e, BM_ELEM_SMOOTH))
continue;
-
- if ((douvs || dovcols) && compareFaceAttribs(bm, e, douvs, dovcols))
+
+ if (do_mat && f1->mat_nr != f2->mat_nr)
continue;
- if (domat && f1->mat_nr != f2->mat_nr)
+ if ((do_uv || do_tf || do_vcol) && (bm_edge_faces_cmp(bm, e, do_uv, do_tf, do_vcol) == FALSE))
continue;
measure = measure_facepair(v1, v2, v3, v4, limit);
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 0caa766c0f0..d3e98dd96c1 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -244,11 +244,11 @@ static int vergaverco(const void *e1, const void *e2)
else return 0;
}
-#define VERT_TESTED 1
+// #define VERT_TESTED 1 // UNUSED
#define VERT_DOUBLE 2
#define VERT_TARGET 4
#define VERT_KEEP 8
-#define VERT_MARK 16
+// #define VERT_MARK 16 // UNUSED
#define VERT_IN 32
#define EDGE_MARK 1
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index 88ed1250264..72e55b2700c 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -668,6 +668,13 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
cont = FALSE;
}
break;
+
+ case SIMFACE_FREESTYLE:
+ if (BM_elem_flag_test(fm, BM_ELEM_FREESTYLE) == BM_elem_flag_test(fs, BM_ELEM_FREESTYLE)) {
+ BMO_elem_flag_enable(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
}
}
}
@@ -873,6 +880,13 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
cont = FALSE;
}
break;
+
+ case SIMEDGE_FREESTYLE:
+ if (BM_elem_flag_test(e, BM_ELEM_FREESTYLE) == BM_elem_flag_test(es, BM_ELEM_FREESTYLE)) {
+ BMO_elem_flag_enable(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
}
}
}
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index f1f1efdbd33..a15dadda8cf 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -103,7 +103,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
// So we have to export it. The export will keep the image state intact,
// so the exported file will not be associated with the image.
- if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, image->colorspace_settings.name, true) == 0) {
+ if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) {
fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path);
return;
}
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index f7e0f75ec5c..fbb18887d1b 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -76,6 +76,7 @@ int collada_export(Scene *sce,
if (!BLI_exists(filepath)) {
BLI_make_existing_file(filepath); /* makes the dir if its not there */
if (BLI_file_touch(filepath) == 0) {
+ fprintf(stdout, "Collada export: Can not create: %s\n", filepath);
return 0;
}
}
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index 0994f3f8890..bdbe21f82ea 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -253,7 +253,7 @@ static void imp2radangle(float A, float B, float C, float F, float *a, float *b,
}
}
-float clipuv(float x, float limit)
+static float clipuv(float x, float limit)
{
x = (x < 0) ? 0 : ((x >= limit) ? (limit - 1) : x);
return x;
diff --git a/source/blender/compositor/intern/COM_NodeBase.h b/source/blender/compositor/intern/COM_NodeBase.h
index b55e444be80..64d669b5e9a 100644
--- a/source/blender/compositor/intern/COM_NodeBase.h
+++ b/source/blender/compositor/intern/COM_NodeBase.h
@@ -97,7 +97,7 @@ public:
* @return [true:false]
* @see NodeOperation
*/
- virtual const int isOperation() const { return false; }
+ virtual const bool isOperation() const { return false; }
/**
* @brief check if this is an input node
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 93a19529d34..dfa22a29e41 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -88,7 +88,7 @@ public:
* @return [true:false]
* @see NodeBase
*/
- const int isOperation() const { return true; }
+ const bool isOperation() const { return true; }
/**
* @brief determine the resolution of this node
diff --git a/source/blender/compositor/intern/COM_OutputSocket.h b/source/blender/compositor/intern/COM_OutputSocket.h
index dc5ca27cbda..c6b7993c561 100644
--- a/source/blender/compositor/intern/COM_OutputSocket.h
+++ b/source/blender/compositor/intern/COM_OutputSocket.h
@@ -64,7 +64,7 @@ public:
/**
* @brief determine the actual data type and channel info.
*/
- void relinkConnections(OutputSocket *relinkToSocket) { this->relinkConnections(relinkToSocket, false); };
+ void relinkConnections(OutputSocket *relinkToSocket) { this->relinkConnections(relinkToSocket, false); }
void relinkConnections(OutputSocket *relinkToSocket, bool single);
const int getNumberOfConnections() { return this->m_connections.size(); }
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index f732a40e768..eb9c26d4f43 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -25,6 +25,7 @@
#include "BKE_global.h"
+#include "COM_compositor.h"
#include "COM_WorkScheduler.h"
#include "COM_CPUDevice.h"
#include "COM_OpenCLDevice.h"
@@ -265,7 +266,7 @@ bool WorkScheduler::hasGPUDevices()
#endif
}
-extern void clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data)
+static void clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data)
{
printf("OPENCL error: %s\n", errinfo);
}
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index 5cfcd83f8f1..49ab9db5dd8 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -37,7 +37,7 @@ extern "C" {
static ThreadMutex s_compositorMutex;
static char is_compositorMutex_init = FALSE;
-void intern_freeCompositorCaches()
+static void intern_freeCompositorCaches()
{
deintializeDistortionCache();
}
@@ -93,7 +93,7 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
BLI_mutex_unlock(&s_compositorMutex);
}
-void COM_freeCaches()
+static void UNUSED_FUNCTION(COM_freeCaches)()
{
if (is_compositorMutex_init) {
BLI_mutex_lock(&s_compositorMutex);
@@ -102,7 +102,7 @@ void COM_freeCaches()
}
}
-void COM_deinitialize()
+void COM_deinitialize()
{
if (is_compositorMutex_init) {
BLI_mutex_lock(&s_compositorMutex);
diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.h b/source/blender/compositor/operations/COM_DespeckleOperation.h
index 5b79d7cb7e0..99635e61544 100644
--- a/source/blender/compositor/operations/COM_DespeckleOperation.h
+++ b/source/blender/compositor/operations/COM_DespeckleOperation.h
@@ -27,8 +27,8 @@ private:
float m_threshold;
float m_threshold_neighbour;
- int m_filterWidth;
- int m_filterHeight;
+ // int m_filterWidth;
+ // int m_filterHeight;
protected:
SocketReader *m_inputOperation;
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
index c4b4452fbb0..9c09c9bf034 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
@@ -79,7 +79,7 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y,
const int miny = max(y - this->m_scope, rect->ymin);
const int maxx = min(x + this->m_scope, rect->xmax);
const int maxy = min(y + this->m_scope, rect->ymax);
- const int bufferWidth = BLI_RCT_SIZE_X(rect);
+ const int bufferWidth = BLI_rcti_size_x(rect);
int offset;
this->m_inputProgram->read(inputValue, x, y, NULL);
@@ -199,7 +199,7 @@ void DilateDistanceOperation::executePixel(float output[4], int x, int y, void *
const int miny = max(y - this->m_scope, rect->ymin);
const int maxx = min(x + this->m_scope, rect->xmax);
const int maxy = min(y + this->m_scope, rect->ymax);
- const int bufferWidth = BLI_RCT_SIZE_X(rect);
+ const int bufferWidth = BLI_rcti_size_x(rect);
int offset;
float value = 0.0f;
@@ -273,7 +273,7 @@ void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *d
const int miny = max(y - this->m_scope, rect->ymin);
const int maxx = min(x + this->m_scope, rect->xmax);
const int maxy = min(y + this->m_scope, rect->ymax);
- const int bufferWidth = BLI_RCT_SIZE_X(rect);
+ const int bufferWidth = BLI_rcti_size_x(rect);
int offset;
float value = 1.0f;
diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp
index 560bbbdd244..c8ebb845bb6 100644
--- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp
+++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp
@@ -51,7 +51,7 @@ void DisplaceSimpleOperation::initExecution()
/* minimum distance (in pixels) a pixel has to be displaced
* in order to take effect */
-#define DISPLACE_EPSILON 0.01f
+// #define DISPLACE_EPSILON 0.01f
void DisplaceSimpleOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
index 7f7429bf2e6..efdf0134c4b 100644
--- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
@@ -244,7 +244,7 @@ static void fht_convolve(fREAL *d1, fREAL *d2, unsigned int M, unsigned int N)
}
//------------------------------------------------------------------------------
-void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
+static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
{
fREAL *data1, *data2, *fp;
unsigned int w2, h2, hw, hh, log2_w, log2_h;
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 86f729502bb..12c0e851f88 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -47,6 +47,7 @@
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
#include "DNA_meta_types.h"
@@ -84,6 +85,7 @@
/* size of indent steps */
#define INDENT_STEP_SIZE 7
+/* size of string buffers used for animation channel displayed names */
#define ANIM_CHAN_NAME_SIZE 256
/* get the pointer used for some flag */
@@ -292,7 +294,7 @@ static short acf_nodetree_rootType_offset(bNodeTree *ntree)
}
}
- // unknown
+ /* unknown */
return 0;
}
@@ -422,7 +424,7 @@ static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
BLI_strncpy(name, "DopeSheet Summary", ANIM_CHAN_NAME_SIZE);
}
-// TODO: this is really a temp icon I think
+// FIXME: this is really a temp icon I think
static int acf_summary_icon(bAnimListElem *UNUSED(ale))
{
return ICON_BORDERMOVE;
@@ -601,7 +603,6 @@ static int acf_object_icon(bAnimListElem *ale)
Object *ob = base->object;
/* icon depends on object-type */
-
switch (ob->type) {
case OB_LAMP:
return ICON_OUTLINER_OB_LAMP;
@@ -628,7 +629,6 @@ static int acf_object_icon(bAnimListElem *ale)
default:
return ICON_OBJECT_DATA;
}
-
}
/* name for object */
@@ -2011,6 +2011,83 @@ static bAnimChannelType ACF_DSNTREE =
acf_dsntree_setting_ptr /* pointer for setting */
};
+/* LineStyle Expander ------------------------------------------- */
+
+// TODO: just get this from RNA?
+static int acf_dslinestyle_icon(bAnimListElem *ale)
+{
+ return ICON_BRUSH_DATA; /* FIXME */
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dslinestyle_setting_flag(bAnimContext *ac, int setting, short *neg)
+{
+ /* clear extra return data first */
+ *neg= 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return LS_DS_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg= 1;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale, int setting, short *type)
+{
+ FreestyleLineStyle *linestyle= (FreestyleLineStyle *)ale->data;
+
+ /* clear extra return data first */
+ *type= 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(linestyle->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (linestyle->adt)
+ return GET_ACF_FLAG_PTR(linestyle->adt->flag, type);
+ else
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* node tree expander type define */
+static bAnimChannelType ACF_DSLINESTYLE=
+{
+ "Line Style Expander", /* type name */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop,/* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_nameprop, /* name prop */
+ acf_dslinestyle_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dslinestyle_setting_flag, /* flag for setting */
+ acf_dslinestyle_setting_ptr /* pointer for setting */
+};
+
/* Mesh Expander ------------------------------------------- */
// TODO: just get this from RNA?
@@ -2178,7 +2255,7 @@ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
{
/* clear extra return data first */
*neg = 0;
-
+
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return SPK_DS_EXPAND;
@@ -2202,10 +2279,10 @@ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
static void *acf_dsspk_setting_ptr(bAnimListElem *ale, int setting, short *type)
{
Speaker *spk = (Speaker *)ale->data;
-
+
/* clear extra return data first */
*type = 0;
-
+
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return GET_ACF_FLAG_PTR(spk->flag, type);
@@ -2477,7 +2554,7 @@ static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), int setting, short *ne
return GP_LAYER_HIDE;
case ACHANNEL_SETTING_PROTECT: /* protected */
- // *neg = 1; - if we change this to edtiability
+ // *neg = 1; - if we change this to editability
return GP_LAYER_LOCKED;
default: /* unsupported */
@@ -2526,7 +2603,7 @@ static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale),
// TODO: just get this from RNA?
static int acf_mask_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_GREASEPENCIL; // MASK_TODO - need real icon
+ return ICON_MOD_MASK;
}
/* check if some setting exists for this channel */
@@ -2573,15 +2650,15 @@ static void *acf_mask_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short
/* mask datablock type define */
static bAnimChannelType ACF_MASKDATA =
{
- "Mask Datablock", /* type name */
+ "Mask Datablock", /* type name */
acf_mask_color, /* backdrop color */
- acf_group_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_group_offset, /* offset */
+ acf_group_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ acf_generic_group_offset, /* offset */
- acf_generic_idblock_name, /* name */
- acf_generic_idfill_nameprop, /* name prop */
+ acf_generic_idblock_name, /* name */
+ acf_generic_idfill_nameprop, /* name prop */
acf_mask_icon, /* icon */
acf_mask_setting_valid, /* has setting */
@@ -2642,7 +2719,7 @@ static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short
// return GP_LAYER_HIDE;
case ACHANNEL_SETTING_PROTECT: /* protected */
- // *neg = 1; - if we change this to edtiability
+ // *neg = 1; - if we change this to editability
return MASK_LAYERFLAG_LOCKED;
default: /* unsupported */
@@ -2654,7 +2731,7 @@ static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short
static void *acf_masklay_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type)
{
MaskLayer *masklay = (MaskLayer *)ale->data;
-
+
/* all flags are just in agrp->flag for now... */
return GET_ACF_FLAG_PTR(masklay->flag, type);
}
@@ -2662,20 +2739,20 @@ static void *acf_masklay_setting_ptr(bAnimListElem *ale, int UNUSED(setting), sh
/* grease pencil layer type define */
static bAnimChannelType ACF_MASKLAYER =
{
- "Mask Layer", /* type name */
-
+ "Mask Layer", /* type name */
+
acf_generic_channel_color, /* backdrop color */
acf_generic_channel_backdrop, /* backdrop */
acf_generic_indention_flexible, /* indent level */
acf_generic_group_offset, /* offset */
-
- acf_masklay_name, /* name */
- acf_masklay_name_prop, /* name prop */
+
+ acf_masklay_name, /* name */
+ acf_masklay_name_prop, /* name prop */
NULL, /* icon */
-
- acf_masklay_setting_valid, /* has setting */
- acf_masklay_setting_flag, /* flag for setting */
- acf_masklay_setting_ptr /* pointer for setting */
+
+ acf_masklay_setting_valid, /* has setting */
+ acf_masklay_setting_flag, /* flag for setting */
+ acf_masklay_setting_ptr /* pointer for setting */
};
@@ -2723,6 +2800,7 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSTEX; /* Texture Channel */
animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
+ animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
@@ -2776,7 +2854,7 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
acf->name(ale, name);
else
BLI_strncpy(name, "<No name>", sizeof(name));
-
+
/* print type name + ui name */
printf("ChanType: <%s> Name: \"%s\"\n", acf->channel_type_name, name);
}
@@ -2920,7 +2998,6 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, int setting,
#define RENAME_TEXT_WIDTH 100
/* Draw the given channel */
-// TODO: make this use UI controls for the buttons
void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
@@ -3010,20 +3087,20 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* TODO: when renaming, we might not want to draw this, especially if name happens to be longer than channel */
if (acf->name) {
char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
-
+
/* set text color */
/* XXX: if active, highlight differently? */
if (selected)
UI_ThemeColor(TH_TEXT_HI);
else
UI_ThemeColor(TH_TEXT);
-
+
/* get name */
acf->name(ale, name);
-
+
offset += 3;
UI_DrawString(offset, ytext, name);
-
+
/* draw red underline if channel is disabled */
if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_DISABLED)) {
/* FIXME: replace hardcoded color here, and check on extents! */
@@ -3068,7 +3145,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
}
/* check if there's enough space for the toggles if the sliders are drawn too */
- if (!(draw_sliders) || (BLI_RCT_SIZE_X(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) {
+ if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) {
/* protect... */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT))
offset += ICON_WIDTH;
@@ -3153,7 +3230,6 @@ static void achannel_setting_rename_done_cb(bContext *C, void *ads_poin, void *U
ads->renameIndex = 0;
/* send notifiers */
- // XXX: right notifier?
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
}
@@ -3199,7 +3275,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
{
Key *key = (Key *)key_poin;
KeyBlock *kb = (KeyBlock *)kb_poin;
- char *rna_path = key_get_curValue_rnaPath(key, kb);
+ char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
ReportList *reports = CTX_wm_reports(C);
Scene *scene = CTX_data_scene(C);
@@ -3437,7 +3513,6 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
offset = 0;
// TODO: when drawing sliders, make those draw instead of these toggles if not enough space
-
if (v2d) {
short draw_sliders = 0;
@@ -3460,7 +3535,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
}
/* check if there's enough space for the toggles if the sliders are drawn too */
- if (!(draw_sliders) || (BLI_RCT_SIZE_X(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) {
+ if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) {
/* protect... */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
offset += ICON_WIDTH;
@@ -3507,7 +3582,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
KeyBlock *kb = (KeyBlock *)ale->data;
Key *key = (Key *)ale->id;
- rna_path = key_get_curValue_rnaPath(key, kb);
+ rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
free_path = 1;
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index d35f39a48e0..ee31276a8c4 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -124,6 +124,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
case ANIMTYPE_DSMESH:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -169,6 +170,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -249,6 +251,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
@@ -343,6 +346,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -2185,6 +2189,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* sanity checking... */
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index 6ce9fc638be..98071fafc1e 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -142,7 +142,6 @@ static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGro
/* check if there are bones, and whether the name matches any
* NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone
*/
- // TODO: if bone gets renamed, it would be best to be able to rename the group
if (ob->pose) {
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
bArmature *arm = ob->data;
@@ -319,7 +318,6 @@ void ANIM_sync_animchannels_to_data(const bContext *C)
FCurve *active_fcurve = NULL;
/* get animation context info for filtering the channels */
- // TODO: check on whether we need to set the area specially instead, since active area might not be ok?
if (ANIM_animdata_get_context(C, &ac) == 0)
return;
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 209414550e3..eb7bc68ff8f 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -55,6 +55,7 @@
#include "DNA_camera_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_key_types.h"
#include "DNA_mask_types.h"
#include "DNA_material_types.h"
@@ -99,7 +100,7 @@
/* ----------- Private Stuff - Action Editor ------------- */
/* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */
-/* Note: there's a similar function in key.c (ob_get_key) */
+/* Note: there's a similar function in key.c (BKE_key_from_object) */
static Key *actedit_get_shapekeys(bAnimContext *ac)
{
Scene *scene = ac->scene;
@@ -114,7 +115,7 @@ static Key *actedit_get_shapekeys(bAnimContext *ac)
//if (saction->pin) return NULL;
/* shapekey data is stored with geometry data */
- key = ob_get_key(ob);
+ key = BKE_key_from_object(ob);
if (key) {
if (key->type == KEY_RELATIVE)
@@ -163,30 +164,30 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction)
ac->mode = saction->mode;
return 1;
-
+
case SACTCONT_GPENCIL: /* Grease Pencil */ /* XXX review how this mode is handled... */
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
saction->ads.source = (ID *)ac->scene;
-
+
ac->datatype = ANIMCONT_GPENCIL;
ac->data = &saction->ads;
-
+
ac->mode = saction->mode;
return 1;
-
- case SACTCONT_MASK: /* Grease Pencil */ /* XXX review how this mode is handled... */
- /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+
+ case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
{
/* TODO, other methods to get the mask */
// Sequence *seq = BKE_sequencer_active_get(ac->scene);
//MovieClip *clip = ac->scene->clip;
// struct Mask *mask = seq ? seq->mask : NULL;
-
+
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
saction->ads.source = (ID *)ac->scene;
-
+
ac->datatype = ANIMCONT_MASK;
ac->data = &saction->ads;
-
+
ac->mode = saction->mode;
return 1;
}
@@ -688,12 +689,12 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
{
Speaker *spk = (Speaker *)data;
AnimData *adt = spk->adt;
-
+
ale->flag = FILTER_SPK_OBJD(spk);
-
+
ale->key_data = (adt) ? adt->action : NULL;
ale->datatype = ALE_ACT;
-
+
ale->adt = BKE_animdata_from_id(data);
}
break;
@@ -736,6 +737,19 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
ale->adt = BKE_animdata_from_id(data);
}
break;
+ case ANIMTYPE_DSLINESTYLE:
+ {
+ FreestyleLineStyle *linestyle= (FreestyleLineStyle *)data;
+ AnimData *adt= linestyle->adt;
+
+ ale->flag= FILTER_LS_SCED(linestyle);
+
+ ale->key_data= (adt) ? adt->action : NULL;
+ ale->datatype= ALE_ACT;
+
+ ale->adt= BKE_animdata_from_id(data);
+ }
+ break;
case ANIMTYPE_DSPART:
{
ParticleSettings *part = (ParticleSettings *)ale->data;
@@ -799,7 +813,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
/* the corresponding keyframes are from the animdata */
if (ale->adt && ale->adt->action) {
bAction *act = ale->adt->action;
- char *rna_path = key_get_curValue_rnaPath(key, kb);
+ char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
/* try to find the F-Curve which corresponds to this exactly,
* then free the MEM_alloc'd string
@@ -824,18 +838,18 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
ale->datatype = ALE_GPFRAME;
}
break;
-
+
case ANIMTYPE_MASKLAYER:
{
MaskLayer *masklay = (MaskLayer *)data;
-
+
ale->flag = masklay->flag;
-
+
ale->key_data = NULL;
ale->datatype = ALE_MASKLAY;
}
break;
-
+
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt = (NlaTrack *)data;
@@ -1138,7 +1152,6 @@ static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeShee
/* don't include anything from this action if it is linked in from another file,
* and we're getting stuff for editing...
*/
- // TODO: need a way of tagging other channels that may also be affected...
if ((filter_mode & ANIMFILTER_FOREDIT) && (act->id.lib))
return 0;
@@ -1240,11 +1253,11 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
{
AnimData *adt = BKE_animdata_from_id(id);
size_t items = 0;
-
+
/* image object datablocks have no anim-data so check for NULL */
if (adt) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
-
+
/* NOTE: this macro is used instead of inlining the logic here, since this sort of filtering is still needed
* in a few places in he rest of the code still - notably for the few cases where special mode-based
* different types of data expanders are required.
@@ -1265,7 +1278,7 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
}
);
}
-
+
return items;
}
@@ -1283,7 +1296,6 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke
/* loop through the channels adding ShapeKeys as appropriate */
for (kb = key->block.first; kb; kb = kb->next) {
/* skip the first one, since that's the non-animatable basis */
- // XXX maybe in future this may become handy?
if (kb == key->block.first) continue;
/* only work with this channel and its subchannels if it is editable */
@@ -1485,6 +1497,54 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data,
return items;
}
+static size_t animdata_filter_ds_linestyle (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+{
+ SceneRenderLayer *srl;
+ size_t items = 0;
+
+ for (srl= sce->r.layers.first; srl; srl= srl->next) {
+ FreestyleLineSet *lineset;
+
+ /* skip render layers without Freestyle enabled */
+ if (!(srl->layflag & SCE_LAY_FRS))
+ continue;
+
+ /* loop over linesets defined in the render layer */
+ for (lineset= srl->freestyleConfig.linesets.first; lineset; lineset= lineset->next) {
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+
+ /* add scene-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)linestyle, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include anim-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if ANIMCHANNEL_ACTIVEOK(linestyle) {
+ ANIMCHANNEL_NEW_CHANNEL(linestyle, ANIMTYPE_DSLINESTYLE, sce);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
+ items += tmp_items;
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
/* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */
static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
{
@@ -1597,7 +1657,6 @@ static size_t animdata_filter_ds_material(bAnimContext *ac, ListBase *anim_data,
/* did we find anything? */
if (tmp_items) {
/* include material-expand widget first */
- // hmm... do we need to store the index of this material in the array anywhere?
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if (ANIMCHANNEL_ACTIVEOK(ma)) {
@@ -1809,11 +1868,11 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b
{
Lamp *la = ob->data;
bNodeTree *ntree = la->nodetree;
-
+
/* nodetree */
if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE))
tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, &la->id, ntree, filter_mode);
-
+
/* textures */
if (!(ads->filterflag & ADS_FILTER_NOTEX))
tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, &la->id, filter_mode);
@@ -1943,7 +2002,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
/* filter data contained under object first */
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_OBJC(ob))
{
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
/* object-level animation */
if ((ob->adt) && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
@@ -2120,6 +2179,11 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)sce, ntree, filter_mode);
}
+ /* line styles */
+ if ((ads->filterflag & ADS_FILTER_NOLINESTYLE) == 0) {
+ tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, ads, sce, filter_mode);
+ }
+
/* TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here */
}
END_ANIMFILTER_SUBCHANNELS;
@@ -2277,7 +2341,7 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
size_t items = 0;
/* data to filter depends on channel type */
- // XXX: only common channel-types have been handled for now
+ /* NOTE: only common channel-types have been handled for now. More can be added as necessary */
switch (channel->type) {
case ANIMTYPE_SUMMARY:
items += animdata_filter_dopesheet(ac, anim_data, ads, filter_mode);
@@ -2290,6 +2354,10 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
case ANIMTYPE_OBJECT:
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
break;
+
+ default:
+ printf("ERROR: Unsupported channel type (%d) in animdata_filter_animchan()\n", channel->type);
+ break;
}
return items;
@@ -2414,9 +2482,9 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo
}
break;
- case ANIMCONT_FCURVES: /* Graph Editor -> FCurves/Animation Editing */
+ case ANIMCONT_FCURVES: /* Graph Editor -> F-Curves/Animation Editing */
case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */
- case ANIMCONT_NLA: /* NLA Editor */
+ case ANIMCONT_NLA: /* NLA Editor */
{
/* all of these editors use the basic DopeSheet data for filtering options, but don't have all the same features */
items = animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 445b684c261..270e7fc8f90 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -354,7 +354,7 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
xpos = marker->frame;
/* no time correction for framelen! space is drawn with old values */
- ypixels = BLI_RCT_SIZE_Y(&v2d->mask);
+ ypixels = BLI_rcti_size_y(&v2d->mask);
UI_view2d_getscale(v2d, &xscale, &yscale);
glScalef(1.0f / xscale, 1.0f, 1.0f);
@@ -773,7 +773,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
if (hasNumInput(&mm->num))
break;
- dx = BLI_RCT_SIZE_X(&v2d->cur) / BLI_RCT_SIZE_X(&v2d->mask);
+ dx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
if (evt->x != mm->evtx) { /* XXX maybe init for first time */
int a, offs, totmark = 0;
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index e254fb7a3c4..30e4d8570cb 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -74,13 +74,6 @@
#define B_REDR 1
#define B_FMODIFIER_REDRAW 20
-/* macro for use here to draw background box and set height */
-// XXX for now, roundbox has it's callback func set to NULL to not intercept events
-#define DRAW_BACKDROP(height) \
- { \
- uiDefBut(block, ROUNDBOX, B_REDR, "", -3, yco - height, width + 3, height - 1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \
- } (void)0
-
/* callback to verify modifier data */
static void validate_fmodifier_cb(bContext *UNUSED(C), void *fcm_v, void *UNUSED(arg))
{
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 5e0459bea90..1791d84d90b 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1836,7 +1836,7 @@ static short object_frame_has_keyframe(Object *ob, float frame, short filter)
/* try shapekey keyframes (if available, and allowed by filter) */
if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) {
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
/* shapekeys can have keyframes ('Relative Shape Keys')
* or depend on time (old 'Absolute Shape Keys')
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 78d3d8dc64d..f3f985fa97d 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -644,7 +644,7 @@ static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], in
short pval[2];
int pdist;
- project_short_noclip(ar, stk->points[i].p, pval);
+ ED_view3d_project_short_noclip(ar, stk->points[i].p, pval);
pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
@@ -679,7 +679,7 @@ static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones,
{
copy_v3_v3(vec, bone->head);
mul_m4_v3(ob->obmat, vec);
- project_short_noclip(ar, vec, pval);
+ ED_view3d_project_short_noclip(ar, vec, pval);
pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
@@ -695,7 +695,7 @@ static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones,
copy_v3_v3(vec, bone->tail);
mul_m4_v3(ob->obmat, vec);
- project_short_noclip(ar, vec, pval);
+ ED_view3d_project_short_noclip(ar, vec, pval);
pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
@@ -907,7 +907,7 @@ static void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end,
float delta = len_v3v3(stk->points[i].p, stk->points[i + 1].p);
float pval[2];
- project_float(ar, stk->points[i].p, pval);
+ ED_view3d_project_float(ar, stk->points[i].p, pval);
ED_view3d_win_to_ray(ar, v3d, pval, ray_start, ray_normal);
mul_v3_fl(ray_normal, distance * progress / length);
@@ -934,7 +934,7 @@ static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_Dr
initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
/* method taken from editview.c - mouse_cursor() */
- project_short_noclip(ar, fp, cval);
+ ED_view3d_project_short_noclip(ar, fp, cval);
VECSUB2D(mval_f, cval, dd->mval);
ED_view3d_win_to_delta(ar, mval_f, dvec);
sub_v3_v3v3(vec, fp, dvec);
@@ -1453,8 +1453,8 @@ static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gestu
float s_p2[3] = {0, 0, 0};
int g_i;
- project_float(ar, gesture->points[s_i].p, s_p1);
- project_float(ar, gesture->points[s_i + 1].p, s_p2);
+ ED_view3d_project_float(ar, gesture->points[s_i].p, s_p1);
+ ED_view3d_project_float(ar, gesture->points[s_i + 1].p, s_p2);
/* start checking from second next, because two consecutive cannot intersect */
for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++) {
@@ -1463,8 +1463,8 @@ static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gestu
float vi[3];
float lambda;
- project_float(ar, gesture->points[g_i].p, g_p1);
- project_float(ar, gesture->points[g_i + 1].p, g_p2);
+ ED_view3d_project_float(ar, gesture->points[g_i].p, g_p1);
+ ED_view3d_project_float(ar, gesture->points[g_i + 1].p, g_p2);
if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) {
SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
@@ -1531,8 +1531,8 @@ static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, S
float s_p2[3] = {0, 0, 0};
int g_i;
- project_float(ar, stk->points[s_i].p, s_p1);
- project_float(ar, stk->points[s_i + 1].p, s_p2);
+ ED_view3d_project_float(ar, stk->points[s_i].p, s_p1);
+ ED_view3d_project_float(ar, stk->points[s_i + 1].p, s_p2);
for (g_i = 0; g_i < gesture->nb_points - 1; g_i++) {
float g_p1[3] = {0, 0, 0};
@@ -1540,8 +1540,8 @@ static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, S
float vi[3];
float lambda;
- project_float(ar, gesture->points[g_i].p, g_p1);
- project_float(ar, gesture->points[g_i + 1].p, g_p2);
+ ED_view3d_project_float(ar, gesture->points[g_i].p, g_p1);
+ ED_view3d_project_float(ar, gesture->points[g_i + 1].p, g_p2);
if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) {
SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
@@ -1784,8 +1784,8 @@ int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *UNUSED(sketc
short start_val[2], end_val[2];
short dist;
- project_short_noclip(ar, gest->stk->points[0].p, start_val);
- project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
+ ED_view3d_project_short_noclip(ar, gest->stk->points[0].p, start_val);
+ ED_view3d_project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index ac1766aff69..2f5eaabc12b 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -81,6 +81,23 @@
#include "armature_intern.h"
+/* matches logic with ED_operator_posemode_context() */
+Object *ED_pose_object_from_context(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ Object *ob;
+
+ /* since this call may also be used from the buttons window, we need to check for where to get the object */
+ if (sa && sa->spacetype == SPACE_BUTS) {
+ ob = ED_object_context(C);
+ }
+ else {
+ ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ }
+
+ return ob;
+}
+
/* This function is used to process the necessary updates for */
void ED_armature_enter_posemode(bContext *C, Base *base)
{
@@ -1331,15 +1348,8 @@ void POSE_OT_paste(wmOperatorType *ot)
static int pose_group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- Object *ob;
-
- /* since this call may also be used from the buttons window, we need to check for where to get the object */
- if (sa->spacetype == SPACE_BUTS)
- ob = ED_object_context(C);
- else
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
+ Object *ob = ED_pose_object_from_context(C);
+
/* only continue if there's an object */
if (ob == NULL)
return OPERATOR_CANCELLED;
@@ -1362,7 +1372,7 @@ void POSE_OT_group_add(wmOperatorType *ot)
/* api callbacks */
ot->exec = pose_group_add_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = ED_operator_posemode_context;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1371,14 +1381,7 @@ void POSE_OT_group_add(wmOperatorType *ot)
static int pose_group_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- Object *ob;
-
- /* since this call may also be used from the buttons window, we need to check for where to get the object */
- if (sa->spacetype == SPACE_BUTS)
- ob = ED_object_context(C);
- else
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Object *ob = ED_pose_object_from_context(C);
/* only continue if there's an object */
if (ob == NULL)
@@ -1402,7 +1405,7 @@ void POSE_OT_group_remove(wmOperatorType *ot)
/* api callbacks */
ot->exec = pose_group_remove_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = ED_operator_posemode_context;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1413,8 +1416,7 @@ void POSE_OT_group_remove(wmOperatorType *ot)
/* invoke callback which presents a list of bone-groups for the user to choose from */
static int pose_groups_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
{
- ScrArea *sa = CTX_wm_area(C);
- Object *ob;
+ Object *ob = ED_pose_object_from_context(C);
bPose *pose;
uiPopupMenu *pup;
@@ -1422,12 +1424,6 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(
bActionGroup *grp;
int i;
- /* since this call may also be used from the buttons window, we need to check for where to get the object */
- if (sa->spacetype == SPACE_BUTS)
- ob = ED_object_context(C);
- else
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
/* only continue if there's an object, and a pose there too */
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
@@ -1466,17 +1462,10 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(
/* Assign selected pchans to the bone group that the user selects */
static int pose_group_assign_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- Object *ob;
+ Object *ob = ED_pose_object_from_context(C);
bPose *pose;
short done = FALSE;
-
- /* since this call may also be used from the buttons window, we need to check for where to get the object */
- if (sa->spacetype == SPACE_BUTS)
- ob = ED_object_context(C);
- else
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
+
/* only continue if there's an object, and a pose there too */
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
@@ -1518,7 +1507,7 @@ void POSE_OT_group_assign(wmOperatorType *ot)
/* api callbacks */
ot->invoke = pose_groups_menu_invoke;
ot->exec = pose_group_assign_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = ED_operator_posemode_context;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1530,16 +1519,9 @@ void POSE_OT_group_assign(wmOperatorType *ot)
static int pose_group_unassign_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- Object *ob;
+ Object *ob = ED_pose_object_from_context(C);
short done = FALSE;
- /* since this call may also be used from the buttons window, we need to check for where to get the object */
- if (sa->spacetype == SPACE_BUTS)
- ob = ED_object_context(C);
- else
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
/* only continue if there's an object, and a pose there too */
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
@@ -1573,7 +1555,7 @@ void POSE_OT_group_unassign(wmOperatorType *ot)
/* api callbacks */
ot->exec = pose_group_unassign_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = ED_operator_posemode_context;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1581,7 +1563,7 @@ void POSE_OT_group_unassign(wmOperatorType *ot)
static int group_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_pose_object_from_context(C);
bPose *pose = (ob) ? ob->pose : NULL;
bPoseChannel *pchan;
bActionGroup *grp;
@@ -1654,7 +1636,7 @@ void POSE_OT_group_move(wmOperatorType *ot)
/* api callbacks */
ot->exec = group_move_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = ED_operator_posemode_context;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1679,7 +1661,7 @@ static int compare_agroup(const void *sgrp_a_ptr, const void *sgrp_b_ptr)
static int group_sort_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_pose_object_from_context(C);
bPose *pose = (ob) ? ob->pose : NULL;
bPoseChannel *pchan;
tSortActionGroup *agrp_array;
@@ -1738,7 +1720,7 @@ void POSE_OT_group_sort(wmOperatorType *ot)
/* api callbacks */
ot->exec = group_sort_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = ED_operator_posemode_context;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1766,14 +1748,7 @@ static void pose_group_select(bContext *C, Object *ob, int select)
static int pose_group_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- Object *ob;
-
- /* since this call may also be used from the buttons window, we need to check for where to get the object */
- if (sa->spacetype == SPACE_BUTS)
- ob = ED_object_context(C);
- else
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Object *ob = ED_pose_object_from_context(C);
/* only continue if there's an object, and a pose there too */
if (ELEM(NULL, ob, ob->pose))
@@ -1796,7 +1771,7 @@ void POSE_OT_group_select(wmOperatorType *ot)
/* api callbacks */
ot->exec = pose_group_select_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = ED_operator_posemode_context;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1804,14 +1779,7 @@ void POSE_OT_group_select(wmOperatorType *ot)
static int pose_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- Object *ob;
-
- /* since this call may also be used from the buttons window, we need to check for where to get the object */
- if (sa->spacetype == SPACE_BUTS)
- ob = ED_object_context(C);
- else
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Object *ob = ED_pose_object_from_context(C);
/* only continue if there's an object, and a pose there too */
if (ELEM(NULL, ob, ob->pose))
@@ -1834,7 +1802,7 @@ void POSE_OT_group_deselect(wmOperatorType *ot)
/* api callbacks */
ot->exec = pose_group_deselect_exec;
- ot->poll = ED_operator_posemode;
+ ot->poll = ED_operator_posemode_context;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index d780429784f..9c13f4be6a9 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1233,12 +1233,12 @@ void make_editNurb(Object *obedit)
set_actNurb(obedit, NULL);
if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- actkey = ob_get_keyblock(obedit);
+ actkey = BKE_keyblock_from_object(obedit);
if (actkey) {
// XXX strcpy(G.editModeTitleExtra, "(Key) ");
undo_editmode_clear();
- key_to_curve(actkey, cu, &cu->nurb);
+ BKE_key_convert_to_curve(actkey, cu, &cu->nurb);
}
if (editnurb) {
@@ -6070,7 +6070,7 @@ void CURVE_OT_shade_flat(wmOperatorType *ot)
}
/************** join operator, to be used externally? ****************/
-
+/* TODO: shape keys - as with meshes */
int join_curve_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
@@ -6191,10 +6191,9 @@ static const char *get_surf_defname(int type)
}
-Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
+Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob)
{
static int xzproj = 0; /* this function calls itself... */
- Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ED_view3d_context_rv3d(C);
@@ -6431,7 +6430,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
break;
case CU_PRIM_TUBE: /* Cylinder */
if (cutype == CU_NURBS) {
- nu = add_nurbs_primitive(C, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
+ nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
nu->resolu = cu->resolu;
nu->flag = CU_SMOOTH;
BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
@@ -6510,7 +6509,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
float tmp_vec[3] = {0.f, 0.f, 1.f};
xzproj = 1;
- nu = add_nurbs_primitive(C, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
+ nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
xzproj = 0;
nu->resolu = cu->resolu;
nu->resolv = cu->resolv;
@@ -6607,7 +6606,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
- nu = add_nurbs_primitive(C, mat, type, newob);
+ nu = add_nurbs_primitive(C, obedit, mat, type, newob);
editnurb = object_editcurve_get(obedit);
BLI_addtail(editnurb, nu);
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 5d67b63af18..659e99607f0 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -422,8 +422,8 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin
}
else {
if (subrect) {
- mvalf[0] = (((float)pt->x / 100.0f) * BLI_RCT_SIZE_X(subrect)) + subrect->xmin;
- mvalf[1] = (((float)pt->y / 100.0f) * BLI_RCT_SIZE_Y(subrect)) + subrect->ymin;
+ mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
+ mvalf[1] = (((float)pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
}
else {
mvalf[0] = (float)pt->x / 100.0f * ar->winx;
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 4e281b96fc3..8ba4985ffc4 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -278,7 +278,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
gp_get_3d_reference(p, rvec);
/* method taken from editview.c - mouse_cursor() */
- project_int_noclip(p->ar, rvec, mval_prj);
+ ED_view3d_project_int_noclip(p->ar, rvec, mval_prj);
VECSUB2D(mval_f, mval_prj, mval);
ED_view3d_win_to_delta(p->ar, mval_f, dvec);
@@ -299,8 +299,8 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
out[1] = (float)(mval[1]) / (float)(p->ar->winy) * 100;
}
else { /* camera view, use subrect */
- out[0] = ((mval[0] - p->subrect->xmin) / BLI_RCT_SIZE_X(p->subrect)) * 100;
- out[1] = ((mval[1] - p->subrect->ymin) / BLI_RCT_SIZE_Y(p->subrect)) * 100;
+ out[0] = ((mval[0] - p->subrect->xmin) / BLI_rctf_size_x(p->subrect)) * 100;
+ out[1] = ((mval[1] - p->subrect->ymin) / BLI_rctf_size_y(p->subrect)) * 100;
}
}
}
@@ -808,7 +808,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
else if (gps->totpoints == 1) {
/* get coordinates */
if (gps->flag & GP_STROKE_3DSPACE) {
- project_int(p->ar, &gps->points->x, xyval);
+ ED_view3d_project_int(p->ar, &gps->points->x, xyval);
x0 = xyval[0];
y0 = xyval[1];
}
@@ -821,8 +821,8 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
y0 = (int)(gps->points->y / 100 * p->ar->winy);
}
else { /* camera view, use subrect */
- x0 = (int)((gps->points->x / 100) * BLI_RCT_SIZE_X(p->subrect)) + p->subrect->xmin;
- y0 = (int)((gps->points->y / 100) * BLI_RCT_SIZE_Y(p->subrect)) + p->subrect->ymin;
+ x0 = (int)((gps->points->x / 100) * BLI_rctf_size_x(p->subrect)) + p->subrect->xmin;
+ y0 = (int)((gps->points->y / 100) * BLI_rctf_size_y(p->subrect)) + p->subrect->ymin;
}
}
@@ -847,11 +847,11 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
/* get coordinates */
if (gps->flag & GP_STROKE_3DSPACE) {
- project_int(p->ar, &pt1->x, xyval);
+ ED_view3d_project_int(p->ar, &pt1->x, xyval);
x0 = xyval[0];
y0 = xyval[1];
- project_int(p->ar, &pt2->x, xyval);
+ ED_view3d_project_int(p->ar, &pt2->x, xyval);
x1 = xyval[0];
y1 = xyval[1];
}
@@ -868,10 +868,10 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
y1 = (int)(pt2->y / 100 * p->ar->winy);
}
else { /* camera view, use subrect */
- x0 = (int)((pt1->x / 100) * BLI_RCT_SIZE_X(p->subrect)) + p->subrect->xmin;
- y0 = (int)((pt1->y / 100) * BLI_RCT_SIZE_Y(p->subrect)) + p->subrect->ymin;
- x1 = (int)((pt2->x / 100) * BLI_RCT_SIZE_X(p->subrect)) + p->subrect->xmin;
- y1 = (int)((pt2->y / 100) * BLI_RCT_SIZE_Y(p->subrect)) + p->subrect->ymin;
+ x0 = (int)((pt1->x / 100) * BLI_rctf_size_x(p->subrect)) + p->subrect->xmin;
+ y0 = (int)((pt1->y / 100) * BLI_rctf_size_y(p->subrect)) + p->subrect->ymin;
+ x1 = (int)((pt2->x / 100) * BLI_rctf_size_x(p->subrect)) + p->subrect->xmin;
+ y1 = (int)((pt2->y / 100) * BLI_rctf_size_y(p->subrect)) + p->subrect->ymin;
}
}
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index e1401a8ff88..fbddd26c959 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -155,6 +155,7 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSMESH,
ANIMTYPE_DSTEX,
ANIMTYPE_DSLAT,
+ ANIMTYPE_DSLINESTYLE,
ANIMTYPE_DSSPK,
ANIMTYPE_SHAPEKEY,
@@ -236,6 +237,7 @@ typedef enum eAnimFilter_Flags {
#define EXPANDED_SCEC(sce) ((sce->flag & SCE_DS_COLLAPSED) == 0)
/* 'Sub-Scene' channels (flags stored in Data block) */
#define FILTER_WOR_SCED(wo) ((wo->flag & WO_DS_EXPAND))
+#define FILTER_LS_SCED(linestyle) ((linestyle->flag & LS_DS_EXPAND))
/* 'Object' channels */
#define SEL_OBJC(base) ((base->flag & SELECT))
#define EXPANDED_OBJC(ob) ((ob->nlaflag & OB_ADS_COLLAPSED) == 0)
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 07f3498580c..4e33404be7e 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -148,6 +148,7 @@ void ED_armature_enter_posemode(struct bContext *C, struct Base *base);
int ED_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan);
void ED_pose_deselectall(struct Object *ob, int test);
void ED_pose_recalculate_paths(struct Scene *scene, struct Object *ob);
+struct Object *ED_pose_object_from_context(struct bContext *C);
/* sketch */
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index ac8d82e9060..d66cc49a5d0 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -67,7 +67,7 @@ void BKE_curve_editNurb_free(struct Curve *cu);
int mouse_nurb(struct bContext *C, const int mval[2], int extend, int deselect, int toggle);
-struct Nurb *add_nurbs_primitive(struct bContext *C, float mat[4][4], int type, int newob);
+struct Nurb *add_nurbs_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob);
int isNurbsel(struct Nurb *nu);
void ED_nurb_set_spline_type(struct Nurb *nu, int type);
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index b4b739e4d06..5ce6db97305 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -38,7 +38,7 @@ struct wmKeyConfig;
void ED_operatortypes_metaball(void);
void ED_keymap_metaball(struct wmKeyConfig *keyconf);
-struct MetaElem *add_metaball_primitive(struct bContext *C, float mat[4][4], int type, int newname);
+struct MetaElem *add_metaball_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newname);
int mouse_mball(struct bContext *C, const int mval[2], int extend, int deselect, int toggle);
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 1d4fbe81e02..3d15f349f9b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -148,7 +148,7 @@ struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, int *dist);
int EDBM_select_pick(struct bContext *C, const int mval[2], short extend, short deselect, short toggle);
void EDBM_selectmode_set(struct BMEditMesh *em);
-void EDBM_selectmode_convert(struct BMEditMesh *em, short oldmode, const short selectmode);
+void EDBM_selectmode_convert(struct BMEditMesh *em, short selectmode_old, const short selectmode_new);
void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index fc20bdfb9c5..860d176ffb3 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -111,6 +111,7 @@ ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
struct ScrArea *ED_screen_full_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa);
+void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
/* anim */
void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute);
@@ -170,6 +171,7 @@ int ED_operator_editmball(struct bContext *C);
int ED_operator_uvedit(struct bContext *C);
int ED_operator_uvmap(struct bContext *C);
int ED_operator_posemode_exclusive(struct bContext *C);
+int ED_operator_posemode_context(struct bContext *C);
int ED_operator_posemode(struct bContext *C);
int ED_operator_mask(struct bContext *C);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index b1bccfa32c5..9536dd76581 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -89,139 +89,45 @@ float *give_cursor(struct Scene *scene, struct View3D *v3d);
int initgrabz(struct RegionView3D *rv3d, float x, float y, float z);
-/**
- * Calculate a 3d location from 2d window coordinates.
- * \param ar The region (used for the window width and height).
- * \param depth_pt The reference location used to calculate the Z depth.
- * \param mval The area relative location (such as event->mval converted to floats).
- * \param out The resulting world-space location.
- */
void ED_view3d_win_to_3d(struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]);
-
-/**
- * Calculate a 3d difference vector from 2d window offset.
- * note that initgrabz() must be called first to determine
- * the depth used to calculate the delta.
- * \param ar The region (used for the window width and height).
- * \param mval The area relative 2d difference (such as event->mval[0] - other_x).
- * \param out The resulting world-space delta.
- */
void ED_view3d_win_to_delta(struct ARegion *ar, const float mval[2], float out[3]);
-
-/**
- * Calculate a 3d direction vector from 2d window coordinates.
- * This direction vector starts and the view in the direction of the 2d window coordinates.
- * In orthographic view all window coordinates yield the same vector.
- * \param ar The region (used for the window width and height).
- * \param mval The area relative 2d location (such as event->mval converted to floats).
- * \param out The resulting normalized world-space direction vector.
- */
void ED_view3d_win_to_vector(struct ARegion *ar, const float mval[2], float out[3]);
-
-/**
- * Calculate a 3d segment from 2d window coordinates.
- * This ray_start is located at the viewpoint, ray_end is a far point.
- * ray_start and ray_end are clipped by the view near and far limits
- * so points along this line are always in view.
- * In orthographic view all resulting segments will be parallel.
- * \param ar The region (used for the window width and height).
- * \param v3d The 3d viewport (used for near and far clipping range).
- * \param mval The area relative 2d location (such as event->mval, converted into float[2]).
- * \param ray_start The world-space starting point of the segment.
- * \param ray_end The world-space end point of the segment.
- */
void ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]);
-
-/**
- * Calculate a 3d viewpoint and direction vector from 2d window coordinates.
- * This ray_start is located at the viewpoint, ray_normal is the direction towards mval.
- * ray_start is clipped by the view near limit so points in front of it are always in view.
- * In orthographic view the resulting ray_normal will match the view vector.
- * \param ar The region (used for the window width and height).
- * \param v3d The 3d viewport (used for near clipping value).
- * \param mval The area relative 2d location (such as event->mval, converted into float[2]).
- * \param ray_start The world-space starting point of the segment.
- * \param ray_normal The normalized world-space direction of towards mval.
- */
void ED_view3d_win_to_ray(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]);
-/**
- * Calculate a normalized 3d direction vector from the viewpoint towards a global location.
- * In orthographic view the resulting vector will match the view vector.
- * \param rv3d The region (used for the window width and height).
- * \param coord The world-space location.
- * \param vec The resulting normalized vector.
- */
void ED_view3d_global_to_vector(struct RegionView3D *rv3d, const float coord[3], float vec[3]);
-
-/**
- * Calculate the view transformation matrix from RegionView3D input.
- * The resulting matrix is equivalent to RegionView3D.viewinv
- * \param mat The view 4x4 transformation matrix to calculate.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], const float dist);
-
-/**
- * Set the view transformation from a 4x4 matrix.
- * \param mat The view 4x4 transformation matrix to assign.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist);
-/**
- * Set the RegionView3D members from an objects transformation and optionally lens.
- * \param ob The object to set the view to.
- * \param ofs The view offset to be set, normally from RegionView3D.ofs.
- * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
- * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
- */
void ED_view3d_from_object(struct Object *ob, float ofs[3], float quat[4], float *dist, float *lens);
-
-/**
- * Set the object transformation from RegionView3D members.
- * \param ob The object which has the transformation assigned.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
void ED_view3d_to_object(struct Object *ob, const float ofs[3], const float quat[4], const float dist);
-//#if 0 /* UNUSED */
-void view3d_unproject(struct bglMats *mats, float out[3], const short x, const short y, const float z);
-//#endif
-
/* Depth buffer */
-void ED_view3d_depth_update(struct ARegion *ar);
+void ED_view3d_depth_update(struct ARegion *ar);
float ED_view3d_depth_read_cached(struct ViewContext *vc, int x, int y);
-void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
+void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
/* Projection */
#define IS_CLIPPED 12000
-void ED_view3d_calc_clipping(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect);
-
-void project_short(struct ARegion *ar, const float vec[3], short adr[2]);
-void project_short_noclip(struct ARegion *ar, const float vec[3], short adr[2]);
-
-void project_int(struct ARegion *ar, const float vec[3], int adr[2]);
-void project_int_noclip(struct ARegion *ar, const float vec[3], int adr[2]);
-
-void apply_project_float(float persmat[4][4], int winx, int winy, const float vec[], float adr[2]);
-void project_float(struct ARegion *ar, const float vec[3], float adr[2]);
-void project_float_noclip(struct ARegion *ar, const float vec[3], float adr[2]);
-
-int ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *clipsta, float *clipend);
-int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend);
+/* TODO, these functions work quite differently, we should make them behave in a uniform way
+ * otherwise we can't be sure bugs are not added when we need to move from short->float types for eg
+ * - Campbell */
+void ED_view3d_project_short(struct ARegion *ar, const float co[3], short r_co[2]);
+void ED_view3d_project_short_noclip(struct ARegion *ar, const float vec[3], short r_co[2]);
+void ED_view3d_project_int(struct ARegion *ar, const float co[3], int r_co[2]);
+void ED_view3d_project_int_noclip(struct ARegion *ar, const float co[3], int r_co[2]);
+void ED_view3d_project_float(struct ARegion *ar, const float co[3], float r_co[2]);
+void ED_view3d_project_float_noclip(struct ARegion *ar, const float co[3], float r_co[2]);
+void ED_view3d_project_float_v2_m4(const struct ARegion *a, const float co[3], float r_co[2], float mat[4][4]);
+void ED_view3d_project_float_v3_m4(struct ARegion *a, const float co[3], float r_co[3], float mat[4][4]);
+
+void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z);
+
+int ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *clipsta, float *clipend);
+int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend);
void ED_view3d_ob_project_mat_get(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, struct rctf *viewborder_r, short no_shift);
-void ED_view3d_project_float_v2(const struct ARegion *a, const float vec[3], float adr[2], float mat[4][4]);
-void ED_view3d_project_float_v3(struct ARegion *a, const float vec[3], float adr[3], float mat[4][4]);
void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, float size_r[2]);
/* drawobject.c iterators */
@@ -231,6 +137,7 @@ void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData,
void nurbs_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt, int beztindex, int x, int y), void *userData);
void lattice_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BPoint *bp, int x, int y), void *userData);
+void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect);
void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[][4]);
int ED_view3d_clipping_test(struct RegionView3D *rv3d, const float vec[3], const int is_local);
void ED_view3d_clipping_set(struct RegionView3D *rv3d);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 917153c9199..32132f497a8 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -120,11 +120,12 @@ typedef struct uiLayout uiLayout;
#define UI_BLOCK_CLIP_EVENTS 8192 /* stop handling mouse events */
/* uiPopupBlockHandle->menuretval */
-#define UI_RETURN_CANCEL 1 /* cancel all menus cascading */
-#define UI_RETURN_OK 2 /* choice made */
-#define UI_RETURN_OUT 4 /* left the menu */
-#define UI_RETURN_UPDATE 8 /* update the button that opened */
-#define UI_RETURN_POPUP_OK 16 /* popup is ok to be handled */
+#define UI_RETURN_CANCEL 1 /* cancel all menus cascading */
+#define UI_RETURN_OK 2 /* choice made */
+#define UI_RETURN_OUT 4 /* left the menu */
+#define UI_RETURN_OUT_PARENT 8 /* let the parent handle this event */
+#define UI_RETURN_UPDATE 16 /* update the button that opened */
+#define UI_RETURN_POPUP_OK 32 /* popup is ok to be handled */
/* block->flag bits 12-15 are identical to but->flag bits */
@@ -810,6 +811,8 @@ void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char
void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic);
void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_layer);
+void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
+ PointerRNA *used_ptr, const char *used_propname, int active_state);
void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact);
void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management);
void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index e879a01dbfb..77aa2ce154d 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -199,6 +199,9 @@ enum {
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE,
+ TH_FREESTYLE_EDGE_MARK,
+ TH_FREESTYLE_FACE_MARK,
+
TH_MATCH, /* highlight color for search matches */
TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 792c96fe7c8..24759fa778a 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -163,7 +163,8 @@ void UI_view2d_view_orthoSpecial(struct ARegion *ar, struct View2D *v2d, short x
void UI_view2d_view_restore(const struct bContext *C);
/* grid drawing */
-View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d, short xunits, short xclamp, short yunits, short yclamp, int winx, int winy);
+View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d,
+ short xunits, short xclamp, short yunits, short yclamp, int winx, int winy);
void UI_view2d_grid_draw(struct View2D *v2d, View2DGrid *grid, int flag);
void UI_view2d_constant_grid_draw(struct View2D *v2d);
void UI_view2d_multi_grid_draw(struct View2D *v2d, float step, int level_size, int totlevels);
@@ -171,14 +172,21 @@ void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy);
void UI_view2d_grid_free(View2DGrid *grid);
/* scrollbar drawing */
-View2DScrollers *UI_view2d_scrollers_calc(const struct bContext *C, struct View2D *v2d, short xunits, short xclamp, short yunits, short yclamp);
+View2DScrollers *UI_view2d_scrollers_calc(const struct bContext *C, struct View2D *v2d,
+ short xunits, short xclamp, short yunits, short yclamp);
void UI_view2d_scrollers_draw(const struct bContext *C, struct View2D *v2d, View2DScrollers *scrollers);
void UI_view2d_scrollers_free(View2DScrollers *scrollers);
/* list view tools */
-void UI_view2d_listview_cell_to_view(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int column, int row, struct rctf *rect);
-void UI_view2d_listview_view_to_cell(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, float viewx, float viewy, int *column, int *row);
-void UI_view2d_listview_visible_cells(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int *column_min, int *column_max, int *row_min, int *row_max);
+void UI_view2d_listview_cell_to_view(struct View2D *v2d, short columnwidth, short rowheight,
+ float startx, float starty, int column, int row,
+ struct rctf *rect);
+void UI_view2d_listview_view_to_cell(struct View2D *v2d, short columnwidth, short rowheight,
+ float startx, float starty, float viewx, float viewy,
+ int *column, int *row);
+void UI_view2d_listview_visible_cells(struct View2D *v2d, short columnwidth, short rowheight,
+ float startx, float starty, int *column_min, int *column_max,
+ int *row_min, int *row_max);
/* coordinate conversion */
void UI_view2d_region_to_view(struct View2D *v2d, int x, int y, float *viewx, float *viewy);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 742aed4fbb1..810cbc25862 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -79,10 +79,6 @@
#include "interface_intern.h"
-#define MENU_WIDTH 120
-#define MENU_ITEM_HEIGHT 20
-#define MENU_SEP_HEIGHT 6
-
#define PRECISION_FLOAT_MAX 6
#define PRECISION_FLOAT_MAX_POW 1000000 /* pow(10, PRECISION_FLOAT_MAX) */
@@ -106,8 +102,8 @@ void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y
float gx, gy;
int sx, sy, getsizex, getsizey;
- getsizex = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- getsizey = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ getsizex = BLI_rcti_size_x(&ar->winrct) + 1;
+ getsizey = BLI_rcti_size_y(&ar->winrct) + 1;
sx = ar->winrct.xmin;
sy = ar->winrct.ymin;
@@ -152,8 +148,8 @@ void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y
float a, b, c, d, e, f, px, py;
int sx, sy, getsizex, getsizey;
- getsizex = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- getsizey = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ getsizex = BLI_rcti_size_x(&ar->winrct) + 1;
+ getsizey = BLI_rcti_size_y(&ar->winrct) + 1;
sx = ar->winrct.xmin;
sy = ar->winrct.ymin;
@@ -279,7 +275,7 @@ void ui_bounds_block(uiBlock *block)
block->rect.ymax += block->bounds;
}
- block->rect.xmax = block->rect.xmin + maxf(BLI_RCT_SIZE_X(&block->rect), block->minbounds);
+ block->rect.xmax = block->rect.xmin + maxf(BLI_rctf_size_x(&block->rect), block->minbounds);
/* hardcoded exception... but that one is annoying with larger safety */
bt = block->buttons.first;
@@ -307,8 +303,8 @@ static void ui_centered_bounds_block(const bContext *C, uiBlock *block)
ui_bounds_block(block);
- width = BLI_RCT_SIZE_X(&block->rect);
- height = BLI_RCT_SIZE_Y(&block->rect);
+ width = BLI_rctf_size_x(&block->rect);
+ height = BLI_rctf_size_y(&block->rect);
startx = (xmax * 0.5f) - (width * 0.5f);
starty = (ymax * 0.5f) - (height * 0.5f);
@@ -332,8 +328,8 @@ static void ui_popup_bounds_block(const bContext *C, uiBlock *block, eBlockBound
wm_window_get_size(window, &xmax, &ymax);
- oldwidth = BLI_RCT_SIZE_X(&block->rect);
- oldheight = BLI_RCT_SIZE_Y(&block->rect);
+ oldwidth = BLI_rctf_size_x(&block->rect);
+ oldheight = BLI_rctf_size_y(&block->rect);
/* first we ensure wide enough text bounds */
if (bounds_calc == UI_BLOCK_BOUNDS_POPUP_MENU) {
@@ -348,8 +344,8 @@ static void ui_popup_bounds_block(const bContext *C, uiBlock *block, eBlockBound
ui_bounds_block(block);
/* and we adjust the position to fit within window */
- width = BLI_RCT_SIZE_X(&block->rect);
- height = BLI_RCT_SIZE_Y(&block->rect);
+ width = BLI_rctf_size_x(&block->rect);
+ height = BLI_rctf_size_y(&block->rect);
/* avoid divide by zero below, caused by calling with no UI, but better not crash */
oldwidth = oldwidth > 0 ? oldwidth : MAX2(1, width);
@@ -495,10 +491,10 @@ static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines)
if (line->from == NULL || line->to == NULL) return;
- rect.xmin = BLI_RCT_CENTER_X(&line->from->rect);
- rect.ymin = BLI_RCT_CENTER_Y(&line->from->rect);
- rect.xmax = BLI_RCT_CENTER_X(&line->to->rect);
- rect.ymax = BLI_RCT_CENTER_Y(&line->to->rect);
+ rect.xmin = BLI_rctf_cent_x(&line->from->rect);
+ rect.ymin = BLI_rctf_cent_y(&line->from->rect);
+ rect.xmax = BLI_rctf_cent_x(&line->to->rect);
+ rect.ymax = BLI_rctf_cent_y(&line->to->rect);
if (line->flag & UI_SELECT)
glColor3ub(100, 100, 100);
@@ -2257,7 +2253,7 @@ void ui_check_but(uiBut *but)
/* safety is 4 to enable small number buttons (like 'users') */
- // okwidth= -4 + (BLI_RCT_SIZE_X(&but->rect)); // UNUSED
+ // okwidth= -4 + (BLI_rcti_size_x(&but->rect)); // UNUSED
/* name: */
switch (but->type) {
@@ -2265,7 +2261,7 @@ void ui_check_but(uiBut *but)
case MENU:
case ICONTEXTROW:
- if (BLI_RCT_SIZE_X(&but->rect) > 24.0f) {
+ if (BLI_rctf_size_x(&but->rect) > 24.0f) {
UI_GET_BUT_VALUE_INIT(but, value);
ui_set_name_menu(but, (int)value);
}
@@ -2572,7 +2568,9 @@ void ui_block_do_align(uiBlock *block)
ui_block_do_align_but(but, nr);
/* skip with same number */
- for (; but && but->alignnr == nr; but = but->next) ;
+ for (; but && but->alignnr == nr; but = but->next) {
+ /* pass */
+ }
if (!but) {
break;
@@ -2621,6 +2619,9 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
uiBut *but;
int slen;
+ BLI_assert(width >= 0);
+ BLI_assert(height >= 0);
+
/* we could do some more error checks here */
if ((type & BUTTYPE) == LABEL) {
BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)) == FALSE);
@@ -3788,15 +3789,16 @@ void uiButGetStrInfo(bContext *C, uiBut *but, int nbr, ...)
if (type == BUT_GET_LABEL) {
if (but->str) {
/* Menu labels can have some complex formating stuff marked by pipes or %t, we don't want those here! */
- const char *tc;
-
- if (but->type == MENU)
- tc = strstr(but->str, "%t");
- else
- tc = strchr(but->str, '|');
-
- if (tc)
- tmp = BLI_strdupn(but->str, tc - but->str);
+ const char *tc1, *tc2;
+
+ tc1 = strstr(but->str, "%t");
+ tc2 = strstr(but->str, "|"); /* XXX For some reason strchr seems to not work here? */
+
+ if (tc2 && (!tc1 || tc1 > tc2))
+ tc1 = tc2;
+
+ if (tc1)
+ tmp = BLI_strdupn(but->str, tc1 - but->str);
else
tmp = BLI_strdup(but->str);
}
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index f535c3c3e2a..e7c7d934f9f 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -60,8 +60,6 @@
/* own include */
#include "interface_intern.h"
-#define UI_DISABLED_ALPHA_OFFS -160
-
static int roundboxtype = UI_CNR_ALL;
void uiSetRoundBox(int type)
@@ -86,7 +84,7 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r
/* mult */
for (a = 0; a < 7; a++) {
- vec[a][0] *= rad; vec[a][1] *= rad;
+ mul_v2_fl(vec[a], rad);
}
glBegin(mode);
@@ -157,18 +155,18 @@ void uiDrawBoxShade(int mode, float minx, float miny, float maxx, float maxy, fl
/* mult */
for (a = 0; a < 7; a++) {
- vec[a][0] *= rad; vec[a][1] *= rad;
+ mul_v2_fl(vec[a], rad);
}
/* get current color, needs to be outside of glBegin/End */
glGetFloatv(GL_CURRENT_COLOR, color);
/* 'shade' defines strength of shading */
- coltop[0] = color[0] + shadetop; if (coltop[0] > 1.0f) coltop[0] = 1.0f;
- coltop[1] = color[1] + shadetop; if (coltop[1] > 1.0f) coltop[1] = 1.0f;
- coltop[2] = color[2] + shadetop; if (coltop[2] > 1.0f) coltop[2] = 1.0f;
- coldown[0] = color[0] + shadedown; if (coldown[0] < 0.0f) coldown[0] = 0.0f;
- coldown[1] = color[1] + shadedown; if (coldown[1] < 0.0f) coldown[1] = 0.0f;
- coldown[2] = color[2] + shadedown; if (coldown[2] < 0.0f) coldown[2] = 0.0f;
+ coltop[0] = minf(1.0f, color[0] + shadetop);
+ coltop[1] = minf(1.0f, color[1] + shadetop);
+ coltop[2] = minf(1.0f, color[2] + shadetop);
+ coldown[0] = maxf(0.0f, color[0] + shadedown);
+ coldown[1] = maxf(0.0f, color[1] + shadedown);
+ coldown[2] = maxf(0.0f, color[2] + shadedown);
glShadeModel(GL_SMOOTH);
glBegin(mode);
@@ -266,18 +264,18 @@ void uiDrawBoxVerticalShade(int mode, float minx, float miny, float maxx, float
/* mult */
for (a = 0; a < 7; a++) {
- vec[a][0] *= rad; vec[a][1] *= rad;
+ mul_v2_fl(vec[a], rad);
}
/* get current color, needs to be outside of glBegin/End */
glGetFloatv(GL_CURRENT_COLOR, color);
/* 'shade' defines strength of shading */
- colLeft[0] = color[0] + shadeLeft; if (colLeft[0] > 1.0f) colLeft[0] = 1.0f;
- colLeft[1] = color[1] + shadeLeft; if (colLeft[1] > 1.0f) colLeft[1] = 1.0f;
- colLeft[2] = color[2] + shadeLeft; if (colLeft[2] > 1.0f) colLeft[2] = 1.0f;
- colRight[0] = color[0] + shadeRight; if (colRight[0] < 0.0f) colRight[0] = 0.0f;
- colRight[1] = color[1] + shadeRight; if (colRight[1] < 0.0f) colRight[1] = 0.0f;
- colRight[2] = color[2] + shadeRight; if (colRight[2] < 0.0f) colRight[2] = 0.0f;
+ colLeft[0] = minf(1.0f, color[0] + shadeLeft);
+ colLeft[1] = minf(1.0f, color[1] + shadeLeft);
+ colLeft[2] = minf(1.0f, color[2] + shadeLeft);
+ colRight[0] = maxf(0.0f, color[0] + shadeRight);
+ colRight[1] = maxf(0.0f, color[1] + shadeRight);
+ colRight[2] = maxf(0.0f, color[2] + shadeRight);
glShadeModel(GL_SMOOTH);
glBegin(mode);
@@ -440,8 +438,8 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
//glColor4f(1.0, 0.f, 0.f, 1.f);
//fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax)
- w = BLI_RCT_SIZE_X(rect);
- h = BLI_RCT_SIZE_Y(rect);
+ w = BLI_rcti_size_x(rect);
+ h = BLI_rcti_size_y(rect);
/* prevent drawing outside widget area */
glGetIntegerv(GL_SCISSOR_BOX, scissor);
glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin + rect->ymin, w, h);
@@ -494,8 +492,8 @@ static void ui_draw_but_CHARTAB(uiBut *but)
charmax = G.charmax = 0xffff;
/* Calculate the size of the button */
- width = abs(BLI_RCT_SIZE_X(rect));
- height = abs(BLI_RCT_SIZE_Y(rect));
+ width = abs(BLI_rcti_size_x(rect));
+ height = abs(BLI_rcti_size_y(rect));
butw = floor(width / 12);
buth = floor(height / 6);
@@ -601,7 +599,8 @@ static void ui_draw_but_CHARTAB(uiBut *but)
}
/* Calculate the next position and character */
- sx += butw; ex += butw;
+ sx += butw;
+ ex += butw;
cs++;
}
/* Add the y position and reset x position */
@@ -633,7 +632,7 @@ static void ui_draw_but_CHARTAB(uiBut *but)
#endif /* WITH_INTERNATIONAL */
#endif
-static void draw_scope_end(rctf *rect, GLint *scissor)
+static void draw_scope_end(const rctf *rect, GLint *scissor)
{
float scaler_x1, scaler_x2;
@@ -643,8 +642,8 @@ static void draw_scope_end(rctf *rect, GLint *scissor)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* scale widget */
- scaler_x1 = rect->xmin + BLI_RCT_SIZE_X(rect) / 2 - SCOPE_RESIZE_PAD;
- scaler_x2 = rect->xmin + BLI_RCT_SIZE_X(rect) / 2 + SCOPE_RESIZE_PAD;
+ scaler_x1 = rect->xmin + BLI_rctf_size_x(rect) / 2 - SCOPE_RESIZE_PAD;
+ scaler_x2 = rect->xmin + BLI_rctf_size_y(rect) / 2 + SCOPE_RESIZE_PAD;
glColor4f(0.f, 0.f, 0.f, 0.25f);
fdrawline(scaler_x1, rect->ymin - 4, scaler_x2, rect->ymin - 4);
@@ -733,8 +732,8 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2;
rect.ymax = (float)recti->ymax - 1;
- w = BLI_RCT_SIZE_X(&rect);
- h = BLI_RCT_SIZE_Y(&rect) * hist->ymax;
+ w = BLI_rctf_size_x(&rect);
+ h = BLI_rctf_size_y(&rect) * hist->ymax;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -806,9 +805,9 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
if (scopes->wavefrm_yfac < 0.5f)
scopes->wavefrm_yfac = 0.98f;
- w = BLI_RCT_SIZE_X(&rect) - 7;
- h = BLI_RCT_SIZE_Y(&rect) * scopes->wavefrm_yfac;
- yofs = rect.ymin + (BLI_RCT_SIZE_Y(&rect) - h) / 2.0f;
+ w = BLI_rctf_size_x(&rect) - 7;
+ h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
+ yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f;
w3 = w / 3.0f;
/* log scale for alpha */
@@ -1034,8 +1033,8 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2;
rect.ymax = (float)recti->ymax - 1;
- w = BLI_RCT_SIZE_X(&rect);
- h = BLI_RCT_SIZE_Y(&rect);
+ w = BLI_rctf_size_x(&rect);
+ h = BLI_rctf_size_y(&rect);
centerx = rect.xmin + w / 2;
centery = rect.ymin + h / 2;
diam = (w < h) ? w : h;
@@ -1146,8 +1145,9 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
glBegin(GL_QUAD_STRIP);
glColor4fv(&cbd->r);
- glVertex2fv(v1); glVertex2fv(v2);
-
+ glVertex2fv(v1);
+ glVertex2fv(v2);
+
for (a = 1; a <= sizex; a++) {
pos = ((float)a) / (sizex - 1);
do_colorband(coba, pos, colf);
@@ -1157,7 +1157,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
v1[0] = v2[0] = x1 + a;
glColor4fv(colf);
- glVertex2fv(v1); glVertex2fv(v2);
+ glVertex2fv(v1);
+ glVertex2fv(v2);
}
glEnd();
@@ -1244,7 +1245,8 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
/* sphere color */
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn);
- glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
/* disable blender light */
for (a = 0; a < 8; a++) {
@@ -1267,12 +1269,12 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
/* transform to button */
glPushMatrix();
- glTranslatef(rect->xmin + 0.5f * BLI_RCT_SIZE_X(rect), rect->ymin + 0.5f * BLI_RCT_SIZE_Y(rect), 0.0f);
+ glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f);
- if (BLI_RCT_SIZE_X(rect) < BLI_RCT_SIZE_Y(rect))
- size = BLI_RCT_SIZE_X(rect) / 200.f;
+ if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect))
+ size = BLI_rcti_size_x(rect) / 200.f;
else
- size = BLI_RCT_SIZE_Y(rect) / 200.f;
+ size = BLI_rcti_size_y(rect) / 200.f;
glScalef(size, size, size);
@@ -1378,12 +1380,12 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect
BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
glScissor(scissor_new.xmin,
scissor_new.ymin,
- BLI_RCT_SIZE_X(&scissor_new),
- BLI_RCT_SIZE_Y(&scissor_new));
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
/* calculate offset and zoom */
- zoomx = (BLI_RCT_SIZE_X(rect) - 2.0f * but->aspect) / BLI_RCT_SIZE_X(&cumap->curr);
- zoomy = (BLI_RCT_SIZE_Y(rect) - 2.0f * but->aspect) / BLI_RCT_SIZE_Y(&cumap->curr);
+ zoomx = (BLI_rcti_size_x(rect) - 2.0f * but->aspect) / BLI_rctf_size_x(&cumap->curr);
+ zoomy = (BLI_rcti_size_y(rect) - 2.0f * but->aspect) / BLI_rctf_size_y(&cumap->curr);
offsx = cumap->curr.xmin - but->aspect / zoomx;
offsy = cumap->curr.ymin - but->aspect / zoomy;
@@ -1561,8 +1563,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2;
rect.ymax = (float)recti->ymax - 1;
- width = BLI_RCT_SIZE_X(&rect) + 1;
- height = BLI_RCT_SIZE_Y(&rect);
+ width = BLI_rctf_size_x(&rect) + 1;
+ height = BLI_rctf_size_y(&rect);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1637,8 +1639,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
glTranslatef(rect.xmin + track_pos[0], rect.ymin + track_pos[1], 0.f);
glScissor(ar->winrct.xmin + rect.xmin,
ar->winrct.ymin + rect.ymin,
- BLI_RCT_SIZE_X(&rect),
- BLI_RCT_SIZE_Y(&rect));
+ BLI_rctf_size_x(&rect),
+ BLI_rctf_size_y(&rect));
for (a = 0; a < 2; a++) {
if (a == 1) {
@@ -1729,7 +1731,7 @@ void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, fl
}
-void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
+void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
{
int i;
float rad;
@@ -1738,8 +1740,8 @@ void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int UNUSE
glEnable(GL_BLEND);
- if (radius > (BLI_RCT_SIZE_Y(rct) - 10.0f) / 2.0f)
- rad = (BLI_RCT_SIZE_Y(rct) - 10.0f) / 2.0f;
+ if (radius > (BLI_rctf_size_y(rct) - 10.0f) / 2.0f)
+ rad = (BLI_rctf_size_y(rct) - 10.0f) / 2.0f;
else
rad = radius;
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index f7b22098835..593744f01e0 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -78,6 +78,9 @@
#include "WM_api.h"
#include "WM_types.h"
+/* place the mouse at the scaled down location when un-grabbing */
+#define USE_CONT_MOUSE_CORRECT
+
/* proto */
static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to);
static void ui_add_link(bContext *C, uiBut *from, uiBut *to);
@@ -152,6 +155,12 @@ typedef struct uiHandleButtonData {
float dragf, dragfstart;
CBData *dragcbd;
+#ifdef USE_CONT_MOUSE_CORRECT
+ /* when ungrabbing buttons which are #ui_is_a_warp_but(), we may want to position them
+ * FLT_MAX signifies do-nothing, use #ui_block_to_window_fl() to get this into a usable space */
+ float ungrab_mval[2];
+#endif
+
/* menu open (watch uiFreeActiveButtons) */
uiPopupBlockHandle *menu;
int menuretval;
@@ -697,10 +706,10 @@ static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, wmEvent *event)
if (but->imb) ; /* use button size itself */
else if (but->flag & UI_ICON_LEFT) {
- rect.xmax = rect.xmin + (BLI_RCT_SIZE_Y(&rect));
+ rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect));
}
else {
- int delta = BLI_RCT_SIZE_X(&rect) - BLI_RCT_SIZE_Y(&rect);
+ int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect);
rect.xmin += delta / 2;
rect.xmax -= delta / 2;
}
@@ -721,7 +730,7 @@ static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
if (but->imb)
- WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_RCT_SIZE_X(&but->rect), BLI_RCT_SIZE_Y(&but->rect));
+ WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
return 1;
}
@@ -808,6 +817,8 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
uiLink *link = from->link;
+ PointerRNA props_ptr, object_ptr;
+
if (link->ppoin)
sens_from_links = (bController ***)(link->ppoin);
else return;
@@ -836,9 +847,15 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
/* only works if the sensor and the actuator are from the same object */
if (!act_iter) return;
+
+ /* in case the linked controller is not the active one */
+ RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
+
+ WM_operator_properties_create(&props_ptr, "LOGIC_OT_controller_add");
+ RNA_string_set(&props_ptr, "object", ob->id.name+2);
/* (3) add a new controller */
- if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, NULL) & OPERATOR_FINISHED) {
+ if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, &props_ptr) & OPERATOR_FINISHED) {
cont = (bController *)ob->controllers.last;
cont->type = CONT_LOGIC_AND; /* Quick fix to make sure we always have an AND controller. It might be nicer to make sure the operator gives us the right one though... */
@@ -858,6 +875,7 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
MEM_freeN(tmp_but->link);
MEM_freeN(tmp_but);
}
+ WM_operator_properties_free(&props_ptr);
}
static void ui_add_link(bContext *C, uiBut *from, uiBut *to)
@@ -1309,7 +1327,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
/* XXX solve generic */
if (but->type == NUM || but->type == NUMSLI)
- startx += (int)(0.5f * (BLI_RCT_SIZE_Y(&but->rect)));
+ startx += (int)(0.5f * (BLI_rctf_size_y(&but->rect)));
else if (ELEM(but->type, TEX, SEARCH_MENU)) {
startx += 5;
if (but->flag & UI_HAS_ICON)
@@ -1386,13 +1404,13 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, short x)
{
- if (x > data->selstartx) data->selextend = EXTEND_RIGHT;
+ if (x > data->selstartx) data->selextend = EXTEND_RIGHT;
else if (x < data->selstartx) data->selextend = EXTEND_LEFT;
ui_textedit_set_cursor_pos(but, data, x);
- if (data->selextend == EXTEND_RIGHT) but->selend = but->pos;
- if (data->selextend == EXTEND_LEFT) but->selsta = but->pos;
+ if (data->selextend == EXTEND_RIGHT) but->selend = but->pos;
+ else if (data->selextend == EXTEND_LEFT) but->selsta = but->pos;
ui_check_but(but);
}
@@ -1596,6 +1614,7 @@ static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste
/* paste */
if (paste) {
+ /* TODO, ensure UTF8 ui_is_but_utf8() - campbell */
/* extract the first line from the clipboard */
p = pbuf = WM_clipboard_text_get(0);
@@ -1955,8 +1974,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
if (changed) {
/* only update when typing for TAB key */
- if (update && data->interactive) ui_apply_button(C, block, but, data, 1);
- else ui_check_but(but);
+ if (update && data->interactive) {
+ ui_apply_button(C, block, but, data, 1);
+ }
+ else {
+ ui_check_but(but);
+ }
but->changed = TRUE;
if (data->searchbox)
@@ -2047,8 +2070,12 @@ static void ui_numedit_end(uiBut *but, uiHandleButtonData *data)
static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
{
- if (data->interactive) ui_apply_button(C, block, but, data, 1);
- else ui_check_but(but);
+ if (data->interactive) {
+ ui_apply_button(C, block, but, data, 1);
+ }
+ else {
+ ui_check_but(but);
+ }
ED_region_tag_redraw(data->region);
}
@@ -2373,14 +2400,14 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa
}
if (snap == 1) {
- if (softrange < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
+ if (softrange < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
else if (softrange < 21.0f) tempf = floorf(tempf);
- else tempf = 10.0f * floorf(tempf / 10.0f);
+ else tempf = 10.0f * floorf(tempf / 10.0f);
}
else if (snap == 2) {
- if (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf);
- else if (softrange < 21.0f) tempf = 0.1f * floorf(10.0f * tempf);
- else tempf = floor(tempf);
+ if (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf);
+ else if (softrange < 21.0f) tempf = 0.1f * floorf(10.0f * tempf);
+ else tempf = floor(tempf);
}
if (fac != 1.0f)
@@ -2459,9 +2486,9 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
}
}
else {
- if (softrange > 256) fac = 1.0; /* 1px == 1 */
- else if (softrange > 32) fac = 1.0 / 2.0; /* 2px == 1 */
- else fac = 1.0 / 16.0; /* 16px == 1? */
+ if (softrange > 256) fac = 1.0; /* 1px == 1 */
+ else if (softrange > 32) fac = 1.0 / 2.0; /* 2px == 1 */
+ else fac = 1.0 / 16.0; /* 16px == 1? */
temp = data->startvalue + (((double)mx - data->dragstartx) * (double)fac);
temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
@@ -2493,10 +2520,9 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
deler = 500;
if (!ui_is_but_float(but)) {
/* prevent large ranges from getting too out of control */
- if (softrange > 600) deler = powf(softrange, 0.75);
-
- if (softrange < 100) deler = 200.0;
- if (softrange < 25) deler = 50.0;
+ if (softrange > 600) deler = powf(softrange, 0.75);
+ else if (softrange < 100) deler = 200.0;
+ else if (softrange < 25) deler = 50.0;
}
deler /= fac;
@@ -2582,8 +2608,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
- else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS)
+ else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
click = 1;
+ }
else if (event->type == MINUSKEY && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
data->value = -data->value;
@@ -2611,7 +2638,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
fac = 1.0f;
if (event->shift) fac /= 10.0f;
- if (event->alt) fac /= 20.0f;
+ if (event->alt) fac /= 20.0f;
snap = (event->ctrl) ? (event->shift) ? 2 : 1 : 0;
@@ -2639,7 +2666,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
softmax = but->softmax;
if (!ui_is_but_float(but)) {
- if (mx < (but->rect.xmin + BLI_RCT_SIZE_X(&but->rect) / 3 - 3)) {
+ if (mx < (but->rect.xmin + BLI_rctf_size_x(&but->rect) / 3 - 3)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
temp = (int)data->value - 1;
@@ -2650,7 +2677,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- else if (mx > (but->rect.xmin + (2 * BLI_RCT_SIZE_X(&but->rect) / 3) + 3)) {
+ else if (mx > (but->rect.xmin + (2 * BLI_rctf_size_x(&but->rect) / 3) + 3)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
temp = (int)data->value + 1;
@@ -2661,11 +2688,12 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- else
+ else {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
}
else {
- if (mx < (but->rect.xmin + BLI_RCT_SIZE_X(&but->rect) / 3 - 3)) {
+ if (mx < (but->rect.xmin + BLI_rctf_size_x(&but->rect) / 3 - 3)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
tempf = (float)data->value - 0.01f * but->a1;
@@ -2674,7 +2702,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- else if (mx > but->rect.xmin + (2 * (BLI_RCT_SIZE_X(&but->rect) / 3) + 3)) {
+ else if (mx > but->rect.xmin + (2 * (BLI_rctf_size_x(&but->rect) / 3) + 3)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
tempf = (float)data->value + 0.01f * but->a1;
@@ -2683,8 +2711,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- else
+ else {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
}
retval = WM_UI_HANDLER_BREAK;
@@ -2702,14 +2731,20 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, const short
softmax = but->softmax;
softrange = softmax - softmin;
- if (but->type == NUMSLI) deler = (BLI_RCT_SIZE_X(&but->rect) - 5.0f * but->aspect);
- else if (but->type == HSVSLI) deler = (BLI_RCT_SIZE_X(&but->rect) / 2.0f - 5.0f * but->aspect);
+ if (but->type == NUMSLI) {
+ deler = (BLI_rctf_size_x(&but->rect) - 5.0f * but->aspect);
+ }
+ else if (but->type == HSVSLI) {
+ deler = (BLI_rctf_size_x(&but->rect) / 2.0f - 5.0f * but->aspect);
+ }
else if (but->type == SCROLL) {
- int horizontal = (BLI_RCT_SIZE_X(&but->rect) > BLI_RCT_SIZE_Y(&but->rect));
- float size = (horizontal) ? BLI_RCT_SIZE_X(&but->rect) : -BLI_RCT_SIZE_Y(&but->rect);
+ int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
+ float size = (horizontal) ? BLI_rctf_size_x(&but->rect) : -BLI_rctf_size_y(&but->rect);
deler = size * (but->softmax - but->softmin) / (but->softmax - but->softmin + but->a1);
}
- else deler = (BLI_RCT_SIZE_X(&but->rect) - 5.0f * but->aspect);
+ else {
+ deler = (BLI_rctf_size_x(&but->rect) - 5.0f * but->aspect);
+ }
f = (float)(mx - data->dragstartx) / deler + data->dragfstart;
@@ -2721,19 +2756,21 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, const short
temp = floorf(tempf + 0.5f);
if (ctrl) {
- if (tempf == softmin || tempf == softmax) ;
+ if (tempf == softmin || tempf == softmax) {
+ /* pass */
+ }
else if (ui_is_but_float(but)) {
if (shift) {
- if (tempf == softmin || tempf == softmax) ;
+ if (tempf == softmin || tempf == softmax) {}
else if (softmax - softmin < 2.10f) tempf = 0.01f * floorf(100.0f * tempf);
- else if (softmax - softmin < 21.0f) tempf = 0.1f * floorf(10.0f * tempf);
- else tempf = floorf(tempf);
+ else if (softmax - softmin < 21.0f) tempf = 0.1f * floorf(10.0f * tempf);
+ else tempf = floorf(tempf);
}
else {
- if (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
+ if (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
else if (softmax - softmin < 21.0f) tempf = floorf(tempf);
- else tempf = 10.0f * floorf(tempf / 10.0f);
+ else tempf = 10.0f * floorf(tempf / 10.0f);
}
}
else {
@@ -2792,7 +2829,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
/* alt-click on sides to get "arrows" like in NUM buttons, and match wheel usage above */
else if (event->type == LEFTMOUSE && event->alt) {
- int halfpos = BLI_RCT_CENTER_X(&but->rect);
+ int halfpos = BLI_rctf_cent_x(&but->rect);
click = 2;
if (mx < halfpos)
mx = but->rect.xmin;
@@ -2805,8 +2842,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
- else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS)
+ else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
click = 1;
+ }
else if (event->type == MINUSKEY && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
data->value = -data->value;
@@ -2859,12 +2897,12 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
#if 0
if (but->type == SLI) {
- f = (float)(mx - but->rect.xmin) / (BLI_RCT_SIZE_X(&but->rect)); /* same as below */
+ f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect)); /* same as below */
}
else
#endif
{
- f = (float)(mx - but->rect.xmin) / (BLI_RCT_SIZE_X(&but->rect));
+ f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect));
}
f = softmin + f * softrange;
@@ -2905,7 +2943,7 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
{
int mx, my /*, click= 0 */;
int retval = WM_UI_HANDLER_CONTINUE;
- int horizontal = (BLI_RCT_SIZE_X(&but->rect) > BLI_RCT_SIZE_Y(&but->rect));
+ int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
mx = event->x;
my = event->y;
@@ -3063,7 +3101,7 @@ static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, i
* else we'll get a harmless but annoying jump when first clicking */
fp = data->origvec;
- rad = BLI_RCT_SIZE_X(&but->rect);
+ rad = BLI_rctf_size_x(&but->rect);
radsq = rad * rad;
if (fp[2] > 0.0f) {
@@ -3076,7 +3114,9 @@ static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, i
mdx = 2.0f * mrad * fp[0] - (rad * fp[0]);
mdy = 2.0f * mrad * fp[1] - (rad * fp[1]);
}
- else mdx = mdy = 0;
+ else {
+ mdx = mdy = 0;
+ }
dx = (float)(mx + mdx - data->dragstartx);
dy = (float)(my + mdy - data->dragstarty);
@@ -3140,8 +3180,9 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS)
+ else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
return WM_UI_HANDLER_BREAK;
}
@@ -3160,6 +3201,15 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
+#ifdef USE_CONT_MOUSE_CORRECT
+ if (ui_is_a_warp_but(but)) {
+ /* OK but can go outside bounds */
+ data->ungrab_mval[0] = mx_fl;
+ data->ungrab_mval[1] = my_fl;
+ BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
+ }
+#endif
+
if (but->rnaprop) {
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
color_profile = FALSE;
@@ -3173,8 +3223,8 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
rgb_to_hsv_compat_v(rgb, hsv);
/* relative position within box */
- x = ((float)mx_fl - but->rect.xmin) / BLI_RCT_SIZE_X(&but->rect);
- y = ((float)my_fl - but->rect.ymin) / BLI_RCT_SIZE_Y(&but->rect);
+ x = ((float)mx_fl - but->rect.xmin) / BLI_rctf_size_x(&but->rect);
+ y = ((float)my_fl - but->rect.ymin) / BLI_rctf_size_y(&but->rect);
CLAMP(x, 0.0f, 1.0f);
CLAMP(y, 0.0f, 1.0f);
@@ -3364,8 +3414,9 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS)
+ else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
return WM_UI_HANDLER_BREAK;
}
@@ -3383,6 +3434,22 @@ static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, float
ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
+#ifdef USE_CONT_MOUSE_CORRECT
+ if (ui_is_a_warp_but(but)) {
+ /* OK but can go outside bounds */
+ data->ungrab_mval[0] = mx_fl;
+ data->ungrab_mval[1] = my_fl;
+ { /* clamp */
+ const float radius = minf(BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect)) / 2.0f;
+ const float cent[2] = {BLI_rctf_cent_x(&but->rect), BLI_rctf_cent_y(&but->rect)};
+ const float len = len_v2v2(cent, data->ungrab_mval);
+ if (len > radius) {
+ dist_ensure_v2_v2fl(data->ungrab_mval, cent, radius);
+ }
+ }
+ }
+#endif
+
BLI_rcti_rctf_copy(&rect, &but->rect);
ui_get_but_vectorf(but, rgb);
@@ -3575,7 +3642,7 @@ static int ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int mx
if (data->draglastx == mx)
return changed;
- dx = ((float)(mx - data->draglastx)) / BLI_RCT_SIZE_X(&but->rect);
+ dx = ((float)(mx - data->draglastx)) / BLI_rctf_size_x(&but->rect);
data->dragcbd->pos += dx;
CLAMP(data->dragcbd->pos, 0.0f, 1.0f);
@@ -3604,7 +3671,7 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
if (event->ctrl) {
/* insert new key on mouse location */
- float pos = ((float)(mx - but->rect.xmin)) / BLI_RCT_SIZE_X(&but->rect);
+ float pos = ((float)(mx - but->rect.xmin)) / BLI_rctf_size_x(&but->rect);
colorband_element_add(coba, pos);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -3616,7 +3683,7 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
/* activate new key when mouse is close */
for (a = 0, cbd = coba->data; a < coba->tot; a++, cbd++) {
- xco = but->rect.xmin + (cbd->pos * BLI_RCT_SIZE_X(&but->rect));
+ xco = but->rect.xmin + (cbd->pos * BLI_rctf_size_x(&but->rect));
xco = ABS(xco - mx);
if (a == coba->cur) xco += 5; // selected one disadvantage
if (xco < mindist) {
@@ -3639,8 +3706,9 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
ui_numedit_apply(C, block, but, data);
}
}
- else if (event->type == LEFTMOUSE && event->val != KM_PRESS)
+ else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
return WM_UI_HANDLER_BREAK;
}
@@ -3657,8 +3725,8 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
float fx, fy, zoomx, zoomy /*, offsx, offsy */ /* UNUSED */;
int a, changed = 0;
- zoomx = BLI_RCT_SIZE_X(&but->rect) / BLI_RCT_SIZE_X(&cumap->curr);
- zoomy = BLI_RCT_SIZE_Y(&but->rect) / BLI_RCT_SIZE_Y(&cumap->curr);
+ zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr);
+ zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr);
/* offsx= cumap->curr.xmin; */
/* offsy= cumap->curr.ymin; */
@@ -3673,9 +3741,10 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
}
if (data->dragsel != -1) {
+ CurveMapPoint *cmp_last = NULL;
const float mval_factor = ui_mouse_scale_warp_factor(shift);
int moved_point = 0; /* for ctrl grid, can't use orig coords because of sorting */
-
+
fx = (mx - data->draglastx) / zoomx;
fy = (my - data->draglasty) / zoomy;
@@ -3693,6 +3762,8 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
}
if (cmp[a].x != origx || cmp[a].y != origy)
moved_point = 1;
+
+ cmp_last = &cmp[a];
}
}
@@ -3702,6 +3773,18 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
data->draglastx = mx;
data->draglasty = my;
changed = 1;
+
+#ifdef USE_CONT_MOUSE_CORRECT
+ /* note: using 'cmp_last' is weak since there may be multiple points selected,
+ * but in practice this isnt really an issue */
+ if (ui_is_a_warp_but(but)) {
+ /* OK but can go outside bounds */
+ data->ungrab_mval[0] = but->rect.xmin + ((cmp_last->x - cumap->curr.xmin) * zoomx);
+ data->ungrab_mval[1] = but->rect.ymin + ((cmp_last->y - cumap->curr.ymin) * zoomy);
+ BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
+ }
+#endif
+
}
data->dragchange = 1; /* mark for selection */
@@ -3753,8 +3836,8 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
float dist, mindist = 200.0f; // 14 pixels radius
int sel = -1;
- zoomx = BLI_RCT_SIZE_X(&but->rect) / BLI_RCT_SIZE_X(&cumap->curr);
- zoomy = BLI_RCT_SIZE_Y(&but->rect) / BLI_RCT_SIZE_Y(&cumap->curr);
+ zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr);
+ zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr);
offsx = cumap->curr.xmin;
offsy = cumap->curr.ymin;
@@ -3818,12 +3901,14 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
/* ok, we move a point */
/* deselect all if this one is deselect. except if we hold shift */
if (event->shift == FALSE) {
- for (a = 0; a < cuma->totpoint; a++)
+ for (a = 0; a < cuma->totpoint; a++) {
cmp[a].flag &= ~CUMA_SELECT;
+ }
cmp[sel].flag |= CUMA_SELECT;
}
- else
+ else {
cmp[sel].flag ^= CUMA_SELECT;
+ }
}
else {
/* move the view */
@@ -3899,7 +3984,7 @@ static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx
if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
/* resize histogram widget itself */
- hist->height = BLI_RCT_SIZE_Y(&but->rect) + (data->dragstarty - my);
+ hist->height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
}
else {
/* scale histogram values (dy / 10 for better control) */
@@ -3983,7 +4068,7 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx,
if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
/* resize waveform widget itself */
- scopes->wavefrm_height = BLI_RCT_SIZE_Y(&but->rect) + (data->dragstarty - my);
+ scopes->wavefrm_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
}
else {
/* scale waveform values */
@@ -4065,7 +4150,7 @@ static int ui_numedit_but_VECTORSCOPE(uiBut *but, uiHandleButtonData *data, int
if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
/* resize vectorscope widget itself */
- scopes->vecscope_height = BLI_RCT_SIZE_Y(&but->rect) + (data->dragstarty - my);
+ scopes->vecscope_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
}
data->draglastx = mx;
@@ -4135,8 +4220,8 @@ static int ui_do_but_CHARTAB(bContext *UNUSED(C), uiBlock *UNUSED(block), uiBut
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
/* Calculate the size of the button */
- width = abs(BLI_RCT_SIZE_X(&but->rect));
- height = abs(BLI_RCT_SIZE_Y(&but->rect));
+ width = abs(BLI_rctf_size_x(&but->rect));
+ height = abs(BLI_rctf_size_y(&but->rect));
butw = floor(width / 12);
buth = floor(height / 6);
@@ -4268,7 +4353,7 @@ static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonDa
if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
/* resize preview widget itself */
- scopes->track_preview_height = BLI_RCT_SIZE_Y(&but->rect) + (data->dragstarty - my);
+ scopes->track_preview_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
}
else {
if (!scopes->track_locked) {
@@ -4276,8 +4361,8 @@ static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonDa
scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr);
scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
- scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_RCT_SIZE_X(&but->block->rect);
- scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_RCT_SIZE_Y(&but->block->rect);
+ scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_rctf_size_x(&but->block->rect);
+ scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_rctf_size_y(&but->block->rect);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
}
@@ -4466,6 +4551,7 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
static int ui_but_menu(bContext *C, uiBut *but)
{
+ ARegion *ar = CTX_wm_region(C);
uiPopupMenu *pup;
uiLayout *layout;
int length;
@@ -4477,17 +4563,8 @@ static int ui_but_menu(bContext *C, uiBut *but)
button_timers_tooltip_remove(C, but);
-#if 0
- if (but->rnaprop)
- name = RNA_property_ui_name(but->rnaprop);
- else if (but->optype && but->optype->srna)
- name = RNA_struct_ui_name(but->optype->srna);
- else
- name = IFACE_("<needs_name>"); // XXX - should never happen.
-#else
uiButGetStrInfo(C, but, 1, &label);
name = label.strinfo;
-#endif
pup = uiPupMenuBegin(C, name, ICON_NONE);
layout = uiPupMenuLayout(pup);
@@ -4531,7 +4608,9 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
- else if (but->flag & UI_BUT_DRIVEN) ;
+ else if (but->flag & UI_BUT_DRIVEN) {
+ /* pass */
+ }
else if (is_anim) {
if (length) {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"),
@@ -4539,9 +4618,10 @@ static int ui_but_menu(bContext *C, uiBut *but)
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
}
- else
+ else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"),
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
+ }
}
if (but->flag & UI_BUT_ANIMATED) {
@@ -4567,17 +4647,21 @@ static int ui_but_menu(bContext *C, uiBut *but)
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"),
ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0);
}
- else
+ else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"),
ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0);
+ }
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"),
ICON_NONE, "ANIM_OT_copy_driver_button");
- if (ANIM_driver_can_paste())
+ if (ANIM_driver_can_paste()) {
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
ICON_NONE, "ANIM_OT_paste_driver_button");
+ }
+ }
+ else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) {
+ /* pass */
}
- else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) ;
else if (is_anim) {
uiItemS(layout);
@@ -4587,13 +4671,15 @@ static int ui_but_menu(bContext *C, uiBut *but)
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single Driver"),
ICON_NONE, "ANIM_OT_driver_button_add", "all", 0);
}
- else
+ else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
ICON_NONE, "ANIM_OT_driver_button_add", "all", 0);
+ }
- if (ANIM_driver_can_paste())
+ if (ANIM_driver_can_paste()) {
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
ICON_NONE, "ANIM_OT_paste_driver_button");
+ }
}
/* Keying Sets */
@@ -4630,9 +4716,10 @@ static int ui_but_menu(bContext *C, uiBut *but)
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"),
ICON_NONE, "UI_OT_reset_default_button", "all", 0);
}
- else
+ else {
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
ICON_NONE, "UI_OT_reset_default_button");
+ }
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
ICON_NONE, "UI_OT_copy_data_path_button");
@@ -4679,7 +4766,12 @@ static int ui_but_menu(bContext *C, uiBut *but)
uiItemS(layout);
}
-
+ /* Show header tools for header buttons. */
+ if (ar->regiontype == RGN_TYPE_HEADER) {
+ uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
+ uiItemS(layout);
+ }
+
{ /* Docs */
char buf[512];
PointerRNA ptr_props;
@@ -5237,12 +5329,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
/* automatic open pulldown block timer */
if (ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) {
- if ((data->used_mouse == TRUE) &&
- (data->autoopentimer == FALSE) &&
- /* don't popup the first time,
- * see description on this member for info */
- (but->block->auto_is_first_event == FALSE))
- {
+ if (data->used_mouse && !data->autoopentimer) {
int time;
if (but->block->auto_open == TRUE) { /* test for toolbox */
@@ -5262,8 +5349,6 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
data->autoopentimer = WM_event_add_timer(data->wm, data->window, TIMER, 0.02 * (double)time);
}
}
-
- but->block->auto_is_first_event = FALSE;
}
}
else {
@@ -5287,8 +5372,24 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
ui_numedit_end(but, data);
- if (ui_is_a_warp_but(but))
- WM_cursor_grab_disable(CTX_wm_window(C));
+ if (ui_is_a_warp_but(but)) {
+
+#ifdef USE_CONT_MOUSE_CORRECT
+ if (data->ungrab_mval[0] != FLT_MAX) {
+ int mouse_ungrab_xy[2];
+ ui_block_to_window_fl(data->region, but->block, &data->ungrab_mval[0], &data->ungrab_mval[1]);
+ mouse_ungrab_xy[0] = data->ungrab_mval[0];
+ mouse_ungrab_xy[1] = data->ungrab_mval[1];
+
+ WM_cursor_grab_disable(data->window, mouse_ungrab_xy);
+ }
+ else {
+ WM_cursor_grab_disable(data->window, NULL);
+ }
+#else
+ WM_cursor_grab_disable(data->window, );
+#endif
+ }
}
/* menu open */
if (state == BUTTON_STATE_MENU_OPEN)
@@ -5351,6 +5452,10 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
data->window = CTX_wm_window(C);
data->region = ar;
+#ifdef USE_CONT_MOUSE_CORRECT
+ copy_v2_fl(data->ungrab_mval, FLT_MAX);
+#endif
+
if (ELEM(but->type, BUT_CURVE, SEARCH_MENU)) {
/* XXX curve is temp */
}
@@ -5632,20 +5737,24 @@ void uiContextAnimUpdate(const bContext *C)
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
ED_region_tag_redraw(ar);
- if (but->active)
+ if (but->active) {
activebut = but;
- else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE))
+ }
+ else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) {
activebut = but;
+ }
}
}
if (activebut) {
/* always recurse into opened menu, so all buttons update (like colorpicker) */
uiHandleButtonData *data = activebut->active;
- if (data && data->menu)
+ if (data && data->menu) {
ar = data->menu->region;
- else
+ }
+ else {
return;
+ }
}
else {
/* no active button */
@@ -5675,8 +5784,9 @@ static int ui_handle_button_over(bContext *C, wmEvent *event, ARegion *ar)
if (event->type == MOUSEMOVE) {
but = ui_but_find_mouse_over(ar, event->x, event->y);
- if (but)
+ if (but) {
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ }
}
else if (event->type == EVT_BUT_OPEN) {
but = uit_but_find_open_event(ar, event);
@@ -6179,7 +6289,7 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my)
return 0;
}
-static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int UNUSED(topmenu))
+static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int level)
{
ARegion *ar;
uiBlock *block;
@@ -6224,10 +6334,22 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
}
/* first block own event func */
- if (block->block_event_func && block->block_event_func(C, block, event)) ;
- /* events not for active search menu button */
+ if (block->block_event_func && block->block_event_func(C, block, event)) {
+ /* pass */
+ } /* events not for active search menu button */
else if (but == NULL || but->type != SEARCH_MENU) {
switch (event->type) {
+
+
+ /* let the parent menu get the event */
+#define PASS_EVENT_TO_PARENT_IF_NONACTIVE \
+ if ((level != 0) && (but == NULL)) { \
+ menu->menuretval = UI_RETURN_OUT | UI_RETURN_OUT_PARENT; \
+ BLI_assert(retval == WM_UI_HANDLER_CONTINUE); \
+ break; \
+ } (void)0
+
+
/* closing sublevels of pulldowns */
case LEFTARROWKEY:
if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP))
@@ -6240,6 +6362,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
/* opening sublevels of pulldowns */
case RIGHTARROWKEY:
if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
+
+ PASS_EVENT_TO_PARENT_IF_NONACTIVE;
+
but = ui_but_find_activated(ar);
if (!but) {
@@ -6265,6 +6390,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
}
else if (inside || (block->flag & UI_BLOCK_LOOP)) {
if (event->val == KM_PRESS) {
+
+ PASS_EVENT_TO_PARENT_IF_NONACTIVE;
+
but = ui_but_find_activated(ar);
if (but) {
/* is there a situation where UI_LEFT or UI_RIGHT would also change navigation direction? */
@@ -6344,6 +6472,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
if (act == 0) act = 10;
if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
+
+ PASS_EVENT_TO_PARENT_IF_NONACTIVE;
+
if (event->alt) act += 10;
count = 0;
@@ -6421,6 +6552,8 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
(event->ctrl == FALSE) &&
(event->oskey == FALSE))
{
+ PASS_EVENT_TO_PARENT_IF_NONACTIVE;
+
for (but = block->buttons.first; but; but = but->next) {
if (but->menu_key == event->type) {
@@ -6510,6 +6643,10 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
retval = WM_UI_HANDLER_BREAK;
}
}
+
+ /* end switch */
+#undef PASS_EVENT_TO_PARENT_IF_NONACTIVE
+
}
}
@@ -6598,7 +6735,7 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo
return WM_UI_HANDLER_BREAK;
}
-static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu)
+static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int level)
{
uiBut *but;
uiHandleButtonData *data;
@@ -6611,14 +6748,20 @@ static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHa
submenu = (data) ? data->menu : NULL;
if (submenu)
- retval = ui_handle_menus_recursive(C, event, submenu);
+ retval = ui_handle_menus_recursive(C, event, submenu, level + 1);
/* now handle events for our own menu */
if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
- if (submenu && submenu->menuretval)
+ if (submenu && submenu->menuretval) {
retval = ui_handle_menu_return_submenu(C, event, menu);
- else
- retval = ui_handle_menu_event(C, event, menu, (submenu == NULL));
+ /* we may wan't to quit the submenu and handle the even in this menu */
+ if ((retval == WM_UI_HANDLER_BREAK) && (submenu->menuretval & UI_RETURN_OUT_PARENT)) {
+ retval = ui_handle_menu_event(C, event, menu, level);
+ }
+ }
+ else {
+ retval = ui_handle_menu_event(C, event, menu, level); /* same as above */
+ }
}
return retval;
@@ -6706,7 +6849,7 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user
if (data->state == BUTTON_STATE_MENU_OPEN) {
/* handle events for menus and their buttons recursively,
* this will handle events from the top to the bottom menu */
- retval = ui_handle_menus_recursive(C, event, data->menu);
+ retval = ui_handle_menus_recursive(C, event, data->menu, 0);
/* handle events for the activated button */
if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
@@ -6750,7 +6893,7 @@ static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
retval = WM_UI_HANDLER_CONTINUE;
}
- ui_handle_menus_recursive(C, event, menu);
+ ui_handle_menus_recursive(C, event, menu, 0);
/* free if done, does not free handle itself */
if (menu->menuretval) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 928e1671cee..b48c9bcab7e 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -305,17 +305,7 @@ struct uiBlock {
char direction;
char dt; /* drawtype: UI_EMBOSS, UI_EMBOSSN ... etc, copied to buttons */
char auto_open;
-
- /* this setting is used so newly opened menu's dont popout the first item under the mouse,
- * the reasoning behind this is because of muscle memory for opening menus.
- *
- * Without this, the first time opening a Submenu and activating an item in it will be 2 steps,
- * but the second time the same item is accessed the menu memory would auto activate the
- * last used menu and the key intended to select that submenu ends up being passed into the submenu.
- * - Campbell
- */
- char auto_is_first_event;
- char _pad[6];
+ char _pad[7];
double auto_open_last;
const char *lockstr;
@@ -473,7 +463,7 @@ extern int ui_handler_panel_region(struct bContext *C, struct wmEvent *event);
extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, rcti *rect);
/* interface_draw.c */
-extern void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int select);
+extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const float alpha);
@@ -509,7 +499,7 @@ void ui_widget_color_init(struct ThemeUI *tui);
void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
-extern unsigned char checker_stipple_sml[];
+extern unsigned char checker_stipple_sml[32 * 32 / 8];
/* used for transp checkers */
#define UI_TRANSP_DARK 100
#define UI_TRANSP_LIGHT 160
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 803fd928085..8ffbcd6d399 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -239,10 +239,8 @@ static void ui_item_size(uiItem *item, int *r_w, int *r_h)
if (item->type == ITEM_BUTTON) {
uiButtonItem *bitem = (uiButtonItem *)item;
-
-
- if (r_w) *r_w = BLI_RCT_SIZE_X(&bitem->but->rect);
- if (r_h) *r_h = BLI_RCT_SIZE_Y(&bitem->but->rect);
+ if (r_w) *r_w = BLI_rctf_size_x(&bitem->but->rect);
+ if (r_h) *r_h = BLI_rctf_size_y(&bitem->but->rect);
}
else {
uiLayout *litem = (uiLayout *)item;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index fa3e04d1351..49e96bea6c6 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -357,14 +357,14 @@ void UI_DrawTriIcon(float x, float y, char dir)
}
/* triangle 'icon' inside rect */
-static void ui_draw_tria_rect(rctf *rect, char dir)
+static void ui_draw_tria_rect(const rctf *rect, char dir)
{
if (dir == 'h') {
- float half = 0.5f * BLI_RCT_SIZE_Y(rect);
+ float half = 0.5f * BLI_rctf_size_y(rect);
ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half);
}
else {
- float half = 0.5f * BLI_RCT_SIZE_X(rect);
+ float half = 0.5f * BLI_rctf_size_x(rect);
ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin);
}
}
@@ -479,12 +479,12 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, rcti *r
}
}
-static void rectf_scale(rctf *rect, float scale)
+static void rectf_scale(rctf *rect, const float scale)
{
- float centx = 0.5f * (rect->xmin + rect->xmax);
- float centy = 0.5f * (rect->ymin + rect->ymax);
- float sizex = 0.5f * scale * BLI_RCT_SIZE_X(rect);
- float sizey = 0.5f * scale * BLI_RCT_SIZE_Y(rect);
+ float centx = BLI_rctf_cent_x(rect);
+ float centy = BLI_rctf_cent_y(rect);
+ float sizex = BLI_rctf_size_x(rect) * 0.5f * scale;
+ float sizey = BLI_rctf_size_y(rect) * 0.5f * scale;
rect->xmin = centx - sizex;
rect->xmax = centx + sizex;
@@ -547,7 +547,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
/* itemrect smaller */
itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
- itemrect.xmin = itemrect.xmax - BLI_RCT_SIZE_Y(&headrect);
+ itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect);
itemrect.ymin = headrect.ymin;
itemrect.ymax = headrect.ymax;
@@ -596,7 +596,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
/* itemrect smaller */
itemrect.xmin = headrect.xmin + 5.0f / block->aspect;
- itemrect.xmax = itemrect.xmin + BLI_RCT_SIZE_Y(&headrect);
+ itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&headrect);
itemrect.ymin = headrect.ymin;
itemrect.ymax = headrect.ymax;
@@ -985,8 +985,8 @@ static void ui_do_drag(const bContext *C, wmEvent *event, Panel *panel)
dx = (event->x - data->startx) & ~(PNL_GRID - 1);
dy = (event->y - data->starty) & ~(PNL_GRID - 1);
- dx *= (float)BLI_RCT_SIZE_X(&ar->v2d.cur) / (float)BLI_RCT_SIZE_X(&ar->winrct);
- dy *= (float)BLI_RCT_SIZE_Y(&ar->v2d.cur) / (float)BLI_RCT_SIZE_Y(&ar->winrct);
+ dx *= (float)BLI_rctf_size_x(&ar->v2d.cur) / (float)BLI_rcti_size_x(&ar->winrct);
+ dy *= (float)BLI_rctf_size_y(&ar->v2d.cur) / (float)BLI_rcti_size_y(&ar->winrct);
if (data->state == PANEL_STATE_DRAG_SCALE) {
panel->sizex = MAX2(data->startsizex + dx, UI_PANEL_MINX);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index dc9347b3852..adf839d433b 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -70,7 +70,6 @@
#include "interface_intern.h"
-#define MENU_SEPR_HEIGHT 6
#define B_NOP -1
#define MENU_SHADOW_SIDE 8
#define MENU_SHADOW_BOTTOM 10
@@ -393,7 +392,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
/* draw text */
uiStyleFontSet(&data->fstyle);
- bbox.ymax = bbox.ymax - 0.5f * (BLI_RCT_SIZE_Y(&bbox) - data->toth);
+ bbox.ymax = bbox.ymax - 0.5f * (BLI_rcti_size_y(&bbox) - data->toth);
bbox.ymin = bbox.ymax - data->lineh;
for (i = 0; i < data->totline; i++) {
@@ -732,9 +731,9 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
/* widget rect, in region coords */
data->bbox.xmin = MENU_SHADOW_SIDE;
- data->bbox.xmax = BLI_RCT_SIZE_X(&rect_i) + MENU_SHADOW_SIDE;
+ data->bbox.xmax = BLI_rcti_size_x(&rect_i) + MENU_SHADOW_SIDE;
data->bbox.ymin = MENU_SHADOW_BOTTOM;
- data->bbox.ymax = BLI_RCT_SIZE_Y(&rect_i) + MENU_SHADOW_BOTTOM;
+ data->bbox.ymax = BLI_rcti_size_y(&rect_i) + MENU_SHADOW_BOTTOM;
/* region bigger for shadow */
ar->winrct.xmin = rect_i.xmin - MENU_SHADOW_SIDE;
@@ -867,8 +866,8 @@ static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr)
{
/* thumbnail preview */
if (data->preview) {
- int butw = BLI_RCT_SIZE_X(&data->bbox) / data->prv_cols;
- int buth = (BLI_RCT_SIZE_Y(&data->bbox) - 2 * MENU_TOP) / data->prv_rows;
+ int butw = BLI_rcti_size_x(&data->bbox) / data->prv_cols;
+ int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / data->prv_rows;
int row, col;
*rect = data->bbox;
@@ -884,7 +883,7 @@ static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr)
}
/* list view */
else {
- int buth = (BLI_RCT_SIZE_Y(&data->bbox) - 2 * MENU_TOP) / SEARCH_ITEMS;
+ int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / SEARCH_ITEMS;
*rect = data->bbox;
rect->xmin = data->bbox.xmin + 3.0f;
@@ -1097,13 +1096,13 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
glEnable(GL_BLEND);
- UI_icon_draw((BLI_RCT_SIZE_X(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
+ UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
glDisable(GL_BLEND);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
glEnable(GL_BLEND);
- UI_icon_draw((BLI_RCT_SIZE_X(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
+ UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
glDisable(GL_BLEND);
}
}
@@ -1178,16 +1177,16 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
/* widget rect, in region coords */
data->bbox.xmin = MENU_SHADOW_SIDE;
- data->bbox.xmax = BLI_RCT_SIZE_X(&ar->winrct) - MENU_SHADOW_SIDE;
+ data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - MENU_SHADOW_SIDE;
data->bbox.ymin = MENU_SHADOW_BOTTOM;
- data->bbox.ymax = BLI_RCT_SIZE_Y(&ar->winrct) - MENU_SHADOW_BOTTOM;
+ data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - MENU_SHADOW_BOTTOM;
/* check if button is lower half */
- if (but->rect.ymax < BLI_RCT_CENTER_Y(&but->block->rect)) {
- data->bbox.ymin += BLI_RCT_SIZE_Y(&but->rect);
+ if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) {
+ data->bbox.ymin += BLI_rctf_size_y(&but->rect);
}
else {
- data->bbox.ymax -= BLI_RCT_SIZE_Y(&but->rect);
+ data->bbox.ymax -= BLI_rctf_size_y(&but->rect);
}
}
else {
@@ -1202,7 +1201,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
BLI_rctf_translate(&rect_fl, ofsx, ofsy);
/* minimal width */
- if (BLI_RCT_SIZE_X(&rect_fl) < 150) {
+ if (BLI_rctf_size_x(&rect_fl) < 150) {
rect_fl.xmax = rect_fl.xmin + 150; /* XXX arbitrary */
}
@@ -1235,15 +1234,15 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
UI_view2d_to_region_no_clip(&butregion->v2d, 0, but->rect.ymax + ofsy, NULL, &newy1);
newy1 += butregion->winrct.ymin;
- rect_i.ymax = BLI_RCT_SIZE_Y(&rect_i) + newy1;
+ rect_i.ymax = BLI_rcti_size_y(&rect_i) + newy1;
rect_i.ymin = newy1;
}
/* widget rect, in region coords */
data->bbox.xmin = MENU_SHADOW_SIDE;
- data->bbox.xmax = BLI_RCT_SIZE_X(&rect_i) + MENU_SHADOW_SIDE;
+ data->bbox.xmax = BLI_rcti_size_x(&rect_i) + MENU_SHADOW_SIDE;
data->bbox.ymin = MENU_SHADOW_BOTTOM;
- data->bbox.ymax = BLI_RCT_SIZE_Y(&rect_i) + MENU_SHADOW_BOTTOM;
+ data->bbox.ymax = BLI_rcti_size_y(&rect_i) + MENU_SHADOW_BOTTOM;
/* region bigger for shadow */
ar->winrct.xmin = rect_i.xmin - MENU_SHADOW_SIDE;
@@ -1358,15 +1357,15 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
}
}
- /* aspect = (float)(BLI_RCT_SIZE_X(&block->rect) + 4);*/ /*UNUSED*/
+ /* aspect = (float)(BLI_rcti_size_x(&block->rect) + 4);*/ /*UNUSED*/
ui_block_to_window_fl(butregion, but->block, &block->rect.xmin, &block->rect.ymin);
ui_block_to_window_fl(butregion, but->block, &block->rect.xmax, &block->rect.ymax);
//block->rect.xmin -= 2.0; block->rect.ymin -= 2.0;
//block->rect.xmax += 2.0; block->rect.ymax += 2.0;
- xsize = BLI_RCT_SIZE_X(&block->rect) + 4; /* 4 for shadow */
- ysize = BLI_RCT_SIZE_Y(&block->rect) + 4;
+ xsize = BLI_rctf_size_x(&block->rect) + 4; /* 4 for shadow */
+ ysize = BLI_rctf_size_y(&block->rect) + 4;
/* aspect /= (float)xsize;*/ /*UNUSED*/
{
@@ -1497,8 +1496,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
/* safety calculus */
{
- const float midx = BLI_RCT_CENTER_X(&butrct);
- const float midy = BLI_RCT_CENTER_Y(&butrct);
+ const float midx = BLI_rctf_cent_x(&butrct);
+ const float midy = BLI_rctf_cent_y(&butrct);
/* when you are outside parent button, safety there should be smaller */
@@ -1874,12 +1873,6 @@ static void ui_warp_pointer(int x, int y)
/********************* Color Button ****************/
-/* picker sizes S hsize, F full size, D spacer, B button/pallette height */
-#define SPICK 110.0
-#define FPICK 180.0
-#define DPICK 6.0
-#define BPICK 24.0
-
/* for picker, while editing hsv */
void ui_set_but_hsv(uiBut *but)
{
@@ -2053,10 +2046,6 @@ static void do_picker_new_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a
picker_new_hide_reveal(bt->block, colormode);
}
-/* picker sizes S hsize, F full size, D spacer, B button/pallette height */
-#define SPICK1 150.0
-#define DPICK1 6.0
-
#define PICKER_H 150
#define PICKER_W 150
#define PICKER_SPACE 6
@@ -2343,7 +2332,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
if (pup->but) {
/* minimum width to enforece */
- minwidth = BLI_RCT_SIZE_X(&pup->but->rect);
+ minwidth = BLI_rctf_size_x(&pup->but->rect);
if (pup->but->type == PULLDOWN || pup->but->menu_create_func) {
direction = UI_DOWN;
@@ -2385,7 +2374,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
* button, so it doesn't overlap the text too much, also note
* the offset is negative because we are inverse moving the
* block to be under the mouse */
- offset[0] = -(bt->rect.xmin + 0.8f * BLI_RCT_SIZE_X(&bt->rect));
+ offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
}
else {
@@ -2393,7 +2382,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
* on the first item */
offset[0] = 0;
for (bt = block->buttons.first; bt; bt = bt->next)
- offset[0] = mini(offset[0], -(bt->rect.xmin + 0.8f * BLI_RCT_SIZE_X(&bt->rect)));
+ offset[0] = mini(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)));
offset[1] = 1.5 * UI_UNIT_Y;
}
@@ -2502,7 +2491,6 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
pup->block = uiBeginBlock(C, NULL, __func__, UI_EMBOSSP);
pup->block->flag |= UI_BLOCK_POPUP_MEMORY;
pup->block->puphash = ui_popup_menu_hash(title);
- pup->block->auto_is_first_event = TRUE;
pup->layout = uiBlockLayout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, style);
uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
@@ -2576,6 +2564,11 @@ static void confirm_cancel_operator(void *opv)
}
static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap)
+#ifdef __GNUC__
+__attribute__ ((format(printf, 4, 0)))
+#endif
+;
+static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap)
{
uiPopupBlockHandle *handle;
char *s, buf[512];
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index b16250021d3..acf7712f97b 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -152,17 +152,17 @@ void uiStyleFontDrawExt(uiFontStyle *fs, rcti *rect, const char *str,
uiStyleFontSet(fs);
height = BLF_ascender(fs->uifont_id);
- yofs = ceil(0.5f * (BLI_RCT_SIZE_Y(rect) - height));
+ yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
if (fs->align == UI_STYLE_TEXT_CENTER) {
- xofs = floor(0.5f * (BLI_RCT_SIZE_X(rect) - BLF_width(fs->uifont_id, str)));
+ xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str)));
/* don't center text if it chops off the start of the text, 2 gives some margin */
if (xofs < 2) {
xofs = 2;
}
}
else if (fs->align == UI_STYLE_TEXT_RIGHT) {
- xofs = BLI_RCT_SIZE_X(rect) - BLF_width(fs->uifont_id, str) - 1;
+ xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str) - 1;
}
/* clip is very strict, so we give it some space */
@@ -209,7 +209,7 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str)
height = BLF_ascender(fs->uifont_id);
/* becomes x-offset when rotated */
- xofs = ceil(0.5f * (BLI_RCT_SIZE_Y(rect) - height));
+ xofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
/* ignore UI_STYLE, always aligned to top */
@@ -219,8 +219,8 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str)
angle = 90.0f;
/* translate rect to vertical */
- txtrect.xmin = rect->xmin - BLI_RCT_SIZE_Y(rect);
- txtrect.ymin = rect->ymin - BLI_RCT_SIZE_X(rect);
+ txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect);
+ txtrect.ymin = rect->ymin - BLI_rcti_size_x(rect);
txtrect.xmax = rect->xmin;
txtrect.ymax = rect->ymin;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 79b9d313775..37503acfeb0 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -35,6 +35,7 @@
#include "DNA_dynamicpaint_types.h"
#include "DNA_key_types.h"
#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
#include "DNA_userdef_types.h"
#include "BLI_utildefines.h"
@@ -56,6 +57,7 @@
#include "BKE_texture.h"
#include "BKE_report.h"
#include "BKE_displist.h"
+#include "BKE_sca.h"
#include "BKE_scene.h"
#include "ED_screen.h"
@@ -334,6 +336,7 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_BR: return N_("Browse Brush to be linked");
case ID_PA: return N_("Browse Particle System to be linked");
case ID_GD: return N_("Browse Grease Pencil Data to be linked");
+ case ID_LS: return N_("Browse Line Style Data to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -427,8 +430,15 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
TIP_("Display number of users of this data (click to make a single-user copy)"));
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
- if (!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable)
+ if (/* test only */
+ (id_copy(id, NULL, 1) == FALSE) ||
+ (idfrom && idfrom->lib) ||
+ (editable == FALSE) ||
+ /* object in editmode - don't change data */
+ (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT)))
+ {
uiButSetFlag(but, UI_BUT_DISABLED);
+ }
}
if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
@@ -929,28 +939,26 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
#include "BKE_action.h"
#include "BKE_constraint.h"
-#define REDRAWIPO 1
-#define REDRAWNLA 2
-#define REDRAWBUTSOBJECT 3
-#define REDRAWACTION 4
#define B_CONSTRAINT_TEST 5
-#define B_CONSTRAINT_CHANGETARGET 6
-#define REMAKEIPO 8
-#define B_DIFF 9
+// #define B_CONSTRAINT_CHANGETARGET 6
static void do_constraint_panels(bContext *C, void *ob_pt, int event)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Object *ob = (Object *)ob_pt;
switch (event) {
case B_CONSTRAINT_TEST:
break; /* no handling */
+#if 0 /* UNUSED */
case B_CONSTRAINT_CHANGETARGET:
+ {
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
if (ob->pose) ob->pose->flag |= POSE_RECALC; /* checks & sorts pose channels */
DAG_scene_sort(bmain, scene);
break;
+ }
+#endif
default:
break;
}
@@ -1262,8 +1270,6 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
RNA_property_update(C, &cb->ptr, cb->prop);
}
-#define B_BANDCOL 1
-
static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
{
ColorBand *coba = coba_v;
@@ -1379,7 +1385,7 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand
static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
{
uiBut *bt;
- float unit = BLI_RCT_SIZE_X(butr) / 14.0f;
+ float unit = BLI_rctf_size_x(butr) / 14.0f;
float xs = butr->xmin;
uiBlockBeginAlign(block);
@@ -1405,7 +1411,7 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand
TIP_("Set interpolation between color stops"));
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
- bt = uiDefBut(block, BUT_COLORBAND, 0, "", xs, butr->ymin, BLI_RCT_SIZE_X(butr), UI_UNIT_Y, coba, 0, 0, 0, 0, "");
+ bt = uiDefBut(block, BUT_COLORBAND, 0, "", xs, butr->ymin, BLI_rctf_size_x(butr), UI_UNIT_Y, coba, 0, 0, 0, 0, "");
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
uiBlockEndAlign(block);
@@ -1480,7 +1486,7 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname
hist->height = (hist->height <= UI_UNIT_Y) ? UI_UNIT_Y : hist->height;
- bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_RCT_SIZE_X(&rect), hist->height, hist, 0, 0, 0, 0, "");
+ bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist, 0, 0, 0, 0, "");
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
MEM_freeN(cb);
@@ -1517,7 +1523,7 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
scopes->wavefrm_height = (scopes->wavefrm_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->wavefrm_height;
- bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_RCT_SIZE_X(&rect), scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
+ bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
(void)bt; /* UNUSED */
MEM_freeN(cb);
@@ -1554,7 +1560,7 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna
scopes->vecscope_height = (scopes->vecscope_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->vecscope_height;
- bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_RCT_SIZE_X(&rect), scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
+ bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
MEM_freeN(cb);
@@ -1569,11 +1575,11 @@ static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(ar
float d;
/* we allow 20 times zoom */
- if (BLI_RCT_SIZE_X(&cumap->curr) > 0.04f * BLI_RCT_SIZE_X(&cumap->clipr)) {
- d = 0.1154f * BLI_RCT_SIZE_X(&cumap->curr);
+ if (BLI_rctf_size_x(&cumap->curr) > 0.04f * BLI_rctf_size_x(&cumap->clipr)) {
+ d = 0.1154f * BLI_rctf_size_x(&cumap->curr);
cumap->curr.xmin += d;
cumap->curr.xmax -= d;
- d = 0.1154f * BLI_RCT_SIZE_Y(&cumap->curr);
+ d = 0.1154f * BLI_rctf_size_y(&cumap->curr);
cumap->curr.ymin += d;
cumap->curr.ymax -= d;
}
@@ -1587,8 +1593,8 @@ static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(u
float d, d1;
/* we allow 20 times zoom, but don't view outside clip */
- if (BLI_RCT_SIZE_X(&cumap->curr) < 20.0f * BLI_RCT_SIZE_X(&cumap->clipr)) {
- d = d1 = 0.15f * BLI_RCT_SIZE_X(&cumap->curr);
+ if (BLI_rctf_size_x(&cumap->curr) < 20.0f * BLI_rctf_size_x(&cumap->clipr)) {
+ d = d1 = 0.15f * BLI_rctf_size_x(&cumap->curr);
if (cumap->flag & CUMA_DO_CLIP)
if (cumap->curr.xmin - d < cumap->clipr.xmin)
@@ -1601,7 +1607,7 @@ static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(u
d1 = -cumap->curr.xmax + cumap->clipr.xmax;
cumap->curr.xmax += d1;
- d = d1 = 0.15f * BLI_RCT_SIZE_Y(&cumap->curr);
+ d = d1 = 0.15f * BLI_rctf_size_y(&cumap->curr);
if (cumap->flag & CUMA_DO_CLIP)
if (cumap->curr.ymin - d < cumap->clipr.ymin)
@@ -1869,7 +1875,7 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
- if (cumap->flag & CUMA_DO_CLIP) icon = ICON_CLIPUV_HLT; else icon = ICON_CLIPUV_DEHLT;
+ icon = (cumap->flag & CUMA_DO_CLIP) ? ICON_CLIPUV_HLT : ICON_CLIPUV_DEHLT;
bt = uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options"));
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
@@ -2085,6 +2091,74 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
}
}
+void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propname,
+ PointerRNA *used_ptr, const char *used_propname, int active_state)
+{
+ uiLayout *uRow, *uCol;
+ PropertyRNA *prop, *used_prop = NULL;
+ int groups, cols, states;
+ int group, col, state, row;
+ int cols_per_group = 5;
+ Object *ob = (Object *)ptr->id.data;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ RNA_warning("states property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ /* the number of states determines the way we group them
+ * - we want 2 rows only (for now)
+ * - the number of columns (cols) is the total number of buttons per row
+ * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
+ * - for now, only split into groups if group will have at least 5 items
+ */
+ states = RNA_property_array_length(ptr, prop);
+ cols = (states / 2) + (states % 2);
+ groups = ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
+
+ if (used_ptr && used_propname) {
+ used_prop = RNA_struct_find_property(used_ptr, used_propname);
+ if (!used_prop) {
+ RNA_warning("used layers property not found: %s.%s", RNA_struct_identifier(ptr->type), used_propname);
+ return;
+ }
+
+ if (RNA_property_array_length(used_ptr, used_prop) < states)
+ used_prop = NULL;
+ }
+
+ /* layers are laid out going across rows, with the columns being divided into groups */
+
+ for (group = 0; group < groups; group++) {
+ uCol = uiLayoutColumn(layout, TRUE);
+
+ for (row = 0; row < 2; row++) {
+ uiBlock *block;
+ uiBut *but;
+
+ uRow = uiLayoutRow(uCol, TRUE);
+ block = uiLayoutGetBlock(uRow);
+ state = groups * cols_per_group * row + cols_per_group * group;
+
+ /* add layers as toggle buts */
+ for (col = 0; (col < cols_per_group) && (state < states); col++, state++) {
+ int icon = 0;
+ int butlay = 1 << state;
+
+ if (active_state & butlay)
+ icon = ICON_LAYER_ACTIVE;
+ else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, state))
+ icon = ICON_LAYER_USED;
+
+ but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop, state, 0, 0, -1, -1, sca_state_name_get(ob, state));
+ uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(state));
+ but->type = TOG;
+ }
+ }
+ }
+}
+
/************************* List Template **************************/
@@ -2164,7 +2238,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
uiBlockSetEmboss(block, UI_EMBOSS);
uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
}
- else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
+ else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer) || RNA_struct_is_a(itemptr->type, &RNA_FreestyleLineSet)) {
uiItemL(sub, name, icon);
uiBlockSetEmboss(block, UI_EMBOSS);
uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 8a7f2d9ca47..f3539af821e 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -259,8 +259,8 @@ static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int r
rad += step;
- if (2.0f * rad > BLI_RCT_SIZE_Y(rect))
- rad = 0.5f * BLI_RCT_SIZE_Y(rect);
+ if (2.0f * rad > BLI_rcti_size_y(rect))
+ rad = 0.5f * BLI_rcti_size_y(rect);
minx = rect->xmin - step;
miny = rect->ymin - step;
@@ -345,8 +345,8 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
const int vnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)) == (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT) ||
(roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) == (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2;
- minsize = mini(BLI_RCT_SIZE_X(rect) * hnum,
- BLI_RCT_SIZE_Y(rect) * vnum);
+ minsize = mini(BLI_rcti_size_x(rect) * hnum,
+ BLI_rcti_size_y(rect) * vnum);
if (2.0f * rad > minsize)
rad = 0.5f * minsize;
@@ -491,7 +491,7 @@ static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, cha
float centx, centy, sizex, sizey, minsize;
int a, i1 = 0, i2 = 1;
- minsize = mini(BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect));
+ minsize = mini(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
/* center position and size */
centx = (float)rect->xmin + 0.5f * minsize;
@@ -526,7 +526,7 @@ static void widget_scroll_circle(uiWidgetTrias *tria, rcti *rect, float triasize
float centx, centy, sizex, sizey, minsize;
int a, i1 = 0, i2 = 1;
- minsize = mini(BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect));
+ minsize = mini(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
/* center position and size */
centx = (float)rect->xmin + 0.5f * minsize;
@@ -570,14 +570,14 @@ static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect)
int a;
/* center position and size */
- centx = rect->xmax - 0.5f * BLI_RCT_SIZE_Y(rect);
- centy = rect->ymin + 0.5f * BLI_RCT_SIZE_Y(rect);
- size = 0.4f * BLI_RCT_SIZE_Y(rect);
+ centx = rect->xmax - 0.5f * BLI_rcti_size_y(rect);
+ centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
+ size = 0.4f * BLI_rcti_size_y(rect);
/* XXX exception */
- asp = ((float)BLI_RCT_SIZE_X(rect)) / ((float)BLI_RCT_SIZE_Y(rect));
+ asp = ((float)BLI_rcti_size_x(rect)) / ((float)BLI_rcti_size_y(rect));
if (asp > 1.2f && asp < 2.6f)
- centx = rect->xmax - 0.3f * BLI_RCT_SIZE_Y(rect);
+ centx = rect->xmax - 0.3f * BLI_rcti_size_y(rect);
for (a = 0; a < 6; a++) {
tria->vec[a][0] = size * menu_tria_vert[a][0] + centx;
@@ -594,9 +594,9 @@ static void widget_check_trias(uiWidgetTrias *tria, rcti *rect)
int a;
/* center position and size */
- centx = rect->xmin + 0.5f * BLI_RCT_SIZE_Y(rect);
- centy = rect->ymin + 0.5f * BLI_RCT_SIZE_Y(rect);
- size = 0.5f * BLI_RCT_SIZE_Y(rect);
+ centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
+ centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
+ size = 0.5f * BLI_rcti_size_y(rect);
for (a = 0; a < 6; a++) {
tria->vec[a][0] = size * check_tria_vert[a][0] + centx;
@@ -840,8 +840,8 @@ static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), rcti *rect)
if (icon == ICON_NONE)
return;
- w = BLI_RCT_SIZE_X(rect);
- h = BLI_RCT_SIZE_Y(rect);
+ w = BLI_rcti_size_x(rect);
+ h = BLI_rcti_size_y(rect);
size = MIN2(w, h);
size -= PREVIEW_PAD * 2; /* padding */
@@ -965,48 +965,77 @@ static void ui_text_clip_give_next_off(uiBut *but)
but->ofs += bytes;
}
-/* sets but->ofs to make sure text is correctly visible */
-static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
+/**
+ * Cut off the start of the text to fit into the width of \a rect
+ *
+ * \note Sets but->ofs to make sure text is correctly visible.
+ * \note Clips right in some cases, this function could be cleaned up.
+ */
+static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, rcti *rect)
{
int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
- int okwidth = BLI_RCT_SIZE_X(rect) - border;
-
+ int okwidth = BLI_rcti_size_x(rect) - border;
if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE;
-
+
/* need to set this first */
uiStyleFontSet(fstyle);
if (fstyle->kerning == 1) /* for BLF_width */
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- /* if text editing we define ofs dynamically */
- if (but->editstr && but->pos >= 0) {
+ but->ofs = 0;
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr);
+
+ while (but->strwidth > okwidth) {
+ ui_text_clip_give_next_off(but);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
+ if (but->strwidth < 10) break;
+ }
+
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+}
+
+/**
+ * Cut off the text, taking into account the cursor location (text display while editing).
+ */
+static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect)
+{
+ int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
+ int okwidth = BLI_rcti_size_x(rect) - border;
+ if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE;
+
+ BLI_assert(but->editstr && but->pos >= 0);
+
+ /* need to set this first */
+ uiStyleFontSet(fstyle);
+
+ if (fstyle->kerning == 1) /* for BLF_width */
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+
+ if ((but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr)) <= okwidth) {
+ but->ofs = 0;
+ }
+ else {
+ /* define ofs dynamically */
if (but->ofs > but->pos)
but->ofs = but->pos;
- if (BLF_width(fstyle->uifont_id, but->drawstr) <= okwidth)
- but->ofs = 0;
- }
- else but->ofs = 0;
-
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
-
- while (but->strwidth > okwidth) {
-
- /* textbut exception, clip right when... */
- if (but->editstr && but->pos >= 0) {
+ while (but->strwidth > okwidth) {
float width;
char buf[UI_MAX_DRAW_STR];
-
+
/* copy draw string */
BLI_strncpy_utf8(buf, but->drawstr, sizeof(buf));
/* string position of cursor */
buf[but->pos] = 0;
width = BLF_width(fstyle->uifont_id, buf + but->ofs);
-
+
/* if cursor is at 20 pixels of right side button we clip left */
- if (width > okwidth - 20)
+ if (width > okwidth - 20) {
ui_text_clip_give_next_off(but);
+ }
else {
int len, bytes;
/* shift string to the left */
@@ -1016,25 +1045,30 @@ static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len));
but->drawstr[len - bytes] = 0;
}
- }
- else
- ui_text_clip_give_next_off(but);
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
-
- if (but->strwidth < 10) break;
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
+
+ if (but->strwidth < 10) break;
+ }
}
-
- if (fstyle->kerning == 1)
+
+ if (fstyle->kerning == 1) {
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
-static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
+/**
+ * Cut off the end of text to fit into the width of \a rect.
+ *
+ * \note deals with ': ' especially for number buttons
+ */
+static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, rcti *rect)
{
int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
- int okwidth = BLI_RCT_SIZE_X(rect) - border;
+ int okwidth = BLI_rcti_size_x(rect) - border;
char *cpoin = NULL;
- char *cpend = but->drawstr + strlen(but->drawstr);
+ int drawstr_len = strlen(but->drawstr);
+ char *cpend = but->drawstr + drawstr_len;
/* need to set this first */
uiStyleFontSet(fstyle);
@@ -1045,6 +1079,13 @@ static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr);
but->ofs = 0;
+
+ /* First shorten num-buttopns eg,
+ * Translucency: 0.000
+ * becomes
+ * Trans: 0.000
+ */
+
/* find the space after ':' separator */
cpoin = strrchr(but->drawstr, ':');
@@ -1057,8 +1098,11 @@ static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
int bytes = cp2 - prev_utf8;
/* shift the text after and including cp2 back by 1 char, +1 to include null terminator */
- memmove(cp2 - bytes, cp2, strlen(cp2) + 1);
+ memmove(cp2 - bytes, cp2, drawstr_len + 1);
cp2 -= bytes;
+
+ drawstr_len -= bytes;
+ // BLI_assert(strlen(but->drawstr) == drawstr_len);
but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
if (but->strwidth < 10) break;
@@ -1074,14 +1118,17 @@ static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
}
+
+ /* Now just remove trailing chars */
/* once the label's gone, chop off the least significant digits */
while (but->strwidth > okwidth) {
- int len = strlen(but->drawstr);
- int bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len));
+ int bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + drawstr_len));
if (bytes < 0)
bytes = 1;
- but->drawstr[len - bytes] = 0;
+ drawstr_len -= bytes;
+ but->drawstr[drawstr_len] = 0;
+ // BLI_assert(strlen(but->drawstr) == drawstr_len);
but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
if (but->strwidth < 10) break;
@@ -1229,30 +1276,31 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* draws text and icons for buttons */
static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
-
- if (but == NULL) return;
+ if (but == NULL) {
+ return;
+ }
/* clip but->drawstr to fit in available space */
if (but->editstr && but->pos >= 0) {
- ui_text_leftclip(fstyle, but, rect);
+ ui_text_clip_cursor(fstyle, but, rect);
}
else if (ELEM4(but->type, NUM, NUMABS, NUMSLI, SLI)) {
- ui_text_label_rightclip(fstyle, but, rect);
+ ui_text_clip_right_label(fstyle, but, rect);
}
else if (ELEM(but->type, TEX, SEARCH_MENU)) {
- ui_text_leftclip(fstyle, but, rect);
+ ui_text_clip_left(fstyle, but, rect);
}
else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) {
- ui_text_leftclip(fstyle, but, rect);
+ ui_text_clip_left(fstyle, but, rect);
}
else but->ofs = 0;
-
+
/* check for button text label */
if (but->type == ICONTEXTROW) {
widget_draw_icon(but, (BIFIconID) (but->icon + but->iconadd), 1.0f, rect);
}
else {
-
+
if (but->type == BUT_TOGDUAL) {
int dualset = 0;
if (but->pointype == UI_BUT_POIN_SHORT) {
@@ -1261,30 +1309,30 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
else if (but->pointype == UI_BUT_POIN_INT) {
dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr);
}
-
+
widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect);
}
else if (but->type == MENU && (but->flag & UI_BUT_NODE_LINK)) {
int tmp = rect->xmin;
- rect->xmin = rect->xmax - BLI_RCT_SIZE_Y(rect) - 1;
+ rect->xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect);
rect->xmin = tmp;
}
-
+
/* If there's an icon too (made with uiDefIconTextBut) then draw the icon
* and offset the text label to accommodate it */
-
+
if (but->flag & UI_HAS_ICON) {
widget_draw_icon(but, but->icon + but->iconadd, 1.0f, rect);
-
+
rect->xmin += (int)((float)UI_icon_get_width(but->icon + but->iconadd) * UI_DPI_ICON_FAC);
-
- if (but->editstr || (but->flag & UI_TEXT_LEFT))
+
+ if (but->editstr || (but->flag & UI_TEXT_LEFT))
rect->xmin += 5;
}
- else if ((but->flag & UI_TEXT_LEFT))
+ else if ((but->flag & UI_TEXT_LEFT))
rect->xmin += 5;
-
+
/* always draw text for textbutton cursor */
widget_draw_text(fstyle, wcol, but, rect);
@@ -1761,8 +1809,8 @@ static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float
float quad_strip[WIDGET_SIZE_MAX * 2][2];
/* prevent tooltips to not show round shadow */
- if (2.0f * radout > 0.2f * BLI_RCT_SIZE_Y(&rect1))
- rect1.ymax -= 0.2f * BLI_RCT_SIZE_Y(&rect1);
+ if (2.0f * radout > 0.2f * BLI_rcti_size_y(&rect1))
+ rect1.ymax -= 0.2f * BLI_rcti_size_y(&rect1);
else
rect1.ymax -= 2.0f * radout;
@@ -1844,14 +1892,14 @@ static void ui_hsv_cursor(float x, float y)
void ui_hsvcircle_vals_from_pos(float *valrad, float *valdist, rcti *rect, float mx, float my)
{
/* duplication of code... well, simple is better now */
- float centx = BLI_RCT_CENTER_X_FL(rect);
- float centy = BLI_RCT_CENTER_Y_FL(rect);
+ float centx = BLI_rcti_cent_x_fl(rect);
+ float centy = BLI_rcti_cent_y_fl(rect);
float radius, dist;
- if (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect))
- radius = (float)BLI_RCT_SIZE_Y(rect) / 2;
+ if (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect))
+ radius = (float)BLI_rcti_size_y(rect) / 2;
else
- radius = (float)BLI_RCT_SIZE_X(rect) / 2;
+ radius = (float)BLI_rcti_size_x(rect) / 2;
mx -= centx;
my -= centy;
@@ -1877,13 +1925,13 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect)
color_profile = FALSE;
radstep = 2.0f * (float)M_PI / (float)tot;
- centx = BLI_RCT_CENTER_X_FL(rect);
- centy = BLI_RCT_CENTER_Y_FL(rect);
+ centx = BLI_rcti_cent_x_fl(rect);
+ centy = BLI_rcti_cent_y_fl(rect);
- if (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect))
- radius = (float)BLI_RCT_SIZE_Y(rect) / 2;
+ if (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect))
+ radius = (float)BLI_rcti_size_y(rect) / 2;
else
- radius = (float)BLI_RCT_SIZE_X(rect) / 2;
+ radius = (float)BLI_rcti_size_x(rect) / 2;
/* color */
ui_get_but_vectorf(but, rgb);
@@ -2062,10 +2110,10 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa
}
/* rect */
- sx1 = rect->xmin + dx * BLI_RCT_SIZE_X(rect);
- sx2 = rect->xmin + (dx + color_step) * BLI_RCT_SIZE_X(rect);
+ sx1 = rect->xmin + dx * BLI_rcti_size_x(rect);
+ sx2 = rect->xmin + (dx + color_step) * BLI_rcti_size_x(rect);
sy = rect->ymin;
- dy = BLI_RCT_SIZE_Y(rect) / 3.0;
+ dy = BLI_rcti_size_y(rect) / 3.0;
glBegin(GL_QUADS);
for (a = 0; a < 3; a++, sy += dy) {
@@ -2120,8 +2168,8 @@ static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
}
/* cursor */
- x = rect->xmin + x * BLI_RCT_SIZE_X(rect);
- y = rect->ymin + y * BLI_RCT_SIZE_Y(rect);
+ x = rect->xmin + x * BLI_rcti_size_x(rect);
+ y = rect->ymin + y * BLI_rcti_size_y(rect);
CLAMP(x, rect->xmin + 3.0f, rect->xmax - 3.0f);
CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
@@ -2136,7 +2184,7 @@ static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
{
uiWidgetBase wtb;
- float rad = 0.5f * BLI_RCT_SIZE_X(rect);
+ float rad = 0.5f * BLI_rcti_size_x(rect);
float x, y;
float rgb[3], hsv[3], v, range;
int color_profile = but->block->color_profile;
@@ -2171,8 +2219,8 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
widgetbase_draw(&wtb, &wcol_tmp);
/* cursor */
- x = rect->xmin + 0.5f * BLI_RCT_SIZE_X(rect);
- y = rect->ymin + v * BLI_RCT_SIZE_Y(rect);
+ x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
+ y = rect->ymin + v * BLI_rcti_size_y(rect);
CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
ui_hsv_cursor(x, y);
@@ -2183,7 +2231,7 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
/* ************ separator, for menus etc ***************** */
static void ui_draw_separator(rcti *rect, uiWidgetColors *wcol)
{
- int y = rect->ymin + BLI_RCT_SIZE_Y(rect) / 2 - 1;
+ int y = rect->ymin + BLI_rcti_size_y(rect) / 2 - 1;
unsigned char col[4];
col[0] = wcol->text[0];
@@ -2202,7 +2250,7 @@ static void ui_draw_separator(rcti *rect, uiWidgetColors *wcol)
static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
uiWidgetBase wtb;
- float rad = 0.5f * BLI_RCT_SIZE_Y(rect);
+ float rad = 0.5f * BLI_rcti_size_y(rect);
float textofs = rad * 0.75f;
if (state & UI_SELECT)
@@ -2283,12 +2331,12 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat
widget_init(&wtb);
/* determine horizontal/vertical */
- horizontal = (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect));
+ horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
if (horizontal)
- rad = 0.5f * BLI_RCT_SIZE_Y(rect);
+ rad = 0.5f * BLI_rcti_size_y(rect);
else
- rad = 0.5f * BLI_RCT_SIZE_X(rect);
+ rad = 0.5f * BLI_rcti_size_x(rect);
wtb.shadedir = (horizontal) ? 1 : 0;
@@ -2300,7 +2348,7 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat
widgetbase_draw(&wtb, wcol);
/* slider */
- if ((BLI_RCT_SIZE_X(slider) < 2) || (BLI_RCT_SIZE_Y(slider) < 2)) {
+ if ((BLI_rcti_size_x(slider) < 2) || (BLI_rcti_size_y(slider) < 2)) {
/* pass */
}
else {
@@ -2366,17 +2414,17 @@ static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
rect1 = *rect;
/* determine horizontal/vertical */
- horizontal = (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect));
+ horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
if (horizontal) {
- fac = BLI_RCT_SIZE_X(rect) / size;
+ fac = BLI_rcti_size_x(rect) / size;
rect1.xmin = rect1.xmin + ceilf(fac * ((float)value - but->softmin));
rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin));
/* ensure minimium size */
- min = BLI_RCT_SIZE_Y(rect);
+ min = BLI_rcti_size_y(rect);
- if (BLI_RCT_SIZE_X(&rect1) < min) {
+ if (BLI_rcti_size_x(&rect1) < min) {
rect1.xmax = rect1.xmin + min;
if (rect1.xmax > rect->xmax) {
@@ -2386,14 +2434,14 @@ static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
}
}
else {
- fac = BLI_RCT_SIZE_Y(rect) / size;
+ fac = BLI_rcti_size_y(rect) / size;
rect1.ymax = rect1.ymax - ceilf(fac * ((float)value - but->softmin));
rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin));
/* ensure minimium size */
- min = BLI_RCT_SIZE_X(rect);
+ min = BLI_rcti_size_x(rect);
- if (BLI_RCT_SIZE_Y(&rect1) < min) {
+ if (BLI_rcti_size_y(&rect1) < min) {
rect1.ymax = rect1.ymin + min;
if (rect1.ymax > rect->ymax) {
@@ -2421,10 +2469,10 @@ static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int
rect_prog.ymax = rect_prog.ymin + 4;
rect_bar.ymax = rect_bar.ymin + 4;
- w = value * BLI_RCT_SIZE_X(&rect_prog);
+ w = value * BLI_rcti_size_x(&rect_prog);
/* ensure minimium size */
- min = BLI_RCT_SIZE_Y(&rect_prog);
+ min = BLI_rcti_size_y(&rect_prog);
w = MAX2(w, min);
rect_bar.xmax = rect_bar.xmin + w;
@@ -2444,8 +2492,8 @@ static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, in
UI_ThemeColor(TH_TEXT_HI);
- rectlink.xmin = BLI_RCT_CENTER_X(rect);
- rectlink.ymin = BLI_RCT_CENTER_Y(rect);
+ rectlink.xmin = BLI_rcti_cent_x(rect);
+ rectlink.ymin = BLI_rcti_cent_y(rect);
rectlink.xmax = but->linkto[0];
rectlink.ymax = but->linkto[1];
@@ -2467,7 +2515,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
/* backdrop first */
/* fully rounded */
- offs = 0.5f * BLI_RCT_SIZE_Y(rect);
+ offs = 0.5f * BLI_rcti_size_y(rect);
toffs = offs * 0.75f;
round_box_edges(&wtb, roundboxalign, rect, offs);
@@ -2488,7 +2536,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
rect1 = *rect;
value = ui_get_but_val(but);
- fac = ((float)value - but->softmin) * (BLI_RCT_SIZE_X(&rect1) - offs) / (but->softmax - but->softmin);
+ fac = ((float)value - but->softmin) * (BLI_rcti_size_x(&rect1) - offs) / (but->softmax - but->softmin);
/* left part of slider, always rounded */
rect1.xmax = rect1.xmin + ceil(offs + 1.0f);
@@ -2621,7 +2669,7 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
widgetbase_draw(&wtb, wcol);
/* text space */
- rect->xmax -= BLI_RCT_SIZE_Y(rect);
+ rect->xmax -= BLI_rcti_size_y(rect);
}
static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
@@ -2664,7 +2712,7 @@ static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int
{
if (state & UI_ACTIVE) {
uiWidgetBase wtb;
- float rad = 0.5f * BLI_RCT_SIZE_Y(rect); /* 4.0f */
+ float rad = 0.5f * BLI_rcti_size_y(rect); /* 4.0f */
widget_init(&wtb);
@@ -2710,10 +2758,10 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
widget_init(&wtb);
/* square */
- recttemp.xmax = recttemp.xmin + BLI_RCT_SIZE_Y(&recttemp);
+ recttemp.xmax = recttemp.xmin + BLI_rcti_size_y(&recttemp);
/* smaller */
- delta = 1 + BLI_RCT_SIZE_Y(&recttemp) / 8;
+ delta = 1 + BLI_rcti_size_y(&recttemp) / 8;
recttemp.xmin += delta;
recttemp.ymin += delta;
recttemp.xmax -= delta;
@@ -2730,7 +2778,7 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
widgetbase_draw(&wtb, wcol);
/* text space */
- rect->xmin += BLI_RCT_SIZE_Y(rect) * 0.7 + delta;
+ rect->xmin += BLI_rcti_size_y(rect) * 0.7 + delta;
}
@@ -2792,7 +2840,7 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int
static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
- float rad = 5.0f; /* 0.5f * BLI_RCT_SIZE_Y(rect); */
+ float rad = 5.0f; /* 0.5f * BLI_rcti_size_y(rect); */
widget_init(&wtb);
@@ -3275,12 +3323,12 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
if (block->flag & UI_BLOCK_CLIPTOP) {
/* XXX no scaling for UI here yet */
glColor3ubv((unsigned char *)wt->wcol.text);
- UI_DrawTriIcon(BLI_RCT_CENTER_X(rect), rect->ymax - 8, 't');
+ UI_DrawTriIcon(BLI_rcti_cent_x(rect), rect->ymax - 8, 't');
}
if (block->flag & UI_BLOCK_CLIPBOTTOM) {
/* XXX no scaling for UI here yet */
glColor3ubv((unsigned char *)wt->wcol.text);
- UI_DrawTriIcon(BLI_RCT_CENTER_X(rect), rect->ymin + 10, 'v');
+ UI_DrawTriIcon(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v');
}
}
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index b379a2e7b4c..1d0cd2707ac 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -343,6 +343,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->handle_sel_vect; break;
case TH_HANDLE_SEL_ALIGN:
cp = ts->handle_sel_align; break;
+ case TH_FREESTYLE_EDGE_MARK:
+ cp = ts->freestyle_edge_mark; break;
+ case TH_FREESTYLE_FACE_MARK:
+ cp = ts->freestyle_face_mark; break;
case TH_SYNTAX_B:
cp = ts->syntaxb; break;
@@ -710,6 +714,8 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.button_text_hi, 255, 255, 255, 255);
rgba_char_args_set(btheme->tv3d.button_title, 0, 0, 0, 255);
rgba_char_args_set(btheme->tv3d.title, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
+ rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
btheme->tv3d.facedot_size = 4;
@@ -1934,6 +1940,19 @@ void init_userdef_do_versions(void)
}
}
+ /* Freestyle color settings */
+ {
+ bTheme *btheme;
+
+ for(btheme= U.themes.first; btheme; btheme= btheme->next) {
+ /* check for alpha==0 is safe, then color was never set */
+ if(btheme->tv3d.freestyle_edge_mark[3]==0) {
+ rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
+ rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
+ }
+ }
+ }
+
/* GL Texture Garbage Collection (variable abused above!) */
if (U.textimeout == 0) {
U.texcollectrate = 60;
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 9c71746d045..47bee92be62 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -96,11 +96,11 @@ static void view2d_masks(View2D *v2d)
/* check size if: */
if (v2d->scroll & V2D_SCROLL_HORIZONTAL)
if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL))
- if (BLI_RCT_SIZE_X(&v2d->tot) <= BLI_RCT_SIZE_X(&v2d->cur))
+ if (BLI_rctf_size_x(&v2d->tot) <= BLI_rcti_size_x(&v2d->cur))
v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
if (v2d->scroll & V2D_SCROLL_VERTICAL)
if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL))
- if (BLI_RCT_SIZE_Y(&v2d->tot) <= BLI_RCT_SIZE_Y(&v2d->cur))
+ if (BLI_rctf_size_y(&v2d->tot) <= BLI_rctf_size_y(&v2d->cur))
v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
#endif
scroll = view2d_scroll_mapped(v2d->scroll);
@@ -328,8 +328,8 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
rctf *cur, *tot;
/* use mask as size of region that View2D resides in, as it takes into account scrollbars already */
- winx = (float)(BLI_RCT_SIZE_X(&v2d->mask) + 1);
- winy = (float)(BLI_RCT_SIZE_Y(&v2d->mask) + 1);
+ winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
+ winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
/* get pointers to rcts for less typing */
cur = &v2d->cur;
@@ -347,10 +347,10 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
* - firstly, we calculate the sizes of the rects
* - curwidth and curheight are saved as reference... modify width and height values here
*/
- totwidth = BLI_RCT_SIZE_X(tot);
- totheight = BLI_RCT_SIZE_Y(tot);
- curwidth = width = BLI_RCT_SIZE_X(cur);
- curheight = height = BLI_RCT_SIZE_Y(cur);
+ totwidth = BLI_rctf_size_x(tot);
+ totheight = BLI_rctf_size_y(tot);
+ curwidth = width = BLI_rctf_size_x(cur);
+ curheight = height = BLI_rctf_size_y(cur);
/* if zoom is locked, size on the appropriate axis is reset to mask size */
if (v2d->keepzoom & V2D_LOCKZOOM_X)
@@ -499,16 +499,16 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
/* resize from centerpoint, unless otherwise specified */
if (width != curwidth) {
if (v2d->keepofs & V2D_LOCKOFS_X) {
- cur->xmax += width - BLI_RCT_SIZE_X(cur);
+ cur->xmax += width - BLI_rctf_size_x(cur);
}
else if (v2d->keepofs & V2D_KEEPOFS_X) {
if (v2d->align & V2D_ALIGN_NO_POS_X)
- cur->xmin -= width - BLI_RCT_SIZE_X(cur);
+ cur->xmin -= width - BLI_rctf_size_x(cur);
else
- cur->xmax += width - BLI_RCT_SIZE_X(cur);
+ cur->xmax += width - BLI_rctf_size_x(cur);
}
else {
- temp = BLI_RCT_CENTER_X(cur);
+ temp = BLI_rctf_cent_x(cur);
dh = width * 0.5f;
cur->xmin = temp - dh;
@@ -517,16 +517,16 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
}
if (height != curheight) {
if (v2d->keepofs & V2D_LOCKOFS_Y) {
- cur->ymax += height - BLI_RCT_SIZE_Y(cur);
+ cur->ymax += height - BLI_rctf_size_y(cur);
}
else if (v2d->keepofs & V2D_KEEPOFS_Y) {
if (v2d->align & V2D_ALIGN_NO_POS_Y)
- cur->ymin -= height - BLI_RCT_SIZE_Y(cur);
+ cur->ymin -= height - BLI_rctf_size_y(cur);
else
- cur->ymax += height - BLI_RCT_SIZE_Y(cur);
+ cur->ymax += height - BLI_rctf_size_y(cur);
}
else {
- temp = BLI_RCT_CENTER_Y(cur);
+ temp = BLI_rctf_cent_y(cur);
dh = height * 0.5f;
cur->ymin = temp - dh;
@@ -540,8 +540,8 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
float temp, diff;
/* recalculate extents of cur */
- curwidth = BLI_RCT_SIZE_X(cur);
- curheight = BLI_RCT_SIZE_Y(cur);
+ curwidth = BLI_rctf_size_x(cur);
+ curheight = BLI_rctf_size_y(cur);
/* width */
if ((curwidth > totwidth) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_X | V2D_LIMITZOOM))) {
@@ -592,7 +592,7 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
*/
if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
/* outside boundaries on both sides, so take middle-point of tot, and place in balanced way */
- temp = BLI_RCT_CENTER_X(tot);
+ temp = BLI_rctf_cent_x(tot);
diff = curheight * 0.5f;
cur->xmin = temp - diff;
@@ -642,7 +642,7 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
*/
if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
/* outside boundaries on both sides, so take middle-point of tot, and place in balanced way */
- temp = BLI_RCT_CENTER_Y(tot);
+ temp = BLI_rctf_cent_y(tot);
diff = curheight * 0.5f;
cur->ymin = temp - diff;
@@ -791,8 +791,8 @@ void UI_view2d_curRect_reset(View2D *v2d)
float width, height;
/* assume width and height of 'cur' rect by default, should be same size as mask */
- width = (float)(BLI_RCT_SIZE_X(&v2d->mask) + 1);
- height = (float)(BLI_RCT_SIZE_Y(&v2d->mask) + 1);
+ width = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
+ height = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
/* handle width - posx and negx flags are mutually exclusive, so watch out */
if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
@@ -958,8 +958,8 @@ static void view2d_map_cur_using_mask(View2D *v2d, rctf *curmasked)
*curmasked = v2d->cur;
if (view2d_scroll_mapped(v2d->scroll)) {
- float dx = BLI_RCT_SIZE_X(&v2d->cur) / ((float)(BLI_RCT_SIZE_X(&v2d->mask) + 1));
- float dy = BLI_RCT_SIZE_Y(&v2d->cur) / ((float)(BLI_RCT_SIZE_Y(&v2d->mask) + 1));
+ float dx = BLI_rctf_size_x(&v2d->cur) / ((float)(BLI_rcti_size_x(&v2d->mask) + 1));
+ float dy = BLI_rctf_size_y(&v2d->cur) / ((float)(BLI_rcti_size_y(&v2d->mask) + 1));
if (v2d->mask.xmin != 0)
curmasked->xmin -= dx * (float)v2d->mask.xmin;
@@ -985,14 +985,13 @@ void UI_view2d_view_ortho(View2D *v2d)
*/
/* XXX brecht: instead of zero at least use a tiny offset, otherwise
* pixel rounding is effectively random due to float inaccuracy */
- xofs = 0.001f * BLI_RCT_SIZE_X(&v2d->cur) / BLI_RCT_SIZE_X(&v2d->mask);
- yofs = 0.001f * BLI_RCT_SIZE_Y(&v2d->cur) / BLI_RCT_SIZE_Y(&v2d->mask);
+ xofs = 0.001f * BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+ yofs = 0.001f * BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
/* apply mask-based adjustments to cur rect (due to scrollers), to eliminate scaling artifacts */
view2d_map_cur_using_mask(v2d, &curmasked);
-
- curmasked.xmin -= xofs; curmasked.xmax -= xofs;
- curmasked.ymin -= yofs; curmasked.ymax -= yofs;
+
+ BLI_rctf_translate(&curmasked, -xofs, -yofs);
/* XXX ton: this flag set by outliner, for icons */
if (v2d->flag & V2D_PIXELOFS_X) {
@@ -1044,8 +1043,8 @@ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, short xaxis)
void UI_view2d_view_restore(const bContext *C)
{
ARegion *ar = CTX_wm_region(C);
- int width = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- int height = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ int width = BLI_rcti_size_x(&ar->winrct) + 1;
+ int height = BLI_rcti_size_y(&ar->winrct) + 1;
wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
glLoadIdentity();
@@ -1117,7 +1116,8 @@ static void step_to_grid(float *step, int *power, int unit)
* - winx = width of region we're drawing to, note: not used but keeping for completeness.
* - winy = height of region we're drawing into
*/
-View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy)
+View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d,
+ short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy)
{
View2DGrid *grid;
@@ -1140,8 +1140,8 @@ View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, short xunits, short x
/* calculate x-axis grid scale (only if both args are valid) */
if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) {
- space = BLI_RCT_SIZE_X(&v2d->cur);
- pixels = (float)BLI_RCT_SIZE_X(&v2d->mask);
+ space = BLI_rctf_size_x(&v2d->cur);
+ pixels = (float)BLI_rcti_size_x(&v2d->mask);
if (pixels != 0.0f) {
grid->dx = (U.v2d_min_gridsize * space) / (seconddiv * pixels);
@@ -1158,7 +1158,7 @@ View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, short xunits, short x
/* calculate y-axis grid scale (only if both args are valid) */
if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) {
- space = BLI_RCT_SIZE_Y(&v2d->cur);
+ space = BLI_rctf_size_y(&v2d->cur);
pixels = (float)winy;
grid->dy = U.v2d_min_gridsize * space / pixels;
@@ -1206,7 +1206,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec2[1] = v2d->cur.ymax;
/* minor gridlines */
- step = (BLI_RCT_SIZE_X(&v2d->mask) + 1) / U.v2d_min_gridsize;
+ step = (BLI_rcti_size_x(&v2d->mask) + 1) / U.v2d_min_gridsize;
UI_ThemeColor(TH_GRID);
for (a = 0; a < step; a++) {
@@ -1240,7 +1240,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec1[0] = grid->startx;
vec2[0] = v2d->cur.xmax;
- step = (BLI_RCT_SIZE_Y(&v2d->mask) + 1) / U.v2d_min_gridsize;
+ step = (BLI_rcti_size_y(&v2d->mask) + 1) / U.v2d_min_gridsize;
UI_ThemeColor(TH_GRID);
for (a = 0; a <= step; a++) {
@@ -1414,7 +1414,8 @@ struct View2DScrollers {
};
/* Calculate relevant scroller properties */
-View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short xunits, short xclamp, short yunits, short yclamp)
+View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
+ short xunits, short xclamp, short yunits, short yclamp)
{
View2DScrollers *scrollers;
rcti vert, hor;
@@ -1457,8 +1458,8 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short
/* horizontal scrollers */
if (scroll & V2D_SCROLL_HORIZONTAL) {
/* scroller 'button' extents */
- totsize = BLI_RCT_SIZE_X(&v2d->tot);
- scrollsize = (float)BLI_RCT_SIZE_X(&hor);
+ totsize = BLI_rctf_size_x(&v2d->tot);
+ scrollsize = (float)BLI_rcti_size_x(&hor);
if (totsize == 0.0f) totsize = 1.0f; /* avoid divide by zero */
fac1 = (v2d->cur.xmin - v2d->tot.xmin) / totsize;
@@ -1498,8 +1499,8 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short
/* vertical scrollers */
if (scroll & V2D_SCROLL_VERTICAL) {
/* scroller 'button' extents */
- totsize = BLI_RCT_SIZE_Y(&v2d->tot);
- scrollsize = (float)BLI_RCT_SIZE_Y(&vert);
+ totsize = BLI_rctf_size_y(&v2d->tot);
+ scrollsize = (float)BLI_rcti_size_y(&vert);
if (totsize == 0.0f) totsize = 1.0f; /* avoid divide by zero */
fac1 = (v2d->cur.ymin - v2d->tot.ymin) / totsize;
@@ -1547,7 +1548,7 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short
scrollers->grid = UI_view2d_grid_calc(CTX_data_scene(C), v2d,
xunits, xclamp, yunits, yclamp,
- BLI_RCT_SIZE_X(&hor), BLI_RCT_SIZE_Y(&vert));
+ BLI_rcti_size_x(&hor), BLI_rcti_size_y(&vert));
}
/* return scrollers */
@@ -1631,7 +1632,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
*/
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
- (BLI_RCT_SIZE_X(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+ (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
{
state |= UI_SCROLL_ARROWS;
}
@@ -1651,11 +1652,11 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
* - fac is x-coordinate to draw to
* - dfac is gap between scale markings
*/
- fac = (grid->startx - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur);
- fac = (float)hor.xmin + fac * BLI_RCT_SIZE_X(&hor);
+ fac = (grid->startx - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
+ fac = (float)hor.xmin + fac * BLI_rcti_size_x(&hor);
- dfac = grid->dx / BLI_RCT_SIZE_X(&v2d->cur);
- dfac = dfac * BLI_RCT_SIZE_X(&hor);
+ dfac = grid->dx / BLI_rctf_size_x(&v2d->cur);
+ dfac = dfac * BLI_rcti_size_x(&hor);
/* set starting value, and text color */
UI_ThemeColor(TH_TEXT);
@@ -1742,7 +1743,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
*/
if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
- (BLI_RCT_SIZE_Y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+ (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
{
state |= UI_SCROLL_ARROWS;
}
@@ -1765,11 +1766,11 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
* - these involve a correction for horizontal scrollbar
* NOTE: it's assumed that that scrollbar is there if this is involved!
*/
- fac = (grid->starty - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur);
- fac = vert.ymin + fac * BLI_RCT_SIZE_Y(&vert);
+ fac = (grid->starty - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
+ fac = vert.ymin + fac * BLI_rcti_size_y(&vert);
- dfac = grid->dy / BLI_RCT_SIZE_Y(&v2d->cur);
- dfac = dfac * BLI_RCT_SIZE_Y(&vert);
+ dfac = grid->dy / BLI_rctf_size_y(&v2d->cur);
+ dfac = dfac * BLI_rcti_size_y(&vert);
/* set starting value, and text color */
UI_ThemeColor(TH_TEXT);
@@ -1823,7 +1824,9 @@ void UI_view2d_scrollers_free(View2DScrollers *scrollers)
* - column, row = the 2d-coordinates (in 2D-view / 'tot' rect space) the cell exists at
* - rect = coordinates of the cell (passed as single var instead of 4 separate, as it's more useful this way)
*/
-void UI_view2d_listview_cell_to_view(View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int column, int row, rctf *rect)
+void UI_view2d_listview_cell_to_view(View2D *v2d, short columnwidth, short rowheight,
+ float startx, float starty,
+ int column, int row, rctf *rect)
{
/* sanity checks */
if (ELEM(NULL, v2d, rect)) {
@@ -1927,17 +1930,17 @@ void UI_view2d_region_to_view(View2D *v2d, int x, int y, float *r_viewx, float *
float div, ofs;
if (r_viewx) {
- div = (float)BLI_RCT_SIZE_X(&v2d->mask);
+ div = (float)BLI_rcti_size_x(&v2d->mask);
ofs = (float)v2d->mask.xmin;
- *r_viewx = v2d->cur.xmin + BLI_RCT_SIZE_X(&v2d->cur) * ((float)x - ofs) / div;
+ *r_viewx = v2d->cur.xmin + BLI_rctf_size_x(&v2d->cur) * ((float)x - ofs) / div;
}
if (r_viewy) {
- div = (float)BLI_RCT_SIZE_Y(&v2d->mask);
+ div = (float)BLI_rcti_size_y(&v2d->mask);
ofs = (float)v2d->mask.ymin;
- *r_viewy = v2d->cur.ymin + BLI_RCT_SIZE_Y(&v2d->cur) * ((float)y - ofs) / div;
+ *r_viewy = v2d->cur.ymin + BLI_rctf_size_y(&v2d->cur) * ((float)y - ofs) / div;
}
}
@@ -1956,15 +1959,15 @@ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *regionx, int *
*regiony = V2D_IS_CLIPPED;
/* express given coordinates as proportional values */
- x = (x - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur);
- y = (y - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur);
+ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
+ y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
/* check if values are within bounds */
if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) {
if (regionx)
- *regionx = (int)(v2d->mask.xmin + x * BLI_RCT_SIZE_X(&v2d->mask));
+ *regionx = (int)(v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask));
if (regiony)
- *regiony = (int)(v2d->mask.ymin + y * BLI_RCT_SIZE_Y(&v2d->mask));
+ *regiony = (int)(v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask));
}
}
@@ -1977,12 +1980,12 @@ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *regionx, int *
void UI_view2d_to_region_no_clip(View2D *v2d, float x, float y, int *regionx, int *regiony)
{
/* step 1: express given coordinates as proportional values */
- x = (x - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur);
- y = (y - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur);
+ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
+ y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
/* step 2: convert proportional distances to screen coordinates */
- x = v2d->mask.xmin + x * BLI_RCT_SIZE_X(&v2d->mask);
- y = v2d->mask.ymin + y * BLI_RCT_SIZE_Y(&v2d->mask);
+ x = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask);
+ y = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
/* although we don't clamp to lie within region bounds, we must avoid exceeding size of ints */
if (regionx) {
@@ -2035,8 +2038,8 @@ View2D *UI_view2d_fromcontext_rwin(const bContext *C)
*/
void UI_view2d_getscale(View2D *v2d, float *x, float *y)
{
- if (x) *x = BLI_RCT_SIZE_X(&v2d->mask) / BLI_RCT_SIZE_X(&v2d->cur);
- if (y) *y = BLI_RCT_SIZE_Y(&v2d->mask) / BLI_RCT_SIZE_Y(&v2d->cur);
+ if (x) *x = BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur);
+ if (y) *y = BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur);
}
/* Check if mouse is within scrollers
@@ -2142,7 +2145,7 @@ void UI_view2d_text_cache_draw(ARegion *ar)
const char *str = (const char *)(v2s + 1);
int xofs = 0, yofs;
- yofs = ceil(0.5f * (BLI_RCT_SIZE_Y(&v2s->rect) - default_height));
+ yofs = ceil(0.5f * (BLI_rcti_size_y(&v2s->rect) - default_height));
if (yofs < 1) yofs = 1;
if (col_pack_prev != v2s->col.pack) {
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 99313edc289..3d3f309a8d4 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -119,10 +119,10 @@ static int view_pan_init(bContext *C, wmOperator *op)
vpd->ar = ar;
/* calculate translation factor - based on size of view */
- winx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1);
- winy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1);
- vpd->facx = (BLI_RCT_SIZE_X(&v2d->cur)) / winx;
- vpd->facy = (BLI_RCT_SIZE_Y(&v2d->cur)) / winy;
+ winx = (float)(BLI_rcti_size_x(&ar->winrct) + 1);
+ winy = (float)(BLI_rcti_size_y(&ar->winrct) + 1);
+ vpd->facx = (BLI_rctf_size_x(&v2d->cur)) / winx;
+ vpd->facy = (BLI_rctf_size_y(&v2d->cur)) / winy;
return 1;
}
@@ -471,7 +471,7 @@ static int view_scrollup_exec(bContext *C, wmOperator *op)
if (RNA_boolean_get(op->ptr, "page")) {
ARegion *ar = CTX_wm_region(C);
- RNA_int_set(op->ptr, "deltay", BLI_RCT_SIZE_Y(&ar->v2d.mask));
+ RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask));
}
/* apply movement, then we're done */
@@ -590,12 +590,12 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
facy = RNA_float_get(op->ptr, "zoomfacy");
if (facx >= 0.0f) {
- dx = BLI_RCT_SIZE_X(&v2d->cur) * facx;
- dy = BLI_RCT_SIZE_Y(&v2d->cur) * facy;
+ dx = BLI_rctf_size_x(&v2d->cur) * facx;
+ dy = BLI_rctf_size_y(&v2d->cur) * facy;
}
else {
- dx = (BLI_RCT_SIZE_X(&v2d->cur) / (1.0f + 2.0f * facx)) * facx;
- dy = (BLI_RCT_SIZE_Y(&v2d->cur) / (1.0f + 2.0f * facy)) * facy;
+ dx = (BLI_rctf_size_x(&v2d->cur) / (1.0f + 2.0f * facx)) * facx;
+ dy = (BLI_rctf_size_y(&v2d->cur) / (1.0f + 2.0f * facy)) * facy;
}
/* only resize view on an axis if change is allowed */
@@ -611,7 +611,7 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
}
else {
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur);
+ float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
float mval_faci = 1.0f - mval_fac;
float ofs = (mval_fac * dx) - (mval_faci * dx);
@@ -636,7 +636,7 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
}
else {
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur);
+ float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
float mval_faci = 1.0f - mval_fac;
float ofs = (mval_fac * dy) - (mval_faci * dy);
@@ -845,7 +845,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
}
else {
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur);
+ float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
float mval_faci = 1.0f - mval_fac;
float ofs = (mval_fac * dx) - (mval_faci * dx);
@@ -864,7 +864,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
}
else {
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur);
+ float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
float mval_faci = 1.0f - mval_fac;
float ofs = (mval_fac * dy) - (mval_faci * dy);
@@ -942,8 +942,8 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
* with magnify information that is stored in x axis
*/
fac = 0.01f * (event->x - event->prevx);
- dx = fac * BLI_RCT_SIZE_X(&v2d->cur) / 10.0f;
- dy = fac * BLI_RCT_SIZE_Y(&v2d->cur) / 10.0f;
+ dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f;
+ dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f;
RNA_float_set(op->ptr, "deltax", dx);
RNA_float_set(op->ptr, "deltay", dy);
@@ -1009,14 +1009,14 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event)
float dist;
/* x-axis transform */
- dist = BLI_RCT_SIZE_X(&v2d->mask) / 2.0f;
+ dist = BLI_rcti_size_x(&v2d->mask) / 2.0f;
dx = 1.0f - (fabsf(vzd->lastx - dist) + 2.0f) / (fabsf(event->x - dist) + 2.0f);
- dx *= 0.5f * BLI_RCT_SIZE_X(&v2d->cur);
+ dx *= 0.5f * BLI_rctf_size_x(&v2d->cur);
/* y-axis transform */
- dist = BLI_RCT_SIZE_Y(&v2d->mask) / 2.0f;
+ dist = BLI_rcti_size_y(&v2d->mask) / 2.0f;
dy = 1.0f - (fabsf(vzd->lasty - dist) + 2.0f) / (fabsf(event->y - dist) + 2.0f);
- dy *= 0.5f * BLI_RCT_SIZE_Y(&v2d->cur);
+ dy *= 0.5f * BLI_rctf_size_y(&v2d->cur);
}
else {
/* 'continuous' or 'dolly' */
@@ -1024,11 +1024,11 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event)
/* x-axis transform */
fac = 0.01f * (event->x - vzd->lastx);
- dx = fac * BLI_RCT_SIZE_X(&v2d->cur);
+ dx = fac * BLI_rctf_size_x(&v2d->cur);
/* y-axis transform */
fac = 0.01f * (event->y - vzd->lasty);
- dy = fac * BLI_RCT_SIZE_Y(&v2d->cur);
+ dy = fac * BLI_rctf_size_y(&v2d->cur);
#if 0
/* continuous zoom shouldn't move that fast... */
if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop?
@@ -1161,17 +1161,17 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op)
/* TODO: is this zoom factor calculation valid? It seems to produce same results everytime... */
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) {
- size = BLI_RCT_SIZE_X(&cur_new);
- zoom = size / BLI_RCT_SIZE_X(&rect);
- center = BLI_RCT_CENTER_X(&cur_new);
+ size = BLI_rctf_size_x(&cur_new);
+ zoom = size / BLI_rctf_size_x(&rect);
+ center = BLI_rctf_cent_x(&cur_new);
cur_new.xmin = center - (size * zoom);
cur_new.xmax = center + (size * zoom);
}
if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) {
- size = BLI_RCT_SIZE_Y(&cur_new);
- zoom = size / BLI_RCT_SIZE_Y(&rect);
- center = BLI_RCT_CENTER_Y(&cur_new);
+ size = BLI_rctf_size_y(&cur_new);
+ zoom = size / BLI_rctf_size_y(&rect);
+ center = BLI_rctf_cent_y(&cur_new);
cur_new.ymin = center - (size * zoom);
cur_new.ymax = center + (size * zoom);
@@ -1221,14 +1221,14 @@ struct SmoothView2DStore {
*/
static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b)
{
- float size_a[2] = {BLI_RCT_SIZE_X(rect_a),
- BLI_RCT_SIZE_Y(rect_a)};
- float size_b[2] = {BLI_RCT_SIZE_X(rect_b),
- BLI_RCT_SIZE_Y(rect_b)};
- float cent_a[2] = {BLI_RCT_CENTER_X(rect_a),
- BLI_RCT_CENTER_Y(rect_a)};
- float cent_b[2] = {BLI_RCT_CENTER_X(rect_b),
- BLI_RCT_CENTER_Y(rect_b)};
+ float size_a[2] = {BLI_rctf_size_x(rect_a),
+ BLI_rctf_size_y(rect_a)};
+ float size_b[2] = {BLI_rctf_size_x(rect_b),
+ BLI_rctf_size_y(rect_b)};
+ float cent_a[2] = {BLI_rctf_cent_x(rect_a),
+ BLI_rctf_cent_y(rect_a)};
+ float cent_b[2] = {BLI_rctf_cent_x(rect_b),
+ BLI_rctf_cent_y(rect_b)};
float fac_max = 0.0f;
float tfac;
@@ -1501,8 +1501,8 @@ static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event,
if (in_scroller == 'h') {
/* horizontal scroller - calculate adjustment factor first */
- mask_size = (float)BLI_RCT_SIZE_X(&v2d->hor);
- vsm->fac = BLI_RCT_SIZE_X(&v2d->tot) / mask_size;
+ mask_size = (float)BLI_rcti_size_x(&v2d->hor);
+ vsm->fac = BLI_rctf_size_x(&v2d->tot) / mask_size;
/* get 'zone' (i.e. which part of scroller is activated) */
vsm->zone = mouse_in_scroller_handle(event->mval[0], v2d->hor.xmin, v2d->hor.xmax, scrollers->hor_min, scrollers->hor_max);
@@ -1517,8 +1517,8 @@ static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event,
}
else {
/* vertical scroller - calculate adjustment factor first */
- mask_size = (float)BLI_RCT_SIZE_Y(&v2d->vert);
- vsm->fac = BLI_RCT_SIZE_Y(&v2d->tot) / mask_size;
+ mask_size = (float)BLI_rcti_size_y(&v2d->vert);
+ vsm->fac = BLI_rctf_size_y(&v2d->tot) / mask_size;
/* get 'zone' (i.e. which part of scroller is activated) */
vsm->zone = mouse_in_scroller_handle(event->mval[1], v2d->vert.ymin, v2d->vert.ymax, scrollers->vert_min, scrollers->vert_max);
@@ -1798,8 +1798,8 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
int winx, winy;
/* zoom 1.0 */
- winx = (float)(BLI_RCT_SIZE_X(&v2d->mask) + 1);
- winy = (float)(BLI_RCT_SIZE_Y(&v2d->mask) + 1);
+ winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
+ winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
v2d->cur.xmax = v2d->cur.xmin + winx;
v2d->cur.ymax = v2d->cur.ymin + winy;
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 0e6b8f77528..0ec99325752 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -54,6 +54,8 @@
#include "../../collada/collada.h"
+#include "io_collada.h"
+
static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -121,32 +123,32 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
/* get editmode results */
ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */
- if (collada_export(
- CTX_data_scene(C),
- filepath,
- apply_modifiers,
- export_mesh_type,
- selected,
- include_children,
- include_armatures,
- deform_bones_only,
-
- active_uv_only,
- include_uv_textures,
- include_material_textures,
- use_texture_copies,
-
- use_object_instantiation,
- sort_by_name,
- second_life)) {
+ if (collada_export(CTX_data_scene(C),
+ filepath,
+ apply_modifiers,
+ export_mesh_type,
+ selected,
+ include_children,
+ include_armatures,
+ deform_bones_only,
+
+ active_uv_only,
+ include_uv_textures,
+ include_material_textures,
+ use_texture_copies,
+
+ use_object_instantiation,
+ sort_by_name,
+ second_life)) {
return OPERATOR_FINISHED;
}
else {
+ BKE_report(op->reports, RPT_WARNING, "Export file not created.");
return OPERATOR_CANCELLED;
}
}
-void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
+static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
{
uiLayout *box, *row, *col, *split;
@@ -233,7 +235,7 @@ void WM_OT_collada_export(wmOperatorType *ot)
ot->name = "Export COLLADA";
ot->description = "Save a Collada file";
ot->idname = "WM_OT_collada_export";
-
+
ot->invoke = wm_collada_export_invoke;
ot->exec = wm_collada_export_exec;
ot->poll = WM_operator_winactive;
@@ -241,7 +243,7 @@ void WM_OT_collada_export(wmOperatorType *ot)
ot->flag |= OPTYPE_PRESET;
ot->ui = wm_collada_export_draw;
-
+
WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
@@ -296,7 +298,7 @@ void WM_OT_collada_export(wmOperatorType *ot)
static int wm_collada_import_exec(bContext *C, wmOperator *op)
{
char filename[FILE_MAX];
-
+
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
return OPERATOR_CANCELLED;
@@ -304,9 +306,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", filename);
if (collada_import(C, filename)) return OPERATOR_FINISHED;
-
+
BKE_report(op->reports, RPT_ERROR, "Errors found during parsing COLLADA document. Please see console for error log.");
-
+
return OPERATOR_FINISHED;
}
@@ -315,11 +317,11 @@ void WM_OT_collada_import(wmOperatorType *ot)
ot->name = "Import COLLADA";
ot->description = "Load a Collada file";
ot->idname = "WM_OT_collada_import";
-
+
ot->invoke = WM_operator_filesel;
ot->exec = wm_collada_import_exec;
ot->poll = WM_operator_winactive;
-
+
WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
}
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 7fe1ac09df6..a254a6a9278 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -64,7 +64,7 @@ static int find_nearest_diff_point(const bContext *C, Mask *mask, const float no
MaskLayer *masklay, *point_masklay;
MaskSpline *point_spline;
MaskSplinePoint *point = NULL;
- float dist, co[2];
+ float dist = FLT_MAX, co[2];
int width, height;
float u;
float scalex, scaley;
@@ -125,7 +125,7 @@ static int find_nearest_diff_point(const bContext *C, Mask *mask, const float no
cur_dist = dist_to_line_segment_v2(co, a, b);
- if (point == NULL || cur_dist < dist) {
+ if (cur_dist < dist) {
if (tangent)
sub_v2_v2v2(tangent, &diff_points[2 * i + 2], &diff_points[2 * i]);
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 655458bd4cb..fe6567424b6 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -520,12 +520,12 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
- /* w = BLI_RCT_SIZE_X(&v2d->tot); */
- /* h = BLI_RCT_SIZE_Y(&v2d->tot);/*/
+ /* w = BLI_rctf_size_x(&v2d->tot); */
+ /* h = BLI_rctf_size_y(&v2d->tot);/*/
- zoomx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_X(&ar->v2d.cur));
- zoomy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_Y(&ar->v2d.cur));
+ zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / BLI_rctf_size_x(&ar->v2d.cur);
+ zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / BLI_rctf_size_y(&ar->v2d.cur);
if (do_scale_applied) {
zoomx /= width;
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 94e10b53b29..a677f1272a3 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -533,8 +533,8 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
unsigned int *rt;
char *selar;
int a, index;
- int sx = BLI_RCT_SIZE_X(rect) + 1;
- int sy = BLI_RCT_SIZE_Y(rect) + 1;
+ int sx = BLI_rcti_size_x(rect) + 1;
+ int sy = BLI_rcti_size_y(rect) + 1;
me = BKE_mesh_from_object(ob);
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 8b032bb1a3d..fdaddec5246 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -55,9 +55,9 @@
/* ********* add primitive operators ************* */
-static void make_prim_init(bContext *C, const char *idname,
- float *dia, float mat[][4],
- int *state, const float loc[3], const float rot[3], const unsigned int layer)
+static Object *make_prim_init(bContext *C, const char *idname,
+ float *dia, float mat[][4],
+ int *state, const float loc[3], const float rot[3], const unsigned int layer)
{
Object *obedit = CTX_data_edit_object(C);
@@ -74,11 +74,12 @@ static void make_prim_init(bContext *C, const char *idname,
}
*dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
+
+ return obedit;
}
-static void make_prim_finish(bContext *C, int *state, int enter_editmode)
+static void make_prim_finish(bContext *C, Object *obedit, int *state, int enter_editmode)
{
- Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
/* Primitive has all verts selected, use vert select flush
@@ -104,9 +105,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "vertout",
@@ -115,7 +114,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -148,9 +147,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_cube mat=%m4 size=%f", mat, dia * 2.0f)) {
@@ -158,7 +155,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
}
/* BMESH_TODO make plane side this: M_SQRT2 - plane (diameter of 1.41 makes it unit size) */
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -200,9 +197,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "vertout",
@@ -213,7 +208,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -257,9 +252,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- make_prim_init(C, "Cylinder", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Cylinder", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(
@@ -274,7 +267,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -320,9 +313,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- make_prim_init(C, "Cone", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Cone", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(
@@ -334,7 +325,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -379,9 +370,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "vertout",
@@ -393,7 +382,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -436,16 +425,14 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
if (!view_aligned)
rot[0] += (float)M_PI / 2.0f;
- make_prim_init(C, "Monkey", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Monkey", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_monkey mat=%m4", mat)) {
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -477,9 +464,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "vertout",
@@ -490,7 +475,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -531,9 +516,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- make_prim_init(C, "Icosphere", &dia, mat, &state, loc, rot, layer);
-
- obedit = CTX_data_edit_object(C);
+ obedit = make_prim_init(C, "Icosphere", &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(
@@ -545,7 +528,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, &state, enter_editmode);
+ make_prim_finish(C, obedit, &state, enter_editmode);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_bvh.c b/source/blender/editors/mesh/editmesh_bvh.c
index 0b7d396b696..c249d764ac1 100644
--- a/source/blender/editors/mesh/editmesh_bvh.c
+++ b/source/blender/editors/mesh/editmesh_bvh.c
@@ -309,7 +309,7 @@ static void vertsearchcallback(void *userdata, int index, const float *UNUSED(co
}
}
-BMVert *BMBVH_FindClosestVert(BMBVHTree *tree, const float co[3], float maxdist)
+BMVert *BMBVH_FindClosestVert(BMBVHTree *tree, const float co[3], const float maxdist)
{
BVHTreeNearest hit;
@@ -325,7 +325,7 @@ BMVert *BMBVH_FindClosestVert(BMBVHTree *tree, const float co[3], float maxdist)
float dist, curdist = tree->maxdist, v[3];
int cur = 0, i;
- maxdist = tree->maxdist;
+ /* maxdist = tree->maxdist; */ /* UNUSED */
for (i = 0; i < 3; i++) {
sub_v3_v3v3(v, hit.co, ls[i]->v->co);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 7ecfb712c18..1dcbf574b44 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -29,7 +29,9 @@
* \ingroup edmesh
*/
-#define _USE_MATH_DEFINES
+#ifdef _MSC_VER
+# define _USE_MATH_DEFINES
+#endif
#include "MEM_guardedalloc.h"
@@ -222,7 +224,7 @@ static void knife_update_header(bContext *C, KnifeTool_OpData *kcd)
static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3])
{
- ED_view3d_project_float_v3(kcd->ar, co, sco, kcd->projmat);
+ ED_view3d_project_float_v3_m4(kcd->ar, co, sco, kcd->projmat);
}
static void knife_pos_data_clear(KnifePosData *kpd)
@@ -1203,7 +1205,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
}
knife_project_v3(kcd, p, sp);
- view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
+ ED_view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
mul_m4_v3(kcd->ob->imat, view);
if (kcd->cut_through) {
@@ -1386,7 +1388,7 @@ static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2],
mval[1] = (float)mval_i[1];
/* unproject to find view ray */
- view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f);
+ ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f);
if (kcd->is_ortho) {
negate_v3_v3(r_ray, kcd->vc.rv3d->viewinv[2]);
@@ -1753,6 +1755,9 @@ static int knife_update_active(KnifeTool_OpData *kcd)
return 1;
}
+#define SCANFILL_CUTS 0
+#if SCANFILL_CUTS
+
#define MARK 4
#define DEL 8
#define VERT_ON_EDGE 16
@@ -1761,9 +1766,6 @@ static int knife_update_active(KnifeTool_OpData *kcd)
#define BOUNDARY 128
#define FACE_NEW 256
-#define SCANFILL_CUTS 0
-#if SCANFILL_CUTS
-
typedef struct facenet_entry {
struct facenet_entry *next, *prev;
KnifeEdge *kfe;
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 60c5244ddbc..8b13cc61d3e 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -29,7 +29,9 @@
*/
#include <float.h>
-#define _USE_MATH_DEFINES
+#ifdef _MSC_VER
+# define _USE_MATH_DEFINES
+#endif
#include <math.h>
#include <string.h>
#include <ctype.h>
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 4d4a890300f..53b877f2a6e 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -61,8 +61,8 @@ static float edbm_rip_rip_edgedist(ARegion *ar, float mat[][4],
{
float vec1[3], vec2[3];
- ED_view3d_project_float_v2(ar, co1, vec1, mat);
- ED_view3d_project_float_v2(ar, co2, vec2, mat);
+ ED_view3d_project_float_v2_m4(ar, co1, vec1, mat);
+ ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
/* TODO: use dist_squared_to_line_segment_v2() looks like we only ever use for comparison */
return dist_to_line_segment_v2(mvalf, vec1, vec2);
@@ -97,11 +97,11 @@ static float edbm_rip_edge_side_measure(BMEdge *e, BMLoop *e_l,
mid_v3_v3v3(cent, v1_other->co, v2_other->co);
mid_v3_v3v3(mid, e->v1->co, e->v2->co);
- ED_view3d_project_float_v2(ar, cent, cent, projectMat);
- ED_view3d_project_float_v2(ar, mid, mid, projectMat);
+ ED_view3d_project_float_v2_m4(ar, cent, cent, projectMat);
+ ED_view3d_project_float_v2_m4(ar, mid, mid, projectMat);
- ED_view3d_project_float_v2(ar, e->v1->co, e_v1_co, projectMat);
- ED_view3d_project_float_v2(ar, e->v2->co, e_v2_co, projectMat);
+ ED_view3d_project_float_v2_m4(ar, e->v1->co, e_v1_co, projectMat);
+ ED_view3d_project_float_v2_m4(ar, e->v2->co, e_v2_co, projectMat);
sub_v2_v2v2(vec, cent, mid);
normalize_v2(vec);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 81776ff7f4f..f6ae661a369 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -487,7 +487,6 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int
vec[0] = eed->v1->co[0] + labda * (eed->v2->co[0] - eed->v1->co[0]);
vec[1] = eed->v1->co[1] + labda * (eed->v2->co[1] - eed->v1->co[1]);
vec[2] = eed->v1->co[2] + labda * (eed->v2->co[2] - eed->v1->co[2]);
- mul_m4_v3(data->vc.obedit->obmat, vec);
if (ED_view3d_clipping_test(data->vc.rv3d, vec, TRUE) == 0) {
data->dist = distance;
@@ -531,7 +530,7 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, int *dist)
data.closest = NULL;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
+ mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_CLIP_TEST_REGION);
*dist = data.dist;
return data.closest;
@@ -691,6 +690,7 @@ static EnumPropertyItem prop_similar_types[] = {
{SIMEDGE_BEVEL, "BEVEL", 0, "Bevel", ""},
{SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
{SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
+ {SIMEDGE_FREESTYLE, "FREESTYLE_EDGE", 0, "Freestyle Edge Marks", ""},
{SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
{SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
@@ -698,6 +698,7 @@ static EnumPropertyItem prop_similar_types[] = {
{SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
{SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
{SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
+ {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -863,7 +864,7 @@ static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUS
}
}
else if (em->selectmode & SCE_SELECT_FACE) {
- for (a = SIMFACE_MATERIAL; a <= SIMFACE_COPLANAR; a++) {
+ for (a = SIMFACE_MATERIAL; a <= SIMFACE_FREESTYLE; a++) {
RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
}
}
@@ -1056,8 +1057,8 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring)
/* We can't be sure this has already been set... */
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
- project_float_noclip(vc.ar, eed->v1->co, v1_co);
- project_float_noclip(vc.ar, eed->v2->co, v2_co);
+ ED_view3d_project_float_noclip(vc.ar, eed->v1->co, v1_co);
+ ED_view3d_project_float_noclip(vc.ar, eed->v2->co, v2_co);
#if 0
printf("mouse to v1: %f\nmouse to v2: %f\n", len_squared_v2v2(mvalf, v1_co),
len_squared_v2v2(mvalf, v2_co));
@@ -1085,7 +1086,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring)
float co[2], tdist;
BM_face_calc_center_mean(f, cent);
- project_float_noclip(vc.ar, cent, co);
+ ED_view3d_project_float_noclip(vc.ar, cent, co);
tdist = len_squared_v2v2(mvalf, co);
if (tdist < best_dist) {
/* printf("Best face: %p (%f)\n", f, tdist);*/
@@ -1216,6 +1217,9 @@ static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val
case EDGE_MODE_TAG_SHARP:
BM_elem_flag_set(e, BM_ELEM_SMOOTH, !val);
break;
+ case EDGE_MODE_TAG_FREESTYLE:
+ BM_elem_flag_set(e, BM_ELEM_FREESTYLE, val);
+ break;
case EDGE_MODE_TAG_CREASE:
{
float *crease = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_CREASE);
@@ -1240,6 +1244,8 @@ static int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *e)
return BM_elem_flag_test(e, BM_ELEM_SEAM);
case EDGE_MODE_TAG_SHARP:
return !BM_elem_flag_test(e, BM_ELEM_SMOOTH);
+ case EDGE_MODE_TAG_FREESTYLE:
+ return !BM_elem_flag_test(e, BM_ELEM_FREESTYLE);
case EDGE_MODE_TAG_CREASE:
return BM_elem_float_data_get(&em->bm->edata, e, CD_CREASE) ? 1 : 0;
case EDGE_MODE_TAG_BEVEL:
@@ -1441,6 +1447,9 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2])
case EDGE_MODE_TAG_BEVEL:
me->drawflag |= ME_DRAWBWEIGHTS;
break;
+ case EDGE_MODE_TAG_FREESTYLE:
+ me->drawflag |= ME_DRAW_FREESTYLE_EDGE;
+ break;
}
EDBM_update_generic(C, em, FALSE);
diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c
index 86ea5bc8651..bd1d13f3528 100644
--- a/source/blender/editors/mesh/editmesh_slide.c
+++ b/source/blender/editors/mesh/editmesh_slide.c
@@ -388,10 +388,10 @@ static BMEdge *vtx_slide_nrst_in_frame(VertexSlideOp *vso, const float mval[2])
edge = vso->edge_frame[i];
mul_v3_m4v3(v1_proj, vso->obj->obmat, edge->v1->co);
- project_float_noclip(vso->active_region, v1_proj, v1_proj);
+ ED_view3d_project_float_noclip(vso->active_region, v1_proj, v1_proj);
mul_v3_m4v3(v2_proj, vso->obj->obmat, edge->v2->co);
- project_float_noclip(vso->active_region, v2_proj, v2_proj);
+ ED_view3d_project_float_noclip(vso->active_region, v2_proj, v2_proj);
dist = dist_to_line_segment_v2(mval, v1_proj, v2_proj);
if (dist < min_dist) {
@@ -455,10 +455,10 @@ static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event)
/* Project points onto screen and do interpolation in 2D */
mul_v3_m4v3(start_vtx_proj, vso->obj->obmat, vso->start_vtx->co);
- project_float_noclip(vso->active_region, start_vtx_proj, start_vtx_proj);
+ ED_view3d_project_float_noclip(vso->active_region, start_vtx_proj, start_vtx_proj);
mul_v3_m4v3(edge_other_proj, vso->obj->obmat, other->co);
- project_float_noclip(vso->active_region, edge_other_proj, edge_other_proj);
+ ED_view3d_project_float_noclip(vso->active_region, edge_other_proj, edge_other_proj);
closest_to_line_v2(closest_2d, mval_float, start_vtx_proj, edge_other_proj);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 546b28bfb25..7c700cc9731 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -163,7 +163,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, Object *obedit, BMEditMes
float mval[2], vec[3], no_dummy[3];
int dist_dummy;
mul_v3_m4v3(vec, obedit->obmat, eve->co);
- project_float_noclip(ar, vec, mval);
+ ED_view3d_project_float_noclip(ar, vec, mval);
if (snapObjectsContext(C, mval, &dist_dummy, vec, no_dummy, SNAP_NOT_OBEDIT)) {
mul_v3_m4v3(eve->co, obedit->imat, vec);
}
@@ -761,8 +761,8 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
float co1[3], co2[3];
mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
- project_float_noclip(vc.ar, co1, co1);
- project_float_noclip(vc.ar, co2, co2);
+ ED_view3d_project_float_noclip(vc.ar, co1, co1);
+ ED_view3d_project_float_noclip(vc.ar, co2, co2);
/* 2D rotate by 90d while adding.
* (x, y) = (y, -x)
@@ -2526,12 +2526,6 @@ void MESH_OT_solidify(wmOperatorType *ot)
RNA_def_property_ui_range(prop, -10, 10, 0.1, 4);
}
-#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
-#define TRAIL_FREEHAND 2
-#define TRAIL_MIXED 3 /* (1|2) */
-#define TRAIL_AUTO 4
-#define TRAIL_MIDPOINTS 8
-
typedef struct CutCurve {
float x;
float y;
@@ -2776,7 +2770,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
copy_v3_v3(co, bv->co);
co[3] = 1.0f;
mul_m4_v4(obedit->obmat, co);
- project_float(ar, co, scr);
+ ED_view3d_project_float(ar, co, scr);
BLI_ghash_insert(gh, bv, scr);
}
@@ -2858,9 +2852,6 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
Base *base_new;
- BMIter iter;
- BMVert *v;
- BMEdge *e;
Object *obedit = base_old->object;
BMesh *bm_new;
@@ -2886,15 +2877,10 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh
BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
"delete geom=%hvef context=%i", BM_ELEM_TAG, DEL_FACES);
- /* deselect loose data - this used to get deleted */
- BM_ITER_MESH (e, &iter, bm_old, BM_EDGES_OF_MESH) {
- BM_edge_select_set(bm_old, e, FALSE);
- }
-
- /* clean up any loose verts */
- BM_ITER_MESH (v, &iter, bm_old, BM_VERTS_OF_MESH) {
- BM_vert_select_set(bm_old, v, FALSE);
- }
+ /* deselect loose data - this used to get deleted,
+ * we could de-select edges and verts only, but this turns out to be less complicated
+ * since de-selecting all skips selection flushing logic */
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
BM_mesh_normals_update(bm_new, FALSE);
@@ -2908,7 +2894,10 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh
static int mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
- /* tag -> select */
+ /* we may have tags from previous operators */
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, FALSE);
+
+ /* sel -> tag */
BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, TRUE, BM_ELEM_SELECT);
return mesh_separate_tagged(bmain, scene, base_old, bm_old);
@@ -4721,7 +4710,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
mdiff[0] = opdata->mcenter[0] - event->mval[0];
mdiff[1] = opdata->mcenter[1] - event->mval[1];
- factor = -len_v2(mdiff) / opdata->initial_length + 1.0f;
+ factor = opdata->initial_length / -len_v2(mdiff) + 1.0f;
/* Fake shift-transform... */
if (event->shift) {
@@ -5085,9 +5074,9 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
mdiff[1] = opdata->mcenter[1] - event->mval[1];
if (opdata->modify_depth)
- amount = opdata->old_depth + len_v2(mdiff) / opdata->initial_length - 1.0f;
+ amount = opdata->old_depth + opdata->initial_length / len_v2(mdiff) - 1.0f;
else
- amount = opdata->old_thickness - len_v2(mdiff) / opdata->initial_length + 1.0f;
+ amount = opdata->old_thickness - opdata->initial_length / len_v2(mdiff) + 1.0f;
/* Fake shift-transform... */
if (opdata->shift)
@@ -5387,3 +5376,107 @@ void MESH_OT_convex_hull(wmOperatorType *ot)
join_triangle_props(ot);
}
+
+static int edbm_mark_freestyle_edge(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Mesh *me = ((Mesh *)obedit->data);
+ BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
+ BMEdge *eed;
+ BMIter iter;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ if (em == NULL) return OPERATOR_FINISHED;
+
+ /* auto-enable seams drawing */
+ if (clear == 0) {
+ me->drawflag |= ME_DRAW_FREESTYLE_EDGE;
+ }
+
+ if (clear) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN))
+ BM_elem_flag_disable(eed, BM_ELEM_FREESTYLE);
+ }
+ }
+ else {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN))
+ BM_elem_flag_enable(eed, BM_ELEM_FREESTYLE);
+ }
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Mark Freestyle Edge";
+ ot->description = "(un)mark selected edges as Freestyle feature edges";
+ ot->idname = "MESH_OT_mark_freestyle_edge";
+
+ /* api callbacks */
+ ot->exec = edbm_mark_freestyle_edge;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
+
+static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Mesh *me = ((Mesh *)obedit->data);
+ BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ if (em == NULL) return OPERATOR_FINISHED;
+
+ /* auto-enable Freestyle face mark drawing */
+ if(!clear) {
+ me->drawflag |= ME_DRAW_FREESTYLE_FACE;
+ }
+
+ if(clear) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ BM_elem_flag_disable(efa, BM_ELEM_FREESTYLE);
+ }
+ } else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ BM_elem_flag_enable(efa, BM_ELEM_FREESTYLE);
+ }
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Mark Freestyle Face";
+ ot->description = "(un)mark selected faces for exclusion from Freestyle feature edge detection";
+ ot->idname = "MESH_OT_mark_freestyle_face";
+
+ /* api callbacks */
+ ot->exec = edbm_mark_freestyle_face_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
+
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 03e2f2691a8..b844ba0baa2 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -535,6 +535,16 @@ static void *getEditMesh(bContext *C)
typedef struct UndoMesh {
Mesh me;
int selectmode;
+
+ /** \note
+ * this isn't a prefect solution, if you edit keys and change shapes this works well (fixing [#32442]),
+ * but editing shape keys, going into object mode, removing or changing their order,
+ * then go back into editmode and undo will give issues - where the old index will be out of sync
+ * with the new object index.
+ *
+ * There are a few ways this could be made to work but for now its a known limitation with mixing
+ * object and editmode operations - Campbell */
+ int shapenr;
} UndoMesh;
/* undo simply makes copies of a bmesh */
@@ -546,13 +556,14 @@ static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
UndoMesh *um = MEM_callocN(sizeof(UndoMesh), "undo Mesh");
/* make sure shape keys work */
- um->me.key = obme->key ? copy_key_nolib(obme->key) : NULL;
+ um->me.key = obme->key ? BKE_key_copy_nolib(obme->key) : NULL;
/* BM_mesh_validate(em->bm); */ /* for troubleshooting */
BM_mesh_bm_to_me(em->bm, &um->me, FALSE);
um->selectmode = em->selectmode;
+ um->shapenr = em->bm->shapenr;
return um;
}
@@ -564,7 +575,7 @@ static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *UNUSED(obdata))
UndoMesh *um = umv;
BMesh *bm;
- ob->shapenr = em->bm->shapenr;
+ ob->shapenr = em->bm->shapenr = um->shapenr;
EDBM_mesh_free(em);
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 09d89a961e4..a52c8d47ecd 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -47,6 +47,8 @@
#include "BLI_array.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
+#include "BLI_linklist.h"
+#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
@@ -74,6 +76,64 @@
#include "mesh_intern.h"
+static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_tot)
+{
+ CustomData *data;
+ BMesh *bm = (me->edit_btmesh) ? me->edit_btmesh->bm : NULL;
+ int tot;
+
+ /* this */
+ switch (htype) {
+ case BM_VERT:
+ if (bm) {
+ data = &bm->vdata;
+ tot = bm->totvert;
+ }
+ else {
+ data = &me->vdata;
+ tot = me->totvert;
+ }
+ break;
+ case BM_EDGE:
+ if (bm) {
+ data = &bm->edata;
+ tot = bm->totedge;
+ }
+ else {
+ data = &me->edata;
+ tot = me->totedge;
+ }
+ break;
+ case BM_LOOP:
+ if (bm) {
+ data = &bm->ldata;
+ tot = bm->totloop;
+ }
+ else {
+ data = &me->ldata;
+ tot = me->totloop;
+ }
+ break;
+ case BM_FACE:
+ if (bm) {
+ data = &bm->pdata;
+ tot = bm->totface;
+ }
+ else {
+ data = &me->pdata;
+ tot = me->totpoly;
+ }
+ break;
+ default:
+ BLI_assert(0);
+ tot = 0;
+ data = NULL;
+ }
+
+ *r_tot = tot;
+ return data;
+}
+
#define GET_CD_DATA(me, data) (me->edit_btmesh ? &me->edit_btmesh->bm->data : &me->data)
static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
{
@@ -85,24 +145,10 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
int i, actindex, rndindex, cloneindex, stencilindex, tot;
if (layer->type == CD_MLOOPCOL || layer->type == CD_MLOOPUV) {
- if (me->edit_btmesh) {
- data = &me->edit_btmesh->bm->ldata;
- tot = me->edit_btmesh->bm->totloop;
- }
- else {
- data = &me->ldata;
- tot = me->totloop;
- }
+ data = mesh_customdata_get_type(me, BM_LOOP, &tot);
}
else {
- if (me->edit_btmesh) {
- data = &me->edit_btmesh->bm->pdata;
- tot = me->edit_btmesh->bm->totface;
- }
- else {
- data = &me->pdata;
- tot = me->totpoly;
- }
+ data = mesh_customdata_get_type(me, BM_FACE, &tot);
}
index = CustomData_get_layer_index(data, type);
@@ -701,22 +747,20 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/*********************** sticky operators ************************/
+/* *** CustomData clear functions, we need an operator for each *** */
-static int mesh_sticky_add_exec(bContext *C, wmOperator *UNUSED(op))
+static int mesh_customdata_clear_exec__internal(bContext *C,
+ char htype, int type)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Object *obedit = ED_object_context(C);
+ Mesh *me = obedit->data;
- /* why is this commented out? */
-#if 0
- if (me->msticky)
- return OPERATOR_CANCELLED;
-#endif
+ int tot;
+ CustomData *data = mesh_customdata_get_type(me, htype, &tot);
- RE_make_sticky(scene, v3d);
+ BLI_assert(CustomData_layertype_is_singleton(type) == TRUE);
+
+ CustomData_free_layers(data, type, tot);
DAG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
@@ -724,48 +768,79 @@ static int mesh_sticky_add_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void MESH_OT_sticky_add(wmOperatorType *ot)
+/* Clear Mask */
+static int mesh_customdata_clear_mask_poll(bContext *C)
+{
+ Object *ob = ED_object_context(C);
+ if (ob && ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ /* special case - can't run this if we're in sculpt mode */
+ if (ob->mode & OB_MODE_SCULPT) {
+ return FALSE;
+ }
+
+ if (me->id.lib == NULL) {
+ CustomData *data = GET_CD_DATA(me, vdata);
+ if (CustomData_has_layer(data, CD_PAINT_MASK)) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_PAINT_MASK);
+}
+
+void MESH_OT_customdata_clear_mask(wmOperatorType *ot)
{
+
/* identifiers */
- ot->name = "Add Sticky";
- ot->description = "Add sticky UV texture layer";
- ot->idname = "MESH_OT_sticky_add";
-
+ ot->name = "Clear Sculpt-Mask Data";
+ ot->idname = "MESH_OT_customdata_clear_mask";
+ ot->description = "Clear vertex sculpt masking data from the mesh";
+
/* api callbacks */
- ot->poll = layers_poll;
- ot->exec = mesh_sticky_add_exec;
+ ot->exec = mesh_customdata_clear_mask_exec;
+ ot->poll = mesh_customdata_clear_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int mesh_sticky_remove_exec(bContext *C, wmOperator *UNUSED(op))
+/* Clear Skin */
+static int mesh_customdata_clear_skin_poll(bContext *C)
{
Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
- if (!me->msticky)
- return OPERATOR_CANCELLED;
-
- CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
- me->msticky = NULL;
-
- DAG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
-
- return OPERATOR_FINISHED;
+ if (ob && ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ if (me->id.lib == NULL) {
+ CustomData *data = GET_CD_DATA(me, vdata);
+ if (CustomData_has_layer(data, CD_MVERT_SKIN)) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+static int mesh_customdata_clear_skin_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN);
}
-void MESH_OT_sticky_remove(wmOperatorType *ot)
+void MESH_OT_customdata_clear_skin(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Sticky";
- ot->description = "Remove sticky UV texture layer";
- ot->idname = "MESH_OT_sticky_remove";
-
+ ot->name = "Clear Skin Data";
+ ot->idname = "MESH_OT_customdata_clear_skin";
+ ot->description = "Clear vertex skin layer";
+
/* api callbacks */
- ot->poll = layers_poll;
- ot->exec = mesh_sticky_remove_exec;
+ ot->exec = mesh_customdata_clear_skin_exec;
+ ot->poll = mesh_customdata_clear_skin_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 41666740730..b68c1836992 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -133,6 +133,7 @@ void MESH_OT_select_random(struct wmOperatorType *ot);
void MESH_OT_loop_multi_select(struct wmOperatorType *ot);
void MESH_OT_mark_seam(struct wmOperatorType *ot);
void MESH_OT_mark_sharp(struct wmOperatorType *ot);
+void MESH_OT_mark_freestyle_edge(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
void MESH_OT_noise(struct wmOperatorType *ot);
void MESH_OT_flip_normals(struct wmOperatorType *ot);
@@ -180,6 +181,7 @@ void MESH_OT_rip(struct wmOperatorType *ot);
void MESH_OT_shape_propagate_to_all(struct wmOperatorType *ot);
void MESH_OT_blend_from_shape(struct wmOperatorType *ot);
void MESH_OT_sort_elements(struct wmOperatorType *ot);
+void MESH_OT_mark_freestyle_face(struct wmOperatorType *ot);
/* ******************* mesh_data.c */
@@ -187,8 +189,10 @@ void MESH_OT_uv_texture_add(struct wmOperatorType *ot);
void MESH_OT_uv_texture_remove(struct wmOperatorType *ot);
void MESH_OT_vertex_color_add(struct wmOperatorType *ot);
void MESH_OT_vertex_color_remove(struct wmOperatorType *ot);
-void MESH_OT_sticky_add(struct wmOperatorType *ot);
-void MESH_OT_sticky_remove(struct wmOperatorType *ot);
+/* no create_mask yet */
+void MESH_OT_customdata_clear_mask(struct wmOperatorType *ot);
+void MESH_OT_customdata_clear_skin(struct wmOperatorType *ot);
+
void MESH_OT_drop_named_image(struct wmOperatorType *ot);
/* ************* bmesh_tools.c ***********/
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index dfa1beb614f..ccf91958e08 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -117,6 +117,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_faces_shade_smooth);
WM_operatortype_append(MESH_OT_faces_shade_flat);
WM_operatortype_append(MESH_OT_sort_elements);
+ WM_operatortype_append(MESH_OT_mark_freestyle_face);
WM_operatortype_append(MESH_OT_delete);
WM_operatortype_append(MESH_OT_edge_collapse);
@@ -131,10 +132,10 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_loop_multi_select);
WM_operatortype_append(MESH_OT_mark_seam);
WM_operatortype_append(MESH_OT_mark_sharp);
+ WM_operatortype_append(MESH_OT_mark_freestyle_edge);
WM_operatortype_append(MESH_OT_vertices_smooth);
WM_operatortype_append(MESH_OT_noise);
WM_operatortype_append(MESH_OT_flip_normals);
- //WM_operatortype_append(MESH_OT_knife_cut);
WM_operatortype_append(MESH_OT_rip);
WM_operatortype_append(MESH_OT_blend_from_shape);
WM_operatortype_append(MESH_OT_shape_propagate_to_all);
@@ -143,8 +144,8 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_uv_texture_remove);
WM_operatortype_append(MESH_OT_vertex_color_add);
WM_operatortype_append(MESH_OT_vertex_color_remove);
- WM_operatortype_append(MESH_OT_sticky_add);
- WM_operatortype_append(MESH_OT_sticky_remove);
+ WM_operatortype_append(MESH_OT_customdata_clear_mask);
+ WM_operatortype_append(MESH_OT_customdata_clear_skin);
WM_operatortype_append(MESH_OT_drop_named_image);
WM_operatortype_append(MESH_OT_edgering_select);
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index a7467ee4c79..f2b7a2e9c22 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -104,7 +104,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
MLoop *mloop = NULL;
Key *key, *nkey = NULL;
KeyBlock *kb, *okb, *kbn;
- float imat[4][4], cmat[4][4], *fp1, *fp2, curpos;
+ float imat[4][4], cmat[4][4], *fp1, *fp2;
int a, b, totcol, totmat = 0, totedge = 0, totvert = 0, ok = 0;
int totloop = 0, totpoly = 0, vertofs, *matmap = NULL;
int i, j, index, haskey = 0, edgeofs, loopofs, polyofs;
@@ -196,7 +196,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
else if (haskey) {
/* add a new key-block and add to the mesh */
- key = me->key = add_key((ID *)me);
+ key = me->key = BKE_key_add((ID *)me);
key->type = KEY_RELATIVE;
}
@@ -243,29 +243,29 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* if this mesh has shapekeys, check if destination mesh already has matching entries too */
if (me->key && key) {
- for (kb = me->key->block.first; kb; kb = kb->next) {
+ /* for remapping KeyBlock.relative */
+ int *index_map = MEM_mallocN(sizeof(int) * me->key->totkey, __func__);
+ KeyBlock **kb_map = MEM_mallocN(sizeof(KeyBlock *) * me->key->totkey, __func__);
+
+ for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
+ BLI_assert(i < me->key->totkey);
+
+ kbn = BKE_keyblock_find_name(key, kb->name);
/* if key doesn't exist in destination mesh, add it */
- if (key_get_named_keyblock(key, kb->name) == NULL) {
- /* copy this existing one over to the new shapekey block */
- kbn = MEM_dupallocN(kb);
- kbn->prev = kbn->next = NULL;
-
+ if (kbn) {
+ index_map[i] = BLI_findindex(&key->block, kbn);
+ }
+ else {
+ index_map[i] = key->totkey;
+
+ kbn = BKE_keyblock_add(key, kb->name);
+
+ BKE_keyblock_copy_settings(kbn, kb);
+
/* adjust settings to fit (allocate a new data-array) */
kbn->data = MEM_callocN(sizeof(float) * 3 * totvert, "joined_shapekey");
- kbn->totelem = totvert;
- kbn->weights = NULL;
-
- okb = key->block.last;
- curpos = (okb) ? okb->pos : -0.1f;
- if (key->type == KEY_RELATIVE)
- kbn->pos = curpos + 0.1f;
- else
- kbn->pos = curpos;
-
- BLI_addtail(&key->block, kbn);
- key->totkey++;
- if (key->totkey == 1) key->refkey = kbn;
-
+ kbn->totelem = totvert;
+
/* XXX 2.5 Animato */
#if 0
/* also, copy corresponding ipo-curve to ipo-block if applicable */
@@ -275,13 +275,26 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
#endif
}
+
+ kb_map[i] = kbn;
}
+
+ /* remap relative index values */
+ for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
+ if (LIKELY(kb->relative < me->key->totkey)) { /* sanity check, should always be true */
+ kb_map[i]->relative = index_map[kb->relative];
+ }
+ }
+
+ MEM_freeN(index_map);
+ MEM_freeN(kb_map);
}
}
}
}
CTX_DATA_END;
-
+
+
/* setup new data for destination mesh */
memset(&vdata, 0, sizeof(vdata));
memset(&edata, 0, sizeof(edata));
@@ -356,7 +369,8 @@ int join_mesh_exec(bContext *C, wmOperator *op)
fp1 = ((float *)kb->data) + (vertofs * 3);
/* check if this mesh has such a shapekey */
- okb = key_get_named_keyblock(me->key, kb->name);
+ okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
+
if (okb) {
/* copy this mesh's shapekey to the destination shapekey (need to transform first) */
fp2 = ((float *)(okb->data));
@@ -386,7 +400,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
fp1 = ((float *)kb->data) + (vertofs * 3);
/* check if this was one of the original shapekeys */
- okb = key_get_named_keyblock(nkey, kb->name);
+ okb = BKE_keyblock_find_name(nkey, kb->name);
if (okb) {
/* copy this mesh's shapekey to the destination shapekey */
fp2 = ((float *)(okb->data));
@@ -427,8 +441,8 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if ((mmd = get_multires_modifier(scene, base->object, TRUE))) {
ED_object_iter_other(bmain, base->object, TRUE,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
+ ED_object_multires_update_totlevels_cb,
+ &mmd->totlvl);
}
}
@@ -548,6 +562,12 @@ int join_mesh_exec(bContext *C, wmOperator *op)
MEM_freeN(nkey);
}
+ /* ensure newly inserted keys are time sorted */
+ if (key && (key->type != KEY_RELATIVE)) {
+ BKE_key_sort(key);
+ }
+
+
DAG_scene_sort(bmain, scene); // removed objects, need to rebuild dag before editmode call
#if 0
@@ -607,12 +627,12 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
}
if (key == NULL) {
- key = me->key = add_key((ID *)me);
+ key = me->key = BKE_key_add((ID *)me);
key->type = KEY_RELATIVE;
/* first key added, so it was the basis. initialize it with the existing mesh */
- kb = add_keyblock(key, NULL);
- mesh_to_key(me, kb);
+ kb = BKE_keyblock_add(key, NULL);
+ BKE_key_convert_from_mesh(me, kb);
}
/* now ready to add new keys from selected meshes */
@@ -628,7 +648,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
if (!dm) continue;
- kb = add_keyblock(key, base->object->id.name + 2);
+ kb = BKE_keyblock_add(key, base->object->id.name + 2);
DM_to_meshkey(dm, me, kb);
@@ -709,9 +729,9 @@ static void mesh_octree_add_nodes(MocNode **basetable, const float co[3], const
float fx, fy, fz;
int vx, vy, vz;
- if (!finite(co[0]) ||
- !finite(co[1]) ||
- !finite(co[2]))
+ if ((finite(co[0]) == FALSE) ||
+ (finite(co[1]) == FALSE) ||
+ (finite(co[2]) == FALSE))
{
return;
}
@@ -940,9 +960,9 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
intptr_t poinval;
/* ignore nan verts */
- if (!finite(co[0]) ||
- !finite(co[1]) ||
- !finite(co[2]))
+ if ((finite(co[0]) == FALSE) ||
+ (finite(co[1]) == FALSE) ||
+ (finite(co[2]) == FALSE))
{
return NULL;
}
@@ -1217,7 +1237,7 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2],
const int v_idx = me->mloop[mp->loopstart + fidx].v;
dm->getVertCo(dm, v_idx, co);
mul_m4_v3(ob->obmat, co);
- project_float_noclip(ar, co, sco);
+ ED_view3d_project_float_noclip(ar, co, sco);
len = len_squared_v2v2(mval_f, sco);
if (len < len_best) {
len_best = len;
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 50d5569c483..22ccd7bbed8 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -98,9 +98,8 @@ void load_editMball(Object *UNUSED(obedit))
}
/* Add metaelem primitive to metaball object (which is in edit mode) */
-MetaElem *add_metaball_primitive(bContext *C, float mat[4][4], int type, int UNUSED(newname))
+MetaElem *add_metaball_primitive(bContext *UNUSED(C), Object *obedit, float mat[4][4], int type, int UNUSED(newname))
{
- Object *obedit = CTX_data_edit_object(C);
MetaBall *mball = (MetaBall *)obedit->data;
MetaElem *ml;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index d73bbbabf84..4942b9e4390 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -439,7 +439,7 @@ static Object *effector_add_type(bContext *C, wmOperator *op, int type)
((Curve *)ob->data)->flag |= CU_PATH | CU_3D;
ED_object_enter_editmode(C, 0);
ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
- BLI_addtail(object_editcurve_get(ob), add_nurbs_primitive(C, mat, CU_NURBS | CU_PRIM_PATH, 1));
+ BLI_addtail(object_editcurve_get(ob), add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1));
if (!enter_editmode)
ED_object_exit_editmode(C, EM_FREEDATA);
@@ -574,7 +574,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
- /* elem= (MetaElem *) */ add_metaball_primitive(C, mat, RNA_enum_get(op->ptr, "type"), newob);
+ /* elem= (MetaElem *) */ add_metaball_primitive(C, obedit, mat, RNA_enum_get(op->ptr, "type"), newob);
/* userdef */
if (newob && !enter_editmode) {
@@ -1826,7 +1826,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
/* check if obdata is copied */
if (didit) {
- Key *key = ob_get_key(obn);
+ Key *key = BKE_key_from_object(obn);
if (dupflag & USER_DUP_ACT) {
bActuator *act;
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index f03cb312e3e..0ea2f78a415 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -1329,11 +1329,12 @@ static int test_bake_internal(bContext *C, ReportList *reports)
static void init_bake_internal(BakeRender *bkr, bContext *C)
{
Scene *scene = CTX_data_scene(C);
+ bScreen *sc = CTX_wm_screen(C);
/* get editmode results */
ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */
- bkr->sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_IMAGE, 10); /* can be NULL */
+ bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; /* can be NULL */
bkr->main = CTX_data_main(C);
bkr->scene = scene;
bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index aa885320b37..f95a186990e 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -649,11 +649,11 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
for (base = FIRSTBASE; base; base = base->next) {
if ((base != BASACT) && (TESTBASELIB(v3d, base))) {
if (nr == 1) { /* replace */
- copy_properties(&base->object->prop, &ob->prop);
+ BKE_bproperty_copy_list(&base->object->prop, &ob->prop);
}
else {
for (prop = ob->prop.first; prop; prop = prop->next) {
- set_ob_property(base->object, prop);
+ BKE_bproperty_object_set(base->object, prop);
}
}
}
@@ -665,7 +665,7 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
if (prop) {
for (base = FIRSTBASE; base; base = base->next) {
if ((base != BASACT) && (TESTBASELIB(v3d, base))) {
- set_ob_property(base->object, prop);
+ BKE_bproperty_object_set(base->object, prop);
}
}
}
@@ -1585,7 +1585,7 @@ static int game_property_new(bContext *C, wmOperator *op)
char name[MAX_NAME];
int type = RNA_enum_get(op->ptr, "type");
- prop = new_property(type);
+ prop = BKE_bproperty_new(type);
BLI_addtail(&ob->prop, prop);
RNA_string_get(op->ptr, "name", name);
@@ -1593,7 +1593,7 @@ static int game_property_new(bContext *C, wmOperator *op)
BLI_strncpy(prop->name, name, sizeof(prop->name));
}
- unique_property(NULL, prop, 0); // make_unique_prop_names(prop->name);
+ BKE_bproperty_unique(NULL, prop, 0); // make_unique_prop_names(prop->name);
WM_event_add_notifier(C, NC_LOGIC, NULL);
return OPERATOR_FINISHED;
@@ -1631,7 +1631,7 @@ static int game_property_remove(bContext *C, wmOperator *op)
if (prop) {
BLI_remlink(&ob->prop, prop);
- free_property(prop);
+ BKE_bproperty_free(prop);
WM_event_add_notifier(C, NC_LOGIC, NULL);
return OPERATOR_FINISHED;
@@ -1711,7 +1711,7 @@ static int game_property_copy_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
{
if (ob != ob_iter)
- set_ob_property(ob_iter, prop);
+ BKE_bproperty_object_set(ob_iter, prop);
} CTX_DATA_END;
}
}
@@ -1721,12 +1721,12 @@ static int game_property_copy_exec(bContext *C, wmOperator *op)
{
if (ob != ob_iter) {
if (type == COPY_PROPERTIES_REPLACE) {
- copy_properties(&ob_iter->prop, &ob->prop);
+ BKE_bproperty_copy_list(&ob_iter->prop, &ob->prop);
}
else {
/* merge - the default when calling with no argument */
for (prop = ob->prop.first; prop; prop = prop->next) {
- set_ob_property(ob_iter, prop);
+ BKE_bproperty_object_set(ob_iter, prop);
}
}
}
@@ -1763,7 +1763,7 @@ static int game_property_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
{
- free_properties(&ob_iter->prop);
+ BKE_bproperty_free_list(&ob_iter->prop);
}
CTX_DATA_END;
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 89f9f5de311..1f7be0bf9a6 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -92,9 +92,9 @@ void make_editLatt(Object *obedit)
free_editLatt(obedit);
- actkey = ob_get_keyblock(obedit);
+ actkey = BKE_keyblock_from_object(obedit);
if (actkey)
- key_to_latt(actkey, lt);
+ BKE_key_convert_to_lattice(actkey, lt);
lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt");
lt->editlatt->latt = MEM_dupallocN(lt);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 4858fdf1c35..6fe7ad05a70 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -565,15 +565,15 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M
}
if (key == NULL) {
- key = me->key = add_key((ID *)me);
+ key = me->key = BKE_key_add((ID *)me);
key->type = KEY_RELATIVE;
/* if that was the first key block added, then it was the basis.
* Initialize it with the mesh, and add another for the modifier */
- kb = add_keyblock(key, NULL);
- mesh_to_key(me, kb);
+ kb = BKE_keyblock_add(key, NULL);
+ BKE_key_convert_from_mesh(me, kb);
}
- kb = add_keyblock(key, md->name);
+ kb = BKE_keyblock_add(key, md->name);
DM_to_meshkey(dm, me, kb);
dm->release(dm);
@@ -1692,11 +1692,9 @@ static void skin_armature_bone_create(Object *skin_ob,
v = (e->v1 == parent_v ? e->v2 : e->v1);
- bone = MEM_callocN(sizeof(EditBone),
- "skin_armature_bone_create EditBone");
+ bone = ED_armature_edit_bone_add(arm, "Bone");
bone->parent = parent_bone;
- bone->layer = 1;
bone->flag |= BONE_CONNECTED;
copy_v3_v3(bone->head, mvert[parent_v].co);
@@ -1704,8 +1702,6 @@ static void skin_armature_bone_create(Object *skin_ob,
bone->rad_head = bone->rad_tail = 0.25;
BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
- BLI_addtail(arm->edbo, bone);
-
/* add bDeformGroup */
if ((dg = ED_vgroup_add_name(skin_ob, bone->name))) {
ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
@@ -1770,16 +1766,13 @@ static Object *modifier_skin_armature_create(struct Scene *scene,
* a fake root bone (have it going off in the Y direction
* (arbitrary) */
if (emap[v].count > 1) {
- bone = MEM_callocN(sizeof(EditBone), "EditBone");
+ bone = ED_armature_edit_bone_add(arm, "Bone");
copy_v3_v3(bone->head, me->mvert[v].co);
copy_v3_v3(bone->tail, me->mvert[v].co);
- bone->layer = 1;
bone->head[1] = 1.0f;
bone->rad_head = bone->rad_tail = 0.25;
-
- BLI_addtail(arm->edbo, bone);
}
if (emap[v].count >= 1) {
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 7eb8cc01db9..ff7f33f6107 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -723,7 +723,7 @@ static short objects_share_gameprop(Object *a, Object *b)
/*make a copy of all its properties*/
for (prop = a->prop.first; prop; prop = prop->next) {
- if (get_ob_property(b, prop->name) )
+ if (BKE_bproperty_object_get(b, prop->name) )
return 1;
}
return 0;
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 40b653a62fd..cfd4945688b 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -78,7 +78,7 @@ static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob, int f
{
KeyBlock *kb;
if ((kb = BKE_object_insert_shape_key(scene, ob, NULL, from_mix))) {
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
/* for absolute shape keys, new keys may not be added last */
ob->shapenr = BLI_findindex(&key->block, kb) + 1;
@@ -95,7 +95,7 @@ static int ED_object_shape_key_remove(bContext *C, Object *ob)
Key *key;
//IpoCurve *icu;
- key = ob_get_key(ob);
+ key = BKE_key_from_object(ob);
if (key == NULL)
return 0;
@@ -115,14 +115,14 @@ static int ED_object_shape_key_remove(bContext *C, Object *ob)
/* apply new basis key on original data */
switch (ob->type) {
case OB_MESH:
- key_to_mesh(key->refkey, ob->data);
+ BKE_key_convert_to_mesh(key->refkey, ob->data);
break;
case OB_CURVE:
case OB_SURF:
- key_to_curve(key->refkey, ob->data, BKE_curve_nurbs_get(ob->data));
+ BKE_key_convert_to_curve(key->refkey, ob->data, BKE_curve_nurbs_get(ob->data));
break;
case OB_LATTICE:
- key_to_latt(key->refkey, ob->data);
+ BKE_key_convert_to_lattice(key->refkey, ob->data);
break;
}
}
@@ -155,7 +155,7 @@ static int object_shape_key_mirror(bContext *C, Object *ob)
KeyBlock *kb;
Key *key;
- key = ob_get_key(ob);
+ key = BKE_key_from_object(ob);
if (key == NULL)
return 0;
@@ -323,8 +323,8 @@ void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- Key *key = ob_get_key(ob);
- KeyBlock *kb = ob_get_keyblock(ob);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
if (!key || !kb)
return OPERATOR_CANCELLED;
@@ -357,8 +357,8 @@ void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
static int shape_key_retime_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- Key *key = ob_get_key(ob);
- KeyBlock *kb = ob_get_keyblock(ob);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
float cfra = 0.0f;
if (!key || !kb)
@@ -419,7 +419,7 @@ static int shape_key_move_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_context(C);
int type = RNA_enum_get(op->ptr, "type");
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
if (key) {
KeyBlock *kb, *kb_other;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index b7ce32aa10a..72bbcda2b5e 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -409,7 +409,7 @@ static int key_test_depth(PEData *data, const float co[3])
if ((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0)
return 1;
- project_short(data->vc.ar, co, wco);
+ ED_view3d_project_short(data->vc.ar, co, wco);
if (wco[0] == IS_CLIPPED)
return 0;
@@ -447,7 +447,7 @@ static int key_inside_circle(PEData *data, float rad, const float co[3], float *
float dx, dy, dist;
int sco[2];
- project_int(data->vc.ar, co, sco);
+ ED_view3d_project_int(data->vc.ar, co, sco);
if (sco[0] == IS_CLIPPED)
return 0;
@@ -473,7 +473,7 @@ static int key_inside_rect(PEData *data, const float co[3])
{
int sco[2];
- project_int(data->vc.ar, co, sco);
+ ED_view3d_project_int(data->vc.ar, co, sco);
if (sco[0] == IS_CLIPPED)
return 0;
@@ -1666,7 +1666,7 @@ int PE_lasso_select(bContext *C, int mcords[][2], short moves, short extend, sho
LOOP_KEYS {
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
- project_int(ar, co, vertco);
+ ED_view3d_project_int(ar, co, vertco);
if (BLI_lasso_is_point_inside(mcords, moves, vertco[0], vertco[1], IS_CLIPPED) &&
key_test_depth(&data, co))
{
@@ -1686,7 +1686,7 @@ int PE_lasso_select(bContext *C, int mcords[][2], short moves, short extend, sho
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
- project_int(ar, co, vertco);
+ ED_view3d_project_int(ar, co, vertco);
if (BLI_lasso_is_point_inside(mcords, moves, vertco[0], vertco[1], IS_CLIPPED) &&
key_test_depth(&data, co))
{
@@ -2802,7 +2802,7 @@ static void brush_cut(PEData *data, int pa_index)
cut=0;
- project_int_noclip(ar, key->co, vertco);
+ ED_view3d_project_int_noclip(ar, key->co, vertco);
x0= (float)vertco[0];
x1= (float)vertco[1];
@@ -2820,7 +2820,7 @@ static void brush_cut(PEData *data, int pa_index)
else {
/* calculate path time closest to root that was inside the circle */
for (k=1, key++; k<=keys; k++, key++) {
- project_int_noclip(ar, key->co, vertco);
+ ED_view3d_project_int_noclip(ar, key->co, vertco);
if (key_test_depth(data, key->co) == 0) {
x0= (float)vertco[0];
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt
index 3c5fd0b4ef7..c9be7d0e5e0 100644
--- a/source/blender/editors/render/CMakeLists.txt
+++ b/source/blender/editors/render/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC
set(INC_SYS
${GLEW_INCLUDE_PATH}
+ ../../freestyle
)
set(SRC
diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript
index 0b19ecdab8e..9f769a68ecf 100644
--- a/source/blender/editors/render/SConscript
+++ b/source/blender/editors/render/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../gpu'
+incs += ' ../../gpu ../../freestyle'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
incs += ' ../../blenloader ../../bmesh'
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index 18ba2b5abf9..40d0c9536f4 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -53,6 +53,22 @@ void MATERIAL_OT_paste(struct wmOperatorType *ot);
void SCENE_OT_render_layer_add(struct wmOperatorType *ot);
void SCENE_OT_render_layer_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_move(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_copy(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_paste(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_move(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_linestyle_new(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_color_modifier_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_alpha_modifier_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_thickness_modifier_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_geometry_modifier_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_modifier_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_modifier_move(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_modifier_copy(struct wmOperatorType *ot);
void TEXTURE_OT_slot_copy(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index ebacac917e8..c08ea2b6429 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -80,7 +80,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
float *rectf = NULL;
int ymin, ymax, xmin, xmax;
int rymin, rxmin;
- unsigned char *rectc;
+ /* unsigned char *rectc; */ /* UNUSED */
/* if renrect argument, we only refresh scanlines */
if (renrect) {
@@ -124,8 +124,14 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
if (rr->rectf)
rectf = rr->rectf;
else {
- if (rr->rect32)
+ if (rr->rect32) {
+ /* special case, currently only happens with sequencer rendering,
+ * which updates the whole frame, so we can only mark display buffer
+ * as invalid here (sergey)
+ */
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
return;
+ }
else {
if (rr->renlay == NULL || rr->renlay->rectf == NULL) return;
rectf = rr->renlay->rectf;
@@ -137,7 +143,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
imb_addrectImBuf(ibuf);
rectf += 4 * (rr->rectx * ymin + xmin);
- rectc = (unsigned char *)(ibuf->rect + ibuf->x * rymin + rxmin);
+ /* rectc = (unsigned char *)(ibuf->rect + ibuf->x * rymin + rxmin); */ /* UNUSED */
IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin,
&scene->view_settings, &scene->display_settings,
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index c9e6dc90515..eb9a4cb30e4 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -62,6 +62,23 @@ void ED_operatortypes_render(void)
WM_operatortype_append(SCENE_OT_render_layer_add);
WM_operatortype_append(SCENE_OT_render_layer_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_module_add);
+ WM_operatortype_append(SCENE_OT_freestyle_module_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_module_move);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_add);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_copy);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_paste);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_move);
+ WM_operatortype_append(SCENE_OT_freestyle_linestyle_new);
+ WM_operatortype_append(SCENE_OT_freestyle_color_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_alpha_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_thickness_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_geometry_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_move);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_copy);
+
#if (defined(WITH_QUICKTIME) && !defined(USE_QTKIT))
WM_operatortype_append(SCENE_OT_render_data_set_quicktime_codec);
#endif
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index a829ef57b85..6b6018e51d2 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -485,8 +485,8 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
char name[32];
int do_gamma_correct = FALSE, do_predivide = FALSE;
int offx = 0;
- int newx = BLI_RCT_SIZE_X(rect);
- int newy = BLI_RCT_SIZE_Y(rect);
+ int newx = BLI_rcti_size_x(rect);
+ int newy = BLI_rcti_size_y(rect);
if (id && GS(id->name) != ID_TE) {
/* exception: don't color manage texture previews - show the raw values */
@@ -569,8 +569,8 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
SpaceButs *sbuts = sa->spacedata.first;
rcti newrect;
int ok;
- int newx = BLI_RCT_SIZE_X(rect);
- int newy = BLI_RCT_SIZE_Y(rect);
+ int newx = BLI_rcti_size_x(rect);
+ int newy = BLI_rcti_size_y(rect);
newrect.xmin = rect->xmin;
newrect.xmax = rect->xmin;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 8bdd4e544e8..b1b27e1424a 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -55,6 +55,7 @@
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
@@ -69,7 +70,10 @@
#include "GPU_material.h"
+#include "FRS_freestyle.h"
+
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -570,6 +574,617 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_add_module(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Freestyle Module";
+ ot->idname= "SCENE_OT_freestyle_module_add";
+ ot->description="Add a style module into the list of modules";
+
+ /* api callbacks */
+ ot->exec= freestyle_module_add_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module= ptr.data;
+
+ FRS_delete_module(&srl->freestyleConfig, module);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Freestyle Module";
+ ot->idname= "SCENE_OT_freestyle_module_remove";
+ ot->description="Remove the style module from the stack";
+
+ /* api callbacks */
+ ot->exec= freestyle_module_remove_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_module_move_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module= ptr.data;
+ int dir= RNA_enum_get(op->ptr, "direction");
+
+ if (dir == 1) {
+ FRS_move_module_up(&srl->freestyleConfig, module);
+ } else {
+ FRS_move_module_down(&srl->freestyleConfig, module);
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name= "Move Freestyle Module";
+ ot->idname= "SCENE_OT_freestyle_module_move";
+ ot->description="Change the position of the style module within in the list of style modules";
+
+ /* api callbacks */
+ ot->exec= freestyle_module_move_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
+static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_add_lineset(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Line Set";
+ ot->idname= "SCENE_OT_freestyle_lineset_add";
+ ot->description="Add a line set into the list of line sets";
+
+ /* api callbacks */
+ ot->exec= freestyle_lineset_add_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_active_lineset_poll(bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ return FRS_get_active_lineset(&srl->freestyleConfig) != NULL;
+}
+
+static int freestyle_lineset_copy_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_copy_active_lineset(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy Line Set";
+ ot->idname= "SCENE_OT_freestyle_lineset_copy";
+ ot->description="Copy the active line set to a buffer";
+
+ /* api callbacks */
+ ot->exec= freestyle_lineset_copy_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_lineset_paste_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_paste_active_lineset(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste Line Set";
+ ot->idname= "SCENE_OT_freestyle_lineset_paste";
+ ot->description="Paste the buffer content to the active line set";
+
+ /* api callbacks */
+ ot->exec= freestyle_lineset_paste_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_delete_active_lineset(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Line Set";
+ ot->idname= "SCENE_OT_freestyle_lineset_remove";
+ ot->description="Remove the active line set from the list of line sets";
+
+ /* api callbacks */
+ ot->exec= freestyle_lineset_remove_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ int dir= RNA_enum_get(op->ptr, "direction");
+
+ if (dir == 1) {
+ FRS_move_active_lineset_up(&srl->freestyleConfig);
+ } else {
+ FRS_move_active_lineset_down(&srl->freestyleConfig);
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name= "Move Line Set";
+ ot->idname= "SCENE_OT_freestyle_lineset_move";
+ ot->description="Change the position of the active line set within the list of line sets";
+
+ /* api callbacks */
+ ot->exec= freestyle_lineset_move_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
+static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig);
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to.");
+ return OPERATOR_CANCELLED;
+ }
+ lineset->linestyle->id.us--;
+ lineset->linestyle = FRS_copy_linestyle(lineset->linestyle);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "New Line Style";
+ ot->idname= "SCENE_OT_freestyle_linestyle_new";
+ ot->description="Create a new line style, reusable by multiple line sets";
+
+ /* api callbacks */
+ ot->exec= freestyle_linestyle_new_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig);
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to.");
+ return OPERATOR_CANCELLED;
+ }
+ if (FRS_add_linestyle_color_modifier(lineset->linestyle, type) < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type.");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Line Color Modifier";
+ ot->idname= "SCENE_OT_freestyle_color_modifier_add";
+ ot->description = "Add a line color modifier to the line style associated with the active lineset";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= freestyle_color_modifier_add_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop= RNA_def_enum(ot->srna, "type", linestyle_color_modifier_type_items, 0, "Type", "");
+}
+
+static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig);
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to.");
+ return OPERATOR_CANCELLED;
+ }
+ if (FRS_add_linestyle_alpha_modifier(lineset->linestyle, type) < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type.");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Alpha Transparency Modifier";
+ ot->idname= "SCENE_OT_freestyle_alpha_modifier_add";
+ ot->description = "Add an alpha transparency modifier to the line style associated with the active lineset";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= freestyle_alpha_modifier_add_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop= RNA_def_enum(ot->srna, "type", linestyle_alpha_modifier_type_items, 0, "Type", "");
+}
+
+static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig);
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to.");
+ return OPERATOR_CANCELLED;
+ }
+ if (FRS_add_linestyle_thickness_modifier(lineset->linestyle, type) < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type.");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Line Thickness Modifier";
+ ot->idname= "SCENE_OT_freestyle_thickness_modifier_add";
+ ot->description = "Add a line thickness modifier to the line style associated with the active lineset";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= freestyle_thickness_modifier_add_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop= RNA_def_enum(ot->srna, "type", linestyle_thickness_modifier_type_items, 0, "Type", "");
+}
+
+static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig);
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to.");
+ return OPERATOR_CANCELLED;
+ }
+ if (FRS_add_linestyle_geometry_modifier(lineset->linestyle, type) < 0) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type.");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Stroke Geometry Modifier";
+ ot->idname= "SCENE_OT_freestyle_geometry_modifier_add";
+ ot->description = "Add a stroke geometry modifier to the line style associated with the active lineset";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= freestyle_geometry_modifier_add_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop= RNA_def_enum(ot->srna, "type", linestyle_geometry_modifier_type_items, 0, "Type", "");
+}
+
+static int freestyle_get_modifier_type(PointerRNA *ptr)
+{
+ if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier))
+ return LS_MODIFIER_TYPE_COLOR;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier))
+ return LS_MODIFIER_TYPE_ALPHA;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier))
+ return LS_MODIFIER_TYPE_THICKNESS;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier))
+ return LS_MODIFIER_TYPE_GEOMETRY;
+ return -1;
+}
+
+static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier= ptr.data;
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to.");
+ return OPERATOR_CANCELLED;
+ }
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ FRS_remove_linestyle_color_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ FRS_remove_linestyle_alpha_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ FRS_remove_linestyle_thickness_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ FRS_remove_linestyle_geometry_modifier(lineset->linestyle, modifier);
+ break;
+ default:
+ BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier.");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Modifier";
+ ot->idname= "SCENE_OT_freestyle_modifier_remove";
+ ot->description="Remove the modifier from the list of modifiers";
+
+ /* api callbacks */
+ ot->exec= freestyle_modifier_remove_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier= ptr.data;
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to.");
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ FRS_copy_linestyle_color_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ FRS_copy_linestyle_alpha_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ FRS_copy_linestyle_thickness_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ FRS_copy_linestyle_geometry_modifier(lineset->linestyle, modifier);
+ break;
+ default:
+ BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier.");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+
+}
+
+void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy Modifier";
+ ot->idname= "SCENE_OT_freestyle_modifier_copy";
+ ot->description="Duplicate the modifier within the list of modifiers";
+
+ /* api callbacks */
+ ot->exec= freestyle_modifier_copy_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier= ptr.data;
+ int dir= RNA_enum_get(op->ptr, "direction");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to.");
+ return OPERATOR_CANCELLED;
+ }
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ FRS_move_linestyle_color_modifier(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ FRS_move_linestyle_alpha_modifier(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ FRS_move_linestyle_thickness_modifier(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ FRS_move_linestyle_geometry_modifier(lineset->linestyle, modifier, dir);
+ break;
+ default:
+ BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier.");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name= "Move Modifier";
+ ot->idname= "SCENE_OT_freestyle_modifier_move";
+ ot->description="Move the modifier within the list of modifiers";
+
+ /* api callbacks */
+ ot->exec= freestyle_modifier_move_exec;
+ ot->poll= freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
static int texture_slot_move(bContext *C, wmOperator *op)
{
ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 0bfe5d04e5e..d14514546f5 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -104,8 +104,8 @@ static void region_draw_emboss(ARegion *ar, rcti *scirct)
void ED_region_pixelspace(ARegion *ar)
{
- int width = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- int height = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ int width = BLI_rcti_size_x(&ar->winrct) + 1;
+ int height = BLI_rcti_size_y(&ar->winrct) + 1;
wmOrtho2(-GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS);
glLoadIdentity();
@@ -901,10 +901,10 @@ static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment)
static int rct_fits(rcti *rect, char dir, int size)
{
if (dir == 'h') {
- return BLI_RCT_SIZE_X(rect) - size;
+ return BLI_rcti_size_x(rect) - size;
}
else { /* 'v' */
- return BLI_RCT_SIZE_Y(rect) - size;
+ return BLI_rcti_size_y(rect) - size;
}
}
@@ -1010,7 +1010,7 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
if (alignment == RGN_ALIGN_HSPLIT) {
if (rct_fits(remainder, 'h', prefsizex) > 4) {
- ar->winrct.xmax = BLI_RCT_CENTER_X(remainder);
+ ar->winrct.xmax = BLI_rcti_cent_x(remainder);
remainder->xmin = ar->winrct.xmax + 1;
}
else {
@@ -1019,7 +1019,7 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
}
else {
if (rct_fits(remainder, 'v', prefsizey) > 4) {
- ar->winrct.ymax = BLI_RCT_CENTER_Y(remainder);
+ ar->winrct.ymax = BLI_rcti_cent_y(remainder);
remainder->ymin = ar->winrct.ymax + 1;
}
else {
@@ -1051,20 +1051,20 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
}
if (quad) {
if (quad == 1) { /* left bottom */
- ar->winrct.xmax = BLI_RCT_CENTER_X(remainder);
- ar->winrct.ymax = BLI_RCT_CENTER_Y(remainder);
+ ar->winrct.xmax = BLI_rcti_cent_x(remainder);
+ ar->winrct.ymax = BLI_rcti_cent_y(remainder);
}
else if (quad == 2) { /* left top */
- ar->winrct.xmax = BLI_RCT_CENTER_X(remainder);
- ar->winrct.ymin = BLI_RCT_CENTER_Y(remainder) + 1;
+ ar->winrct.xmax = BLI_rcti_cent_x(remainder);
+ ar->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
}
else if (quad == 3) { /* right bottom */
- ar->winrct.xmin = BLI_RCT_CENTER_X(remainder) + 1;
- ar->winrct.ymax = BLI_RCT_CENTER_Y(remainder);
+ ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
+ ar->winrct.ymax = BLI_rcti_cent_y(remainder);
}
else { /* right top */
- ar->winrct.xmin = BLI_RCT_CENTER_X(remainder) + 1;
- ar->winrct.ymin = BLI_RCT_CENTER_Y(remainder) + 1;
+ ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
+ ar->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
BLI_rcti_init(remainder, 0, 0, 0, 0);
}
@@ -1073,8 +1073,8 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
}
/* for speedup */
- ar->winx = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- ar->winy = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
+ ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
/* set winrect for azones */
if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
@@ -1096,8 +1096,8 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
if (ar->alignment & RGN_SPLIT_PREV) {
if (ar->prev) {
remainder = remainder_prev;
- ar->prev->winx = BLI_RCT_SIZE_X(&ar->prev->winrct) + 1;
- ar->prev->winy = BLI_RCT_SIZE_Y(&ar->prev->winrct) + 1;
+ ar->prev->winx = BLI_rcti_size_x(&ar->prev->winrct) + 1;
+ ar->prev->winy = BLI_rcti_size_y(&ar->prev->winrct) + 1;
}
}
@@ -1133,8 +1133,8 @@ static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
else sa->totrct.ymax = sa->v2->vec.y;
/* for speedup */
- sa->winx = BLI_RCT_SIZE_X(&sa->totrct) + 1;
- sa->winy = BLI_RCT_SIZE_Y(&sa->totrct) + 1;
+ sa->winx = BLI_rcti_size_x(&sa->totrct) + 1;
+ sa->winy = BLI_rcti_size_y(&sa->totrct) + 1;
}
@@ -1268,8 +1268,8 @@ void ED_region_init(bContext *C, ARegion *ar)
/* refresh can be called before window opened */
region_subwindow(CTX_wm_window(C), ar);
- ar->winx = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- ar->winy = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
+ ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
/* UI convention */
wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
@@ -1574,7 +1574,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
newcontext = UI_view2d_tab_set(v2d, contextnr);
if (vertical) {
- w = BLI_RCT_SIZE_X(&v2d->cur);
+ w = BLI_rctf_size_x(&v2d->cur);
em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
}
else {
@@ -1769,7 +1769,7 @@ void ED_region_header(const bContext *C, ARegion *ar)
}
/* always as last */
- UI_view2d_totRect_set(&ar->v2d, maxco + UI_UNIT_X + 80, BLI_RCT_SIZE_Y(&ar->v2d.tot));
+ UI_view2d_totRect_set(&ar->v2d, maxco + UI_UNIT_X + 80, BLI_rctf_size_y(&ar->v2d.tot));
/* restore view matrix? */
UI_view2d_view_restore(C);
@@ -1798,16 +1798,16 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha)
/* background box */
rect = ar->winrct;
rect.xmin = 0;
- rect.ymin = BLI_RCT_SIZE_Y(&ar->winrct) - header_height;
+ rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height;
if (block) {
- rect.xmax = BLI_RCT_SIZE_X(&ar->winrct);
+ rect.xmax = BLI_rcti_size_x(&ar->winrct);
}
else {
rect.xmax = rect.xmin + BLF_width(fontid, text) + 24;
}
- rect.ymax = BLI_RCT_SIZE_Y(&ar->winrct);
+ rect.ymax = BLI_rcti_size_y(&ar->winrct);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index c93f4156eeb..24053d76672 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -669,8 +669,8 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
void glaDefine2DArea(rcti *screen_rect)
{
- const int sc_w = BLI_RCT_SIZE_X(screen_rect) + 1;
- const int sc_h = BLI_RCT_SIZE_Y(screen_rect) + 1;
+ const int sc_w = BLI_rcti_size_x(screen_rect) + 1;
+ const int sc_h = BLI_rcti_size_y(screen_rect) + 1;
glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h);
@@ -714,10 +714,10 @@ void gla2DSetMap(gla2DDrawInfo *di, rctf *rect)
di->world_rect = *rect;
- sc_w = BLI_RCT_SIZE_X(&di->screen_rect);
- sc_h = BLI_RCT_SIZE_Y(&di->screen_rect);
- wo_w = BLI_RCT_SIZE_X(&di->world_rect);
- wo_h = BLI_RCT_SIZE_Y(&di->world_rect);
+ sc_w = BLI_rcti_size_x(&di->screen_rect);
+ sc_h = BLI_rcti_size_y(&di->screen_rect);
+ wo_w = BLI_rcti_size_x(&di->world_rect);
+ wo_h = BLI_rcti_size_y(&di->world_rect);
di->wo_to_sc[0] = sc_w / wo_w;
di->wo_to_sc[1] = sc_h / wo_h;
@@ -745,10 +745,10 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
di->world_rect.ymax = di->screen_rect.ymax;
}
- sc_w = BLI_RCT_SIZE_X(&di->screen_rect);
- sc_h = BLI_RCT_SIZE_Y(&di->screen_rect);
- wo_w = BLI_RCT_SIZE_X(&di->world_rect);
- wo_h = BLI_RCT_SIZE_Y(&di->world_rect);
+ sc_w = BLI_rcti_size_x(&di->screen_rect);
+ sc_h = BLI_rcti_size_y(&di->screen_rect);
+ wo_w = BLI_rcti_size_x(&di->world_rect);
+ wo_h = BLI_rcti_size_y(&di->world_rect);
di->wo_to_sc[0] = sc_w / wo_w;
di->wo_to_sc[1] = sc_h / wo_h;
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 11d32e11cd0..2e1723027b8 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -40,6 +40,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -704,10 +705,6 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
/* *********************** DRAWING **************************************** */
-
-#define SCR_BACK 0.55
-#define SCR_ROUND 12
-
/* draw vertical shape visualizing future joining (left as well
* right direction of future joining) */
static void draw_horizontal_join_shape(ScrArea *sa, char dir)
@@ -1506,6 +1503,7 @@ void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene)
CTX_data_scene_set(C, scene);
BKE_scene_set_background(bmain, scene);
+ DAG_on_visible_update(bmain, FALSE);
ED_render_engine_changed(bmain);
ED_update_for_newframe(bmain, scene, 1);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 50a210e5d7c..c64a4a37f3a 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -372,6 +372,21 @@ int ED_operator_posemode_exclusive(bContext *C)
return 0;
}
+/* allows for pinned pose objects to be used in the object buttons
+ * and the the non-active pose object to be used in the 3D view */
+int ED_operator_posemode_context(bContext *C)
+{
+ Object *obpose = ED_pose_object_from_context(C);
+
+ if (obpose && !(obpose->mode & OB_MODE_EDIT)) {
+ if (BKE_object_pose_context_check(obpose)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
int ED_operator_posemode(bContext *C)
{
Object *obact = CTX_data_active_object(C);
@@ -1196,9 +1211,6 @@ static void SCREEN_OT_area_move(wmOperatorType *ot)
* call exit() or cancel() and remove handler
*/
-#define SPLIT_STARTED 1
-#define SPLIT_PROGRESS 2
-
typedef struct sAreaSplitData {
int x, y; /* last used mouse position */
@@ -1635,10 +1647,10 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
int dist;
if (edge == AE_RIGHT_TO_TOPLEFT || edge == AE_LEFT_TO_TOPRIGHT) {
- dist = BLI_RCT_SIZE_X(&sa->totrct);
+ dist = BLI_rcti_size_x(&sa->totrct);
}
else { /* AE_BOTTOM_TO_TOPLEFT, AE_TOP_TO_BOTTOMRIGHT */
- dist = BLI_RCT_SIZE_Y(&sa->totrct);
+ dist = BLI_rcti_size_y(&sa->totrct);
}
/* subtractwidth of regions on opposite side
@@ -2850,35 +2862,40 @@ static void SCREEN_OT_header_flip(wmOperatorType *ot)
}
/* ************** header tools operator ***************************** */
-
-static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- uiPopupMenu *pup;
- uiLayout *layout;
-
- pup = uiPupMenuBegin(C, "Header", ICON_NONE);
- layout = uiPupMenuLayout(pup);
-
- // XXX SCREEN_OT_region_flip doesn't work - gets wrong context for active region, so added custom operator
+
+ /* XXX SCREEN_OT_region_flip doesn't work - gets wrong context for active region, so added custom operator. */
if (ar->alignment == RGN_ALIGN_TOP)
- uiItemO(layout, "Flip to Bottom", ICON_NONE, "SCREEN_OT_header_flip");
+ uiItemO(layout, IFACE_("Flip to Bottom"), ICON_NONE, "SCREEN_OT_header_flip");
else
- uiItemO(layout, "Flip to Top", ICON_NONE, "SCREEN_OT_header_flip");
-
+ uiItemO(layout, IFACE_("Flip to Top"), ICON_NONE, "SCREEN_OT_header_flip");
+
uiItemS(layout);
-
+
/* file browser should be fullscreen all the time, but other regions can be maximized/restored... */
if (sa->spacetype != SPACE_FILE) {
if (sa->full)
- uiItemO(layout, "Tile Area", ICON_NONE, "SCREEN_OT_screen_full_area");
+ uiItemO(layout, IFACE_("Tile Area"), ICON_NONE, "SCREEN_OT_screen_full_area");
else
- uiItemO(layout, "Maximize Area", ICON_NONE, "SCREEN_OT_screen_full_area");
+ uiItemO(layout, IFACE_("Maximize Area"), ICON_NONE, "SCREEN_OT_screen_full_area");
}
-
+}
+
+static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+{
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ pup = uiPupMenuBegin(C, N_("Header"), ICON_NONE);
+ layout = uiPupMenuLayout(pup);
+
+ ED_screens_header_tools_menu_create(C, layout, NULL);
+
uiPupMenuEnd(C, pup);
-
+
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 5e54119118a..aeae79aa9d0 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -149,8 +149,8 @@ static void screenshot_crop(ImBuf *ibuf, rcti crop)
{
unsigned int *to = ibuf->rect;
unsigned int *from = ibuf->rect + crop.ymin * ibuf->x + crop.xmin;
- int crop_x = BLI_RCT_SIZE_X(&crop);
- int crop_y = BLI_RCT_SIZE_Y(&crop);
+ int crop_x = BLI_rcti_size_x(&crop);
+ int crop_y = BLI_rcti_size_y(&crop);
int y;
if (crop_x > 0 && crop_y > 0) {
@@ -245,7 +245,7 @@ static void screenshot_draw(bContext *UNUSED(C), wmOperator *op)
/* image template */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr);
- uiTemplateImageSettings(layout, &ptr, TRUE);
+ uiTemplateImageSettings(layout, &ptr, FALSE);
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 8616d4e66eb..e14266c83a7 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -322,8 +322,8 @@ static int project_brush_radius(ViewContext *vc,
add_v3_v3v3(offset, location, ortho);
/* project the center of the brush, and the tangent point to the view onto the screen */
- project_float(vc->ar, location, p1);
- project_float(vc->ar, offset, p2);
+ ED_view3d_project_float(vc->ar, location, p1);
+ ED_view3d_project_float(vc->ar, offset, p2);
/* the distance between these points is the size of the projected brush in pixels */
return len_v2v2(p1, p2);
@@ -441,8 +441,8 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush,
else {
quad.xmin = 0;
quad.ymin = 0;
- quad.xmax = BLI_RCT_SIZE_X(&vc->ar->winrct);
- quad.ymax = BLI_RCT_SIZE_Y(&vc->ar->winrct);
+ quad.xmax = BLI_rcti_size_x(&vc->ar->winrct);
+ quad.ymax = BLI_rcti_size_y(&vc->ar->winrct);
}
/* set quad color */
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index e809267d076..2970bdfb5a4 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -251,7 +251,7 @@ static void clip_planes_from_rect(bContext *C,
view3d_operator_needs_opengl(C);
view3d_set_viewcontext(C, &vc);
view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats);
- ED_view3d_calc_clipping(&bb, clip_planes, &mats, rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, &mats, rect);
mul_m4_fl(clip_planes, -1.0f);
}
@@ -388,7 +388,7 @@ void PAINT_OT_hide_show(struct wmOperatorType *ot)
ot->modal = WM_border_select_modal;
ot->exec = hide_show_exec;
/* sculpt-only for now */
- ot->poll = sculpt_mode_poll;
+ ot->poll = sculpt_mode_poll_view3d;
ot->flag = OPTYPE_REGISTER;
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 64430a263f0..b8e365c4c8e 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -240,8 +240,6 @@ typedef struct ImagePaintRegion {
/* vert flags */
#define PROJ_VERT_CULL 1
-#define PI_80_DEG ((M_PI_2 / 9) * 8)
-
/* This is mainly a convenience struct used so we can keep an array of images we use
* Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
* because 'partRedrawRect' and 'touch' values would not be thread safe */
@@ -3138,7 +3136,7 @@ static void project_paint_begin(ProjPaintState *ps)
ps->is_ortho = params.is_ortho;
}
- /* same as view3d_get_object_project_mat */
+ /* same as #ED_view3d_ob_project_mat_get */
mult_m4_m4m4(vmat, viewmat, ps->ob->obmat);
mult_m4_m4m4(ps->projectMat, winmat, vmat);
}
@@ -4265,7 +4263,7 @@ static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image,
int w = imapaintpartial.x2 - imapaintpartial.x1;
int h = imapaintpartial.y2 - imapaintpartial.y1;
/* Testing with partial update in uv editor too */
- GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h, 0); //!texpaint);
+ GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint);
}
}
@@ -4596,10 +4594,13 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter,
{
ImBuf *ibuf = BKE_image_get_ibuf(image, s->sima ? &s->sima->iuser : NULL);
float pos[2];
+ int is_data;
if (!ibuf)
return 0;
+ is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
+
pos[0] = uv[0] * ibuf->x;
pos[1] = uv[1] * ibuf->y;
@@ -4608,7 +4609,7 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter,
/* OCIO_TODO: float buffers are now always linear, so always use color correction
* this should probably be changed when texture painting color space is supported
*/
- if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, TRUE)) {
+ if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) {
if (update)
imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint);
return 1;
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 7657f78596a..7fabaf7f23d 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -524,8 +524,10 @@ int paint_poll(bContext *C)
{
Paint *p = paint_get_active_from_context(C);
Object *ob = CTX_data_active_object(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
return p && ob && paint_brush(p) &&
- CTX_wm_area(C)->spacetype == SPACE_VIEW3D &&
- CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW;
+ (sa && sa->spacetype == SPACE_VIEW3D) &&
+ (ar && ar->regiontype == RGN_TYPE_WINDOW);
}
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index df64e1c9d90..29a59651cf7 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -98,7 +98,7 @@ int paint_convert_bb_to_rect(rcti *rect,
vec[1] = j ? bb_min[1] : bb_max[1];
vec[2] = k ? bb_min[2] : bb_max[2];
/* convert corner to screen space */
- ED_view3d_project_float_v2(ar, vec, proj, projection_mat);
+ ED_view3d_project_float_v2_m4(ar, vec, proj, projection_mat);
/* expand 2D rectangle */
/* we could project directly to int? */
@@ -137,7 +137,7 @@ void paint_calc_redraw_planes(float planes[4][4],
rect.ymin -= 2;
rect.ymax += 2;
- ED_view3d_calc_clipping(&bb, planes, &mats, &rect);
+ ED_view3d_clipping_calc(&bb, planes, &mats, &rect);
mul_m4_fl(planes, -1.0f);
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index fd5044afc44..8aed92df3af 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -134,7 +134,7 @@ int vertex_paint_poll(bContext *C)
paint_brush(&CTX_data_tool_settings(C)->vpaint->paint))
{
ScrArea *sa = CTX_wm_area(C);
- if (sa->spacetype == SPACE_VIEW3D) {
+ if (sa && sa->spacetype == SPACE_VIEW3D) {
ARegion *ar = CTX_wm_region(C);
if (ar->regiontype == RGN_TYPE_WINDOW)
return 1;
@@ -850,7 +850,7 @@ static float calc_vp_strength_dl(VPaint *vp, ViewContext *vc, const float vert_n
float dist_squared;
float vertco[2], delta[2];
- project_float_noclip(vc->ar, vert_nor, vertco);
+ ED_view3d_project_float_noclip(vc->ar, vert_nor, vertco);
sub_v2_v2v2(delta, mval, vertco);
dist_squared = dot_v2v2(delta, delta); /* len squared */
if (dist_squared > brush_size_pressure * brush_size_pressure) {
@@ -2227,19 +2227,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if (indexar[0]) totindex = 1;
else totindex = 0;
}
-
- if (wp->flag & VP_COLINDEX) {
- for (index = 0; index < totindex; index++) {
- if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
-
- if (mpoly->mat_nr != ob->actcol - 1) {
- indexar[index] = 0;
- }
- }
- }
- }
-
+
if ((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
for (index = 0; index < totindex; index++) {
if (indexar[index] && indexar[index] <= me->totpoly) {
@@ -2639,52 +2627,13 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl
return 1;
}
-#if 0
-static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob,
- const unsigned int index, const float mval[2],
- const float brush_size_pressure, const float brush_alpha_pressure,
- int UNUSED(flip))
+static void copy_lcol_to_mcol(MCol *mcol, const MLoopCol *lcol)
{
- ViewContext *vc = &vpd->vc;
- Brush *brush = paint_brush(&vp->paint);
- Mesh *me = BKE_mesh_from_object(ob);
- MFace *mface = &me->mface[index];
- unsigned int *mcol = ((unsigned int *)me->mcol) + 4 * index;
- unsigned int *mcolorig = ((unsigned int *)vp->vpaint_prev) + 4 * index;
- float alpha;
- int i;
-
- int brush_alpha_pressure_i;
-
- if ((vp->flag & VP_COLINDEX && mface->mat_nr != ob->actcol - 1) ||
- ((me->editflag & ME_EDIT_PAINT_MASK) && !(mface->flag & ME_FACE_SEL)))
- return;
-
- if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
- unsigned int fcol1 = mcol_blend(mcol[0], mcol[1], 128);
- if (mface->v4) {
- unsigned int fcol2 = mcol_blend(mcol[2], mcol[3], 128);
- vpd->paintcol = mcol_blend(fcol1, fcol2, 128);
- }
- else {
- vpd->paintcol = mcol_blend(mcol[2], fcol1, 170);
- }
- }
-
- brush_alpha_pressure_i = (int)(brush_alpha_pressure * 255.0f);
-
- for (i = 0; i < (mface->v4 ? 4 : 3); ++i) {
- alpha = calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos + 6 * (&mface->v1)[i],
- mval, brush_size_pressure, brush_alpha_pressure);
- if (alpha) {
- const int alpha_i = (int)(alpha * 255.0f);
- mcol[i] = vpaint_blend(vp, mcol[i], mcolorig[i], vpd->paintcol, alpha_i, brush_alpha_pressure_i);
- }
- }
+ mcol->a = lcol->a;
+ mcol->r = lcol->r;
+ mcol->g = lcol->g;
+ mcol->b = lcol->b;
}
-#endif
-
-/* BMESH version of vpaint_paint_face (commented above) */
static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Object *ob,
const unsigned int index, const float mval[2],
@@ -2744,33 +2693,22 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Object *ob,
}
if (vpd->use_fast_update) {
-
-#ifdef CPYCOL
-# undef CPYCOL
-#endif
-#define CPYCOL(c, l) (c)->a = (l)->a, (c)->r = (l)->r, (c)->g = (l)->g, (c)->b = (l)->b
-
/* update vertex colors for tessellations incrementally,
* rather then regenerating the tessellation altogether */
for (e = vpd->polyfacemap[index].first; e; e = e->next) {
- mf = me->mface + e->facenr;
- mc = me->mcol + e->facenr * 4;
+ mf = &me->mface[e->facenr];
+ mc = &me->mcol[e->facenr * 4];
ml = me->mloop + mpoly->loopstart;
mlc = me->mloopcol + mpoly->loopstart;
for (j = 0; j < mpoly->totloop; j++, ml++, mlc++) {
- if (ml->v == mf->v1)
- CPYCOL(mc, mlc);
- else if (ml->v == mf->v2)
- CPYCOL(mc + 1, mlc);
- else if (ml->v == mf->v3)
- CPYCOL(mc + 2, mlc);
- else if (mf->v4 && ml->v == mf->v4)
- CPYCOL(mc + 3, mlc);
+ if (ml->v == mf->v1) copy_lcol_to_mcol(mc + 0, mlc);
+ else if (ml->v == mf->v2) copy_lcol_to_mcol(mc + 1, mlc);
+ else if (ml->v == mf->v3) copy_lcol_to_mcol(mc + 2, mlc);
+ else if (mf->v4 && ml->v == mf->v4) copy_lcol_to_mcol(mc + 3, mlc);
}
}
-#undef CPYCOL
}
}
@@ -2804,7 +2742,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
mval[0] -= vc->ar->winrct.xmin;
mval[1] -= vc->ar->winrct.ymin;
-
+
/* which faces are involved */
if (vp->flag & VP_AREA) {
totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
@@ -2814,19 +2752,6 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if (indexar[0]) totindex = 1;
else totindex = 0;
}
-
-
- if (vp->flag & VP_COLINDEX) {
- for (index = 0; index < totindex; index++) {
- if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
-
- if (mpoly->mat_nr != ob->actcol - 1) {
- indexar[index] = 0;
- }
- }
- }
- }
if ((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
for (index = 0; index < totindex; index++) {
@@ -2835,15 +2760,13 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if ((mpoly->flag & ME_FACE_SEL) == 0)
indexar[index] = 0;
- }
+ }
}
}
swap_m4m4(vc->rv3d->persmat, mat);
-
for (index = 0; index < totindex; index++) {
-
if (indexar[index] && indexar[index] <= me->totpoly) {
vpaint_paint_poly(vp, vpd, ob, indexar[index] - 1, mval, brush_size_pressure, brush_alpha_pressure);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 210477e3e5a..05b5b90344c 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -771,7 +771,7 @@ static float tex_strength(SculptSession *ss, Brush *br, float point[3],
if (ss->cache->radial_symmetry_pass)
mul_m4_v3(ss->cache->symm_rot_mat_inv, symm_point);
- ED_view3d_project_float_v2(ss->cache->vc->ar, symm_point, point_2d, ss->cache->projection_mat);
+ ED_view3d_project_float_v2_m4(ss->cache->vc->ar, symm_point, point_2d, ss->cache->projection_mat);
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* keep coordinates relative to mouse */
@@ -2649,7 +2649,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
}
if (is_basis) {
- ofs = key_to_vertcos(ob, kb);
+ ofs = BKE_key_convert_to_vertcos(ob, kb);
/* calculate key coord offsets (from previous location) */
for (a = 0; a < me->totvert; a++) {
@@ -2662,7 +2662,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
int apply_offset = ((currkey != kb) && (ob->shapenr - 1 == currkey->relative));
if (apply_offset)
- offset_to_key(ob, currkey, ofs);
+ BKE_key_convert_from_offset(ob, currkey, ofs);
currkey = currkey->next;
}
@@ -2683,7 +2683,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
}
/* apply new coords on active key block */
- vertcos_to_key(ob, kb, vertCos);
+ BKE_key_convert_from_vertcos(ob, kb, vertCos);
}
static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
@@ -3074,7 +3074,7 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_
/* BMESH ONLY --- at some point we should move sculpt code to use polygons only - but for now it needs tessfaces */
BKE_mesh_tessface_ensure(me);
- if (!mmd) ss->kb = ob_get_keyblock(ob);
+ if (!mmd) ss->kb = BKE_keyblock_from_object(ob);
else ss->kb = NULL;
/* needs to be called after we ensure tessface */
@@ -3109,7 +3109,7 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_
free_sculptsession_deformMats(ss);
- ss->orig_cos = (ss->kb) ? key_to_vertcos(ob, ss->kb) : mesh_getVertexCos(me, NULL);
+ ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : mesh_getVertexCos(me, NULL);
crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
BLI_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
@@ -3123,7 +3123,7 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_
/* if pbvh is deformed, key block is already applied to it */
if (ss->kb && !BLI_pbvh_isDeformed(ss->pbvh)) {
- float (*vertCos)[3] = key_to_vertcos(ob, ss->kb);
+ float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb);
if (vertCos) {
/* apply shape keys coordinates to PBVH */
@@ -3139,6 +3139,11 @@ int sculpt_mode_poll(bContext *C)
return ob && ob->mode & OB_MODE_SCULPT;
}
+int sculpt_mode_poll_view3d(bContext *C)
+{
+ return (sculpt_mode_poll(C) && CTX_wm_region_view3d(C));
+}
+
int sculpt_poll(bContext *C)
{
return sculpt_mode_poll(C) && paint_poll(C);
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index f4467dc22fc..5e79616b0b0 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -56,6 +56,7 @@ struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct
void sculpt(struct Sculpt *sd);
int sculpt_mode_poll(struct bContext *C);
+int sculpt_mode_poll_view3d(struct bContext *C);
int sculpt_poll(struct bContext *C);
void sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob, int need_pmap);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index c62dc687c73..bb2b4b8c743 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -107,8 +107,8 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
if (ss->kb && strcmp(ss->kb->name, unode->shapeName)) {
/* shape key has been changed before calling undo operator */
- Key *key = ob_get_key(ob);
- KeyBlock *kb = key_get_named_keyblock(key, unode->shapeName);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_find_name(key, unode->shapeName);
if (kb) {
ob->shapenr = BLI_findindex(&key->block, kb) + 1;
@@ -127,7 +127,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
if (ss->kb) {
float (*vertCos)[3];
- vertCos = key_to_vertcos(ob, ss->kb);
+ vertCos = BKE_key_convert_to_vertcos(ob, ss->kb);
for (i = 0; i < unode->totvert; i++) {
if (ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 878fd20b27e..10adeb3e721 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -89,7 +89,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
* start of list offset, and the second is as a correction for the scrollers.
*/
height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2));
- if (height > BLI_RCT_SIZE_Y(&v2d->mask)) {
+ if (height > BLI_rcti_size_y(&v2d->mask)) {
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index c95f1dba31d..7635f85a37e 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -365,13 +365,13 @@ static int actkeys_viewall(bContext *C, const short onlySel)
/* set the horizontal range, with an extra offset so that the extreme keys will be in view */
get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, onlySel);
- extra = 0.1f * BLI_RCT_SIZE_X(&v2d->cur);
+ extra = 0.1f * BLI_rctf_size_x(&v2d->cur);
v2d->cur.xmin -= extra;
v2d->cur.xmax += extra;
/* set vertical range */
v2d->cur.ymax = 0.0f;
- v2d->cur.ymin = (float)-BLI_RCT_SIZE_Y(&v2d->mask);
+ v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
/* do View2D syncing */
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 9ab79d73e76..5da348b2a84 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -309,7 +309,7 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
* - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
* used for tweaking timing when "blocking", while channels is not that useful...
*/
- if (BLI_RCT_SIZE_X(&rect) >= BLI_RCT_SIZE_Y(&rect))
+ if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect))
mode = ACTKEYS_BORDERSEL_FRAMERANGE;
else
mode = ACTKEYS_BORDERSEL_CHANNELS;
@@ -912,9 +912,6 @@ void ACTION_OT_select_leftright(wmOperatorType *ot)
* selection mode between replacing the selection (without) and inverting the selection (with).
*/
-/* sensitivity factor for frame-selections */
-#define FRAME_CLICK_THRESH 0.1f
-
/* ------------------- */
/* option 1) select keyframe directly under mouse */
diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c
index 4bcd4a933ed..ebba7d92819 100644
--- a/source/blender/editors/space_buttons/buttons_header.c
+++ b/source/blender/editors/space_buttons/buttons_header.c
@@ -148,7 +148,7 @@ void buttons_header_buttons(const bContext *C, ARegion *ar)
uiBlockEndAlign(block);
/* always as last */
- UI_view2d_totRect_set(&ar->v2d, xco + (UI_UNIT_X / 2), BLI_RCT_SIZE_Y(&ar->v2d.tot));
+ UI_view2d_totRect_set(&ar->v2d, xco + (UI_UNIT_X / 2), BLI_rctf_size_y(&ar->v2d.tot));
uiEndBlock(C, block);
uiDrawBlock(C, block);
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 33229496d0b..c894c1a980b 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -373,6 +373,10 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
sbuts->preview = 1;
break;
+ case NC_LINESTYLE:
+ ED_area_tag_redraw(sa);
+ sbuts->preview= 1;
+ break;
}
if (wmn->data == ND_KEYS)
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 0a1e1d75098..969b0e25928 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -174,7 +174,7 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
scopes->track_preview_height =
(scopes->track_preview_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->track_preview_height;
- uiDefBut(block, TRACKPREVIEW, 0, "", rect.xmin, rect.ymin, BLI_RCT_SIZE_X(&rect),
+ uiDefBut(block, TRACKPREVIEW, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect),
scopes->track_preview_height, scopes, 0, 0, 0, 0, "");
}
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 5d890155e25..cc1b8d444bc 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -274,7 +274,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
dopesheet = &tracking->dopesheet;
height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2);
- if (height > BLI_RCT_SIZE_Y(&v2d->mask)) {
+ if (height > BLI_rcti_size_y(&v2d->mask)) {
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index d486caeacc2..b22c9a60bdc 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -957,12 +957,12 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
{
/* express given coordinates as proportional values */
- x = -v2d->cur.xmin / BLI_RCT_SIZE_X(&v2d->cur);
- y = -v2d->cur.ymin / BLI_RCT_SIZE_Y(&v2d->cur);
+ x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur);
+ y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur);
/* convert proportional distances to screen coordinates */
- *regionx = v2d->mask.xmin + x * BLI_RCT_SIZE_X(&v2d->mask);
- *regiony = v2d->mask.ymin + y * BLI_RCT_SIZE_Y(&v2d->mask);
+ *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask);
+ *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
}
static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index f2a48f299cf..32f91671daf 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -149,8 +149,8 @@ void ED_space_clip_get_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoo
ED_space_clip_get_size(sc, &width, &height);
- *zoomx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_X(&ar->v2d.cur) * width);
- *zoomy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_Y(&ar->v2d.cur) * height);
+ *zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / (BLI_rctf_size_x(&ar->v2d.cur) * width);
+ *zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / (BLI_rctf_size_y(&ar->v2d.cur) * height);
}
void ED_space_clip_get_aspect(SpaceClip *sc, float *aspx, float *aspy)
@@ -388,8 +388,8 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit)
ED_space_clip_get_aspect(sc, &aspx, &aspy);
- width = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- height = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ width = BLI_rcti_size_x(&ar->winrct) + 1;
+ height = BLI_rcti_size_y(&ar->winrct) + 1;
zoomx = (float)width / w / aspx;
zoomy = (float)height / h / aspy;
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index f48d4e8d946..fa235bd2997 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -580,11 +580,11 @@ static int view_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* we need an extra "buffer" factor on either side so that the endpoints are visible */
- extra = 0.01f * BLI_RCT_SIZE_X(&v2d->cur);
+ extra = 0.01f * BLI_rctf_size_x(&v2d->cur);
v2d->cur.xmin -= extra;
v2d->cur.xmax += extra;
- extra = 0.01f * BLI_RCT_SIZE_Y(&v2d->cur);
+ extra = 0.01f * BLI_rctf_size_y(&v2d->cur);
v2d->cur.ymin -= extra;
v2d->cur.ymax += extra;
@@ -610,7 +610,7 @@ void CLIP_OT_graph_view_all(wmOperatorType *ot)
void ED_clip_graph_center_current_frame(Scene *scene, ARegion *ar)
{
View2D *v2d = &ar->v2d;
- float extra = BLI_RCT_SIZE_X(&v2d->cur) / 2.0f;
+ float extra = BLI_rctf_size_x(&v2d->cur) / 2.0f;
/* set extents of view to start/end frames */
v2d->cur.xmin = (float)CFRA - extra;
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index aa2cadbd2d3..5c338f3e6f1 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -90,9 +90,9 @@ static void sclip_zoom_set(const bContext *C, float zoom, float location[2])
if ((width < 4) && (height < 4))
sc->zoom = oldzoom;
- else if (BLI_RCT_SIZE_X(&ar->winrct) <= sc->zoom)
+ else if (BLI_rcti_size_x(&ar->winrct) <= sc->zoom)
sc->zoom = oldzoom;
- else if (BLI_RCT_SIZE_Y(&ar->winrct) <= sc->zoom)
+ else if (BLI_rcti_size_y(&ar->winrct) <= sc->zoom)
sc->zoom = oldzoom;
}
@@ -726,8 +726,8 @@ static int view_all_exec(bContext *C, wmOperator *op)
h = h * aspy;
/* check if the image will fit in the image with zoom == 1 */
- width = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- height = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ width = BLI_rcti_size_x(&ar->winrct) + 1;
+ height = BLI_rcti_size_y(&ar->winrct) + 1;
if (fit_view) {
const int margin = 5; /* margin from border */
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 7f43c404095..3f925df30c7 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -1036,8 +1036,8 @@ static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar)
if (clip)
h *= clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
- winx = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- winy = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ winx = BLI_rcti_size_x(&ar->winrct) + 1;
+ winy = BLI_rcti_size_y(&ar->winrct) + 1;
ar->v2d.tot.xmin = 0;
ar->v2d.tot.ymin = 0;
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index a4f7e30ed7b..b7ef278275e 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -142,7 +142,7 @@ static void console_main_area_init(wmWindowManager *wm, ARegion *ar)
/* always keep the bottom part of the view aligned, less annoying */
if (prev_y_min != ar->v2d.cur.ymin) {
- const float cur_y_range = BLI_RCT_SIZE_Y(&ar->v2d.cur);
+ const float cur_y_range = BLI_rctf_size_y(&ar->v2d.cur);
ar->v2d.cur.ymin = prev_y_min;
ar->v2d.cur.ymax = prev_y_min + cur_y_range;
}
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index a07a560328c..e5c6a839380 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -66,6 +66,7 @@ void FILE_OT_select_border(struct wmOperatorType *ot);
void FILE_OT_select_bookmark(struct wmOperatorType *ot);
void FILE_OT_bookmark_add(struct wmOperatorType *ot);
void FILE_OT_delete_bookmark(struct wmOperatorType *ot);
+void FILE_OT_reset_recent(wmOperatorType *ot);
void FILE_OT_hidedot(struct wmOperatorType *ot);
void FILE_OT_execute(struct wmOperatorType *ot);
void FILE_OT_cancel(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 040f276940d..fcbeb064e4d 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -64,11 +64,6 @@
#include <stdio.h>
#include <ctype.h>
-/* for events */
-#define NOTACTIVEFILE 0
-#define ACTIVATE 1
-#define INACTIVATE 2
-
/* ---------- FILE SELECTION ------------ */
static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const rcti *rect)
{
@@ -459,7 +454,7 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
if (params->dir[0] != '\0') {
char name[FILE_MAX];
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, FS_INSERT_SAVE);
BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
}
@@ -515,6 +510,35 @@ void FILE_OT_delete_bookmark(wmOperatorType *ot)
RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000);
}
+static int reset_recent_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ ScrArea *sa = CTX_wm_area(C);
+ char name[FILE_MAX];
+ struct FSMenu *fsmenu = fsmenu_get();
+
+ while (fsmenu_get_entry(fsmenu, FS_CATEGORY_RECENT, 0) != NULL) {
+ fsmenu_remove_entry(fsmenu, FS_CATEGORY_RECENT, 0);
+ }
+ BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ fsmenu_write_file(fsmenu, name);
+ ED_area_tag_redraw(sa);
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_reset_recent(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Reset Recent";
+ ot->description = "Reset Recent files";
+ ot->idname = "FILE_OT_reset_recent";
+
+ /* api callbacks */
+ ot->exec = reset_recent_exec;
+ ot->poll = ED_operator_file_active;
+
+}
+
int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
{
View2D *v2d = &ar->v2d;
@@ -770,8 +794,9 @@ int file_exec(bContext *C, wmOperator *exec_op)
file_sfile_to_operator(op, sfile, filepath);
- if (BLI_exists(sfile->params->dir))
- fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, 0, 1);
+ if (BLI_exists(sfile->params->dir)) {
+ fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, FS_INSERT_SAVE | FS_INSERT_FIRST);
+ }
BLI_make_file_string(G.main->name, filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu_get(), filepath);
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 51bd660e126..a7054909aaa 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -67,14 +67,14 @@ static void file_panel_cb(bContext *C, void *arg_entry, void *UNUSED(arg_v))
WM_operator_properties_free(&ptr);
}
-static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory category, short *nr, int icon, int allow_delete, int reverse)
+static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory category, short *nr, int icon, int allow_delete)
{
SpaceFile *sfile = CTX_wm_space_file(C);
uiBlock *block;
uiBut *but;
uiLayout *box, *col;
struct FSMenu *fsmenu = fsmenu_get();
- int i, i_iter, nentries = fsmenu_get_nentries(fsmenu, category);
+ int i, nentries = fsmenu_get_nentries(fsmenu, category);
/* reset each time */
*nr = -1;
@@ -89,13 +89,11 @@ static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory cat
box = uiLayoutBox(pa->layout);
col = uiLayoutColumn(box, TRUE);
- for (i_iter = 0; i_iter < nentries; ++i_iter) {
+ for (i = 0; i < nentries; ++i) {
char dir[FILE_MAX];
char temp[FILE_MAX];
uiLayout *layout = uiLayoutRow(col, FALSE);
char *entry;
-
- i = reverse ? nentries - (i_iter + 1) : i_iter;
entry = fsmenu_get_entry(fsmenu, category, i);
@@ -134,7 +132,7 @@ static void file_panel_system(const bContext *C, Panel *pa)
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile)
- file_panel_category(C, pa, FS_CATEGORY_SYSTEM, &sfile->systemnr, ICON_DISK_DRIVE, 0, 0);
+ file_panel_category(C, pa, FS_CATEGORY_SYSTEM, &sfile->systemnr, ICON_DISK_DRIVE, 0);
}
static void file_panel_bookmarks(const bContext *C, Panel *pa)
@@ -147,17 +145,22 @@ static void file_panel_bookmarks(const bContext *C, Panel *pa)
uiItemO(row, IFACE_("Add"), ICON_ZOOMIN, "file.bookmark_add");
uiItemL(row, NULL, ICON_NONE);
- file_panel_category(C, pa, FS_CATEGORY_BOOKMARKS, &sfile->bookmarknr, ICON_BOOKMARKS, 1, 0);
+ file_panel_category(C, pa, FS_CATEGORY_BOOKMARKS, &sfile->bookmarknr, ICON_BOOKMARKS, 1);
}
}
static void file_panel_recent(const bContext *C, Panel *pa)
{
SpaceFile *sfile = CTX_wm_space_file(C);
+ uiLayout *row;
if (sfile) {
if (!(U.uiflag & USER_HIDE_RECENT) ) {
- file_panel_category(C, pa, FS_CATEGORY_RECENT, &sfile->recentnr, ICON_FILE_FOLDER, 0, 1);
+ row = uiLayoutRow(pa->layout, FALSE);
+ uiItemO(row, IFACE_("Reset"), ICON_X, "file.reset_recent");
+ uiItemL(row, NULL, ICON_NONE);
+
+ file_panel_category(C, pa, FS_CATEGORY_RECENT, &sfile->recentnr, ICON_FILE_FOLDER, 0);
}
}
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index d3b4df05aa9..699cb9b4feb 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1150,7 +1150,7 @@ void filelist_from_main(struct FileList *filelist)
if (filelist->dir[0] == 0) {
/* make directories */
- filelist->numfiles = 24;
+ filelist->numfiles = 25;
filelist->filelist = (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
for (a = 0; a < filelist->numfiles; a++) {
@@ -1181,6 +1181,7 @@ void filelist_from_main(struct FileList *filelist)
filelist->filelist[21].relname = BLI_strdup("Action");
filelist->filelist[22].relname = BLI_strdup("NodeTree");
filelist->filelist[23].relname = BLI_strdup("Speaker");
+ filelist->filelist[24].relname= BLI_strdup("FreestyleLineStyle");
filelist_sort(filelist, FILE_SORT_ALPHA);
}
else {
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 09231efd367..1fa89e5db9a 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -270,12 +270,12 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar)
int numfiles;
if (layout->flag & FILE_LAYOUT_HOR) {
- int width = (int)(BLI_RCT_SIZE_X(&ar->v2d.cur) - 2 * layout->tile_border_x);
+ int width = (int)(BLI_rctf_size_x(&ar->v2d.cur) - 2 * layout->tile_border_x);
numfiles = (int)((float)width / (float)layout->tile_w + 0.5f);
return numfiles * layout->rows;
}
else {
- int height = (int)(BLI_RCT_SIZE_Y(&ar->v2d.cur) - 2 * layout->tile_border_y);
+ int height = (int)(BLI_rctf_size_y(&ar->v2d.cur) - 2 * layout->tile_border_y);
numfiles = (int)((float)height / (float)layout->tile_h + 0.5f);
return numfiles * layout->columns;
}
@@ -503,7 +503,7 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->prv_border_y = 6;
layout->tile_w = layout->prv_w + 2 * layout->prv_border_x;
layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight;
- layout->width = (int)(BLI_RCT_SIZE_X(&v2d->cur) - 2 * layout->tile_border_x);
+ layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
layout->columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x);
if (layout->columns > 0)
layout->rows = numfiles / layout->columns + 1; // XXX dirty, modulo is zero
@@ -522,7 +522,7 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->prv_border_x = 0;
layout->prv_border_y = 0;
layout->tile_h = textheight * 3 / 2;
- layout->height = (int)(BLI_RCT_SIZE_Y(&v2d->cur) - 2 * layout->tile_border_y);
+ layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y);
layout->rows = layout->height / (layout->tile_h + 2 * layout->tile_border_y);
column_widths(sfile->files, layout);
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index a127e2ca2bc..66cda3082ea 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -97,84 +97,94 @@ FSMenu *fsmenu_get(void)
static FSMenuEntry *fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory category)
{
- FSMenuEntry *fsms = NULL;
+ FSMenuEntry *fsm_head = NULL;
switch (category) {
case FS_CATEGORY_SYSTEM:
- fsms = fsmenu->fsmenu_system;
+ fsm_head = fsmenu->fsmenu_system;
break;
case FS_CATEGORY_BOOKMARKS:
- fsms = fsmenu->fsmenu_bookmarks;
+ fsm_head = fsmenu->fsmenu_bookmarks;
break;
case FS_CATEGORY_RECENT:
- fsms = fsmenu->fsmenu_recent;
+ fsm_head = fsmenu->fsmenu_recent;
break;
}
- return fsms;
+ return fsm_head;
}
-static void fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsms)
+static void fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head)
{
switch (category) {
case FS_CATEGORY_SYSTEM:
- fsmenu->fsmenu_system = fsms;
+ fsmenu->fsmenu_system = fsm_head;
break;
case FS_CATEGORY_BOOKMARKS:
- fsmenu->fsmenu_bookmarks = fsms;
+ fsmenu->fsmenu_bookmarks = fsm_head;
break;
case FS_CATEGORY_RECENT:
- fsmenu->fsmenu_recent = fsms;
+ fsmenu->fsmenu_recent = fsm_head;
break;
}
}
int fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category)
{
- FSMenuEntry *fsme;
+ FSMenuEntry *fsm_iter;
int count = 0;
- for (fsme = fsmenu_get_category(fsmenu, category); fsme; fsme = fsme->next)
+ for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter; fsm_iter = fsm_iter->next) {
count++;
+ }
return count;
}
char *fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx)
{
- FSMenuEntry *fsme;
+ FSMenuEntry *fsm_iter;
- for (fsme = fsmenu_get_category(fsmenu, category); fsme && idx; fsme = fsme->next)
+ for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter && idx; fsm_iter = fsm_iter->next) {
idx--;
+ }
- return fsme ? fsme->path : NULL;
+ return fsm_iter ? fsm_iter->path : NULL;
}
short fsmenu_can_save(struct FSMenu *fsmenu, FSMenuCategory category, int idx)
{
- FSMenuEntry *fsme;
+ FSMenuEntry *fsm_iter;
- for (fsme = fsmenu_get_category(fsmenu, category); fsme && idx; fsme = fsme->next)
+ for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter && idx; fsm_iter = fsm_iter->next) {
idx--;
+ }
- return fsme ? fsme->save : 0;
+ return fsm_iter ? fsm_iter->save : 0;
}
-void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, int sorted, short save)
+void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, FSMenuInsert flag)
{
- FSMenuEntry *prev;
- FSMenuEntry *fsme;
- FSMenuEntry *fsms;
+ FSMenuEntry *fsm_prev;
+ FSMenuEntry *fsm_iter;
+ FSMenuEntry *fsm_head;
- fsms = fsmenu_get_category(fsmenu, category);
- prev = fsme = fsms;
+ fsm_head = fsmenu_get_category(fsmenu, category);
+ fsm_prev = fsm_head; /* this is odd and not really correct? */
- for (; fsme; prev = fsme, fsme = fsme->next) {
- if (fsme->path) {
- const int cmp_ret = BLI_path_cmp(path, fsme->path);
+ for (fsm_iter = fsm_head; fsm_iter; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next) {
+ if (fsm_iter->path) {
+ const int cmp_ret = BLI_path_cmp(path, fsm_iter->path);
if (cmp_ret == 0) {
+ if (flag & FS_INSERT_FIRST) {
+ if (fsm_iter != fsm_head) {
+ fsm_prev->next = fsm_iter->next;
+ fsm_iter->next = fsm_head;
+ fsmenu_set_category(fsmenu, category, fsm_iter);
+ }
+ }
return;
}
- else if (sorted && cmp_ret < 0) {
+ else if ((flag & FS_INSERT_SORTED) && cmp_ret < 0) {
break;
}
}
@@ -182,78 +192,82 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const c
/* if we're bookmarking this, file should come
* before the last separator, only automatically added
* current dir go after the last sep. */
- if (save) {
+ if (flag & FS_INSERT_SAVE) {
break;
}
}
}
- fsme = MEM_mallocN(sizeof(*fsme), "fsme");
- fsme->path = BLI_strdup(path);
- fsme->save = save;
+ fsm_iter = MEM_mallocN(sizeof(*fsm_iter), "fsme");
+ fsm_iter->path = BLI_strdup(path);
+ fsm_iter->save = (flag & FS_INSERT_SAVE) != 0;
- if (prev) {
- fsme->next = prev->next;
- prev->next = fsme;
+ if (fsm_prev) {
+ if (flag & FS_INSERT_FIRST) {
+ fsm_iter->next = fsm_head;
+ fsmenu_set_category(fsmenu, category, fsm_iter);
+ }
+ else {
+ fsm_iter->next = fsm_prev->next;
+ fsm_prev->next = fsm_iter;
+ }
}
else {
- fsme->next = fsms;
- fsmenu_set_category(fsmenu, category, fsme);
+ fsm_iter->next = fsm_head;
+ fsmenu_set_category(fsmenu, category, fsm_iter);
}
}
void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx)
{
- FSMenuEntry *prev = NULL, *fsme = NULL;
- FSMenuEntry *fsms = fsmenu_get_category(fsmenu, category);
+ FSMenuEntry *fsm_prev = NULL;
+ FSMenuEntry *fsm_iter;
+ FSMenuEntry *fsm_head;
+
+ fsm_head = fsmenu_get_category(fsmenu, category);
- for (fsme = fsms; fsme && idx; prev = fsme, fsme = fsme->next)
+ for (fsm_iter = fsm_head; fsm_iter && idx; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next)
idx--;
- if (fsme) {
+ if (fsm_iter) {
/* you should only be able to remove entries that were
* not added by default, like windows drives.
* also separators (where path == NULL) shouldn't be removed */
- if (fsme->save && fsme->path) {
+ if (fsm_iter->save && fsm_iter->path) {
/* remove fsme from list */
- if (prev) {
- prev->next = fsme->next;
+ if (fsm_prev) {
+ fsm_prev->next = fsm_iter->next;
}
else {
- fsms = fsme->next;
- fsmenu_set_category(fsmenu, category, fsms);
+ fsm_head = fsm_iter->next;
+ fsmenu_set_category(fsmenu, category, fsm_head);
}
/* free entry */
- MEM_freeN(fsme->path);
- MEM_freeN(fsme);
+ MEM_freeN(fsm_iter->path);
+ MEM_freeN(fsm_iter);
}
}
}
void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename)
{
- FSMenuEntry *fsme = NULL;
- int nskip = 0;
+ FSMenuEntry *fsm_iter = NULL;
+ int nwritten = 0;
FILE *fp = BLI_fopen(filename, "w");
if (!fp) return;
fprintf(fp, "[Bookmarks]\n");
- for (fsme = fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsme; fsme = fsme->next) {
- if (fsme->path && fsme->save) {
- fprintf(fp, "%s\n", fsme->path);
+ for (fsm_iter = fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsm_iter; fsm_iter = fsm_iter->next) {
+ if (fsm_iter->path && fsm_iter->save) {
+ fprintf(fp, "%s\n", fsm_iter->path);
}
}
fprintf(fp, "[Recent]\n");
- nskip = fsmenu_get_nentries(fsmenu, FS_CATEGORY_RECENT) - FSMENU_RECENT_MAX;
- /* skip first entries if list too long */
- for (fsme = fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsme && (nskip > 0); fsme = fsme->next, --nskip) {
- /* pass */
- }
- for (; fsme; fsme = fsme->next) {
- if (fsme->path && fsme->save) {
- fprintf(fp, "%s\n", fsme->path);
+ for (fsm_iter = fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsm_iter && (nwritten < FSMENU_RECENT_MAX); fsm_iter = fsm_iter->next, ++nwritten) {
+ if (fsm_iter->path && fsm_iter->save) {
+ fprintf(fp, "%s\n", fsm_iter->path);
}
}
fclose(fp);
@@ -288,7 +302,7 @@ void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
if (BLI_exists(line))
#endif
{
- fsmenu_insert_entry(fsmenu, category, line, 0, 1);
+ fsmenu_insert_entry(fsmenu, category, line, FS_INSERT_SAVE);
}
}
}
@@ -315,16 +329,16 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
tmps[2] = '\\';
tmps[3] = 0;
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, FS_INSERT_SORTED);
}
}
/* Adding Desktop and My Documents */
if (read_bookmarks) {
SHGetSpecialFolderPath(0, line, CSIDL_PERSONAL, 0);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
SHGetSpecialFolderPath(0, line, CSIDL_DESKTOPDIRECTORY, 0);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
}
}
#else
@@ -347,7 +361,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
FSRefMakePath(&dir, path, FILE_MAX);
if (strcmp((char *)path, "/home") && strcmp((char *)path, "/net")) {
/* /net and /home are meaningless on OSX, home folders are stored in /Users */
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, FS_INSERT_SORTED);
}
}
@@ -357,26 +371,26 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
home = getenv("HOME");
if (read_bookmarks && home) {
BLI_snprintf(line, 256, "%s/", home);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
BLI_snprintf(line, 256, "%s/Desktop/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
}
BLI_snprintf(line, 256, "%s/Documents/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
}
BLI_snprintf(line, 256, "%s/Pictures/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
}
BLI_snprintf(line, 256, "%s/Music/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
}
BLI_snprintf(line, 256, "%s/Movies/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
}
}
#else
@@ -409,7 +423,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
if (!CFStringGetCString(pathString, line, 256, kCFStringEncodingASCII))
continue;
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED);
CFRelease(pathString);
CFRelease(cfURL);
@@ -436,7 +450,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
FSRefMakePath(&dir, path, FILE_MAX);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, FS_INSERT_SORTED);
}
/* Finally get user favorite places */
@@ -459,7 +473,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
if (!CFStringGetCString(pathString, line, 256, kCFStringEncodingASCII))
continue;
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
CFRelease(pathString);
CFRelease(cfURL);
@@ -477,10 +491,10 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
if (read_bookmarks && home) {
BLI_snprintf(line, FILE_MAXDIR, "%s/", home);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
BLI_snprintf(line, FILE_MAXDIR, "%s/Desktop/", home);
if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, FS_INSERT_SORTED);
}
}
@@ -505,10 +519,11 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
len = strlen(mnt->mnt_dir);
if (len && mnt->mnt_dir[len - 1] != '/') {
BLI_snprintf(line, FILE_MAXDIR, "%s/", mnt->mnt_dir);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED);
+ }
+ else {
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, FS_INSERT_SORTED);
}
- else
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, 1, 0);
found = 1;
}
@@ -520,7 +535,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* fallback */
if (!found)
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, "/", 1, 0);
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, "/", FS_INSERT_SORTED);
}
}
#endif
@@ -530,15 +545,17 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
static void fsmenu_free_category(struct FSMenu *fsmenu, FSMenuCategory category)
{
- FSMenuEntry *fsme = fsmenu_get_category(fsmenu, category);
+ FSMenuEntry *fsm_iter = fsmenu_get_category(fsmenu, category);
- while (fsme) {
- FSMenuEntry *n = fsme->next;
+ while (fsm_iter) {
+ FSMenuEntry *fsm_next = fsm_iter->next;
- if (fsme->path) MEM_freeN(fsme->path);
- MEM_freeN(fsme);
+ if (fsm_iter->path) {
+ MEM_freeN(fsm_iter->path);
+ }
+ MEM_freeN(fsm_iter);
- fsme = n;
+ fsm_iter = fsm_next;
}
}
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index d7576d71933..30730578085 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -43,6 +43,12 @@ typedef enum FSMenuCategory {
FS_CATEGORY_RECENT
} FSMenuCategory;
+typedef enum FSMenuInsert {
+ FS_INSERT_SORTED = (1 << 0),
+ FS_INSERT_SAVE = (1 << 1),
+ FS_INSERT_FIRST = (1 << 2) /* moves the item to the front of the list when its not already there */
+} FSMenuInsert;
+
struct FSMenu;
struct FSMenu *fsmenu_get(void);
@@ -59,7 +65,7 @@ char *fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index
* Duplicate entries are not added.
* \param sorted Should entry be inserted in sorted order?
*/
-void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, int sorted, short save);
+void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, const FSMenuInsert flag);
/** Return whether the entry was created by the user and can be saved and deleted */
short fsmenu_can_save(struct FSMenu *fsmenu, FSMenuCategory category, int index);
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 4b568b43695..7f39545258d 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -386,6 +386,7 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_bookmark_toggle);
WM_operatortype_append(FILE_OT_bookmark_add);
WM_operatortype_append(FILE_OT_delete_bookmark);
+ WM_operatortype_append(FILE_OT_reset_recent);
WM_operatortype_append(FILE_OT_hidedot);
WM_operatortype_append(FILE_OT_filenum);
WM_operatortype_append(FILE_OT_directory_new);
@@ -537,7 +538,7 @@ static void file_ui_area_draw(const bContext *C, ARegion *ar)
glClear(GL_COLOR_BUFFER_BIT);
/* scrolling here is just annoying, disable it */
- ar->v2d.cur.ymax = BLI_RCT_SIZE_Y(&ar->v2d.cur);
+ ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur);
ar->v2d.cur.ymin = 0;
/* set view2d view matrix for scrolling (without scrollers) */
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index efe62eaf495..0d56b02e086 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -69,12 +69,6 @@
#include "graph_intern.h" // own include
-/* XXX */
-
-/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */
-#define UI_FLT_MAX 10000.0f
-
-
/* ******************* graph editor space & buttons ************** */
#define B_REDR 1
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index e4bda15bc7d..ef2e56afca0 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -88,7 +88,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
{
FMod_Envelope *env = (FMod_Envelope *)fcm->data;
FCM_EnvelopeData *fed;
- const float fac = 0.05f * BLI_RCT_SIZE_X(&v2d->cur);
+ const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
int i;
/* draw two black lines showing the standard reference levels */
@@ -137,7 +137,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), View2D *v2d, short edit, short sel)
{
BezTriple *bezt = fcu->bezt;
- const float fac = 0.05f * BLI_RCT_SIZE_X(&v2d->cur);
+ const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
int i;
/* we use bgl points not standard gl points, to workaround vertex
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index f01d64b46b8..7107a6a2369 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -229,11 +229,11 @@ static int graphkeys_viewall(bContext *C, const short do_sel_only, const short i
&cur_new.ymin, &cur_new.ymax,
do_sel_only, include_handles);
- extra = 0.1f * BLI_RCT_SIZE_X(&cur_new);
+ extra = 0.1f * BLI_rctf_size_x(&cur_new);
cur_new.xmin -= extra;
cur_new.xmax += extra;
- extra = 0.1f * BLI_RCT_SIZE_Y(&cur_new);
+ extra = 0.1f * BLI_rctf_size_y(&cur_new);
cur_new.ymin -= extra;
cur_new.ymax += extra;
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 633f2b72cf6..e2fc1657379 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -325,7 +325,7 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
* - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
* used for tweaking timing when "blocking", while channels is not that useful...
*/
- if ((BLI_RCT_SIZE_X(&rect)) >= (BLI_RCT_SIZE_Y(&rect)))
+ if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect)))
mode = BEZT_OK_FRAMERANGE;
else
mode = BEZT_OK_VALUERANGE;
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index c372973b7b0..0b904f36a8c 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -71,28 +71,6 @@
#include "image_intern.h"
-#define B_REDR 1
-#define B_IMAGECHANGED 2
-#define B_NOP 0
-#define B_TWINANIM 5
-#define B_SIMAGETILE 6
-#define B_IDNAME 10
-#define B_FACESEL_PAINT_TEST 11
-#define B_SIMA_RECORD 12
-#define B_SIMA_PLAY 13
-
-#define B_SIMANOTHING 16
-#define B_SIMABRUSHCHANGE 17
-#define B_SIMABRUSHBROWSE 18
-#define B_SIMABRUSHLOCAL 19
-#define B_SIMABRUSHDELETE 20
-#define B_KEEPDATA 21
-#define B_SIMABTEXBROWSE 22
-#define B_SIMABTEXDELETE 23
-#define B_VPCOLSLI 24
-#define B_SIMACLONEBROWSE 25
-#define B_SIMACLONEDELETE 26
-
/* proto */
static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str)
@@ -228,13 +206,13 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
int mval[2];
if (G.scene->r.mode & R_BORDER) {
- winx *= BLI_RCT_SIZE_X(&G.scene->r.border);
- winy *= BLI_RCT_SIZE_Y(&G.scene->r.border);
+ winx *= BLI_rcti_size_x(&G.scene->r.border);
+ winy *= BLI_rctf_size_y(&G.scene->r.border);
}
/* while dragging we need to update the rects, otherwise it doesn't end with correct one */
- BLI_rctf_init(&dispf, 15.0f, BLI_RCT_SIZE_X(&block->rect) - 15.0f, 15.0f, (BLI_RCT_SIZE_Y(&block->rect)) - 15.0f);
+ BLI_rctf_init(&dispf, 15.0f, BLI_rcti_size_x(&block->rect) - 15.0f, 15.0f, (BLI_rctf_size_y(&block->rect)) - 15.0f);
ui_graphics_to_window_rct(sa->win, &dispf, disprect);
/* correction for gla draw */
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 638a2ac6681..749ba75cfa1 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -78,8 +78,6 @@
#include "image_intern.h"
-#define HEADER_HEIGHT 18
-
static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
{
RenderResult *rr;
@@ -118,7 +116,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
/* noisy, high contrast make impossible to read if lower alpha is used. */
glColor4ub(0, 0, 0, 190);
- glRecti(0.0, 0.0, BLI_RCT_SIZE_X(&ar->winrct) + 1, 20);
+ glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, 20);
glDisable(GL_BLEND);
BLF_size(blf_mono_font, 11, 72);
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 79d01491df7..92433449985 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -161,8 +161,8 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height)
*height = (scene->r.ysch * scene->r.size) / 100;
if ((scene->r.mode & R_BORDER) && (scene->r.mode & R_CROP)) {
- *width *= BLI_RCT_SIZE_X(&scene->r.border);
- *height *= BLI_RCT_SIZE_Y(&scene->r.border);
+ *width *= BLI_rctf_size_x(&scene->r.border);
+ *height *= BLI_rctf_size_y(&scene->r.border);
}
}
@@ -204,8 +204,8 @@ void ED_space_image_get_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float
ED_space_image_get_size(sima, &width, &height);
- *zoomx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_X(&ar->v2d.cur) * width);
- *zoomy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_Y(&ar->v2d.cur) * height);
+ *zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / (float)(BLI_rctf_size_x(&ar->v2d.cur) * width);
+ *zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / (float)(BLI_rctf_size_y(&ar->v2d.cur) * height);
}
void ED_space_image_get_uv_aspect(SpaceImage *sima, float *aspx, float *aspy)
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 16804c5a1c6..16c9405e098 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -99,9 +99,9 @@ static void sima_zoom_set(SpaceImage *sima, ARegion *ar, float zoom, float locat
if ((width < 4) && (height < 4))
sima->zoom = oldzoom;
- else if (BLI_RCT_SIZE_X(&ar->winrct) <= sima->zoom)
+ else if (BLI_rcti_size_x(&ar->winrct) <= sima->zoom)
sima->zoom = oldzoom;
- else if (BLI_RCT_SIZE_Y(&ar->winrct) <= sima->zoom)
+ else if (BLI_rcti_size_y(&ar->winrct) <= sima->zoom)
sima->zoom = oldzoom;
}
@@ -582,8 +582,8 @@ static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op))
h = height * aspy;
/* check if the image will fit in the image with (zoom == 1) */
- width = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- height = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ width = BLI_rcti_size_x(&ar->winrct) + 1;
+ height = BLI_rcti_size_y(&ar->winrct) + 1;
if ((w >= width || h >= height) && (width > 0 && height > 0)) {
/* find the zoom value that will fit the image in the image space */
@@ -1414,7 +1414,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
RNA_boolean_set(op->ptr, "copy", TRUE);
}
- if (ima->source == IMA_SRC_VIEWER)
+ if (ima->source == IMA_SRC_VIEWER || (ima->flag & IMA_VIEW_AS_RENDER))
RNA_boolean_set(op->ptr, "save_as_render", TRUE);
else
RNA_boolean_set(op->ptr, "save_as_render", FALSE);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 5b288bd6149..abe8dfb751b 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -438,6 +438,10 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
break;
case ND_MODE:
+ if (wmn->subtype == NS_EDITMODE_MESH)
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ break;
case ND_RENDER_RESULT:
case ND_RENDER_OPTIONS:
case ND_COMPO_RESULT:
@@ -558,8 +562,8 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar)
if (ima)
h *= ima->aspy / ima->aspx;
- winx = BLI_RCT_SIZE_X(&ar->winrct) + 1;
- winy = BLI_RCT_SIZE_Y(&ar->winrct) + 1;
+ winx = BLI_rcti_size_x(&ar->winrct) + 1;
+ winy = BLI_rcti_size_y(&ar->winrct) + 1;
ar->v2d.tot.xmin = 0;
ar->v2d.tot.ymin = 0;
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 4ffa99319c4..5e5e0c87feb 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -368,7 +368,7 @@ static void stats_string(Scene *scene)
s += sprintf(s, "%s | ", versionstr);
if (scene->obedit) {
- if (ob_get_keyblock(scene->obedit))
+ if (BKE_keyblock_from_object(scene->obedit))
s += sprintf(s, "(Key) ");
if (scene->obedit->type == OB_MESH) {
diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c
index abffb955405..abdfa0ef4dd 100644
--- a/source/blender/editors/space_logic/logic_buttons.c
+++ b/source/blender/editors/space_logic/logic_buttons.c
@@ -84,10 +84,10 @@ static int cut_links_intersect(uiLinkLine *line, float mcoords[][2], int tot)
int i, b;
rcti rectlink;
- rectlink.xmin = (int)BLI_RCT_CENTER_X(&line->from->rect);
- rectlink.ymin = (int)BLI_RCT_CENTER_Y(&line->from->rect);
- rectlink.xmax = (int)BLI_RCT_CENTER_X(&line->to->rect);
- rectlink.ymax = (int)BLI_RCT_CENTER_Y(&line->to->rect);
+ rectlink.xmin = (int)BLI_rctf_cent_x(&line->from->rect);
+ rectlink.ymin = (int)BLI_rctf_cent_y(&line->from->rect);
+ rectlink.xmax = (int)BLI_rctf_cent_x(&line->to->rect);
+ rectlink.ymax = (int)BLI_rctf_cent_y(&line->to->rect);
if (ui_link_bezier_points(&rectlink, coord_array, LINK_RESOL)) {
for (i=0; i<tot-1; i++)
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 6ffac1dcd34..5d7ff77e032 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -72,10 +72,7 @@
#include "logic_intern.h"
-
-#define MAX_RENDER_PASS 100
#define B_REDR 1
-#define B_IDNAME 2
#define B_ADD_SENS 2703
#define B_CHANGE_SENS 2704
@@ -91,7 +88,6 @@
#define B_SOUNDACT_BROWSE 2712
-#define B_SETSECTOR 2713
#define B_SETPROP 2714
#define B_SETACTOR 2715
#define B_SETMAINACTOR 2716
@@ -187,178 +183,6 @@ void make_unique_prop_names(bContext *C, char *str)
MEM_freeN(names);
}
-static void make_unique_prop_names_cb(bContext *C, void *strv, void *UNUSED(redraw_view3d_flagv))
-{
- char *str= strv;
-// int redraw_view3d_flag= GET_INT_FROM_POINTER(redraw_view3d_flagv);
-
- make_unique_prop_names(C, str);
-}
-
-
-static void old_sca_move_sensor(bContext *C, void *datav, void *move_up)
-{
- /* deprecated, no longer using it (moved to sca.c) */
- Scene *scene= CTX_data_scene(C);
- bSensor *sens_to_delete= datav;
- int val;
- Base *base;
- bSensor *sens, *tmp;
-
- // val= pupmenu("Move up%x1|Move down %x2");
- val = move_up ? 1:2;
-
- if (val>0) {
- /* now find out which object has this ... */
- base= FIRSTBASE;
- while (base) {
-
- sens= base->object->sensors.first;
- while (sens) {
- if (sens == sens_to_delete) break;
- sens= sens->next;
- }
-
- if (sens) {
- if ( val==1 && sens->prev) {
- for (tmp=sens->prev; tmp; tmp=tmp->prev) {
- if (tmp->flag & SENS_VISIBLE)
- break;
- }
- if (tmp) {
- BLI_remlink(&base->object->sensors, sens);
- BLI_insertlinkbefore(&base->object->sensors, tmp, sens);
- }
- }
- else if ( val==2 && sens->next) {
- for (tmp=sens->next; tmp; tmp=tmp->next) {
- if (tmp->flag & SENS_VISIBLE)
- break;
- }
- if (tmp) {
- BLI_remlink(&base->object->sensors, sens);
- BLI_insertlink(&base->object->sensors, tmp, sens);
- }
- }
- ED_undo_push(C, "Move sensor");
- break;
- }
-
- base= base->next;
- }
- }
-}
-
-static void old_sca_move_controller(bContext *C, void *datav, void *move_up)
-{
- /* deprecated, no longer using it (moved to sca.c) */
- Scene *scene= CTX_data_scene(C);
- bController *controller_to_del= datav;
- int val;
- Base *base;
- bController *cont, *tmp;
-
- //val= pupmenu("Move up%x1|Move down %x2");
- val = move_up ? 1:2;
-
- if (val>0) {
- /* now find out which object has this ... */
- base= FIRSTBASE;
- while (base) {
-
- cont= base->object->controllers.first;
- while (cont) {
- if (cont == controller_to_del) break;
- cont= cont->next;
- }
-
- if (cont) {
- if ( val==1 && cont->prev) {
- /* locate the controller that has the same state mask but is earlier in the list */
- tmp = cont->prev;
- while (tmp) {
- if (tmp->state_mask & cont->state_mask)
- break;
- tmp = tmp->prev;
- }
- if (tmp) {
- BLI_remlink(&base->object->controllers, cont);
- BLI_insertlinkbefore(&base->object->controllers, tmp, cont);
- }
- }
- else if ( val==2 && cont->next) {
- tmp = cont->next;
- while (tmp) {
- if (tmp->state_mask & cont->state_mask)
- break;
- tmp = tmp->next;
- }
- BLI_remlink(&base->object->controllers, cont);
- BLI_insertlink(&base->object->controllers, tmp, cont);
- }
- ED_undo_push(C, "Move controller");
- break;
- }
-
- base= base->next;
- }
- }
-}
-
-static void old_sca_move_actuator(bContext *C, void *datav, void *move_up)
-{
- /* deprecated, no longer using it (moved to sca.c) */
- Scene *scene= CTX_data_scene(C);
- bActuator *actuator_to_move= datav;
- int val;
- Base *base;
- bActuator *act, *tmp;
-
- //val= pupmenu("Move up%x1|Move down %x2");
- val = move_up ? 1:2;
-
- if (val>0) {
- /* now find out which object has this ... */
- base= FIRSTBASE;
- while (base) {
-
- act= base->object->actuators.first;
- while (act) {
- if (act == actuator_to_move) break;
- act= act->next;
- }
-
- if (act) {
- if ( val==1 && act->prev) {
- /* locate the first visible actuators before this one */
- for (tmp = act->prev; tmp; tmp=tmp->prev) {
- if (tmp->flag & ACT_VISIBLE)
- break;
- }
- if (tmp) {
- BLI_remlink(&base->object->actuators, act);
- BLI_insertlinkbefore(&base->object->actuators, tmp, act);
- }
- }
- else if ( val==2 && act->next) {
- for (tmp=act->next; tmp; tmp=tmp->next) {
- if (tmp->flag & ACT_VISIBLE)
- break;
- }
- if (tmp) {
- BLI_remlink(&base->object->actuators, act);
- BLI_insertlink(&base->object->actuators, tmp, act);
- }
- }
- ED_undo_push(C, "Move actuator");
- break;
- }
-
- base= base->next;
- }
- }
-}
-
static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
{
Main *bmain= CTX_data_main(C);
@@ -631,14 +455,6 @@ static const char *sensor_name(int type)
return "unknown";
}
-static const char *sensor_pup(void)
-{
- /* the number needs to match defines in DNA_sensor_types.h */
- return "Sensors %t|Always %x0|Delay %x13|Keyboard %x3|Mouse %x5|"
- "Touch %x1|Collision %x6|Near %x2|Radar %x7|"
- "Property %x4|Random %x8|Ray %x9|Message %x10|Joystick %x11|Actuator %x12|Armature %x14";
-}
-
static const char *controller_name(int type)
{
switch (type) {
@@ -662,11 +478,6 @@ static const char *controller_name(int type)
return "unknown";
}
-static const char *controller_pup(void)
-{
- return "Controllers %t|AND %x0|OR %x1|XOR %x6|NAND %x4|NOR %x5|XNOR %x7|Expression %x2|Python %x3";
-}
-
static const char *actuator_name(int type)
{
switch (type) {
@@ -718,36 +529,6 @@ static const char *actuator_name(int type)
return "unknown";
}
-
-
-
-static const char *actuator_pup(Object *owner)
-{
- switch (owner->type) {
- case OB_ARMATURE:
- return ("Actuators %t|Action %x15|Armature %x23|Motion %x0|Constraint %x9|Ipo %x1"
- "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
- "|Scene %x11|Random %x13|Message %x14|Game %x17"
- "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22");
- break;
-
- case OB_MESH:
- return ("Actuators %t|Shape Action %x21|Motion %x0|Constraint %x9|Ipo %x1"
- "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
- "|Scene %x11|Random %x13|Message %x14|Game %x17"
- "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22");
- break;
-
- default:
- return ("Actuators %t|Motion %x0|Constraint %x9|Ipo %x1"
- "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10"
- "|Scene %x11|Random %x13|Message %x14|Game %x17"
- "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22");
- }
-}
-
-
-
static void set_sca_ob(Object *ob)
{
bController *cont;
@@ -935,151 +716,6 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf
return idar;
}
-
-static int get_col_sensor(int type)
-{
- /* XXX themecolors not here */
-
- switch (type) {
- case SENS_ALWAYS: return TH_PANEL;
- case SENS_DELAY: return TH_PANEL;
- case SENS_TOUCH: return TH_PANEL;
- case SENS_COLLISION: return TH_PANEL;
- case SENS_NEAR: return TH_PANEL;
- case SENS_KEYBOARD: return TH_PANEL;
- case SENS_PROPERTY: return TH_PANEL;
- case SENS_ARMATURE: return TH_PANEL;
- case SENS_ACTUATOR: return TH_PANEL;
- case SENS_MOUSE: return TH_PANEL;
- case SENS_RADAR: return TH_PANEL;
- case SENS_RANDOM: return TH_PANEL;
- case SENS_RAY: return TH_PANEL;
- case SENS_MESSAGE: return TH_PANEL;
- case SENS_JOYSTICK: return TH_PANEL;
- default: return TH_PANEL;
- }
-}
-static void set_col_sensor(int type, int medium)
-{
- int col= get_col_sensor(type);
- UI_ThemeColorShade(col, medium?30:0);
-}
-
-
-static void verify_logicbutton_func(bContext *UNUSED(C), void *data1, void *data2)
-{
- bSensor *sens= (bSensor*)data1;
-
- if (sens->level && sens->tap) {
- if (data2 == &(sens->level))
- sens->tap= 0;
- else
- sens->level= 0;
- }
-}
-
-static void test_scriptpoin_but(struct bContext *C, const char *name, ID **idpp)
-{
- *idpp= BLI_findstring(&CTX_data_main(C)->text, name, offsetof(ID, name) + 2);
-}
-
-static void test_actionpoin_but(struct bContext *C, const char *name, ID **idpp)
-{
- *idpp= BLI_findstring(&CTX_data_main(C)->action, name, offsetof(ID, name) + 2);
- if (*idpp)
- id_us_plus(*idpp);
-}
-
-
-static void test_obpoin_but(struct bContext *C, const char *name, ID **idpp)
-{
- *idpp= BLI_findstring(&CTX_data_main(C)->object, name, offsetof(ID, name) + 2);
- if (*idpp)
- id_lib_extern(*idpp); /* checks lib data, sets correct flag for saving then */
-}
-
-static void test_meshpoin_but(struct bContext *C, const char *name, ID **idpp)
-{
- *idpp= BLI_findstring(&CTX_data_main(C)->mesh, name, offsetof(ID, name) + 2);
- if (*idpp)
- id_us_plus(*idpp);
-}
-
-static void test_matpoin_but(struct bContext *C, const char *name, ID **idpp)
-{
- *idpp= BLI_findstring(&CTX_data_main(C)->mat, name, offsetof(ID, name) + 2);
- if (*idpp)
- id_us_plus(*idpp);
-}
-
-static void test_scenepoin_but(struct bContext *C, const char *name, ID **idpp)
-{
- *idpp= BLI_findstring(&CTX_data_main(C)->scene, name, offsetof(ID, name) + 2);
- if (*idpp)
- id_us_plus(*idpp);
-}
-
-static void test_keyboard_event(struct bContext *UNUSED(C), void *arg_ks, void *UNUSED(arg))
-{
- bKeyboardSensor *ks= (bKeyboardSensor*)arg_ks;
-
- if (!ISKEYBOARD(ks->key))
- ks->key= 0;
- if (!ISKEYBOARD(ks->qual))
- ks->qual= 0;
- if (!ISKEYBOARD(ks->qual2))
- ks->qual2= 0;
-}
-
-/**
- * Draws a toggle for pulse mode, a frequency field and a toggle to invert
- * the value of this sensor. Operates on the shared data block of sensors.
- */
-static void draw_default_sensor_header(bSensor *sens,
- uiBlock *block,
- short x,
- short y,
- short w)
-{
- uiBut *but;
-
- /* Pulsing and frequency */
- uiBlockBeginAlign(block);
- uiDefIconButBitS(block, TOG, SENS_PULSE_REPEAT, 1, ICON_DOTSUP,
- (short)(x + 10 + 0.0 * (w - 20)), (short)(y - 21), (short)(0.1 * (w - 20)), 19,
- &sens->pulse, 0.0, 0.0, 0, 0,
- "Activate TRUE level triggering (pulse mode)");
-
- uiDefIconButBitS(block, TOG, SENS_NEG_PULSE_MODE, 1, ICON_DOTSDOWN,
- (short)(x + 10 + 0.1 * (w-20)), (short)(y - 21), (short)(0.1 * (w-20)), 19,
- &sens->pulse, 0.0, 0.0, 0, 0,
- "Activate FALSE level triggering (pulse mode)");
- uiDefButS(block, NUM, 1, "f:",
- (short)(x + 10 + 0.2 * (w-20)), (short)(y - 21), (short)(0.275 * (w-20)), 19,
- &sens->freq, 0.0, 10000.0, 0, 0,
- "Delay between repeated pulses (in logic tics, 0 = no delay)");
- uiBlockEndAlign(block);
-
- /* value or shift? */
- uiBlockBeginAlign(block);
- but = uiDefButS(block, TOG, 1, "Level",
- (short)(x + 10 + 0.5 * (w-20)), (short)(y - 21), (short)(0.20 * (w-20)), 19,
- &sens->level, 0.0, 0.0, 0, 0,
- "Level detector, trigger controllers of new states (only applicable upon logic state transition)");
- uiButSetFunc(but, verify_logicbutton_func, sens, &(sens->level));
- but = uiDefButS(block, TOG, 1, "Tap",
- (short)(x + 10 + 0.702 * (w-20)), (short)(y - 21), (short)(0.12 * (w-20)), 19,
- &sens->tap, 0.0, 0.0, 0, 0,
- "Trigger controllers only for an instant, even while the sensor remains true");
- uiButSetFunc(but, verify_logicbutton_func, sens, &(sens->tap));
- uiBlockEndAlign(block);
-
- uiDefButS(block, TOG, 1, "Inv",
- (short)(x + 10 + 0.85 * (w-20)), (short)(y - 21), (short)(0.15 * (w-20)), 19,
- &sens->invert, 0.0, 0.0, 0, 0,
- "Invert the level (output) of this sensor");
-}
-
static void get_armature_bone_constraint(Object *ob, const char *posechannel, const char *constraint_name, bConstraint **constraint)
{
/* check that bone exist in the active object */
@@ -1094,1848 +730,6 @@ static void get_armature_bone_constraint(Object *ob, const char *posechannel, co
}
/* didn't find any */
}
-static void check_armature_bone_constraint(Object *ob, char *posechannel, char *constraint)
-{
- /* check that bone exist in the active object */
- if (ob->type == OB_ARMATURE && ob->pose) {
- bPoseChannel *pchan;
- bPose *pose = ob->pose;
- for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
- if (!strcmp(pchan->name, posechannel)) {
- /* found it, now look for constraint channel */
- bConstraint *con;
- for (con=pchan->constraints.first; con; con=con->next) {
- if (!strcmp(con->name, constraint)) {
- /* found it, all ok */
- return;
- }
- }
- /* didn't find constraint, make empty */
- constraint[0] = 0;
- return;
- }
- }
- }
- /* didn't find any */
- posechannel[0] = 0;
- constraint[0] = 0;
-}
-
-static void check_armature_sensor(bContext *C, void *arg1_but, void *arg2_sens)
-{
- bArmatureSensor *sens = arg2_sens;
- uiBut *but = arg1_but;
- Object *ob= CTX_data_active_object(C);
-
- /* check that bone exist in the active object */
- but->retval = B_REDR;
- check_armature_bone_constraint(ob, sens->posechannel, sens->constraint);
-}
-
-static short draw_sensorbuttons(Object *ob, bSensor *sens, uiBlock *block, short xco, short yco, short width)
-{
- bNearSensor *ns = NULL;
- bTouchSensor *ts = NULL;
- bKeyboardSensor *ks = NULL;
- bPropertySensor *ps = NULL;
- bArmatureSensor *arm = NULL;
- bMouseSensor *ms = NULL;
- bCollisionSensor *cs = NULL;
- bRadarSensor *rs = NULL;
- bRandomSensor *randomSensor = NULL;
- bRaySensor *raySens = NULL;
- bMessageSensor *mes = NULL;
- bJoystickSensor *joy = NULL;
- bActuatorSensor *as = NULL;
- bDelaySensor *ds = NULL;
- uiBut *but;
- short ysize;
- const char *str;
-
- /* yco is at the top of the rect, draw downwards */
-
- set_col_sensor(sens->type, 0);
-
- switch (sens->type) {
- case SENS_ALWAYS:
- {
- ysize= 24;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
-
- yco-= ysize;
-
- break;
- }
- case SENS_TOUCH:
- {
- ysize= 48;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
-
- ts= sens->data;
-
- // uiDefBut(block, TEX, 1, "Property:", xco, yco-22, width, 19, &ts->name, 0, MAX_NAME, 0, 0, "Only look for Objects with this property");
- uiDefIDPoinBut(block, test_matpoin_but, ID_MA, 1, "MA:", (short)(xco + 10), (short)(yco-44), (short)(width - 20), 19, &ts->ma, "Only look for floors with this Material");
- // uiDefButF(block, NUM, 1, "Margin:", xco+width/2, yco-44, width/2, 19, &ts->dist, 0.0, 10.0, 100, 0, "Extra margin (distance) for larger sensitivity");
- yco-= ysize;
- break;
- }
- case SENS_COLLISION:
- {
- ysize= 48;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
- cs= sens->data;
-
- /* The collision sensor will become a generic collision (i.e. it */
- /* absorb the old touch sensor). */
-
- uiDefButBitS(block, TOG, SENS_COLLISION_PULSE, B_REDR, "Pulse", (short)(xco + 10), (short)(yco - 44),
- (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0,
- "Changes to the set of colliding objects generated pulses");
-
- uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P", (short)(xco + 10 + (0.20 * (width-20))), (short)(yco - 44),
- (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0,
- "Toggle collision on material or property");
-
- if (cs->mode & SENS_COLLISION_MATERIAL) {
- uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.40 * (width-20)),
- (short)(yco-44), (short)(0.6*(width-20)), 19, &cs->materialName, 0, MAX_NAME, 0, 0,
- "Only look for Objects with this material");
- }
- else {
- uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.40 * (width-20)), (short)(yco-44),
- (short)(0.6*(width-20)), 19, &cs->name, 0, MAX_NAME, 0, 0,
- "Only look for Objects with this property");
- }
-
- /* uiDefButS(block, NUM, 1, "Damp:", xco+10+width-90, yco-24, 70, 19, &cs->damp, 0, 250, 0, 0, "For 'damp' time don't detect another collision"); */
-
- yco-= ysize;
- break;
- }
- case SENS_NEAR:
- {
- ysize= 72;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
- ns= sens->data;
-
- uiDefBut(block, TEX, 1, "Property:", (short)(10+xco), (short)(yco-44), (short)(width-20), 19,
- &ns->name, 0, MAX_NAME, 0, 0, "Only look for Objects with this property");
- uiDefButF(block, NUM, 1, "Dist", (short)(10+xco), (short)(yco-68), (short)((width-22)/2), 19,
- &ns->dist, 0.0, 1000.0, 1000, 0, "Trigger distance");
- uiDefButF(block, NUM, 1, "Reset", (short)(10+xco+(width-22)/2), (short)(yco-68), (short)((width-22)/2), 19,
- &ns->resetdist, 0.0, 1000.0, 1000, 0, "Reset distance");
- yco-= ysize;
- break;
- }
- case SENS_RADAR:
- {
- ysize= 72;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
-
- rs= sens->data;
-
- uiDefBut(block, TEX, 1, "Prop:",
- (short)(10+xco), (short)(yco-44), (short)(0.7 * (width-20)), 19,
- &rs->name, 0, MAX_NAME, 0, 0,
- "Only look for Objects with this property");
-
- str = "Type %t|+X axis %x0|+Y axis %x1|+Z axis %x2|-X axis %x3|-Y axis %x4|-Z axis %x5";
- uiDefButS(block, MENU, B_REDR, str,
- (short)(10+xco+0.7 * (width-20)), (short)(yco-44), (short)(0.3 * (width-22)), 19,
- &rs->axis, 2.0, 31, 0, 0,
- "Specify along which axis the radar cone is cast");
-
- uiDefButF(block, NUM, 1, "Ang:",
- (short)(10+xco), (short)(yco-68), (short)((width-20)/2), 19,
- &rs->angle, 0.0, 179.9, 10, 0,
- "Opening angle of the radar cone");
- uiDefButF(block, NUM, 1, "Dist:",
- (short)(xco+10 + (width-20)/2), (short)(yco-68), (short)((width-20)/2), 19,
- &rs->range, 0.01, 10000.0, 100, 0,
- "Depth of the radar cone");
- yco-= ysize;
- break;
- }
- case SENS_KEYBOARD:
- {
- ks= sens->data;
-
- /* 5 lines: 120 height */
- ysize= (ks->type&1) ? 96:120;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- /* header line */
- draw_default_sensor_header(sens, block, xco, yco, width);
-
- /* part of line 1 */
- uiDefBut(block, LABEL, 0, "Key", xco, yco-44, 40, 19, NULL, 0, 0, 0, 0, "");
- uiDefButBitS(block, TOG, 1, B_REDR, "All keys", xco+40+(width/2), yco-44, (width/2)-50, 19,
- &ks->type, 0, 0, 0, 0, "");
-
-
- if ((ks->type&1)==0) { /* is All Keys option off? */
- /* line 2: hotkey and allkeys toggle */
- but = uiDefKeyevtButS(block, 0, "", xco+40, yco-44, (width)/2, 19, &ks->key, "Key code");
- uiButSetFunc(but, test_keyboard_event, ks, NULL);
-
- /* line 3: two key modifyers (qual1, qual2) */
- uiDefBut(block, LABEL, 0, "Hold", xco, yco-68, 40, 19, NULL, 0, 0, 0, 0, "");
- but = uiDefKeyevtButS(block, 0, "", xco+40, yco-68, (width-50)/2, 19, &ks->qual, "Modifier key code");
- uiButSetFunc(but, test_keyboard_event, ks, NULL);
- but = uiDefKeyevtButS(block, 0, "", xco+40+(width-50)/2, yco-68, (width-50)/2, 19, &ks->qual2, "Second Modifier key code");
- uiButSetFunc(but, test_keyboard_event, ks, NULL);
- }
-
- /* line 4: toggle property for string logging mode */
- uiDefBut(block, TEX, 1, "LogToggle: ",
- xco+10, yco-((ks->type&1) ? 68:92), (width-20), 19,
- ks->toggleName, 0, MAX_NAME, 0, 0,
- "Property that indicates whether to log "
- "keystrokes as a string");
-
- /* line 5: target property for string logging mode */
- uiDefBut(block, TEX, 1, "Target: ",
- xco+10, yco-((ks->type&1) ? 92:116), (width-20), 19,
- ks->targetName, 0, MAX_NAME, 0, 0,
- "Property that receives the keystrokes in case "
- "a string is logged");
-
- yco-= ysize;
- break;
- }
- case SENS_PROPERTY:
- {
- ysize= 96;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize,
- (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
- ps= sens->data;
-
- str= "Type %t|Equal %x0|Not Equal %x1|Interval %x2|Changed %x3";
- /* str= "Type %t|Equal %x0|Not Equal %x1"; */
- uiDefButI(block, MENU, B_REDR, str, xco+30, yco-44, width-60, 19,
- &ps->type, 0, 31, 0, 0, "Type");
-
- if (ps->type != SENS_PROP_EXPRESSION) {
- uiDefBut(block, TEX, 1, "Prop: ", xco+30, yco-68, width-60, 19,
- ps->name, 0, MAX_NAME, 0, 0, "Property name");
- }
-
- if (ps->type == SENS_PROP_INTERVAL) {
- uiDefBut(block, TEX, 1, "Min: ", xco, yco-92, width/2, 19,
- ps->value, 0, MAX_NAME, 0, 0, "check for min value");
- uiDefBut(block, TEX, 1, "Max: ", xco+width/2, yco-92, width/2, 19,
- ps->maxvalue, 0, MAX_NAME, 0, 0, "check for max value");
- }
- else if (ps->type == SENS_PROP_CHANGED) {
- /* pass */
- }
- else {
- uiDefBut(block, TEX, 1, "Value: ", xco+30, yco-92, width-60, 19,
- ps->value, 0, MAX_NAME, 0, 0, "check for value");
- }
-
- yco-= ysize;
- break;
- }
- case SENS_ARMATURE:
- {
- ysize= 70;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize,
- (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
- arm= sens->data;
-
- if (ob->type == OB_ARMATURE) {
- uiBlockBeginAlign(block);
- but = uiDefBut(block, TEX, 1, "Bone: ",
- (xco+10), (yco-44), (width-20)/2, 19,
- arm->posechannel, 0, MAX_NAME, 0, 0,
- "Bone on which you want to check a constraint");
- uiButSetFunc(but, check_armature_sensor, but, arm);
- but = uiDefBut(block, TEX, 1, "Cons: ",
- (xco+10)+(width-20)/2, (yco-44), (width-20)/2, 19,
- arm->constraint, 0, MAX_NAME, 0, 0,
- "Name of the constraint you want to control");
- uiButSetFunc(but, check_armature_sensor, but, arm);
- uiBlockEndAlign(block);
-
- str= "Type %t|State changed %x0|Lin error below %x1|Lin error above %x2|Rot error below %x3|Rot error above %x4";
-
- uiDefButI(block, MENU, B_REDR, str, xco+10, yco-66, 0.4*(width-20), 19,
- &arm->type, 0, 31, 0, 0, "Type");
-
- if (arm->type != SENS_ARM_STATE_CHANGED) {
- uiDefButF(block, NUM, 1, "Value: ", xco+10+0.4*(width-20), yco-66, 0.6*(width-20), 19,
- &arm->value, -10000.0, 10000.0, 100, 0, "Test the error against this value");
- }
- }
- yco-= ysize;
- break;
- }
- case SENS_ACTUATOR:
- {
- ysize= 48;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize,
- (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
- as= sens->data;
-
- uiDefBut(block, TEX, 1, "Act: ", xco+30, yco-44, width-60, 19,
- as->name, 0, MAX_NAME, 0, 0, "Actuator name, actuator active state modifications will be detected");
- yco-= ysize;
- break;
- }
- case SENS_DELAY:
- {
- ysize= 48;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize,
- (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
- ds = sens->data;
-
- uiDefButS(block, NUM, 0, "Delay", (short)(10+xco), (short)(yco-44), (short)((width-22)*0.4+10), 19,
- &ds->delay, 0.0, 5000.0, 0, 0, "Delay in number of logic tics before the positive trigger (default 60 per second)");
- uiDefButS(block, NUM, 0, "Dur", (short)(10+xco+(width-22)*0.4+10), (short)(yco-44), (short)((width-22)*0.4-10), 19,
- &ds->duration, 0.0, 5000.0, 0, 0, "If >0, delay in number of logic tics before the negative trigger following the positive trigger");
- uiDefButBitS(block, TOG, SENS_DELAY_REPEAT, 0, "REP", (short)(xco + 10 + (width-22)*0.8), (short)(yco - 44),
- (short)(0.20 * (width-22)), 19, &ds->flag, 0.0, 0.0, 0, 0,
- "Toggle repeat option. If selected, the sensor restarts after Delay+Dur logic tics");
- yco-= ysize;
- break;
- }
- case SENS_MOUSE:
- {
- ms= sens->data;
- /* Two lines: 48 pixels high. */
- ysize = 48;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- /* line 1: header */
- draw_default_sensor_header(sens, block, xco, yco, width);
-
- /* Line 2: type selection. The number are a bit mangled to get
- * proper compatibility with older .blend files. */
-
- /* Any sensor type default is 0 but the ms enum starts in 1.
- * Therefore the mouse sensor is initialized to 1 in sca.c */
- str= "Type %t|Left button %x1|Middle button %x2|"
- "Right button %x4|Wheel Up %x5|Wheel Down %x6|Movement %x8|Mouse over %x16|Mouse over any%x32";
- uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, (width*0.8f)-20, 19,
- &ms->type, 0, 31, 0, 0,
- "Specify the type of event this mouse sensor should trigger on");
-
- if (ms->type==32) {
- uiDefButBitS(block, TOG, SENS_MOUSE_FOCUS_PULSE, B_REDR, "Pulse", (short)(xco + 10) + (width*0.8f)-20, (short)(yco - 44),
- (short)(0.20 * (width-20)), 19, &ms->flag, 0.0, 0.0, 0, 0,
- "Moving the mouse over a different object generates a pulse");
- }
-
- yco-= ysize;
- break;
- }
- case SENS_RANDOM:
- {
- ysize = 48;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
- randomSensor = sens->data;
- /* some files were wrongly written, avoid crash now */
- if (randomSensor) {
- uiDefButI(block, NUM, 1, "Seed: ", xco+10, yco-44, (width-20), 19,
- &randomSensor->seed, 0, 1000, 0, 0,
- "Initial seed of the generator. (Choose 0 for not random)");
- }
- yco-= ysize;
- break;
- }
- case SENS_RAY:
- {
- ysize = 72;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- draw_default_sensor_header(sens, block, xco, yco, width);
- raySens = sens->data;
-
- /* 1. property or material */
- uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P",
- xco + 10, yco - 44, 0.20 * (width-20), 19,
- &raySens->mode, 0.0, 0.0, 0, 0,
- "Toggle collision on material or property");
-
- if (raySens->mode & SENS_COLLISION_MATERIAL) {
- uiDefBut(block, TEX, 1, "Material:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19,
- &raySens->matname, 0, MAX_NAME, 0, 0,
- "Only look for Objects with this material");
- }
- else {
- uiDefBut(block, TEX, 1, "Property:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19,
- &raySens->propname, 0, MAX_NAME, 0, 0,
- "Only look for Objects with this property");
- }
-
- /* X-Ray option */
- uiDefButBitS(block, TOG, SENS_RAY_XRAY, 1, "X",
- xco + 10, yco - 68, 0.10 * (width-20), 19,
- &raySens->mode, 0.0, 0.0, 0, 0,
- "Toggle X-Ray option (see through objects that don't have the property)");
- /* 2. sensing range */
- uiDefButF(block, NUM, 1, "Range", xco+10 + 0.10 * (width-20), yco-68, 0.5 * (width-20), 19,
- &raySens->range, 0.01, 10000.0, 100, 0,
- "Sense objects no farther than this distance");
-
- /* 3. axis choice */
- str = "Type %t|+ X axis %x1|+ Y axis %x0|+ Z axis %x2|- X axis %x3|- Y axis %x4|- Z axis %x5";
- uiDefButI(block, MENU, B_REDR, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19,
- &raySens->axisflag, 2.0, 31, 0, 0,
- "Specify along which axis the ray is cast");
-
- yco-= ysize;
- break;
- }
- case SENS_MESSAGE:
- {
- mes = sens->data;
- ysize = 2 * 24; /* total number of lines * 24 pixels/line */
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize,
- (float)xco+width, (float)yco, 1);
-
- /* line 1: header line */
- draw_default_sensor_header(sens, block, xco, yco, width);
-
- /* line 2: Subject filter */
- uiDefBut(block, TEX, 1, "Subject: ",
- (xco+10), (yco-44), (width-20), 19,
- mes->subject, 0, MAX_NAME, 0, 0,
- "Optional subject filter: only accept messages with this subject"
- ", or empty for all");
-
- yco -= ysize;
- break;
- }
- case SENS_JOYSTICK:
- {
-
- ysize = 72;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- /* line 1: header */
- draw_default_sensor_header(sens, block, xco, yco, width);
-
- joy= sens->data;
-
- uiDefButC(block, NUM, 1, "Index:", xco+10, yco-44, 0.33 * (width-20), 19,
- &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0,
- "Specify which joystick to use");
-
- str= "Type %t|Button %x0|Axis %x1|Single Axis %x3|Hat%x2";
- uiDefButC(block, MENU, B_REDR, str, xco+87, yco-44, 0.26 * (width-20), 19,
- &joy->type, 0, 31, 0, 0,
- "The type of event this joystick sensor is triggered on");
-
- if (joy->type != SENS_JOY_AXIS_SINGLE) {
- if (joy->flag & SENS_JOY_ANY_EVENT) {
- switch (joy->type) {
- case SENS_JOY_AXIS:
- str = "All Axis Events";
- break;
- case SENS_JOY_BUTTON:
- str = "All Button Events";
- break;
- default:
- str = "All Hat Events";
- break;
- }
- }
- else {
- str = "All";
- }
-
- uiDefButBitS(block, TOG, SENS_JOY_ANY_EVENT, B_REDR, str,
- xco+10 + 0.475 * (width-20), yco-68, ((joy->flag & SENS_JOY_ANY_EVENT) ? 0.525 : 0.12) * (width-20), 19,
- &joy->flag, 0, 0, 0, 0,
- "Triggered by all events on this joysticks current type (axis/button/hat)");
- }
- if (joy->type == SENS_JOY_BUTTON) {
- if ((joy->flag & SENS_JOY_ANY_EVENT)==0) {
- uiDefButI(block, NUM, 1, "Number:", xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19,
- &joy->button, 0, 18, 100, 0,
- "Specify which button to use");
- }
- }
- else if (joy->type == SENS_JOY_AXIS) {
- uiDefButS(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19,
- &joy->axis, 1, 8.0, 100, 0,
- "Specify which axis pair to use, 1 is useually the main direction input");
-
- uiDefButI(block, NUM, 1, "Threshold:", xco+10 + 0.6 * (width-20), yco-44, 0.4 * (width-20), 19,
- &joy->precision, 0, 32768.0, 100, 0,
- "Specify the precision of the axis");
-
- if ((joy->flag & SENS_JOY_ANY_EVENT)==0) {
- str = "Type %t|Up Axis %x1 |Down Axis %x3|Left Axis %x2|Right Axis %x0";
- uiDefButI(block, MENU, B_REDR, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19,
- &joy->axisf, 2.0, 31, 0, 0,
- "The direction of the axis, use 'All Events' to receive events on any direction");
- }
- }
- else if (joy->type == SENS_JOY_HAT) {
- uiDefButI(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19,
- &joy->hat, 1, 4.0, 100, 0,
- "Specify which hat to use");
-
- if ((joy->flag & SENS_JOY_ANY_EVENT)==0) {
- str = "Direction%t|Up%x1|Down%x4|Left%x8|Right%x2|%l|Up/Right%x3|Down/Left%x12|Up/Left%x9|Down/Right%x6";
- uiDefButI(block, MENU, 0, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19,
- &joy->hatf, 2.0, 31, 0, 0,
- "The direction of the hat, use 'All Events' to receive events on any direction");
- }
- }
- else { /* (joy->type == SENS_JOY_AXIS_SINGLE)*/
- uiDefButS(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19,
- &joy->axis_single, 1, 16.0, 100, 0,
- "Specify a single axis (verticle/horizontal/other) to detect");
-
- uiDefButI(block, NUM, 1, "Threshold:", xco+10 + 0.6 * (width-20), yco-44, 0.4 * (width-20), 19,
- &joy->precision, 0, 32768.0, 100, 0,
- "Specify the precision of the axis");
- }
- yco-= ysize;
- break;
- }
- }
-
- return yco-4;
-}
-
-
-
-static short draw_controllerbuttons(bController *cont, uiBlock *block, short xco, short yco, short width)
-{
- bExpressionCont *ec;
- bPythonCont *pc;
- short ysize;
-
- switch (cont->type) {
- case CONT_EXPRESSION:
- ysize= 28;
-
- UI_ThemeColor(TH_PANEL);
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- /* uiDefBut(block, LABEL, 1, "Not yet...", xco, yco-24, 80, 19, NULL, 0, 0, 0, 0, ""); */
- ec= cont->data;
- /* uiDefBut(block, BUT, 1, "Variables", xco, yco-24, 80, 19, NULL, 0, 0, 0, 0, "Available variables for expression"); */
- uiDefBut(block, TEX, 1, "Exp:", xco + 10, yco-21, width-20, 19,
- ec->str, 0, sizeof(ec->str), 0, 0,
- "Expression");
-
- yco-= ysize;
- break;
- case CONT_PYTHON:
- ysize= 28;
-
- if (cont->data==NULL) init_controller(cont);
- pc= cont->data;
-
- UI_ThemeColor(TH_PANEL);
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
-
- uiBlockBeginAlign(block);
- uiDefButI(block, MENU, B_REDR, "Execution Method%t|Script%x0|Module%x1", xco+4, yco-23, 66, 19, &pc->mode, 0, 0, 0, 0, "Python script type (textblock or module - faster)");
- if (pc->mode==0)
- uiDefIDPoinBut(block, test_scriptpoin_but, ID_TXT, 1, "", xco+70, yco-23, width-74, 19, &pc->text, "Blender textblock to run as a script");
- else {
- uiDefBut(block, TEX, 1, "", xco+70, yco-23, (width-70)-25, 19, pc->module, 0, sizeof(pc->module), 0, 0, "Module name and function to run e.g. \"someModule.main\". Internal texts and external python files can be used");
- uiDefButBitI(block, TOG, CONT_PY_DEBUG, B_REDR, "D", (xco+width)-25, yco-23, 19, 19, &pc->flag, 0, 0, 0, 0, "Continuously reload the module from disk for editing external modules without restarting");
- }
- uiBlockEndAlign(block);
-
- yco-= ysize;
- break;
-
- default:
- ysize= 4;
-
- UI_ThemeColor(TH_PANEL);
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- yco-= ysize;
- }
-
- return yco;
-}
-
-static int get_col_actuator(int type)
-{
- switch (type) {
- case ACT_ACTION: return TH_PANEL;
- case ACT_SHAPEACTION: return TH_PANEL;
- case ACT_OBJECT: return TH_PANEL;
- case ACT_IPO: return TH_PANEL;
- case ACT_PROPERTY: return TH_PANEL;
- case ACT_SOUND: return TH_PANEL;
- case ACT_CAMERA: return TH_PANEL;
- case ACT_EDIT_OBJECT: return TH_PANEL;
- case ACT_GROUP: return TH_PANEL;
- case ACT_RANDOM: return TH_PANEL;
- case ACT_SCENE: return TH_PANEL;
- case ACT_MESSAGE: return TH_PANEL;
- case ACT_GAME: return TH_PANEL;
- case ACT_VISIBILITY: return TH_PANEL;
- case ACT_CONSTRAINT: return TH_PANEL;
- case ACT_STATE: return TH_PANEL;
- case ACT_ARMATURE: return TH_PANEL;
- case ACT_STEERING: return TH_PANEL;
- default: return TH_PANEL;
- }
-}
-static void set_col_actuator(int item, int medium)
-{
- int col= get_col_actuator(item);
- UI_ThemeColorShade(col, medium?30:10);
-
-}
-
-static void change_object_actuator(bContext *UNUSED(C), void *act, void *UNUSED(arg))
-{
- bObjectActuator *oa = act;
-
- if (oa->type != oa->otype) {
- switch (oa->type) {
- case ACT_OBJECT_NORMAL:
- memset(oa, 0, sizeof(bObjectActuator));
- oa->flag = ACT_FORCE_LOCAL|ACT_TORQUE_LOCAL|ACT_DLOC_LOCAL|ACT_DROT_LOCAL;
- oa->type = ACT_OBJECT_NORMAL;
- break;
-
- case ACT_OBJECT_SERVO:
- memset(oa, 0, sizeof(bObjectActuator));
- oa->flag = ACT_LIN_VEL_LOCAL;
- oa->type = ACT_OBJECT_SERVO;
- oa->forcerot[0] = 30.0f;
- oa->forcerot[1] = 0.5f;
- oa->forcerot[2] = 0.0f;
- break;
- }
- }
-}
-
-static void change_ipo_actuator(bContext *UNUSED(C), void *arg1_but, void *arg2_ia)
-{
- bIpoActuator *ia = arg2_ia;
- uiBut *but = arg1_but;
-
- if (but->retval & ACT_IPOFORCE)
- ia->flag &= ~ACT_IPOADD;
- else if (but->retval & ACT_IPOADD)
- ia->flag &= ~ACT_IPOFORCE;
- but->retval = B_REDR;
-}
-
-static void update_object_actuator_PID(bContext *UNUSED(C), void *act, void *UNUSED(arg))
-{
- bObjectActuator *oa = act;
- oa->forcerot[0] = 60.0f*oa->forcerot[1];
-}
-
-static char *get_state_name(Object *ob, short bit)
-{
- bController *cont;
- unsigned int mask;
-
- mask = (1<<bit);
- cont = ob->controllers.first;
- while (cont) {
- if (cont->state_mask & mask) {
- return cont->name;
- }
- cont = cont->next;
- }
- return (char*)"";
-}
-
-static void check_state_mask(bContext *C, void *arg1_but, void *arg2_mask)
-{
- wmWindow *win= CTX_wm_window(C);
- int shift= win->eventstate->shift;
- unsigned int *cont_mask = arg2_mask;
- uiBut *but = arg1_but;
-
- if (*cont_mask == 0 || !(shift))
- *cont_mask = (1<<but->retval);
- but->retval = B_REDR;
-}
-
-static void check_armature_actuator(bContext *C, void *arg1_but, void *arg2_act)
-{
- bArmatureActuator *act = arg2_act;
- uiBut *but = arg1_but;
- Object *ob= CTX_data_active_object(C);
-
- /* check that bone exist in the active object */
- but->retval = B_REDR;
- check_armature_bone_constraint(ob, act->posechannel, act->constraint);
-}
-
-
-static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlock *block, short xco, short yco, short width)
-{
- bSoundActuator *sa = NULL;
- bObjectActuator *oa = NULL;
- bIpoActuator *ia = NULL;
- bPropertyActuator *pa = NULL;
- bCameraActuator *ca = NULL;
- bEditObjectActuator *eoa = NULL;
- bConstraintActuator *coa = NULL;
- bSceneActuator *sca = NULL;
- bGroupActuator *ga = NULL;
- bRandomActuator *randAct = NULL;
- bMessageActuator *ma = NULL;
- bActionActuator *aa = NULL;
- bGameActuator *gma = NULL;
- bVisibilityActuator *visAct = NULL;
- bTwoDFilterActuator *tdfa = NULL;
- bParentActuator *parAct = NULL;
- bStateActuator *staAct = NULL;
- bArmatureActuator *armAct = NULL;
-
- float *fp;
- short ysize = 0, wval;
- const char *str;
- int myline, stbit;
- uiBut *but;
-
-
- /* yco is at the top of the rect, draw downwards */
- set_col_actuator(act->type, 0);
-
- switch (act->type) {
- case ACT_OBJECT:
- {
- oa = act->data;
- wval = (width-100)/3;
- if (oa->type == ACT_OBJECT_NORMAL) {
- if (ob->gameflag & OB_DYNAMIC) {
- ysize= 175;
- }
- else {
- ysize= 72;
- }
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, 0, "Loc", xco, yco-45, 45, 19, NULL, 0, 0, 0, 0, "Sets the location");
- uiDefButF(block, NUM, 0, "", xco+45, yco-45, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-45, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-45, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, "");
- uiBlockEndAlign(block);
-
- uiDefBut(block, LABEL, 0, "Rot", xco, yco-64, 45, 19, NULL, 0, 0, 0, 0, "Sets the rotation");
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, 0, "", xco+45, yco-64, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-64, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-64, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, "");
- uiBlockEndAlign(block);
-
- uiDefButBitS(block, TOG, ACT_DLOC_LOCAL, 0, "L", xco+45+3*wval, yco-45, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
- uiDefButBitS(block, TOG, ACT_DROT_LOCAL, 0, "L", xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
-
- if (ob->gameflag & OB_DYNAMIC) {
- uiDefBut(block, LABEL, 0, "Force", xco, yco-87, 55, 19, NULL, 0, 0, 0, 0, "Sets the force");
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, 0, "", xco+45, yco-87, wval, 19, oa->forceloc, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-87, wval, 19, oa->forceloc+1, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-87, wval, 19, oa->forceloc+2, -10000.0, 10000.0, 10, 0, "");
- uiBlockEndAlign(block);
-
- uiDefBut(block, LABEL, 0, "Torque", xco, yco-106, 55, 19, NULL, 0, 0, 0, 0, "Sets the torque");
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, 0, "", xco+45, yco-106, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-106, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-106, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, "");
- uiBlockEndAlign(block);
- }
-
- if (ob->gameflag & OB_DYNAMIC) {
- uiDefBut(block, LABEL, 0, "LinV", xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Sets the linear velocity");
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, 0, "", xco+45, yco-129, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-129, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-129, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, "");
- uiBlockEndAlign(block);
-
- uiDefBut(block, LABEL, 0, "AngV", xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity");
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, 0, "", xco+45, yco-148, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-148, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-148, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, "");
- uiBlockEndAlign(block);
-
- uiDefBut(block, LABEL, 0, "Damp", xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity");
- uiDefButS(block, NUM, 0, "", xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, "");
-
- uiDefButBitS(block, TOG, ACT_FORCE_LOCAL, 0, "L", xco+45+3*wval, yco-87, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
- uiDefButBitS(block, TOG, ACT_TORQUE_LOCAL, 0, "L", xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
- uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-129, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
- uiDefButBitS(block, TOG, ACT_ANG_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-148, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
-
- uiDefButBitS(block, TOG, ACT_ADD_LIN_VEL, 0, "use_additive", xco+45+3*wval+15, yco-129, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV");
- }
- }
- else if (oa->type == ACT_OBJECT_SERVO) {
- ysize= 195;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefBut(block, LABEL, 0, "Ref", xco, yco-45, 45, 19, NULL, 0, 0, 0, 0, "");
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+45, yco-45, wval*3, 19, &(oa->reference), "Reference object for velocity calculation, leave empty for world reference");
- uiDefBut(block, LABEL, 0, "linV", xco, yco-68, 45, 19, NULL, 0, 0, 0, 0, "Sets the target relative linear velocity, it will be achieved by automatic application of force. Null velocity is a valid target");
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, 0, "", xco+45, yco-68, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-68, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, "");
- uiBlockEndAlign(block);
- uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-68, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Velocity is defined in local coordinates");
-
- uiDefBut(block, LABEL, 0, "Limit", xco, yco-91, 45, 19, NULL, 0, 0, 0, 0, "Select if the force needs to be limited along certain axis (local or global depending on LinV Local flag)");
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_X, B_REDR, "X", xco+45, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the X axis");
- uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_Y, B_REDR, "Y", xco+45+wval, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the Y axis");
- uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_Z, B_REDR, "Z", xco+45+2*wval, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the Z axis");
- uiBlockEndAlign(block);
- uiDefBut(block, LABEL, 0, "Max", xco, yco-110, 45, 19, NULL, 0, 0, 0, 0, "Set the upper limit for force");
- uiDefBut(block, LABEL, 0, "Min", xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Set the lower limit for force");
- if (oa->flag & ACT_SERVO_LIMIT_X) {
- uiDefButF(block, NUM, 0, "", xco+45, yco-110, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45, yco-129, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, "");
- }
- if (oa->flag & ACT_SERVO_LIMIT_Y) {
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-110, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-129, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, "");
- }
- if (oa->flag & ACT_SERVO_LIMIT_Z) {
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-110, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-129, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, "");
- }
- uiDefBut(block, LABEL, 0, "Servo", xco, yco-152, 45, 19, NULL, 0, 0, 0, 0, "Coefficients of the PID servo controller");
- uiDefButF(block, NUMSLI, B_REDR, "P: ", xco+45, yco-152, wval*3, 19, oa->forcerot, 0.00, 200.0, 100, 0, "Proportional coefficient, typical value is 60x Integral coefficient");
- uiDefBut(block, LABEL, 0, "Slow", xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Low value of I coefficient correspond to slow response");
- but = uiDefButF(block, NUMSLI, B_REDR, " I : ", xco+45, yco-171, wval*3, 19, oa->forcerot+1, 0.0, 3.0, 1, 0, "Integral coefficient, low value (0.01) for slow response, high value (0.5) for fast response");
- uiButSetFunc(but, update_object_actuator_PID, oa, NULL);
- uiDefBut(block, LABEL, 0, "Fast", xco+45+3*wval, yco-171, 45, 19, NULL, 0, 0, 0, 0, "High value of I coefficient correspond to fast response");
- uiDefButF(block, NUMSLI, B_REDR, "D: ", xco+45, yco-190, wval*3, 19, oa->forcerot+2, -100.0, 100.0, 100, 0, "Derivate coefficient, not required, high values can cause instability");
- }
- str= "Motion Type %t|Simple motion %x0|Servo Control %x1";
- but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &oa->type, 0.0, 0.0, 0, 0, "");
- oa->otype = oa->type;
- uiButSetFunc(but, change_object_actuator, oa, NULL);
- yco-= ysize;
- break;
- }
- case ACT_ACTION:
- case ACT_SHAPEACTION:
- {
- /* DrawAct */
-#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
- ysize = 112;
-#else
- ysize= 92;
-#endif
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- aa = act->data;
- wval = (width-60)/3;
-
- // str= "Action types %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
-#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
- str= "Action types %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6|Displacement %x7";
-#else
- str= "Action types %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
-#endif
- uiDefButS(block, MENU, B_REDR, str, xco+10, yco-24, width/3, 19, &aa->type, 0.0, 0.0, 0.0, 0.0, "Action playback type");
- uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, 1, "AC: ", xco+10+ (width/3), yco-24, ((width/3)*2) - (20 + 60), 19, &aa->act, "Action name");
-
- uiDefButBitS(block, TOGN, 1, 0, "Continue", xco+((width/3)*2)+20, yco-24, 60, 19,
- &aa->end_reset, 0.0, 0.0, 0, 0, "Restore last frame when switching on/off, otherwise play from the start each time");
-
-
- if (aa->type == ACT_ACTION_FROM_PROP) {
- uiDefBut(block, TEX, 0, "Prop: ", xco+10, yco-44, width-20, 19, aa->name, 0.0, MAX_NAME, 0, 0, "Use this property to define the Action position");
- }
- else {
- uiDefButF(block, NUM, 0, "Sta: ", xco+10, yco-44, (width-20)/2, 19, &aa->sta, 1.0, MAXFRAMEF, 0, 0, "Start frame");
- uiDefButF(block, NUM, 0, "End: ", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &aa->end, 1.0, MAXFRAMEF, 0, 0, "End frame");
- }
-
- uiDefButS(block, NUM, 0, "Blendin: ", xco+10, yco-64, (width-20)/2, 19, &aa->blendin, 0.0, 32767, 0.0, 0.0, "Number of frames of motion blending");
- uiDefButS(block, NUM, 0, "Priority: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers, With 2 or more actions at once, the overriding channels must be lower in the stack");
-
- uiDefBut(block, TEX, 0, "FrameProp: ", xco+10, yco-84, width-20, 19, aa->frameProp, 0.0, MAX_NAME, 0, 0, "Assign the action's current frame number to this property");
-
-
-#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
- if (aa->type == ACT_ACTION_MOTION) {
- uiDefButF(block, NUM, 0, "Cycle: ", xco+30, yco-84, (width-60)/2, 19, &aa->stridelength, 0.0, 2500.0, 0, 0, "Distance covered by a single cycle of the action");
- }
-#endif
-
-
-
- yco-=ysize;
- break;
- }
- case ACT_IPO:
- {
- ia= act->data;
-
- ysize= 72;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- str = "Ipo types %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
-
- uiDefButS(block, MENU, B_REDR, str, xco+10, yco-24, (width-20)/2, 19, &ia->type, 0, 0, 0, 0, "");
-
- but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE,
- "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19,
- &ia->flag, 0, 0, 0, 0,
- "Apply Ipo as a global or local force depending on the local option (dynamic objects only)");
- uiButSetFunc(but, change_ipo_actuator, but, ia);
-
- but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD,
- "Add", xco+3*(width-20)/4, yco-24, (width-20)/4-10, 19,
- &ia->flag, 0, 0, 0, 0,
- "Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag");
- uiButSetFunc(but, change_ipo_actuator, but, ia);
-
- /* Only show the do-force-local toggle if force is requested */
- if (ia->flag & (ACT_IPOFORCE|ACT_IPOADD)) {
- uiDefButBitS(block, TOG, ACT_IPOLOCAL, 0,
- "L", xco+width-30, yco-24, 20, 19,
- &ia->flag, 0, 0, 0, 0,
- "Let the ipo acts in local coordinates, used in Force and Add mode");
- }
-
- if (ia->type==ACT_IPO_FROM_PROP) {
- uiDefBut(block, TEX, 0,
- "Prop: ", xco+10, yco-44, width-80, 19,
- ia->name, 0.0, MAX_NAME, 0, 0,
- "Use this property to define the Ipo position");
- }
- else {
- uiDefButF(block, NUM, 0,
- "Sta", xco+10, yco-44, (width-80)/2, 19,
- &ia->sta, 1.0, MAXFRAMEF, 0, 0,
- "Start frame");
- uiDefButF(block, NUM, 0,
- "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19,
- &ia->end, 1.0, MAXFRAMEF, 0, 0,
- "End frame");
- }
- uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR,
- "Child", xco+10+(width-80), yco-44, 60, 19,
- &ia->flag, 0, 0, 0, 0,
- "Update IPO on all children Objects as well");
- uiDefBut(block, TEX, 0,
- "FrameProp: ", xco+10, yco-64, width-20, 19,
- ia->frameProp, 0.0, MAX_NAME, 0, 0,
- "Assign the action's current frame number to this property");
-
- yco-= ysize;
- break;
- }
- case ACT_PROPERTY:
- {
- ysize= 68;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- pa= act->data;
-
- str= "Type%t|Assign%x0|Add %x1|Copy %x2|Toggle (bool/int/float/timer)%x3";
- uiDefButI(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &pa->type, 0, 31, 0, 0, "Type");
-
- uiDefBut(block, TEX, 1, "Prop: ", xco+30, yco-44, width-60, 19, pa->name, 0, MAX_NAME, 0, 0, "Property name");
-
-
- if (pa->type==ACT_PROP_TOGGLE) {
- /* no ui */
- ysize -= 22;
- }
- else if (pa->type==ACT_PROP_COPY) {
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-64, (width-20)/2, 19, &(pa->ob), "Copy from this Object");
- uiDefBut(block, TEX, 1, "Prop: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, MAX_NAME, 0, 0, "Copy this property");
- }
- else {
- uiDefBut(block, TEX, 1, "Value: ", xco+30, yco-64, width-60, 19, pa->value, 0, MAX_NAME, 0, 0, "change with this value, use \"\" around strings");
- }
- yco-= ysize;
-
- break;
- }
- case ACT_SOUND:
- {
- sa = act->data;
- sa->sndnr = 0;
-
- if (sa->flag & ACT_SND_3D_SOUND)
- ysize = 180;
- else
- ysize = 92;
-
- wval = (width-20)/2;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- if (bmain->sound.first) {
- IDnames_to_pupstring(&str, "Sound files", NULL, &(bmain->sound), (ID *)sa->sound, &(sa->sndnr));
- /* reset this value, it is for handling the event */
- sa->sndnr = 0;
- uiDefButS(block, MENU, B_SOUNDACT_BROWSE, str, xco+10, yco-22, 20, 19, &(sa->sndnr), 0, 0, 0, 0, "");
- uiDefButO(block, BUT, "sound.open", 0, "Load Sound", xco+wval+10, yco-22, wval, 19,
- "Load a sound file (remember to set caching on for small sounds that are played often)");
-
- if (sa->sound) {
- char dummy_str[] = "Sound mode %t|Play Stop %x0|Play End %x1|Loop Stop %x2|"
- "Loop End %x3|Loop Ping Pong Stop %x5|Loop Ping Pong %x4";
- uiDefBut(block, TEX, B_IDNAME, "SO:", xco+30, yco-22, wval-20, 19,
- ((ID *)sa->sound)->name+2, 0.0, MAX_ID_NAME-2, 0, 0, "");
- uiDefButS(block, MENU, 1, dummy_str, xco+10, yco-44, width-20, 19,
- &sa->type, 0.0, 0.0, 0, 0, "");
- uiDefButF(block, NUM, 0, "Volume:", xco+10, yco-66, wval, 19, &sa->volume,
- 0.0, 1.0, 0, 0, "Sets the volume of this sound");
- uiDefButF(block, NUM, 0, "Pitch:", xco+wval+10, yco-66, wval, 19, &sa->pitch, -12.0,
- 12.0, 0, 0, "Sets the pitch of this sound");
- uiDefButS(block, TOG | UI_BUT_POIN_BIT, 0, "3D Sound", xco+10, yco-88, width-20, 19,
- &sa->flag, 0.0, 1.0, 0.0, 0.0, "Plays the sound positioned in 3D space");
- if (sa->flag & ACT_SND_3D_SOUND) {
- uiDefButF(block, NUM, 0, "Minimum Gain: ", xco+10, yco-110, wval, 19,
- &sa->sound3D.min_gain, 0.0, 1.0, 0.0, 0.0,
- "The minimum gain of the sound, no matter how far it is away");
- uiDefButF(block, NUM, 0, "Maximum Gain: ", xco+10, yco-132, wval, 19,
- &sa->sound3D.max_gain, 0.0, 1.0, 0.0, 0.0,
- "The maximum gain of the sound, no matter how near it is");
- uiDefButF(block, NUM, 0, "Reference Distance: ", xco+10, yco-154, wval, 19,
- &sa->sound3D.reference_distance, 0.0, FLT_MAX, 0.0, 0.0,
- "The reference distance is the distance where the sound has a gain of 1.0");
- uiDefButF(block, NUM, 0, "Maximum Distance: ", xco+10, yco-176, wval, 19,
- &sa->sound3D.max_distance, 0.0, FLT_MAX, 0.0, 0.0,
- "The maximum distance at which you can hear the sound");
- uiDefButF(block, NUM, 0, "Rolloff: ", xco+wval+10, yco-110, wval, 19,
- &sa->sound3D.rolloff_factor, 0.0, 5.0, 0.0, 0.0,
- "The rolloff factor defines the influence factor on volume depending on distance");
- uiDefButF(block, NUM, 0, "Cone Outer Gain: ", xco+wval+10, yco-132, wval, 19,
- &sa->sound3D.cone_outer_gain, 0.0, 1.0, 0.0, 0.0,
- "The gain outside the outer cone. The gain in the outer cone will be "
- "interpolated between this value and the normal gain in the inner cone");
- uiDefButF(block, NUM, 0, "Cone Outer Angle: ", xco+wval+10, yco-154, wval,
- 19, &sa->sound3D.cone_outer_angle, 0.0, 360.0, 0.0, 0.0,
- "The angle of the outer cone");
- uiDefButF(block, NUM, 0, "Cone Inner Angle: ", xco+wval+10, yco-176, wval,
- 19, &sa->sound3D.cone_inner_angle, 0.0, 360.0, 0.0, 0.0,
- "The angle of the inner cone");
- }
- }
- MEM_freeN((void *)str);
- }
- else {
- uiDefButO(block, BUT, "sound.open", 0, "Load Sound", xco+10, yco-22, width-20, 19, "Load a sound file");
- }
-
- yco-= ysize;
-
- break;
- }
- case ACT_CAMERA:
-
- ysize= 48;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- ca= act->data;
-
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-24, (width-20)/2, 19, &(ca->ob), "Look at this Object");
- uiDefButF(block, NUM, 0, "Height:", xco+10+(width-20)/2, yco-24, (width-20)/2, 19, &ca->height, 0.0, 20.0, 0, 0, "");
-
- uiDefButF(block, NUM, 0, "Min:", xco+10, yco-44, (width-60)/2, 19, &ca->min, 0.0, 20.0, 0, 0, "");
-
- if (ca->axis==0) ca->axis= 'x';
- uiDefButS(block, ROW, 0, "X", xco+10+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'x', 0, 0, "Camera tries to get behind the X axis");
- uiDefButS(block, ROW, 0, "Y", xco+30+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'y', 0, 0, "Camera tries to get behind the Y axis");
-
- uiDefButF(block, NUM, 0, "Max:", xco+20+(width)/2, yco-44, (width-60)/2, 19, &ca->max, 0.0, 20.0, 0, 0, "");
-
- yco-= ysize;
-
- break;
-
- case ACT_EDIT_OBJECT:
-
- eoa= act->data;
-
- if (eoa->type==ACT_EDOB_ADD_OBJECT) {
- ysize = 92;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Add this Object and all its children (cant be on an visible layer)");
- uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the new Object lives");
-
- wval= (width-60)/3;
- uiDefBut(block, LABEL, 0, "linV", xco, yco-68, 45, 19,
- NULL, 0, 0, 0, 0,
- "Velocity upon creation");
- uiDefButF(block, NUM, 0, "", xco+45, yco-68, wval, 19,
- eoa->linVelocity, -100.0, 100.0, 10, 0,
- "Velocity upon creation, x component");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-68, wval, 19,
- eoa->linVelocity+1, -100.0, 100.0, 10, 0,
- "Velocity upon creation, y component");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19,
- eoa->linVelocity+2, -100.0, 100.0, 10, 0,
- "Velocity upon creation, z component");
- uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_LINV, 0, "L", xco+45+3*wval, yco-68, 15, 19,
- &eoa->localflag, 0.0, 0.0, 0, 0,
- "Apply the transformation locally");
-
-
- uiDefBut(block, LABEL, 0, "AngV", xco, yco-90, 45, 19,
- NULL, 0, 0, 0, 0,
- "Angular velocity upon creation");
- uiDefButF(block, NUM, 0, "", xco+45, yco-90, wval, 19,
- eoa->angVelocity, -10000.0, 10000.0, 10, 0,
- "Angular velocity upon creation, x component");
- uiDefButF(block, NUM, 0, "", xco+45+wval, yco-90, wval, 19,
- eoa->angVelocity+1, -10000.0, 10000.0, 10, 0,
- "Angular velocity upon creation, y component");
- uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-90, wval, 19,
- eoa->angVelocity+2, -10000.0, 10000.0, 10, 0,
- "Angular velocity upon creation, z component");
- uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_ANGV, 0, "L", xco+45+3*wval, yco-90, 15, 19,
- &eoa->localflag, 0.0, 0.0, 0, 0,
- "Apply the rotation locally");
-
-
- }
- else if (eoa->type==ACT_EDOB_END_OBJECT) {
- ysize= 28;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
- }
- else if (eoa->type==ACT_EDOB_REPLACE_MESH) {
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, 1, "ME:", xco+40, yco-44, (width-80)/2, 19, &(eoa->me), "replace the existing, when left blank 'Phys' will remake the existing physics mesh");
-
- uiDefButBitS(block, TOGN, ACT_EDOB_REPLACE_MESH_NOGFX, 0, "Gfx", xco+40 + (width-80)/2, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the display mesh");
- uiDefButBitS(block, TOG, ACT_EDOB_REPLACE_MESH_PHYS, 0, "Phys", xco+40 + (width-80)/2 +(width-80)/4, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the physics mesh (triangle bounds only. compound shapes not supported)");
- }
- else if (eoa->type==ACT_EDOB_TRACK_TO) {
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Track to this Object");
- uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2-40, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the tracking takes");
- uiDefButS(block, TOG, 0, "3D", xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking");
- }
- else if (eoa->type==ACT_EDOB_DYNAMICS) {
- ysize= 69;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3|Set Mass %x4";
- uiDefButS(block, MENU, B_REDR, str, xco+40, yco-44, (width-80), 19, &(eoa->dyn_operation), 0.0, 0.0, 0, 0, "");
- if (eoa->dyn_operation==4) {
- uiDefButF(block, NUM, 0, "", xco+40, yco-63, width-80, 19,
- &eoa->mass, 0.0, 10000.0, 10, 0,
- "Mass for object");
- }
- }
- str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3|Dynamics %x4";
- uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, "");
-
- yco-= ysize;
-
- break;
-
- case ACT_CONSTRAINT:
- coa= act->data;
-
- if (coa->type == ACT_CONST_TYPE_LOC) {
- ysize= 69;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- /* str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4|Rot X %x8|Rot Y %x16|Rot Z %x32"; */
- /* coa->flag &= ~(63); */
- str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4";
- coa->flag &= 7;
- coa->time = 0;
- uiDefButS(block, MENU, 1, str, xco+10, yco-65, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, "");
-
- uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
- uiDefBut(block, LABEL, 0, "Min", xco+80, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, LABEL, 0, "Max", xco+80+(width-90)/2, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
-
- if (coa->flag & ACT_CONST_LOCX) fp= coa->minloc;
- else if (coa->flag & ACT_CONST_LOCY) fp= coa->minloc+1;
- else if (coa->flag & ACT_CONST_LOCZ) fp= coa->minloc+2;
- else if (coa->flag & ACT_CONST_ROTX) fp= coa->minrot;
- else if (coa->flag & ACT_CONST_ROTY) fp= coa->minrot+1;
- else fp= coa->minrot+2;
-
- uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-90)/2, 19, fp, -2000.0, 2000.0, 10, 0, "");
- uiDefButF(block, NUM, 0, "", xco+80+(width-90)/2, yco-65, (width-90)/2, 19, fp+3, -2000.0, 2000.0, 10, 0, "");
- }
- else if (coa->type == ACT_CONST_TYPE_DIST) {
- ysize= 106;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32";
- uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray");
-
- uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
- uiDefBut(block, LABEL, 0, "Range", xco+80, yco-45, (width-115)/2, 19, NULL, 0.0, 0.0, 0, 0, "Set the maximum length of ray");
- uiDefButBitS(block, TOG, ACT_CONST_DISTANCE, B_REDR, "Dist", xco+80+(width-115)/2, yco-45, (width-115)/2, 19, &coa->flag, 0.0, 0.0, 0, 0, "Force distance of object to point of impact of ray");
- uiDefButBitS(block, TOG, ACT_CONST_LOCAL, 0, "L", xco+80+(width-115), yco-45, 25, 19,
- &coa->flag, 0.0, 0.0, 0, 0, "Set ray along object's axis or global axis");
-
- if (coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc;
- else if (coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1;
- else fp= coa->minloc+2;
-
- uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/2, 19, fp+3, 0.0, 2000.0, 10, 0, "Maximum length of ray");
- if (coa->flag & ACT_CONST_DISTANCE)
- uiDefButF(block, NUM, 0, "", xco+80+(width-115)/2, yco-65, (width-115)/2, 19, fp, -2000.0, 2000.0, 10, 0, "Keep this distance to target");
- uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19,
- &coa->flag, 0.0, 0.0, 0, 0, "Set object axis along (local axis) or parallel (global axis) to the normal at hit position");
- uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19,
- &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property");
- if (coa->flag & ACT_CONST_MATERIAL) {
- uiDefBut(block, TEX, 1, "Material:", xco + 50, yco-84, (width-60), 19,
- coa->matprop, 0, MAX_NAME, 0, 0,
- "Ray detects only Objects with this material");
- }
- else {
- uiDefBut(block, TEX, 1, "Property:", xco + 50, yco-84, (width-60), 19,
- coa->matprop, 0, MAX_NAME, 0, 0,
- "Ray detect only Objects with this property");
- }
- uiDefButBitS(block, TOG, ACT_CONST_PERMANENT, 0, "PER", xco+10, yco-103, 40, 19,
- &coa->flag, 0.0, 0.0, 0, 0, "Persistent actuator: stays active even if ray does not reach target");
- uiDefButS(block, NUM, 0, "time", xco+50, yco-103, (width-60)/2, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited");
- uiDefButS(block, NUM, 0, "rotDamp", xco+50+(width-60)/2, yco-103, (width-60)/2, 19, &(coa->rotdamp), 0.0, 100.0, 0, 0, "Use a different damping for orientation");
- }
- else if (coa->type == ACT_CONST_TYPE_ORI) {
- ysize= 87;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4";
- uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Select the axis to be aligned along the reference direction");
-
- uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
- uiDefBut(block, LABEL, 0, "X", xco+80, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, LABEL, 0, "Y", xco+80+(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, LABEL, 0, "Z", xco+80+2*(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
-
- uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/3, 19, &coa->maxrot[0], -2000.0, 2000.0, 10, 0, "X component of reference direction");
- uiDefButF(block, NUM, 0, "", xco+80+(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[1], -2000.0, 2000.0, 10, 0, "Y component of reference direction");
- uiDefButF(block, NUM, 0, "", xco+80+2*(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[2], -2000.0, 2000.0, 10, 0, "Z component of reference direction");
-
- uiDefButS(block, NUM, 0, "time", xco+10, yco-84, 70, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited");
- uiDefButF(block, NUM, 0, "min", xco+80, yco-84, (width-115)/2, 19, &(coa->minloc[0]), 0.0, 180.0, 10, 1, "Minimum angle (in degree) to maintain with target direction. No correction is done if angle with target direction is between min and max");
- uiDefButF(block, NUM, 0, "max", xco+80+(width-115)/2, yco-84, (width-115)/2, 19, &(coa->maxloc[0]), 0.0, 180.0, 10, 1, "Maximum angle (in degree) allowed with target direction. No correction is done if angle with target direction is between min and max");
- }
- else if (coa->type == ACT_CONST_TYPE_FH) {
- ysize= 106;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32";
- uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray (in world coordinate)");
-
- if (coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc;
- else if (coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1;
- else fp= coa->minloc+2;
-
- uiDefButF(block, NUM, 0, "damp", xco+10, yco-45, (width-70)/2, 19, &coa->maxrot[0], 0.0, 1.0, 1, 0, "Damping factor of the Fh spring force");
- uiDefButF(block, NUM, 0, "dist", xco+10+(width-70)/2, yco-45, (width-70)/2, 19, fp, 0.010, 2000.0, 10, 0, "Height of the Fh area");
- uiDefButBitS(block, TOG, ACT_CONST_DOROTFH, 0, "Rot Fh", xco+10+(width-70), yco-45, 50, 19, &coa->flag, 0.0, 0.0, 0, 0, "Keep object axis parallel to normal");
-
- uiDefButF(block, NUMSLI, 0, "Fh ", xco+80, yco-65, (width-115), 19, fp+3, 0.0, 1.0, 0, 0, "Spring force within the Fh area");
- uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19,
- &coa->flag, 0.0, 0.0, 0, 0, "Add a horizontal spring force on slopes");
- uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19,
- &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property");
- if (coa->flag & ACT_CONST_MATERIAL) {
- uiDefBut(block, TEX, 1, "Material:", xco + 50, yco-84, (width-60), 19,
- coa->matprop, 0, MAX_NAME, 0, 0,
- "Ray detects only Objects with this material");
- }
- else {
- uiDefBut(block, TEX, 1, "Property:", xco + 50, yco-84, (width-60), 19,
- coa->matprop, 0, MAX_NAME, 0, 0,
- "Ray detect only Objects with this property");
- }
- uiDefButBitS(block, TOG, ACT_CONST_PERMANENT, 0, "PER", xco+10, yco-103, 40, 19,
- &coa->flag, 0.0, 0.0, 0, 0, "Persistent actuator: stays active even if ray does not reach target");
- uiDefButS(block, NUM, 0, "time", xco+50, yco-103, 90, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited");
- uiDefButF(block, NUM, 0, "rotDamp", xco+140, yco-103, (width-150), 19, &coa->maxrot[1], 0.0, 1.0, 1, 0, "Use a different damping for rotation");
- }
- str= "Constraint Type %t|Location %x0|Distance %x1|Orientation %x2|Force field %x3";
- but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &coa->type, 0.0, 0.0, 0, 0, "");
- yco-= ysize;
- break;
-
- case ACT_SCENE:
- sca= act->data;
-
- if (sca->type==ACT_SCENE_RESTART) {
- ysize= 28;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
- }
- else if (sca->type==ACT_SCENE_CAMERA) {
-
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+40, yco-44, (width-80), 19, &(sca->camera), "Set this Camera. Leave empty to refer to self object");
- }
- else if (sca->type==ACT_SCENE_SET) {
-
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Set this Scene");
- }
- else if (sca->type==ACT_SCENE_ADD_FRONT) {
-
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add an Overlay Scene");
- }
- else if (sca->type==ACT_SCENE_ADD_BACK) {
-
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add a Background Scene");
- }
- else if (sca->type==ACT_SCENE_REMOVE) {
-
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Remove a Scene");
- }
- else if (sca->type==ACT_SCENE_SUSPEND) {
-
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Pause a Scene");
- }
- else if (sca->type==ACT_SCENE_RESUME) {
-
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Unpause a Scene");
- }
-
- str= "Scene %t|Restart %x0|Set Scene %x1|Set Camera %x2|Add OverlayScene %x3|Add BackgroundScene %x4|Remove Scene %x5|Suspend Scene %x6|Resume Scene %x7";
- uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &sca->type, 0.0, 0.0, 0, 0, "");
-
- yco-= ysize;
- break;
- case ACT_GAME:
- {
- gma = act->data;
- if (gma->type == ACT_GAME_LOAD) {
- //ysize = 68;
- ysize = 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
- uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44, width-20, 19, &(gma->filename), 0, sizeof(gma->filename), 0, 0, "Load this blend file, use the \"//\" prefix for a path relative to the current blend file");
- // uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64, width-20, 19, &(gma->loadaniname), 0, sizeof(gma->loadaniname), 0, 0, "Use this loadinganimation");
- }
-#if 0
- else if (gma->type == ACT_GAME_START) {
- ysize = 68;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44, width-20, 19, &(gma->filename), 0, sizeof(gma->filename), 0, 0, "Load this file");
- uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64, width-20, 19, &(gma->loadaniname), 0, sizeof(gma->loadaniname), 0, 0, "Use this loadinganimation");
- }
-#endif
- else if (ELEM4(gma->type, ACT_GAME_RESTART, ACT_GAME_QUIT, ACT_GAME_SAVECFG, ACT_GAME_LOADCFG)) {
- ysize = 28;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
- }
-
- //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3";
- str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3|Save bge.logic.globalDict %x4|Load bge.logic.globalDict %x5";
- uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, "");
-
- yco -= ysize;
- break;
- }
- case ACT_GROUP:
- ga= act->data;
-
- ysize= 52;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- str= "GroupKey types %t|Set Key %x6|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x5";
-
- uiDefButS(block, MENU, 1, str, xco+20, yco-24, width-40, 19, &ga->type, 0, 0, 0, 0, "");
- if (ga->type==ACT_GROUP_SET) {
- uiDefBut(block, TEX, 0, "Key: ", xco+20, yco-44, (width-10)/2, 19, ga->name, 0.0, MAX_NAME, 0, 0, "This name defines groupkey to be set");
- uiDefButI(block, NUM, 0, "Frame:", xco+20+(width-10)/2, yco-44, (width-70)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Set this frame");
- }
- else if (ga->type==ACT_GROUP_FROM_PROP) {
- uiDefBut(block, TEX, 0, "Prop: ", xco+20, yco-44, width-40, 19, ga->name, 0.0, MAX_NAME, 0, 0, "Use this property to define the Group position");
- }
- else {
- uiDefButI(block, NUM, 0, "State", xco+20, yco-44, (width-40)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Start frame");
- uiDefButI(block, NUM, 0, "End", xco+20+(width-40)/2, yco-44, (width-40)/2, 19, &ga->end, 0.0, 2500.0, 0, 0, "End frame");
- }
- yco-= ysize;
- break;
-
- case ACT_VISIBILITY:
- ysize = 24;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco,
- (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- visAct = act->data;
-
- uiBlockBeginAlign(block);
- uiDefButBitI(block, TOGN, ACT_VISIBILITY_INVISIBLE, B_REDR,
- "Visible",
- xco + 10, yco - 20, (width - 20)/3, 19, &visAct->flag,
- 0.0, 0.0, 0, 0,
- "Set the objects visible. Initialized from the objects render restriction toggle (access in the outliner)");
- uiDefButBitI(block, TOG, ACT_VISIBILITY_OCCLUSION, B_REDR,
- "Occlusion",
- xco + 10 + ((width - 20)/3), yco - 20, (width - 20)/3, 19, &visAct->flag,
- 0.0, 0.0, 0, 0,
- "Set the object to occlude objects behind it. Initialized from the object type in physics button");
- uiBlockEndAlign(block);
-
- uiDefButBitI(block, TOG, ACT_VISIBILITY_RECURSIVE, 0,
- "Children",
- xco + 10 + (((width - 20)/3)*2)+10, yco - 20, ((width - 20)/3)-10, 19, &visAct->flag,
- 0.0, 0.0, 0, 0,
- "Sets all the children of this object to the same visibility/occlusion recursively");
-
- yco-= ysize;
-
- break;
-
- case ACT_STATE:
- ysize = 34;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco,
- (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- staAct = act->data;
-
- str= "Operation %t|Cpy %x0|Add %x1|Sub %x2|Inv %x3";
-
- uiDefButI(block, MENU, B_REDR, str,
- xco + 10, yco - 24, 65, 19, &staAct->type,
- 0.0, 0.0, 0, 0,
- "Select the bit operation on object state mask");
-
- for (wval=0; wval<15; wval+=5) {
- uiBlockBeginAlign(block);
- for (stbit=0; stbit<5; stbit++) {
- but = uiDefButBitI(block, TOG, 1<<(stbit+wval), stbit+wval, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval)));
- uiButSetFunc(but, check_state_mask, but, &(staAct->mask));
- }
- for (stbit=0; stbit<5; stbit++) {
- but = uiDefButBitI(block, TOG, 1<<(stbit+wval+15), stbit+wval+15, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval+15)));
- uiButSetFunc(but, check_state_mask, but, &(staAct->mask));
- }
- }
- uiBlockEndAlign(block);
-
- yco-= ysize;
-
- break;
-
- case ACT_RANDOM:
- ysize = 69;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco,
- (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- randAct = act->data;
-
- /* 1. seed */
- uiDefButI(block, NUM, 1, "Seed: ", (xco+10), yco-24, 0.4 *(width-20), 19,
- &randAct->seed, 0, 1000, 0, 0,
- "Initial seed of the random generator. Use Python for more freedom. "
- " (Choose 0 for not random)");
-
- /* 2. distribution type */
- /* One pick per distribution. These numbers MUST match the #defines */
- /* in game.h !!! */
- str= "Distribution %t|Bool Constant %x0|Bool Uniform %x1"
- "|Bool Bernoulli %x2|Int Constant %x3|Int Uniform %x4"
- "|Int Poisson %x5|Float Constant %x6|Float Uniform %x7"
- "|Float Normal %x8|Float Neg. Exp. %x9";
- uiDefButI(block, MENU, B_REDR, str, (xco+10) + 0.4 * (width-20), yco-24, 0.6 * (width-20), 19,
- &randAct->distribution, 0.0, 0.0, 0, 0,
- "Choose the type of distribution");
-
- /* 3. property */
- uiDefBut(block, TEX, 1, "Property:", (xco+10), yco-44, (width-20), 19,
- &randAct->propname, 0, MAX_NAME, 0, 0,
- "Assign the random value to this property");
-
- /*4. and 5. arguments for the distribution*/
- switch (randAct->distribution) {
- case ACT_RANDOM_BOOL_CONST:
- uiDefButBitI(block, TOG, 1, 1, "Always true", (xco+10), yco-64, (width-20), 19,
- &randAct->int_arg_1, 2.0, 1, 0, 0,
- "Always false or always true");
- break;
- case ACT_RANDOM_BOOL_UNIFORM:
- uiDefBut(block, LABEL, 0, " Do a 50-50 pick", (xco+10), yco-64, (width-20), 19,
- NULL, 0, 0, 0, 0,
- "Choose between true and false, 50% chance each");
- break;
- case ACT_RANDOM_BOOL_BERNOUILLI:
- uiDefButF(block, NUM, 1, "Chance", (xco+10), yco-64, (width-20), 19,
- &randAct->float_arg_1, 0.0, 1.0, 0, 0,
- "Pick a number between 0 and 1. Success if you stay "
- "below this value");
- break;
- case ACT_RANDOM_INT_CONST:
- uiDefButI(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19,
- &randAct->int_arg_1, -1000, 1000, 0, 0,
- "Always return this number");
- break;
- case ACT_RANDOM_INT_UNIFORM:
- uiDefButI(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19,
- &randAct->int_arg_1, -1000, 1000, 0, 0,
- "Choose a number from a range. "
- "Lower boundary of the range");
- uiDefButI(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
- &randAct->int_arg_2, -1000, 1000, 0, 0,
- "Choose a number from a range. "
- "Upper boundary of the range");
- break;
- case ACT_RANDOM_INT_POISSON:
- uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20), 19,
- &randAct->float_arg_1, 0.01, 100.0, 0, 0,
- "Expected mean value of the distribution");
- break;
- case ACT_RANDOM_FLOAT_CONST:
- uiDefButF(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19,
- &randAct->float_arg_1, 0.0, 1.0, 0, 0,
- "Always return this number");
- break;
- case ACT_RANDOM_FLOAT_UNIFORM:
- uiDefButF(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19,
- &randAct->float_arg_1, -10000.0, 10000.0, 0, 0,
- "Choose a number from a range"
- "Lower boundary of the range");
- uiDefButF(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
- &randAct->float_arg_2, -10000.0, 10000.0, 0, 0,
- "Choose a number from a range"
- "Upper boundary of the range");
- break;
- case ACT_RANDOM_FLOAT_NORMAL:
- uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20)/2, 19,
- &randAct->float_arg_1, -10000.0, 10000.0, 0, 0,
- "A normal distribution. Mean of the distribution");
- uiDefButF(block, NUM, 1, "SD: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19,
- &randAct->float_arg_2, 0.0, 10000.0, 0, 0,
- "A normal distribution. Standard deviation of the "
- "distribution");
- break;
- case ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL:
- uiDefButF(block, NUM, 1, "Half-life time: ", (xco+10), yco-64, (width-20), 19,
- &randAct->float_arg_1, 0.001, 10000.0, 0, 0,
- "Negative exponential dropoff");
- break;
- default:
- ; /* don't know what this distro is... can be useful for testing */
- /* though :) */
- }
-
- yco-= ysize;
- break;
- case ACT_MESSAGE:
- ma = act->data;
-
- ysize = 4 + (3 * 24); /* footer + number of lines * 24 pixels/line */
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize,
- (float)xco+width, (float)yco, 1);
-
- myline=1;
-
- /* line 1: To */
- uiDefBut(block, TEX, 1, "To: ",
- (xco+10), (yco-(myline++*24)), (width-20), 19,
- &ma->toPropName, 0, MAX_NAME, 0, 0,
- "Optional send message to objects with this name only, or empty to broadcast");
-
- /* line 2: Message Subject */
- uiDefBut(block, TEX, 1, "Subject: ",
- (xco+10), (yco-(myline++*24)), (width-20), 19,
- &ma->subject, 0, MAX_NAME, 0, 0,
- "Optional message subject. This is what can be filtered on");
-
- /* line 3: Text/Property */
- uiDefButBitS(block, TOG, 1, B_REDR, "T/P",
- (xco+10), (yco-(myline*24)), (0.20 * (width-20)), 19,
- &ma->bodyType, 0.0, 0.0, 0, 0,
- "Toggle message type: either Text or a PropertyName");
-
- if (ma->bodyType == ACT_MESG_MESG) {
- /* line 3: Message Body */
- uiDefBut(block, TEX, 1, "Body: ",
- (xco+10+(0.20*(width-20))), (yco-(myline++*24)), (0.8*(width-20)), 19,
- &ma->body, 0, MAX_NAME, 0, 0,
- "Optional message body Text");
- }
- else {
- /* line 3: Property body (set by property) */
- uiDefBut(block, TEX, 1, "Propname: ",
- (xco+10+(0.20*(width-20))), (yco-(myline++*24)), (0.8*(width-20)), 19,
- &ma->body, 0, MAX_NAME, 0, 0,
- "The message body will be set by the Property Value");
- }
-
- yco -= ysize;
- break;
- case ACT_2DFILTER:
- tdfa = act->data;
-
- ysize = 50;
- if (tdfa->type == ACT_2DFILTER_CUSTOMFILTER) {
- ysize +=20;
- }
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- switch (tdfa->type) {
- case ACT_2DFILTER_MOTIONBLUR:
- if (!tdfa->flag) {
- uiDefButS(block, TOG, B_REDR, "D", xco+30, yco-44, 19, 19, &tdfa->flag, 0.0, 0.0, 0.0, 0.0, "Disable Motion Blur");
- uiDefButF(block, NUM, B_REDR, "Value:", xco+52, yco-44, width-82, 19, &tdfa->float_arg, 0.0, 1.0, 0.0, 0.0, "Set motion blur value");
- }
- else {
- uiDefButS(block, TOG, B_REDR, "Disabled", xco+30, yco-44, width-60, 19, &tdfa->flag, 0.0, 0.0, 0.0, 0.0, "Enable Motion Blur");
- }
- break;
- case ACT_2DFILTER_BLUR:
- case ACT_2DFILTER_SHARPEN:
- case ACT_2DFILTER_DILATION:
- case ACT_2DFILTER_EROSION:
- case ACT_2DFILTER_LAPLACIAN:
- case ACT_2DFILTER_SOBEL:
- case ACT_2DFILTER_PREWITT:
- case ACT_2DFILTER_GRAYSCALE:
- case ACT_2DFILTER_SEPIA:
- case ACT_2DFILTER_INVERT:
- case ACT_2DFILTER_NOFILTER:
- case ACT_2DFILTER_DISABLED:
- case ACT_2DFILTER_ENABLED:
- uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30, yco-44, width-60, 19, &tdfa->int_arg, 0.0, MAX_RENDER_PASS-1, 0.0, 0.0, "Set filter order");
- break;
- case ACT_2DFILTER_CUSTOMFILTER:
- uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30, yco-44, width-60, 19, &tdfa->int_arg, 0.0, MAX_RENDER_PASS-1, 0.0, 0.0, "Set filter order");
- uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+30, yco-64, width-60, 19, &tdfa->text, "");
- break;
- }
-
- str= "2D Filter %t|Motion Blur %x1|Blur %x2|Sharpen %x3|Dilation %x4|Erosion %x5|"
- "Laplacian %x6|Sobel %x7|Prewitt %x8|Gray Scale %x9|Sepia %x10|Invert %x11|Custom Filter %x12|"
- "Enable Filter %x-2|Disable Filter %x-1|Remove Filter %x0|";
- uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &tdfa->type, 0.0, 0.0, 0.0, 0.0, "2D filter type");
-
- yco -= ysize;
- break;
- case ACT_PARENT:
- parAct = act->data;
-
- if (parAct->type==ACT_PARENT_SET) {
-
- ysize= 48;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+95, yco-24, (width-100), 19, &(parAct->ob), "Set this object as parent");
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOGN, ACT_PARENT_COMPOUND, B_REDR,
- "Compound",
- xco + 5, yco - 44, (width - 10)/2, 19, &parAct->flag,
- 0.0, 0.0, 0, 0,
- "Add this object shape to the parent shape (only if the parent shape is already compound)");
- uiDefButBitS(block, TOGN, ACT_PARENT_GHOST, B_REDR,
- "Ghost",
- xco + 5 + ((width - 10)/2), yco - 44, (width - 10)/2, 19, &parAct->flag,
- 0.0, 0.0, 0, 0,
- "Make this object ghost while parented (only if not compound)");
- uiBlockEndAlign(block);
- }
- else if (parAct->type==ACT_PARENT_REMOVE) {
-
- ysize= 28;
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
- }
-
- str= "Parent %t|Set Parent %x0|Remove Parent %x1";
- uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, parAct->type==1?(width-80):90, 19, &parAct->type, 0.0, 0.0, 0, 0, "");
-
- yco-= ysize;
- break;
- case ACT_ARMATURE:
- armAct = act->data;
-
- if (ob->type == OB_ARMATURE) {
- str= "Constraint %t|Run armature %x0|Enable %x1|Disable %x2|Set target %x3|Set weight %x4";
- uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, (width-10)*0.35, 19, &armAct->type, 0.0, 0.0, 0, 0, "");
-
- switch (armAct->type) {
- case ACT_ARM_RUN:
- ysize = 28;
- break;
- default:
- uiBlockBeginAlign(block);
- but = uiDefBut(block, TEX, 1, "Bone: ",
- (xco+5), (yco-44), (width-10)/2, 19,
- armAct->posechannel, 0, MAX_NAME, 0, 0,
- "Bone on which the constraint is defined");
- uiButSetFunc(but, check_armature_actuator, but, armAct);
- but = uiDefBut(block, TEX, 1, "Cons: ",
- (xco+5)+(width-10)/2, (yco-44), (width-10)/2, 19,
- armAct->constraint, 0, MAX_NAME, 0, 0,
- "Name of the constraint you want to control");
- uiButSetFunc(but, check_armature_actuator, but, armAct);
- uiBlockEndAlign(block);
- ysize = 48;
- switch (armAct->type) {
- case ACT_ARM_SETTARGET:
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Target: ", xco+5, yco-64, (width-10), 19, &(armAct->target), "Set this object as the target of the constraint");
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Secondary Target: ", xco+5, yco-84, (width-10), 19, &(armAct->subtarget), "Set this object as the secondary target of the constraint (only IK polar target at the moment)");
- ysize += 40;
- break;
- case ACT_ARM_SETWEIGHT:
- uiDefButF(block, NUM, B_REDR, "Weight:", xco+5+(width-10)*0.35, yco-24, (width-10)*0.65, 19, &armAct->weight, 0.0, 1.0, 0.0, 0.0, "Set weight of this constraint");
- break;
- }
- }
- }
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
- yco-= ysize;
- break;
-
- default:
- ysize= 4;
-
- glRects(xco, yco-ysize, xco+width, yco);
- uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
-
- yco-= ysize;
- break;
- }
-
- uiBlockSetEmboss(block, UI_EMBOSS);
-
- return yco-4;
-}
static void do_sensor_menu(bContext *C, void *UNUSED(arg), int event)
{
@@ -3084,8 +878,6 @@ static uiBlock *actuator_menu(bContext *C, ARegion *ar, void *UNUSED(arg))
return block;
}
-
-
static void check_controller_state_mask(bContext *UNUSED(C), void *arg1_but, void *arg2_mask)
{
unsigned int *cont_mask = arg2_mask;
@@ -3096,17 +888,6 @@ static void check_controller_state_mask(bContext *UNUSED(C), void *arg1_but, voi
but->retval = B_REDR;
}
-static int first_bit(unsigned int mask)
-{
- int bit;
-
- for (bit=0; bit<32; bit++) {
- if (mask & (1<<bit))
- return bit;
- }
- return -1;
-}
-
static uiBlock *controller_state_mask_menu(bContext *C, ARegion *ar, void *arg_cont)
{
uiBlock *block;
@@ -3139,44 +920,6 @@ static uiBlock *controller_state_mask_menu(bContext *C, ARegion *ar, void *arg_c
return block;
}
-static void do_object_state_menu(bContext *UNUSED(C), void *arg, int event)
-{
- Object *ob = arg;
-
- switch (event) {
- case 0:
- ob->state = 0x3FFFFFFF;
- break;
- case 1:
- ob->state = ob->init_state;
- if (!ob->state)
- ob->state = 1;
- break;
- case 2:
- ob->init_state = ob->state;
- break;
- }
-}
-
-static uiBlock *object_state_mask_menu(bContext *C, ARegion *ar, void *arg_obj)
-{
- uiBlock *block;
- short xco = 0;
-
- block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP);
- uiBlockSetButmFunc(block, do_object_state_menu, arg_obj);
-
- uiDefBut(block, BUTM, 1, "Set all bits", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, 1, "Recall init state", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, "");
- uiDefBut(block, SEPR, 0, "", 0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, 1, "Store init state", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, "");
-
- uiBlockSetDirection(block, UI_TOP);
- uiEndBlock(C, block);
-
- return block;
-}
-
static int is_sensor_linked(uiBlock *block, bSensor *sens)
{
bController *cont;
@@ -4458,14 +2201,13 @@ static void draw_brick_actuator(uiLayout *layout, PointerRNA *ptr, bContext *C)
}
}
-static void logic_buttons_new(bContext *C, ARegion *ar)
+void logic_buttons(bContext *C, ARegion *ar)
{
SpaceLogic *slogic= CTX_wm_space_logic(C);
Object *ob= CTX_data_active_object(C);
- Object *act_ob= ob;
ID **idar;
- PointerRNA logic_ptr, settings_ptr;
+ PointerRNA logic_ptr, settings_ptr, object_ptr;
uiLayout *layout, *row, *box;
uiBlock *block;
@@ -4558,8 +2300,10 @@ static void logic_buttons_new(bContext *C, ARegion *ar)
row = uiLayoutRow(split, TRUE);
uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide controllers");
- if (ob == act_ob)
- uiItemMenuEnumO(row, "LOGIC_OT_controller_add", "type", "Add Controller", ICON_NONE);
+
+ RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
+ uiLayoutSetContextPointer(row, "object", &object_ptr);
+ uiItemMenuEnumO(row, "LOGIC_OT_controller_add", "type", "Add Controller", ICON_NONE);
if (RNA_boolean_get(&settings_ptr, "show_state_panel")) {
@@ -4574,9 +2318,9 @@ static void logic_buttons_new(bContext *C, ARegion *ar)
col = uiLayoutColumn(subsplit, FALSE);
row = uiLayoutRow(col, FALSE);
uiLayoutSetActive(row, RNA_boolean_get(&settings_ptr, "use_all_states") == FALSE);
- uiTemplateLayers(row, &settings_ptr, "states_visible", &settings_ptr, "used_states", 0);
+ uiTemplateGameStates(row, &settings_ptr, "states_visible", &settings_ptr, "used_states", 0);
row = uiLayoutRow(col, FALSE);
- uiTemplateLayers(row, &settings_ptr, "states_initial", &settings_ptr, "used_states", 0);
+ uiTemplateGameStates(row, &settings_ptr, "states_initial", &settings_ptr, "used_states", 0);
col = uiLayoutColumn(subsplit, FALSE);
uiItemR(col, &settings_ptr, "use_all_states", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
@@ -4653,8 +2397,10 @@ static void logic_buttons_new(bContext *C, ARegion *ar)
row = uiLayoutRow(layout, TRUE);
uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors");
- if (ob == act_ob)
- uiItemMenuEnumO(row, "LOGIC_OT_sensor_add", "type", "Add Sensor", ICON_NONE);
+
+ RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
+ uiLayoutSetContextPointer(row, "object", &object_ptr);
+ uiItemMenuEnumO(row, "LOGIC_OT_sensor_add", "type", "Add Sensor", ICON_NONE);
if ((ob->scaflag & OB_SHOWSENS) == 0) continue;
@@ -4721,8 +2467,10 @@ static void logic_buttons_new(bContext *C, ARegion *ar)
row = uiLayoutRow(layout, TRUE);
uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators");
- if (ob == act_ob)
- uiItemMenuEnumO(row, "LOGIC_OT_actuator_add", "type", "Add Actuator", ICON_NONE);
+
+ RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
+ uiLayoutSetContextPointer(row, "object", &object_ptr);
+ uiItemMenuEnumO(row, "LOGIC_OT_actuator_add", "type", "Add Actuator", ICON_NONE);
if ((ob->scaflag & OB_SHOWACT) == 0) continue;
@@ -4773,377 +2521,3 @@ static void logic_buttons_new(bContext *C, ARegion *ar)
if (idar) MEM_freeN(idar);
}
-void logic_buttons(bContext *C, ARegion *ar)
-{
- Main *bmain= CTX_data_main(C);
- SpaceLogic *slogic= CTX_wm_space_logic(C);
- Object *ob= CTX_data_active_object(C);
- ID **idar;
- bSensor *sens;
- bController *cont;
- bActuator *act;
- uiBlock *block;
- uiBut *but;
- PointerRNA logic_ptr;
- int a, iact, stbit, offset;
- int xco, yco, width, ycoo;
- short count;
- char numstr[32];
- /* pin is a bool used for actuator and sensor drawing with states
- * pin so changing states dosnt hide the logic brick */
- char pin;
-
- if (G.debug_value == 0) {
- logic_buttons_new(C, ar);
- return;
- }
-
- if (ob==NULL) return;
-// uiSetButLock(BKE_object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
-
- BLI_snprintf(numstr, sizeof(numstr), "buttonswin %p", (void *)ar);
- block= uiBeginBlock(C, ar, numstr, UI_EMBOSS);
- uiBlockSetHandleFunc(block, do_logic_buts, NULL);
-
- RNA_pointer_create(NULL, &RNA_SpaceLogicEditor, slogic, &logic_ptr);
-
- idar= get_selected_and_linked_obs(C, &count, slogic->scaflag);
-
- /* clean ACT_LINKED and ACT_VISIBLE of all potentially visible actuators so that
- * we can determine which is actually linked/visible */
- for (a=0; a<count; a++) {
- ob= (Object *)idar[a];
- act= ob->actuators.first;
- while (act) {
- act->flag &= ~(ACT_LINKED|ACT_VISIBLE);
- act = act->next;
- }
- /* same for sensors */
- sens= ob->sensors.first;
- while (sens) {
- sens->flag &= ~(SENS_VISIBLE);
- sens = sens->next;
- }
- }
-
- /* start with the controller because we need to know which one is visible */
- /* ******************************* */
- xco= 400; yco= 170; width= 300;
-
- uiDefBlockBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, UI_UNIT_Y, "");
-
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, BUTS_CONT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
- uiDefButBitS(block, TOG, BUTS_CONT_ACT, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
- uiDefButBitS(block, TOG, BUTS_CONT_LINK, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Sensor/Actuator");
- uiBlockEndAlign(block);
-
- for (a=0; a<count; a++) {
- unsigned int controller_state_mask = 0; /* store a bitmask for states that are used */
-
- ob= (Object *)idar[a];
-// uiClearButLock();
-// uiSetButLock(BKE_object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
- if ((ob->scavisflag & OB_VIS_CONT) == 0) {
- continue;
- }
-
- /* presume it is only objects for now */
- uiBlockBeginAlign(block);
-// if (ob->controllers.first) uiSetCurFont(block, UI_HELVB);
- uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Active Object name");
-// if (ob->controllers.first) uiSetCurFont(block, UI_HELV);
- uiDefButBitS(block, TOG, OB_ADDCONT, B_ADD_CONT, "Add", (short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller");
- uiBlockEndAlign(block);
- yco-=20;
-
- /* mark all actuators linked to these controllers */
- /* note that some of these actuators could be from objects that are not in the display list.
- * It's ok because those actuators will not be displayed here */
- cont= ob->controllers.first;
- while (cont) {
- for (iact=0; iact<cont->totlinks; iact++) {
- act = cont->links[iact];
- if (act)
- act->flag |= ACT_LINKED;
- }
- controller_state_mask |= cont->state_mask;
- cont = cont->next;
- }
-
- if (ob->scaflag & OB_SHOWCONT) {
-
- /* first show the state */
- uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 36, UI_UNIT_Y, "Object state menu: store and retrieve initial state");
-
- if (!ob->state)
- ob->state = 1;
- for (offset=0; offset<15; offset+=5) {
- uiBlockBeginAlign(block);
- for (stbit=0; stbit<5; stbit++) {
- but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset), stbit+offset, "", (short)(xco+31+12*stbit+13*offset), yco, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset)));
- uiButSetFunc(but, check_state_mask, but, &(ob->state));
- }
- for (stbit=0; stbit<5; stbit++) {
- but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset+15)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset+15), stbit+offset+15, "", (short)(xco+31+12*stbit+13*offset), yco-12, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset+15)));
- uiButSetFunc(but, check_state_mask, but, &(ob->state));
- }
- }
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, OB_ALLSTATE, B_SET_STATE_BIT, "All", (short)(xco+226), yco-10, 22, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Set all state bits");
- uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini", (short)(xco+248), yco-10, 22, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Set the initial state");
- uiDefButBitS(block, TOG, OB_DEBUGSTATE, 0, "D", (short)(xco+270), yco-10, 15, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Print state debug info");
- uiBlockEndAlign(block);
-
- yco-=35;
-
- /* display only the controllers that match the current state */
- offset = 0;
- for (stbit=0; stbit<32; stbit++) {
- if (!(ob->state & (1<<stbit)))
- continue;
- /* add a separation between controllers of different states */
- if (offset) {
- offset = 0;
- yco -= 6;
- }
- cont= ob->controllers.first;
- while (cont) {
- if (cont->state_mask & (1<<stbit)) {
- /* this controller is visible, mark all its actuator */
- for (iact=0; iact<cont->totlinks; iact++) {
- act = cont->links[iact];
- if (act)
- act->flag |= ACT_VISIBLE;
- }
- uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X, xco, yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Delete Controller");
- uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Controller settings");
- uiDefIconButBitS(block, TOG, CONT_PRIO, B_REDR, ICON_BOOKMARKS, (short)(xco+width-66), yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Mark controller for execution before all non-marked controllers (good for startup scripts)");
-
- sprintf(numstr, "%d", first_bit(cont->state_mask)+1);
- uiDefBlockBut(block, controller_state_mask_menu, cont, numstr, (short)(xco+width-44), yco, 22, UI_UNIT_Y, "Set controller state index (from 1 to 30)");
-
- if (cont->flag & CONT_SHOW) {
- cont->otype= cont->type;
- uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(), (short)(xco+22), yco, 70, UI_UNIT_Y, &cont->type, 0, 0, 0, 0, "Controller type");
- but = uiDefBut(block, TEX, 1, "", (short)(xco+92), yco, (short)(width-158), UI_UNIT_Y, cont->name, 0, MAX_NAME, 0, 0, "Controller name");
- uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0);
-
- ycoo= yco;
- yco= draw_controllerbuttons(cont, block, xco, yco, width);
- if (yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
- }
- else {
- cpack(0x999999);
- glRecti(xco+22, yco, xco+width-22, yco+19);
- but = uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, UI_UNIT_Y, cont, 0, 0, 0, 0, "Controller type");
- //uiButSetFunc(but, old_sca_move_controller, cont, NULL);
- but = uiDefBut(block, LABEL, 0, cont->name, (short)(xco+92), yco, (short)(width-158), UI_UNIT_Y, cont, 0, 0, 0, 0, "Controller name");
- //uiButSetFunc(but, old_sca_move_controller, cont, NULL);
-
- uiBlockBeginAlign(block);
- but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_UP, (short)(xco+width-(110+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick up");
- uiButSetFunc(but, old_sca_move_controller, cont, (void *)TRUE);
- but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_DOWN, (short)(xco+width-(88+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick down");
- uiButSetFunc(but, old_sca_move_controller, cont, (void *)FALSE);
- uiBlockEndAlign(block);
-
- ycoo= yco;
- }
-
- but = uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR);
-
- uiDefIconBut(block, INLINK, 0, ICON_INLINK, (short)(xco-19), ycoo, UI_UNIT_X, UI_UNIT_Y, cont, LINK_CONTROLLER, 0, 0, 0, "");
- /* offset is >0 if at least one controller was displayed */
- offset++;
- yco-=20;
- }
- cont= cont->next;
- }
-
- }
- yco-= 6;
- }
- }
-
- /* ******************************* */
- xco= 10; yco= 170; width= 300;
-
- uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 70, UI_UNIT_Y, "");
-
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+80, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
- uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+80+(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
- uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+80+2*(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
- uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "State", xco+80+3*(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states");
- uiBlockEndAlign(block);
-
- for (a=0; a<count; a++) {
- ob= (Object *)idar[a];
-// uiClearButLock();
-// uiSetButLock(BKE_object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
-
- if ((ob->scavisflag & OB_VIS_SENS) == 0) {
- continue;
- }
-
- /* presume it is only objects for now */
- uiBlockBeginAlign(block);
-// if (ob->sensors.first) uiSetCurFont(block, UI_HELVB);
- uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors");
-// if (ob->sensors.first) uiSetCurFont(block, UI_HELV);
- uiDefButBitS(block, TOG, OB_ADDSENS, B_ADD_SENS, "Add", (short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor");
- uiBlockEndAlign(block);
- yco-=20;
-
- if (ob->scaflag & OB_SHOWSENS) {
-
- sens= ob->sensors.first;
- while (sens) {
- if (!(slogic->scaflag & BUTS_SENS_STATE) ||
- (sens->totlinks == 0) || /* always display sensor without links so that is can be edited */
- (sens->flag & SENS_PIN && slogic->scaflag & BUTS_SENS_STATE) || /* states can hide some sensors, pinned sensors ignore the visible state */
- (is_sensor_linked(block, sens))
- ) {
- /* should we draw the pin? - for now always draw when there is a state */
- pin = (slogic->scaflag & BUTS_SENS_STATE && (sens->flag & SENS_SHOW || sens->flag & SENS_PIN)) ? 1 : 0;
-
- sens->flag |= SENS_VISIBLE;
- uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Delete Sensor");
- if (pin)
- uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
-
- uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Sensor settings");
-
- ycoo= yco;
- if (sens->flag & SENS_SHOW) {
- uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(), (short)(xco+22), yco, 80, UI_UNIT_Y, &sens->type, 0, 0, 0, 0, "Sensor type");
- but = uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-(pin?146:124)), UI_UNIT_Y, sens->name, 0, MAX_NAME, 0, 0, "Sensor name");
- uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0);
-
- sens->otype= sens->type;
- yco= draw_sensorbuttons(ob, sens, block, xco, yco, width);
- if (yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
- }
- else {
- set_col_sensor(sens->type, 1);
- glRecti(xco + 22, yco, xco + width - 22, yco + 19);
- but = uiDefBut(block, LABEL, 0, sensor_name(sens->type), (short)(xco+22), yco, 80, UI_UNIT_Y, sens, 0, 0, 0, 0, "");
- //uiButSetFunc(but, old_sca_move_sensor, sens, NULL);
- but = uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-(pin?146:124)), UI_UNIT_Y, sens, 0, MAX_NAME, 0, 0, "");
- //uiButSetFunc(but, old_sca_move_sensor, sens, NULL);
-
- uiBlockBeginAlign(block);
- but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_UP, (short)(xco+width-(66+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick up");
- uiButSetFunc(but, old_sca_move_sensor, sens, (void *)TRUE);
- but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_DOWN, (short)(xco+width-(44+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick down");
- uiButSetFunc(but, old_sca_move_sensor, sens, (void *)FALSE);
- uiBlockEndAlign(block);
- }
-
- but = uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER);
-
- yco-=20;
- }
- sens= sens->next;
- }
- yco-= 6;
- }
- }
- /* ******************************* */
- xco= 800; yco= 170; width= 300;
- uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 90, UI_UNIT_Y, "");
-
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, BUTS_ACT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
- uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
- uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
- uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "State", xco+110+3*(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states");
- uiBlockEndAlign(block);
- for (a=0; a<count; a++) {
- ob= (Object *)idar[a];
-// uiClearButLock();
-// uiSetButLock(BKE_object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
- if ((ob->scavisflag & OB_VIS_ACT) == 0) {
- continue;
- }
-
- /* presume it is only objects for now */
- uiBlockBeginAlign(block);
-// if (ob->actuators.first) uiSetCurFont(block, UI_HELVB);
- uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators");
-// if (ob->actuators.first) uiSetCurFont(block, UI_HELV);
- uiDefButBitS(block, TOG, OB_ADDACT, B_ADD_ACT, "Add", (short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Actuator");
- uiBlockEndAlign(block);
- yco-=20;
-
- if (ob->scaflag & OB_SHOWACT) {
-
- act= ob->actuators.first;
- while (act) {
- if (!(slogic->scaflag & BUTS_ACT_STATE) ||
- !(act->flag & ACT_LINKED) || /* always display actuators without links so that is can be edited */
- (act->flag & ACT_VISIBLE) || /* this actuator has visible connection, display it */
- (act->flag & ACT_PIN && slogic->scaflag & BUTS_ACT_STATE))
- {
- pin = (slogic->scaflag & BUTS_ACT_STATE && (act->flag & SENS_SHOW || act->flag & SENS_PIN)) ? 1 : 0;
-
- act->flag |= ACT_VISIBLE; /* mark the actuator as visible to help implementing the up/down action */
- uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Delete Actuator");
- if (pin)
- uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
- uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Display the actuator");
-
- if (act->flag & ACT_SHOW) {
- act->otype= act->type;
- uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob), (short)(xco+22), yco, 90, UI_UNIT_Y, &act->type, 0, 0, 0, 0, "Actuator type");
- but = uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-(pin?156:134)), UI_UNIT_Y, act->name, 0, MAX_NAME, 0, 0, "Actuator name");
- uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0);
-
- ycoo= yco;
- yco= draw_actuatorbuttons(bmain, ob, act, block, xco, yco, width);
- if (yco-6 < ycoo) ycoo= (yco+ycoo-20)/2;
- }
- else {
- set_col_actuator(act->type, 1);
- glRecti((short)(xco+22), yco, (short)(xco+width-22), (short)(yco+19));
- /* but= */ uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 90, UI_UNIT_Y, act, 0, 0, 0, 0, "Actuator type");
- // uiButSetFunc(but, old_sca_move_actuator, act, NULL);
- /* but= */ uiDefBut(block, LABEL, 0, act->name, (short)(xco+112), yco, (short)(width-(pin?156:134)), UI_UNIT_Y, act, 0, 0, 0, 0, "Actuator name");
- // uiButSetFunc(but, old_sca_move_actuator, act, NULL);
-
- uiBlockBeginAlign(block);
- but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_UP, (short)(xco+width-(66+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick up");
- uiButSetFunc(but, old_sca_move_actuator, act, (void *)TRUE);
- but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_DOWN, (short)(xco+width-(44+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick down");
- uiButSetFunc(but, old_sca_move_actuator, act, (void *)FALSE);
- uiBlockEndAlign(block);
-
- ycoo= yco;
- }
-
- uiDefIconBut(block, INLINK, 0, ICON_INLINK, (short)(xco - 19), ycoo, UI_UNIT_X, UI_UNIT_Y, act, LINK_ACTUATOR, 0, 0, 0, "");
-
- yco-=20;
- }
- act= act->next;
- }
- yco-= 6;
- }
- }
-
- uiComposeLinks(block);
-
- uiEndBlock(C, block);
- uiDrawBlock(C, block);
-
- if (idar) MEM_freeN(idar);
-}
-
-
-
-
-
-
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 804d44ba720..badc4dbb533 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -67,9 +67,6 @@
/* ******************* nla editor space & buttons ************** */
-#define B_NOP 1
-#define B_REDR 2
-
/* -------------- */
static void do_nla_region_buttons(bContext *C, void *UNUSED(arg), int event)
@@ -145,6 +142,7 @@ static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* for these channels, we only do AnimData */
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index b3a869ed57d..89a5e9feeef 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -178,6 +178,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor
case ANIMTYPE_DSMESH:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* sanity checking... */
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 2861d17b350..950060dde5f 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -304,13 +304,13 @@ static int nlaedit_viewall(bContext *C, const short onlySel)
/* set the horizontal range, with an extra offset so that the extreme keys will be in view */
get_nlastrip_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, onlySel);
- extra = 0.1f * BLI_RCT_SIZE_X(&v2d->cur);
+ extra = 0.1f * BLI_rctf_size_x(&v2d->cur);
v2d->cur.xmin -= extra;
v2d->cur.xmax += extra;
/* set vertical range */
v2d->cur.ymax = 0.0f;
- v2d->cur.ymin = (float)-BLI_RCT_SIZE_Y(&v2d->mask);
+ v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
/* do View2D syncing */
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
@@ -1170,7 +1170,8 @@ static int nlaedit_bake_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static void NLA_OT_bake(wmOperatorType *ot)
+/* why isn't this used? */
+static void UNUSED_FUNCTION(NLA_OT_bake)(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Bake Strips";
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 222c2414fcb..79be0d0a194 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -309,7 +309,7 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
* - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
* used for tweaking timing when "blocking", while channels is not that useful...
*/
- if (BLI_RCT_SIZE_X(&rect) >= BLI_RCT_SIZE_Y(&rect))
+ if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect))
mode = NLA_BORDERSEL_FRAMERANGE;
else
mode = NLA_BORDERSEL_CHANNELS;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 1f266c98020..3bba02f4fc8 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -69,9 +69,6 @@
#include "node_intern.h" /* own include */
-/* XXX interface.h */
-extern void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int select);
-
/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
@@ -200,25 +197,22 @@ static void node_draw_output_default(const bContext *C, uiBlock *block,
const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width))
{
SpaceNode *snode = CTX_wm_space_node(C);
- float slen;
- int ofs = 0;
const char *ui_name = IFACE_(name);
- int len = strlen(ui_name);
+ float slen;
+
UI_ThemeColor(TH_TEXT);
slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt;
- while (slen > node->width && ofs < len) {
- ofs++;
- slen = (UI_GetStringWidth(ui_name + ofs) + NODE_MARGIN_X) * snode->aspect_sqrt;
+ while (slen > node->width && *ui_name) {
+ ui_name = BLI_str_find_next_char_utf8(ui_name, NULL);
+ slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt;
}
-
- if (ofs < len) {
- uiDefBut(block, LABEL, 0, ui_name + ofs,
- (int)(sock->locx - slen), (int)(sock->locy - 9.0f),
- (short)(node->width - NODE_DY), (short)NODE_DY,
- NULL, 0, 0, 0, 0, "");
+
+ if (*ui_name) {
+ uiDefBut(block, LABEL, 0, ui_name,
+ (int)(sock->locx - slen), (int)(sock->locy - 9.0f),
+ (short)slen, (short)NODE_DY,
+ NULL, 0, 0, 0, 0, "");
}
-
- (void)snode;
}
/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
@@ -387,7 +381,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *
bt = uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "",
(int)butr->xmin, (int)butr->xmin,
- (short)BLI_RCT_SIZE_X(butr), (short)BLI_RCT_SIZE_X(butr),
+ (short)BLI_rctf_size_x(butr), (short)BLI_rctf_size_x(butr),
nor, 0.0f, 1.0f, 0, 0, "");
uiButSetFunc(bt, node_normal_cb, ntree, node);
}
@@ -523,7 +517,7 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
rect->ymax += NODE_DY;
/* input sockets */
- dy = BLI_RCT_CENTER_Y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1));
+ dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1));
gsock = ngroup->inputs.first;
sock = gnode->inputs.first;
while (gsock || sock) {
@@ -571,7 +565,7 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
}
/* output sockets */
- dy = BLI_RCT_CENTER_Y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1));
+ dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1));
gsock = ngroup->outputs.first;
sock = gnode->outputs.first;
while (gsock || sock) {
@@ -646,13 +640,13 @@ static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), v
}
static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock,
- int in_out, float xoffset, float yoffset)
+ int in_out, float xoffset, float yoffset, short width, short height)
{
if (sock->flag & SOCK_DYNAMIC) {
bNodeTree *ngroup = (bNodeTree *)gnode->id;
uiBut *but;
but = uiDefBut(gnode->block, TEX, 0, "",
- sock->locx + xoffset, sock->locy + 1 + yoffset, 72, NODE_DY,
+ sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
sock->name, 0, sizeof(sock->name), 0, 0, "");
if (in_out == SOCK_IN)
uiButSetFunc(but, update_group_input_cb, snode, ngroup);
@@ -662,7 +656,7 @@ static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *
else {
const char *ui_name = IFACE_(sock->name);
uiDefBut(gnode->block, LABEL, 0, ui_name,
- sock->locx + xoffset, sock->locy + 1 + yoffset, 72, NODE_DY,
+ sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
NULL, 0, 0, 0, 0, "");
}
}
@@ -670,23 +664,26 @@ static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *
static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode,
bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out)
{
+ const float dpi_fac = U.dpi / 72.0f;
bNodeTree *ngroup = (bNodeTree *)gnode->id;
bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type);
uiBut *bt;
float offset;
int draw_value;
- float node_group_frame = U.dpi * NODE_GROUP_FRAME / 72;
- float socket_size = NODE_SOCKSIZE * U.dpi / 72;
- float arrowbutw = 0.8f * UI_UNIT_X;
+ const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
+ const float socket_size = NODE_SOCKSIZE * dpi_fac;
+ const float arrowbutw = 0.8f * UI_UNIT_X;
+ const short co_text_w = 72 * dpi_fac;
+ const float co_margin = 6.0f * dpi_fac;
/* layout stuff for buttons on group left frame */
- float colw = 0.6f * node_group_frame;
- float col1 = 6 - node_group_frame;
- float col2 = col1 + colw + 6;
- float col3 = -arrowbutw - 6;
+ const float colw = 0.6f * node_group_frame;
+ const float col1 = co_margin - node_group_frame;
+ const float col2 = col1 + colw + co_margin;
+ const float col3 = -arrowbutw - co_margin;
/* layout stuff for buttons on group right frame */
- float cor1 = 6;
- float cor2 = cor1 + arrowbutw + 6;
- float cor3 = cor2 + arrowbutw + 6;
+ const float cor1 = co_margin;
+ const float cor2 = cor1 + arrowbutw;
+ const float cor3 = cor2 + arrowbutw + co_margin;
/* node and group socket circles */
if (sock)
@@ -716,13 +713,13 @@ static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *nt
if (draw_value) {
/* both name and value buttons */
if (gsock) {
- draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0);
+ draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0, co_text_w, NODE_DY);
if (stype->buttonfunc)
stype->buttonfunc(C, gnode->block, ngroup, NULL, gsock, "",
gsock->locx + offset, gsock->locy - NODE_DY, colw);
}
else {
- draw_group_socket_name(snode, gnode, sock, in_out, offset, 0);
+ draw_group_socket_name(snode, gnode, sock, in_out, offset, 0, co_text_w, NODE_DY);
if (stype->buttonfunc)
stype->buttonfunc(C, gnode->block, ngroup, NULL, sock, "",
sock->locx + offset, sock->locy - NODE_DY, colw);
@@ -731,9 +728,9 @@ static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *nt
else {
/* only name, no value button */
if (gsock)
- draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS);
+ draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
else
- draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS);
+ draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
}
if (gsock && (gsock->flag & SOCK_DYNAMIC)) {
@@ -837,7 +834,7 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN
layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
(int)(rect.xmin + NODE_MARGIN_X), (int)(rect.ymax + (group_header - (2.5f * dpi_fac))),
- mini((int)(BLI_RCT_SIZE_X(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle());
+ mini((int)(BLI_rctf_size_x(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle());
RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr);
uiTemplateIDBrowse(layout, (bContext *)C, &ptr, "node_tree", NULL, NULL, NULL);
uiBlockLayoutResolve(gnode->block, NULL, NULL);
@@ -979,7 +976,7 @@ static void node_draw_frame_label(bNode *node, const float aspect)
ascender = BLF_ascender(fontid);
/* 'x' doesn't need aspect correction */
- x = BLI_RCT_CENTER_X(rct) - (0.5f * width);
+ x = BLI_rctf_cent_x(rct) - (0.5f * width);
y = rct->ymax - (((NODE_DY / 4) / aspect) + (ascender * aspect));
BLF_position(fontid, x, y, 0);
@@ -2609,7 +2606,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE);
if (node->custom1 == 2) {
- uiItemR(layout, ptr, "relative_frame", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE);
}
}
}
@@ -3103,7 +3100,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
/* swap bytes, so alpha is most significant one, then just draw it as luminance int */
glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT,
- ((unsigned char *)ibuf->rect) + ofs);
+ display_buffer + ofs);
glPixelZoom(1.0f, 1.0f);
}
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 7d35f566140..379e9987c4c 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -62,10 +62,8 @@
#include "node_intern.h" /* own include */
#include "COM_compositor.h"
-/* width of socket columns in group display */
-#define NODE_GROUP_FRAME 120
/* XXX interface.h */
-extern void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int select);
+extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
/* XXX update functions for node editor are a mess, needs a clear concept */
void ED_node_tree_update(SpaceNode *snode, Scene *scene)
@@ -343,7 +341,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
}
else {
- float oldh = BLI_RCT_SIZE_Y(&node->prvr);
+ float oldh = BLI_rctf_size_y(&node->prvr);
if (oldh == 0.0f)
oldh = 0.6f * node->width - NODE_DY;
dy -= NODE_DYS / 2;
@@ -584,9 +582,9 @@ void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float
/* not a callback */
static void node_draw_preview(bNodePreview *preview, rctf *prv)
{
- float xscale = BLI_RCT_SIZE_X(prv) / ((float)preview->xsize);
- float yscale = BLI_RCT_SIZE_Y(prv) / ((float)preview->ysize);
- float tile = BLI_RCT_SIZE_X(prv) / 10.0f;
+ float xscale = BLI_rctf_size_x(prv) / ((float)preview->xsize);
+ float yscale = BLI_rctf_size_y(prv) / ((float)preview->ysize);
+ float tile = BLI_rctf_size_x(prv) / 10.0f;
float x, y;
/* draw checkerboard backdrop to show alpha */
@@ -852,8 +850,8 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
{
bNodeSocket *sock;
rctf *rct = &node->totr;
- float dx, centy = BLI_RCT_CENTER_Y(rct);
- float hiddenrad = BLI_RCT_SIZE_Y(rct) / 2.0f;
+ float dx, centy = BLI_rctf_cent_y(rct);
+ float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
float socket_size = NODE_SOCKSIZE * U.dpi / 72;
int color_id = node_get_colorid(node);
char showname[128]; /* 128 is used below */
@@ -932,7 +930,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
uiDefBut(node->block, LABEL, 0, showname,
(int)(rct->xmin + (NODE_MARGIN_X / snode->aspect_sqrt)), (int)(centy - 10),
- (short)(BLI_RCT_SIZE_X(rct) - 18.0f - 12.0f), (short)NODE_DY,
+ (short)(BLI_rctf_size_x(rct) - 18.0f - 12.0f), (short)NODE_DY,
NULL, 0, 0, 0, 0, "");
}
@@ -1108,7 +1106,7 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
glEnable(GL_MAP1_VERTEX_3);
/* aspect+font, set each time */
- snode->aspect = BLI_RCT_SIZE_X(&v2d->cur) / (float)ar->winx;
+ snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
snode->aspect_sqrt = sqrtf(snode->aspect);
// XXX snode->curfont= uiSetCurFont_ext(snode->aspect);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index cc386da2e93..64a8d96a74f 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -2067,8 +2067,8 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
/* calculate "barycenter" for placing on mouse cursor */
zero_v2(center);
for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
- center[0] += BLI_RCT_CENTER_X(&node->totr);
- center[1] += BLI_RCT_CENTER_Y(&node->totr);
+ center[0] += BLI_rctf_cent_x(&node->totr);
+ center[1] += BLI_rctf_cent_y(&node->totr);
}
mul_v2_fl(center, 1.0 / num_nodes);
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index a56d76a3ef7..f7757ce49b4 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -555,8 +555,8 @@ static int do_lasso_select_node(bContext *C, int mcords[][2], short moves, short
/* do actual selection */
for (node = snode->edittree->nodes.first; node; node = node->next) {
int screen_co[2];
- const float cent[2] = {BLI_RCT_CENTER_X(&node->totr),
- BLI_RCT_CENTER_Y(&node->totr)};
+ const float cent[2] = {BLI_rctf_cent_x(&node->totr),
+ BLI_rctf_cent_y(&node->totr)};
/* marker in screen coords */
UI_view2d_view_to_region(&ar->v2d,
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 7881014ed54..3d93a6c14a1 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -230,7 +230,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
/****************************** Node Link Menu *******************************/
-#define UI_NODE_LINK_ADD 0
+// #define UI_NODE_LINK_ADD 0
#define UI_NODE_LINK_DISCONNECT -1
#define UI_NODE_LINK_REMOVE -2
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index 8e38247348f..ccf5c4b540f 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -72,8 +72,8 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
int tot = 0;
int has_frame = FALSE;
- oldwidth = BLI_RCT_SIZE_X(&ar->v2d.cur);
- oldheight = BLI_RCT_SIZE_Y(&ar->v2d.cur);
+ oldwidth = BLI_rctf_size_x(&ar->v2d.cur);
+ oldheight = BLI_rctf_size_y(&ar->v2d.cur);
BLI_rctf_init_minmax(&cur_new);
@@ -91,8 +91,8 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
}
if (tot) {
- width = BLI_RCT_SIZE_X(&cur_new);
- height = BLI_RCT_SIZE_Y(&cur_new);
+ width = BLI_rctf_size_x(&cur_new);
+ height = BLI_rctf_size_y(&cur_new);
/* for single non-frame nodes, don't zoom in, just pan view,
* but do allow zooming out, this allows for big nodes to be zoomed out */
@@ -358,6 +358,13 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float
float fx, fy, bufx, bufy;
int ret = FALSE;
+ if (snode->treetype != NTREE_COMPOSIT || (snode->flag & SNODE_BACKDRAW) == 0) {
+ /* use viewer image for color sampling only if we're in compositor tree
+ * with backdrop enabled
+ */
+ return FALSE;
+ }
+
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (!ibuf) {
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 0874ddcb279..d7e180f982b 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -579,11 +579,11 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
te = outliner_find_id(so, &so->tree, (ID *)OBACT);
if (te) {
/* make te->ys center of view */
- ytop = (int)(te->ys + BLI_RCT_SIZE_Y(&v2d->mask) / 2);
+ ytop = (int)(te->ys + BLI_rcti_size_y(&v2d->mask) / 2);
if (ytop > 0) ytop = 0;
v2d->cur.ymax = (float)ytop;
- v2d->cur.ymin = (float)(ytop - BLI_RCT_SIZE_Y(&v2d->mask));
+ v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask));
/* make te->xs ==> te->xend center of view */
xdelta = (int)(te->xs - v2d->cur.xmin);
@@ -615,7 +615,7 @@ void OUTLINER_OT_show_active(wmOperatorType *ot)
static int outliner_scroll_page_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
- int dy = BLI_RCT_SIZE_Y(&ar->v2d.mask);
+ int dy = BLI_rcti_size_y(&ar->v2d.mask);
int up = 0;
if (RNA_boolean_get(op->ptr, "up"))
@@ -760,10 +760,10 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
tselem->flag |= TSE_SELECTED;
/* make te->ys center of view */
- ytop = (int)(te->ys + BLI_RCT_SIZE_Y(&ar->v2d.mask) / 2);
+ ytop = (int)(te->ys + BLI_rctf_size_y(&ar->v2d.mask) / 2);
if (ytop > 0) ytop = 0;
ar->v2d.cur.ymax = (float)ytop;
- ar->v2d.cur.ymin = (float)(ytop - BLI_RCT_SIZE_Y(&ar->v2d.mask));
+ ar->v2d.cur.ymin = (float)(ytop - BLI_rctf_size_y(&ar->v2d.mask));
/* make te->xs ==> te->xend center of view */
xdelta = (int)(te->xs - ar->v2d.cur.xmin);
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 7363bf2fbd8..f927e83cabe 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -432,7 +432,7 @@ static void draw_seq_extensions(Scene *scene, ARegion *ar, Sequence *seq)
y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
- pixely = BLI_RCT_SIZE_Y(&v2d->cur) / BLI_RCT_SIZE_Y(&v2d->mask);
+ pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
if (pixely <= 0) return; /* can happen when the view is split/resized */
@@ -725,7 +725,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
/* draw sound wave */
if (seq->type == SEQ_TYPE_SOUND_RAM) {
- drawseqwave(scene, seq, x1, y1, x2, y2, BLI_RCT_SIZE_X(&ar->v2d.cur) / ar->winx);
+ drawseqwave(scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
}
/* draw lock */
@@ -1032,10 +1032,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (draw_overlay) {
if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
rctf tot_clip;
- tot_clip.xmin = v2d->tot.xmin + (ABS(BLI_RCT_SIZE_X(&v2d->tot)) * scene->ed->over_border.xmin);
- tot_clip.ymin = v2d->tot.ymin + (ABS(BLI_RCT_SIZE_Y(&v2d->tot)) * scene->ed->over_border.ymin);
- tot_clip.xmax = v2d->tot.xmin + (ABS(BLI_RCT_SIZE_X(&v2d->tot)) * scene->ed->over_border.xmax);
- tot_clip.ymax = v2d->tot.ymin + (ABS(BLI_RCT_SIZE_Y(&v2d->tot)) * scene->ed->over_border.ymax);
+ tot_clip.xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin);
+ tot_clip.ymin = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin);
+ tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
+ tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);
glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin);
glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax);
@@ -1222,7 +1222,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
View2D *v2d = &ar->v2d;
Sequence *last_seq = BKE_sequencer_active_get(scene);
int sel = 0, j;
- float pixelx = BLI_RCT_SIZE_X(&v2d->cur) / BLI_RCT_SIZE_X(&v2d->mask);
+ float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
/* loop through twice, first unselected, then selected */
for (j = 0; j < 2; j++) {
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index f47eb339878..e7d964ba715 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -372,7 +372,7 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
if (ed == NULL) return NULL;
- pixelx = BLI_RCT_SIZE_X(&v2d->cur) / BLI_RCT_SIZE_X(&v2d->mask);
+ pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
@@ -2164,8 +2164,8 @@ static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
float winx = (int)(rd->size * rd->xsch) / 100;
float winy = (int)(rd->size * rd->ysch) / 100;
- float facx = BLI_RCT_SIZE_X(&v2d->mask) / winx;
- float facy = BLI_RCT_SIZE_Y(&v2d->mask) / winy;
+ float facx = BLI_rcti_size_x(&v2d->mask) / winx;
+ float facy = BLI_rcti_size_y(&v2d->mask) / winy;
BLI_rctf_resize(&v2d->cur, (int)(winx * facx * ratio) + 1, (int)(winy * facy * ratio) + 1);
@@ -2268,7 +2268,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
ymax += ymargin;
ymin -= ymargin;
- orig_height = BLI_RCT_SIZE_Y(&cur_new);
+ orig_height = BLI_rctf_size_y(&cur_new);
cur_new.xmin = xmin;
cur_new.xmax = xmax;
@@ -2277,8 +2277,8 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
cur_new.ymax = ymax;
/* only zoom out vertically */
- if (orig_height > BLI_RCT_SIZE_Y(&cur_new)) {
- ymid = BLI_RCT_CENTER_Y(&cur_new);
+ if (orig_height > BLI_rctf_size_y(&cur_new)) {
+ ymid = BLI_rctf_cent_y(&cur_new);
cur_new.ymin = ymid - (orig_height / 2);
cur_new.ymax = ymid + (orig_height / 2);
@@ -2800,11 +2800,11 @@ static int view_ghost_border_exec(bContext *C, wmOperator *op)
if (ed == NULL)
return OPERATOR_CANCELLED;
- rect.xmin /= (float)(ABS(BLI_RCT_SIZE_X(&v2d->tot)));
- rect.ymin /= (float)(ABS(BLI_RCT_SIZE_Y(&v2d->tot)));
+ rect.xmin /= fabsf(BLI_rctf_size_x(&v2d->tot));
+ rect.ymin /= fabsf(BLI_rctf_size_y(&v2d->tot));
- rect.xmax /= (float)(ABS(BLI_RCT_SIZE_X(&v2d->tot)));
- rect.ymax /= (float)(ABS(BLI_RCT_SIZE_Y(&v2d->tot)));
+ rect.xmax /= fabsf(BLI_rctf_size_x(&v2d->tot));
+ rect.ymax /= fabsf(BLI_rctf_size_y(&v2d->tot));
rect.xmin += 0.5f;
rect.xmax += 0.5f;
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index dc5cf98f515..70b288a59e6 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -78,6 +78,9 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_swap_data);
WM_operatortype_append(SEQUENCER_OT_rendersize);
+ WM_operatortype_append(SEQUENCER_OT_copy);
+ WM_operatortype_append(SEQUENCER_OT_paste);
+
WM_operatortype_append(SEQUENCER_OT_view_all);
WM_operatortype_append(SEQUENCER_OT_view_selected);
WM_operatortype_append(SEQUENCER_OT_view_all_preview);
@@ -110,10 +113,9 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_sound_strip_add);
WM_operatortype_append(SEQUENCER_OT_image_strip_add);
WM_operatortype_append(SEQUENCER_OT_effect_strip_add);
- WM_operatortype_append(SEQUENCER_OT_properties);
- WM_operatortype_append(SEQUENCER_OT_copy);
- WM_operatortype_append(SEQUENCER_OT_paste);
+ /* sequencer_buttons.c */
+ WM_operatortype_append(SEQUENCER_OT_properties);
/* sequencer_modifiers.c */
WM_operatortype_append(SEQUENCER_OT_strip_modifier_add);
@@ -132,7 +134,9 @@ void sequencer_keymap(wmKeyConfig *keyconf)
/* Common items ------------------------------------------------------------------ */
keymap = WM_keymap_find(keyconf, "SequencerCommon", SPACE_SEQ, 0);
-
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_properties", NKEY, KM_PRESS, 0, 0);
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "data_path", "scene.sequence_editor.show_overlay");
@@ -141,9 +145,7 @@ void sequencer_keymap(wmKeyConfig *keyconf)
/* Strips Region --------------------------------------------------------------- */
keymap = WM_keymap_find(keyconf, "Sequencer", SPACE_SEQ, 0);
-
- WM_keymap_add_item(keymap, "SEQUENCER_OT_properties", NKEY, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select_all", AKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
@@ -153,12 +155,12 @@ void sequencer_keymap(wmKeyConfig *keyconf)
RNA_enum_set(kmi->ptr, "type", SEQ_CUT_SOFT);
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_cut", KKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "type", SEQ_CUT_HARD);
-
+
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_mute", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", FALSE);
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_mute", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", TRUE);
-
+
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_unmute", HKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "unselected", FALSE);
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_unmute", HKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
@@ -179,7 +181,7 @@ void sequencer_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", DELKEY, KM_PRESS, 0, 0);
-
+
WM_keymap_add_item(keymap, "SEQUENCER_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
@@ -210,7 +212,7 @@ void sequencer_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_swap", LEFTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "side", SEQ_SIDE_LEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_swap", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "side", SEQ_SIDE_RIGHT);
-
+
WM_keymap_add_item(keymap, "SEQUENCER_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_swap_inputs", SKEY, KM_PRESS, KM_ALT, 0);
@@ -245,7 +247,7 @@ void sequencer_keymap(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "linked_left", TRUE);
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "linked_right", TRUE);
-
+
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "linked_left", TRUE);
RNA_boolean_set(kmi->ptr, "linked_right", TRUE);
@@ -293,14 +295,14 @@ void sequencer_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "SEQUENCER_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
-
+
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", FALSE);
kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", TRUE);
-
+
WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
-
+
WM_keymap_add_item(keymap, "SEQUENCER_OT_select_border", BKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
@@ -308,33 +310,32 @@ void sequencer_keymap(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "SEQUENCER_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_menu(keymap, "SEQUENCER_MT_change", CKEY, KM_PRESS, 0, 0);
-
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_int", OKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "scene.sequence_editor.overlay_frame");
RNA_int_set(kmi->ptr, "value", 0);
transform_keymap_for_space(keyconf, keymap, SPACE_SEQ);
-
+
/* special markers hotkeys for anim editors: see note in definition of this function */
ED_marker_keymap_animedit_conflictfree(keymap);
-
-
+
+
/* Preview Region ----------------------------------------------------------- */
keymap = WM_keymap_find(keyconf, "SequencerPreview", SPACE_SEQ, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all_preview", HOMEKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "SEQUENCER_OT_properties", NKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_view_ghost_border", OKEY, KM_PRESS, 0, 0);
/* would prefer to use numpad keys for job */
RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD1, KM_PRESS, 0, 0)->ptr, "ratio", 1.0f);
-
+
/* Setting zoom levels is not that useful, except for back to zoom level 1, removing keymap because of conflicts for now */
#if 0
RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 8.0f);
RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 4.0f);
RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 2.0f);
-
+
RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD2, KM_PRESS, 0, 0)->ptr, "ratio", 0.5f);
RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD4, KM_PRESS, 0, 0)->ptr, "ratio", 0.25f);
RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD8, KM_PRESS, 0, 0)->ptr, "ratio", 0.125f);
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index d09d6a29c10..6ed34a79510 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -449,6 +449,8 @@ static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col)
}
}
+#define HIS_STEPS 512
+
static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
@@ -456,13 +458,13 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
unsigned int n;
unsigned char *src = (unsigned char *) ibuf->rect;
- unsigned int bins[3][256];
+ unsigned int bins[3][HIS_STEPS];
memset(bins, 0, sizeof(bins));
#pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256)
for (y = 0; y < ibuf->y; y++) {
- unsigned int cur_bins[3][512];
+ unsigned int cur_bins[3][HIS_STEPS];
memset(cur_bins, 0, sizeof(cur_bins));
@@ -477,7 +479,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
#pragma omp critical
{
int i;
- for (i = 0; i < 512; i++) {
+ for (i = 0; i < HIS_STEPS; i++) {
bins[0][i] += cur_bins[0][i];
bins[1][i] += cur_bins[1][i];
bins[2][i] += cur_bins[2][i];
@@ -487,7 +489,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
n = 0;
for (c = 0; c < 3; c++) {
- for (x = 0; x < 256; x++) {
+ for (x = 0; x < HIS_STEPS; x++) {
if (bins[c][x] > n) {
n = bins[c][x];
}
@@ -495,7 +497,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
}
for (c = 0; c < 3; c++) {
- for (x = 0; x < 256; x++) {
+ for (x = 0; x < HIS_STEPS; x++) {
draw_histogram_bar(rval, x * 2 + 1, ((float) bins[c][x]) / n, c);
draw_histogram_bar(rval, x * 2 + 2, ((float) bins[c][x]) / n, c);
}
@@ -524,13 +526,13 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
int n, c, x, y;
float *src = ibuf->rect_float;
- unsigned int bins[3][512];
+ unsigned int bins[3][HIS_STEPS];
memset(bins, 0, sizeof(bins));
#pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256)
for (y = 0; y < ibuf->y; y++) {
- unsigned int cur_bins[3][512];
+ unsigned int cur_bins[3][HIS_STEPS];
memset(cur_bins, 0, sizeof(cur_bins));
@@ -545,7 +547,7 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
#pragma omp critical
{
int i;
- for (i = 0; i < 512; i++) {
+ for (i = 0; i < HIS_STEPS; i++) {
bins[0][i] += cur_bins[0][i];
bins[1][i] += cur_bins[1][i];
bins[2][i] += cur_bins[2][i];
@@ -558,14 +560,14 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
n = 0;
for (c = 0; c < 3; c++) {
- for (x = 0; x < 512; x++) {
+ for (x = 0; x < HIS_STEPS; x++) {
if (bins[c][x] > n) {
n = bins[c][x];
}
}
}
for (c = 0; c < 3; c++) {
- for (x = 0; x < 512; x++) {
+ for (x = 0; x < HIS_STEPS; x++) {
draw_histogram_bar(rval, x + 1, (float) bins[c][x] / n, c);
}
}
@@ -575,6 +577,8 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
return rval;
}
+#undef HIS_STEPS
+
ImBuf *make_histogram_view_from_ibuf(ImBuf *ibuf)
{
if (ibuf->rect_float) {
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 97eb5b41db7..5111d20b8ee 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1232,7 +1232,7 @@ static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back)
uiWidgetScrollDraw(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
uiSetRoundBox(UI_CNR_ALL);
- rad = 0.4f * mini(BLI_RCT_SIZE_X(&st->txtscroll), BLI_RCT_SIZE_Y(&st->txtscroll));
+ rad = 0.4f * mini(BLI_rcti_size_x(&st->txtscroll), BLI_rcti_size_y(&st->txtscroll));
UI_GetThemeColor3ubv(TH_HILITE, col);
col[3] = 48;
glColor4ubv(col);
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index b0cd6aeaab4..7dc3ec1ac60 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -59,17 +59,12 @@
#include "WM_types.h"
-
-
-
#ifdef WITH_PYTHON
// XXX #include "BPY_menus.h"
#endif
#include "text_intern.h"
-#define HEADER_PATH_MAX 260
-
/* ************************ header area region *********************** */
/************************** properties ******************************/
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 5af44f93d06..75b8e2f218d 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -602,9 +602,12 @@ static int text_run_script(bContext *C, ReportList *reports)
/* Don't report error messages while live editing */
if (!is_live) {
- if (text->curl != curl_prev || curc_prev != text->curc) {
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ /* text may have freed its self */
+ if (CTX_data_edit_text(C) == text) {
+ if (text->curl != curl_prev || curc_prev != text->curc) {
+ text_update_cursor_moved(C);
+ WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+ }
}
BKE_report(reports, RPT_ERROR, "Python script fail, look in the console for now...");
@@ -2409,8 +2412,8 @@ static int text_scroll_bar_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* jump scroll, works in v2d but needs to be added here too :S */
if (event->type == MIDDLEMOUSE) {
- tsc->old[0] = ar->winrct.xmin + BLI_RCT_CENTER_X(&st->txtbar);
- tsc->old[1] = ar->winrct.ymin + BLI_RCT_CENTER_Y(&st->txtbar);
+ tsc->old[0] = ar->winrct.xmin + BLI_rcti_cent_x(&st->txtbar);
+ tsc->old[1] = ar->winrct.ymin + BLI_rcti_cent_y(&st->txtbar);
tsc->delta[0] = 0;
tsc->delta[1] = 0;
diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c
index f980e19e9c8..966afe22e42 100644
--- a/source/blender/editors/space_text/text_python.c
+++ b/source/blender/editors/space_text/text_python.c
@@ -180,13 +180,9 @@ static void confirm_suggestion(Text *text, int skipleft)
}
// XXX
-#define L_MOUSE 0
-#define M_MOUSE 0
-#define R_MOUSE 0
#define LR_SHIFTKEY 0
#define LR_ALTKEY 0
#define LR_CTRLKEY 0
-#define LR_OSKEY 0
// XXX
static int doc_scroll = 0;
diff --git a/source/blender/editors/space_time/time_ops.c b/source/blender/editors/space_time/time_ops.c
index 733fd27135b..9067fb6933f 100644
--- a/source/blender/editors/space_time/time_ops.c
+++ b/source/blender/editors/space_time/time_ops.c
@@ -151,7 +151,7 @@ static int time_view_all_exec(bContext *C, wmOperator *UNUSED(op))
v2d->cur.xmax = (float)PEFRA;
/* we need an extra "buffer" factor on either side so that the endpoints are visible */
- extra = 0.01f * BLI_RCT_SIZE_X(&v2d->cur);
+ extra = 0.01f * BLI_rctf_size_x(&v2d->cur);
v2d->cur.xmin -= extra;
v2d->cur.xmax += extra;
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index ca4f00be2d5..f05c78e8512 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -638,7 +638,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
MLoopCol *mloopcol = me->mloopcol; /* why does mcol exist? */
MLoopCol *lcol;
- bProperty *prop = get_ob_property(ob, "Text");
+ bProperty *prop = BKE_bproperty_object_get(ob, "Text");
GPUVertexAttribs gattribs;
int a, totpoly = me->totpoly;
@@ -714,7 +714,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
unsigned int j;
lcol = &mloopcol[mp->loopstart];
- for (j = 0; j <= totloop_clamp; j++, lcol++) {
+ for (j = 0; j < totloop_clamp; j++, lcol++) {
MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]);
}
}
@@ -732,7 +732,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
/* The BM_FONT handling is in the gpu module, shared with the
* game engine, was duplicated previously */
- set_property_valstr(prop, string);
+ BKE_bproperty_set_valstr(prop, string);
characters = strlen(string);
if (!BKE_image_get_ibuf(mtpoly->tpage, NULL))
@@ -832,7 +832,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
}
/* draw game engine text hack */
- if (get_ob_property(ob, "Text"))
+ if (BKE_bproperty_object_get(ob, "Text"))
draw_mesh_text(scene, ob, 0);
draw_textured_end();
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index a51ec15bd86..8d58530765a 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -164,7 +164,7 @@ typedef struct drawDMEdgesSel_userData {
} drawDMEdgesSel_userData;
typedef struct drawDMFacesSel_userData {
- unsigned char *cols[3];
+ unsigned char *cols[4];
DerivedMesh *dm; /* BMESH BRANCH ONLY */
BMEditMesh *em; /* BMESH BRANCH ONLY */
@@ -2092,7 +2092,7 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const flo
else {
float co2[2];
mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
- project_short_noclip(data->vc.ar, co2, s);
+ ED_view3d_project_short_noclip(data->vc.ar, co2, s);
}
if (s[0] != IS_CLIPPED)
@@ -2169,8 +2169,8 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const flo
mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
- project_short_noclip(data->vc.ar, v1_co, s[0]);
- project_short_noclip(data->vc.ar, v2_co, s[1]);
+ ED_view3d_project_short_noclip(data->vc.ar, v1_co, s[0]);
+ ED_view3d_project_short_noclip(data->vc.ar, v2_co, s[1]);
if (data->clipVerts == V3D_CLIP_TEST_REGION) {
/* make an int copy */
@@ -2225,7 +2225,7 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const flo
short s[2];
mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
- project_short(data->vc.ar, cent2, s);
+ ED_view3d_project_short(data->vc.ar, cent2, s);
if (s[0] != IS_CLIPPED) {
data->func(data->userData, efa, s[0], s[1], index);
@@ -2632,6 +2632,21 @@ static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
}
+/* Draw only Freestyle feature edges */
+static DMDrawOption draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
+{
+ BMEdge *eed = EDBM_edge_at_index(userData, index);
+
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_FREESTYLE))
+ return DM_DRAW_OPTION_NORMAL;
+ else
+ return DM_DRAW_OPTION_SKIP;
+}
+
+static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
+{
+ dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em);
+}
/* Draw faces with color set based on selection
* return 2 for the active face so it renders with stipple enabled */
@@ -2646,11 +2661,11 @@ static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
if (efa == data->efa_act) {
- glColor4ubv(data->cols[2]);
+ glColor4ubv(data->cols[3]);
return DM_DRAW_OPTION_STIPPLE;
}
else {
- col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
+ col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(efa, BM_ELEM_FREESTYLE) ? 2 : 0];
if (col[3] == 0)
return DM_DRAW_OPTION_SKIP;
glColor4ubv(col);
@@ -2681,8 +2696,8 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
if (efa == data->efa_act || next_efa == data->efa_act)
return 0;
- col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
- next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
+ col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(efa, BM_ELEM_FREESTYLE) ? 2 : 0];
+ next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(next_efa, BM_ELEM_FREESTYLE) ? 2 : 0];
if (col[3] == 0 || next_col[3] == 0)
return 0;
@@ -2692,14 +2707,15 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
/* also draws the active face */
static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
- unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
+ unsigned char *selCol, unsigned char *markCol, unsigned char *actCol, BMFace *efa_act)
{
drawDMFacesSel_userData data;
data.dm = dm;
data.cols[0] = baseCol;
data.em = em;
data.cols[1] = selCol;
- data.cols[2] = actCol;
+ data.cols[2] = markCol;
+ data.cols[3] = actCol;
data.efa_act = efa_act;
data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
@@ -3231,11 +3247,12 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
}
if (me->drawflag & ME_DRAWFACES) { /* transp faces */
- unsigned char col1[4], col2[4], col3[4];
+ unsigned char col1[4], col2[4], col3[4], col4[4];
UI_GetThemeColor4ubv(TH_FACE, col1);
UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
- UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
+ UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col3);
+ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
glEnable(GL_BLEND);
glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
@@ -3244,7 +3261,10 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
if (check_object_draw_texture(scene, v3d, dt))
col1[3] = 0;
- draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
+ if (!(me->drawflag & ME_DRAW_FREESTYLE_FACE))
+ col3[3] = 0;
+
+ draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
glDisable(GL_BLEND);
glDepthMask(1); /* restore write in zbuffer */
@@ -3253,14 +3273,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
/* even if draw faces is off it would be nice to draw the stipple face
* Make all other faces zero alpha except for the active
* */
- unsigned char col1[4], col2[4], col3[4];
- col1[3] = col2[3] = 0; /* don't draw */
- UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
+ unsigned char col1[4], col2[4], col3[4], col4[4];
+ col1[3] = col2[3] = col3[3] = 0; /* don't draw */
+ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
glEnable(GL_BLEND);
glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
- draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
+ draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
glDisable(GL_BLEND);
glDepthMask(1); /* restore write in zbuffer */
@@ -3296,6 +3316,16 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
glLineWidth(1);
}
+ if(me->drawflag & ME_DRAW_FREESTYLE_EDGE) {
+ UI_ThemeColor(TH_FREESTYLE_EDGE_MARK);
+ glLineWidth(2);
+
+ draw_dm_edges_freestyle(em, cageDM);
+
+ glColor3ub(0,0,0);
+ glLineWidth(1);
+ }
+
if (me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
draw_dm_creases(em, cageDM);
}
@@ -3432,7 +3462,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
dm->drawFacesGLSL(dm, GPU_enable_material);
-// if (get_ob_property(ob, "Text"))
+// if (BKE_bproperty_object_get(ob, "Text"))
// XXX draw_mesh_text(ob, 1);
GPU_disable_material();
@@ -3620,7 +3650,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
if (obedit && ob != obedit && ob->data == obedit->data) {
- if (ob_get_key(ob) || ob_get_key(obedit)) {}
+ if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {}
else if (ob->modifiers.first || obedit->modifiers.first) {}
else drawlinked = 1;
}
@@ -6614,7 +6644,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* which wire color */
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- project_short(ar, ob->obmat[3], &base->sx);
+ ED_view3d_project_short(ar, ob->obmat[3], &base->sx);
draw_object_wire_color(scene, base, _ob_wire_col, warning_recursive);
ob_wire_col = _ob_wire_col;
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index c819637fd04..c8aca5674a4 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -83,7 +83,6 @@
/* ******************* view3d space & buttons ************** */
-#define B_NOP 1
#define B_REDR 2
#define B_OBJECTPANELMEDIAN 1008
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 5fbf1971349..c0ea4173392 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -559,7 +559,7 @@ static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
/* we don't want the clipping for cursor */
flag = v3d->flag;
v3d->flag = 0;
- project_int(ar, give_cursor(scene, v3d), co);
+ ED_view3d_project_int(ar, give_cursor(scene, v3d), co);
v3d->flag = flag;
mx = co[0];
@@ -901,7 +901,7 @@ static void draw_selected_name(Scene *scene, Object *ob)
/* try to display active shapekey too */
shapes[0] = '\0';
- key = ob_get_key(ob);
+ key = BKE_key_from_object(ob);
if (key) {
kb = BLI_findlink(&key->block, ob->shapenr - 1);
if (kb) {
@@ -973,10 +973,10 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV
rect_camera = params.viewplane;
/* get camera border within viewport */
- viewborder_r->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_RCT_SIZE_X(&rect_view)) * ar->winx;
- viewborder_r->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_RCT_SIZE_X(&rect_view)) * ar->winx;
- viewborder_r->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_RCT_SIZE_Y(&rect_view)) * ar->winy;
- viewborder_r->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_RCT_SIZE_Y(&rect_view)) * ar->winy;
+ viewborder_r->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
+ viewborder_r->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
+ viewborder_r->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
+ viewborder_r->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
}
void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float size_r[2])
@@ -984,8 +984,8 @@ void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, R
rctf viewborder;
view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, TRUE, TRUE);
- size_r[0] = BLI_RCT_SIZE_X(&viewborder);
- size_r[1] = BLI_RCT_SIZE_Y(&viewborder);
+ size_r[0] = BLI_rctf_size_x(&viewborder);
+ size_r[1] = BLI_rctf_size_y(&viewborder);
}
void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d,
@@ -1341,7 +1341,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
glDisable(GL_MULTISAMPLE_ARB);
region_scissor_winrct(ar, &winrct);
- glScissor(winrct.xmin, winrct.ymin, BLI_RCT_SIZE_X(&winrct), BLI_RCT_SIZE_Y(&winrct));
+ glScissor(winrct.xmin, winrct.ymin, BLI_rcti_size_x(&winrct), BLI_rcti_size_y(&winrct));
glClearColor(0.0, 0.0, 0.0, 0.0);
if (v3d->zbuf) {
@@ -1543,11 +1543,6 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
{
RegionView3D *rv3d = ar->regiondata;
BGpic *bgpic;
- Image *ima;
- MovieClip *clip;
- ImBuf *ibuf = NULL, *freeibuf;
- float vec[4], fac, asp, zoomx, zoomy;
- float x1, y1, x2, y2, cx, cy;
int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0;
for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
@@ -1560,6 +1555,13 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
(rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA)))
{
float image_aspect[2];
+ float fac, asp, zoomx, zoomy;
+ float x1, y1, x2, y2;
+
+ ImBuf *ibuf = NULL, *freeibuf;
+
+ Image *ima;
+ MovieClip *clip;
/* disable individual images */
if ((bgpic->flag & V3D_BGPIC_DISABLED))
@@ -1687,26 +1689,25 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
}
}
else {
+ float tvec[3];
float sco[2];
const float mval_f[2] = {1.0f, 0.0f};
/* calc window coord */
initgrabz(rv3d, 0.0, 0.0, 0.0);
- ED_view3d_win_to_delta(ar, mval_f, vec);
- fac = maxf(fabsf(vec[0]), maxf(fabsf(vec[1]), fabsf(vec[2]))); /* largest abs axis */
+ ED_view3d_win_to_delta(ar, mval_f, tvec);
+ fac = maxf(fabsf(tvec[0]), maxf(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */
fac = 1.0f / fac;
- asp = ( (float)ibuf->y) / (float)ibuf->x;
+ asp = (float)ibuf->y / (float)ibuf->x;
- zero_v3(vec);
- ED_view3d_project_float_v2(ar, vec, sco, rv3d->persmat);
- cx = sco[0];
- cy = sco[1];
+ zero_v3(tvec);
+ ED_view3d_project_float_v2_m4(ar, tvec, sco, rv3d->persmat);
- x1 = cx + fac * (bgpic->xof - bgpic->size);
- y1 = cy + asp * fac * (bgpic->yof - bgpic->size);
- x2 = cx + fac * (bgpic->xof + bgpic->size);
- y2 = cy + asp * fac * (bgpic->yof + bgpic->size);
+ x1 = sco[0] + fac * (bgpic->xof - bgpic->size);
+ y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size);
+ x2 = sco[0] + fac * (bgpic->xof + bgpic->size);
+ y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size);
}
/* complete clip? */
@@ -1772,8 +1773,9 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
glDepthMask(1);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- if (freeibuf)
+ if (freeibuf) {
IMB_freeImBuf(freeibuf);
+ }
}
}
}
@@ -2045,8 +2047,8 @@ void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
x = rect->xmin;
y = rect->ymin;
- w = BLI_RCT_SIZE_X(rect);
- h = BLI_RCT_SIZE_Y(rect);
+ w = BLI_rcti_size_x(rect);
+ h = BLI_rcti_size_y(rect);
if (w <= 0 || h <= 0) {
if (d->depths)
@@ -2879,10 +2881,10 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE);
- cliprct.xmin = viewborder.xmin + scene->r.border.xmin * BLI_RCT_SIZE_X(&viewborder);
- cliprct.ymin = viewborder.ymin + scene->r.border.ymin * BLI_RCT_SIZE_Y(&viewborder);
- cliprct.xmax = viewborder.xmin + scene->r.border.xmax * BLI_RCT_SIZE_X(&viewborder);
- cliprct.ymax = viewborder.ymin + scene->r.border.ymax * BLI_RCT_SIZE_Y(&viewborder);
+ cliprct.xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
+ cliprct.ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
+ cliprct.xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
+ cliprct.ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
cliprct.xmin += ar->winrct.xmin;
cliprct.xmax += ar->winrct.xmin;
@@ -2896,7 +2898,7 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw
if (cliprct.xmax > cliprct.xmin && cliprct.ymax > cliprct.ymin) {
glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor(cliprct.xmin, cliprct.ymin, BLI_RCT_SIZE_X(&cliprct), BLI_RCT_SIZE_Y(&cliprct));
+ glScissor(cliprct.xmin, cliprct.ymin, BLI_rcti_size_x(&cliprct), BLI_rcti_size_y(&cliprct));
}
else
return 0;
@@ -3181,17 +3183,6 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
const char *grid_unit = NULL;
int draw_border = (rv3d->persp == RV3D_CAMOB && (scene->r.mode & R_BORDER));
- /* --- until we get a clue and make viewport threadsafe (temp mango change for stability) */
- if (G.is_rendering) {
- ED_region_pixelspace(ar);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- BLF_draw_default(10,10,0, "do do da da.. da da.. da da.. can't touch this! it's render time", 512);
- return;
- }
- /* --- end temp mango change */
-
/* draw viewport using opengl */
if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) {
view3d_main_area_draw_objects(C, ar, &grid_unit);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 7accdb0c0e4..744ce6f6209 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -375,17 +375,17 @@ typedef struct ViewOpsData {
#define TRACKBALLSIZE (1.1)
-static void calctrackballvec(rcti *rect, int mx, int my, float vec[3])
+static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
{
float x, y, radius, d, z, t;
radius = TRACKBALLSIZE;
/* normalize x and y */
- x = BLI_RCT_CENTER_X(rect) - mx;
- x /= (float)(BLI_RCT_SIZE_X(rect) / 4);
- y = BLI_RCT_CENTER_Y(rect) - my;
- y /= (float)(BLI_RCT_SIZE_Y(rect) / 2);
+ x = BLI_rcti_cent_x(rect) - mx;
+ x /= (float)(BLI_rcti_size_x(rect) / 4);
+ y = BLI_rcti_cent_y(rect) - my;
+ y /= (float)(BLI_rcti_size_y(rect) / 2);
d = sqrt(x * x + y * y);
if (d < radius * (float)M_SQRT1_2) { /* Inside sphere */
@@ -1637,7 +1637,7 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom,
if (use_cam_zoom) {
float delta;
delta = (x - vod->origx + y - vod->origy) / 10.0f;
- vod->rv3d->camzoom = vod->camzoom0 - delta;
+ vod->rv3d->camzoom = vod->camzoom0 + (zoom_invert ? delta : -delta);
CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
}
@@ -1666,8 +1666,8 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom,
int ctr[2], len1, len2;
/* method which zooms based on how far you move the mouse */
- ctr[0] = BLI_RCT_CENTER_X(&vod->ar->winrct);
- ctr[1] = BLI_RCT_CENTER_Y(&vod->ar->winrct);
+ ctr[0] = BLI_rcti_cent_x(&vod->ar->winrct);
+ ctr[1] = BLI_rcti_cent_y(&vod->ar->winrct);
len1 = (int)sqrt((ctr[0] - x) * (ctr[0] - x) + (ctr[1] - y) * (ctr[1] - y)) + 5;
len2 = (int)sqrt((ctr[0] - vod->origx) * (ctr[0] - vod->origx) + (ctr[1] - vod->origy) * (ctr[1] - vod->origy)) + 5;
@@ -2619,10 +2619,10 @@ static int render_border_exec(bContext *C, wmOperator *op)
/* calculate range */
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE);
- scene->r.border.xmin = ((float)rect.xmin - vb.xmin) / BLI_RCT_SIZE_X(&vb);
- scene->r.border.ymin = ((float)rect.ymin - vb.ymin) / BLI_RCT_SIZE_Y(&vb);
- scene->r.border.xmax = ((float)rect.xmax - vb.xmin) / BLI_RCT_SIZE_X(&vb);
- scene->r.border.ymax = ((float)rect.ymax - vb.ymin) / BLI_RCT_SIZE_Y(&vb);
+ scene->r.border.xmin = ((float)rect.xmin - vb.xmin) / BLI_rctf_size_x(&vb);
+ scene->r.border.ymin = ((float)rect.ymin - vb.ymin) / BLI_rctf_size_y(&vb);
+ scene->r.border.xmax = ((float)rect.xmax - vb.xmin) / BLI_rctf_size_x(&vb);
+ scene->r.border.ymax = ((float)rect.ymax - vb.ymin) / BLI_rctf_size_y(&vb);
/* actually set border */
CLAMP(scene->r.border.xmin, 0.0f, 1.0f);
@@ -2786,8 +2786,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
}
/* work out the ratios, so that everything selected fits when we zoom */
- xscale = (BLI_RCT_SIZE_X(&rect) / vb[0]);
- yscale = (BLI_RCT_SIZE_Y(&rect) / vb[1]);
+ xscale = (BLI_rcti_size_x(&rect) / vb[0]);
+ yscale = (BLI_rcti_size_y(&rect) / vb[1]);
new_dist *= maxf(xscale, yscale);
/* zoom in as required, or as far as we can go */
@@ -3465,7 +3465,7 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
view3d_set_viewcontext(C, &vc);
view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */
- ED_view3d_calc_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect);
+ ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, &mats, &rect);
return OPERATOR_FINISHED;
}
@@ -3529,7 +3529,7 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *eve
// if (obedit && ctrl) lr_click= 1;
copy_v3_v3(oldcurs, fp);
- project_int_noclip(ar, fp, mval);
+ ED_view3d_project_int_noclip(ar, fp, mval);
flip = initgrabz(rv3d, fp[0], fp[1], fp[2]);
/* reset the depth based on the view offset */
@@ -3537,7 +3537,7 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *eve
negate_v3_v3(fp, rv3d->ofs);
/* re initialize */
- project_int_noclip(ar, fp, mval);
+ ED_view3d_project_int_noclip(ar, fp, mval);
flip = initgrabz(rv3d, fp[0], fp[1], fp[2]);
(void)flip;
}
@@ -3837,10 +3837,12 @@ int ED_view3d_autodist_depth_seg(ARegion *ar, const int mval_sta[2], const int m
}
/**
- * Gets the view transformation from a camera
- * currently dosnt take camzoom into account
+ * Set the view transformation from a 4x4 matrix.
*
- * The dist is not modified for this function, if NULL its assumed zero
+ * \param mat The view 4x4 transformation matrix to assign.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
*/
void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist)
{
@@ -3871,6 +3873,14 @@ void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist)
}
}
+/**
+ * Calculate the view transformation matrix from RegionView3D input.
+ * The resulting matrix is equivalent to RegionView3D.viewinv
+ * \param mat The view 4x4 transformation matrix to calculate.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
+ */
void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], const float dist)
{
float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]};
@@ -3881,8 +3891,14 @@ void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], co
sub_v3_v3v3(mat[3], dvec, ofs);
}
-
-/* object -> view */
+/**
+ * Set the RegionView3D members from an objects transformation and optionally lens.
+ * \param ob The object to set the view to.
+ * \param ofs The view offset to be set, normally from RegionView3D.ofs.
+ * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
+ * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
+ */
void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
{
ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
@@ -3896,7 +3912,13 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist,
}
}
-/* view -> object */
+/**
+ * Set the object transformation from RegionView3D members.
+ * \param ob The object which has the transformation assigned.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
+ */
void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist)
{
float mat[4][4];
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 855771b17a2..c743b88e889 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -346,7 +346,6 @@ static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event
/* check for flying ortho camera - which we cant support well
* we _could_ also check for an ortho camera but this is easier */
if ((fly->rv3d->persp == RV3D_CAMOB) &&
- (fly->v3d->camera != NULL) &&
(fly->rv3d->is_persp == FALSE))
{
((Camera *)fly->v3d->camera->data)->type = CAM_PERSP;
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index fd43333acfe..b2ae63df662 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -84,25 +84,10 @@
* This can be cleaned when I make some new 'mode' icons.
*/
-/* view3d handler codes */
-#define VIEW3D_HANDLER_BACKGROUND 1
-#define VIEW3D_HANDLER_PROPERTIES 2
-#define VIEW3D_HANDLER_OBJECT 3
-#define VIEW3D_HANDLER_PREVIEW 4
-#define VIEW3D_HANDLER_MULTIRES 5
-#define VIEW3D_HANDLER_TRANSFORM 6
-#define VIEW3D_HANDLER_GREASEPENCIL 7
-#define VIEW3D_HANDLER_BONESKETCH 8
-
/* end XXX ************* */
static void do_view3d_header_buttons(bContext *C, void *arg, int event);
-#define B_SCENELOCK 101
-#define B_FULL 102
-#define B_HOME 103
-#define B_VIEWBUT 104
-#define B_PERSP 105
#define B_MODESELECT 108
#define B_SEL_VERT 110
#define B_SEL_EDGE 111
@@ -110,10 +95,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event);
#define B_MAN_TRANS 116
#define B_MAN_ROT 117
#define B_MAN_SCALE 118
-#define B_NDOF 119
#define B_MAN_MODE 120
-#define B_REDR 122
-#define B_NOP 123
/* XXX quickly ported across */
static void handle_view3d_lock(bContext *C)
@@ -346,10 +328,6 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
/* watch it: if sa->win does not exist, check that when calling direct drawing routines */
switch (event) {
- case B_REDR:
- ED_area_tag_redraw(sa);
- break;
-
case B_MODESELECT:
WM_operator_properties_create(&props_ptr, "OBJECT_OT_mode_set");
RNA_enum_set(&props_ptr, "mode", v3d->modeselect);
@@ -416,9 +394,6 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
}
ED_area_tag_redraw(sa);
break;
- case B_NDOF:
- ED_area_tag_redraw(sa);
- break;
case B_MAN_MODE:
ED_area_tag_redraw(sa);
break;
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 166a62562fd..e409ad4e81e 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -114,7 +114,7 @@ int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int m
mval_cpy[0] = mval[0];
mval_cpy[1] = mval[1];
- project_int_noclip(vc->ar, fp, mval_cpy);
+ ED_view3d_project_int_noclip(vc->ar, fp, mval_cpy);
initgrabz(vc->rv3d, fp[0], fp[1], fp[2]);
@@ -319,11 +319,6 @@ static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
return 1;
}
-
-#define MOVES_GESTURE 50
-#define MOVES_LASSO 500
-
-
/* warning; lasso select with backbuffer-check draws in backbuf with persp(PERSP_WIN)
* and returns with persp(PERSP_VIEW). After lasso select backbuf is not OK
*/
@@ -339,9 +334,9 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, int mcords[][2], s
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if (PBONE_VISIBLE(arm, pchan->bone) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
mul_v3_m4v3(vec, ob->obmat, pchan->pose_head);
- project_int(vc->ar, vec, sco1);
+ ED_view3d_project_int(vc->ar, vec, sco1);
mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
- project_int(vc->ar, vec, sco2);
+ ED_view3d_project_int(vc->ar, vec, sco2);
if (BLI_lasso_is_edge_inside(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1], IS_CLIPPED)) {
if (select) pchan->bone->flag |= BONE_SELECTED;
@@ -376,7 +371,7 @@ static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short move
for (base = vc->scene->base.first; base; base = base->next) {
if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */
- project_short(vc->ar, base->object->obmat[3], &base->sx);
+ ED_view3d_project_short(vc->ar, base->object->obmat[3], &base->sx);
if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
if (select) ED_base_object_select(base, BA_SELECT);
@@ -583,9 +578,9 @@ static void do_lasso_select_armature(ViewContext *vc, int mcords[][2], short mov
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) {
mul_v3_m4v3(vec, vc->obedit->obmat, ebone->head);
- project_short(vc->ar, vec, sco1);
+ ED_view3d_project_short(vc->ar, vec, sco1);
mul_v3_m4v3(vec, vc->obedit->obmat, ebone->tail);
- project_short(vc->ar, vec, sco2);
+ ED_view3d_project_short(vc->ar, vec, sco2);
didpoint = 0;
if (BLI_lasso_is_point_inside(mcords, moves, sco1[0], sco1[1], IS_CLIPPED)) {
@@ -637,7 +632,7 @@ static void do_lasso_select_meta(ViewContext *vc, int mcords[][2], short moves,
for (ml = mb->editelems->first; ml; ml = ml->next) {
mul_v3_m4v3(vec, vc->obedit->obmat, &ml->x);
- project_short(vc->ar, vec, sco);
+ ED_view3d_project_short(vc->ar, vec, sco);
if (BLI_lasso_is_point_inside(mcords, moves, sco[0], sco[1], IS_CLIPPED)) {
if (select) ml->flag |= SELECT;
@@ -654,8 +649,8 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int
unsigned int *rt;
int a, index;
char *selar;
- int sx = BLI_RCT_SIZE_X(rect) + 1;
- int sy = BLI_RCT_SIZE_Y(rect) + 1;
+ int sx = BLI_rcti_size_x(rect) + 1;
+ int sy = BLI_rcti_size_y(rect) + 1;
me = vc->obact->data;
@@ -1065,7 +1060,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
else {
int temp, dist = 15;
- project_short(vc->ar, base->object->obmat[3], &base->sx);
+ ED_view3d_project_short(vc->ar, base->object->obmat[3], &base->sx);
temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]);
if (temp < dist)
@@ -1346,7 +1341,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
base = startbase;
while (base) {
if (BASE_SELECTABLE(v3d, base)) {
- project_short(ar, base->object->obmat[3], &base->sx);
+ ED_view3d_project_short(ar, base->object->obmat[3], &base->sx);
temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]);
if (base == BASACT) temp += 10;
@@ -2383,11 +2378,11 @@ static void pose_circle_select(ViewContext *vc, int select, const int mval[2], f
/* project head location to screenspace */
mul_v3_m4v3(vec, vc->obact->obmat, pchan->pose_head);
- project_short(vc->ar, vec, sco1);
+ ED_view3d_project_short(vc->ar, vec, sco1);
/* project tail location to screenspace */
mul_v3_m4v3(vec, vc->obact->obmat, pchan->pose_tail);
- project_short(vc->ar, vec, sco2);
+ ED_view3d_project_short(vc->ar, vec, sco2);
/* check if the head and/or tail is in the circle
* - the call to check also does the selection already
@@ -2451,11 +2446,11 @@ static void armature_circle_select(ViewContext *vc, int select, const int mval[2
/* project head location to screenspace */
mul_v3_m4v3(vec, vc->obedit->obmat, ebone->head);
- project_short(vc->ar, vec, sco1);
+ ED_view3d_project_short(vc->ar, vec, sco1);
/* project tail location to screenspace */
mul_v3_m4v3(vec, vc->obedit->obmat, ebone->tail);
- project_short(vc->ar, vec, sco2);
+ ED_view3d_project_short(vc->ar, vec, sco2);
/* check if the head and/or tail is in the circle
* - the call to check also does the selection already
@@ -2561,7 +2556,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
select = select ? BA_SELECT : BA_DESELECT;
for (base = FIRSTBASE; base; base = base->next) {
if (BASE_SELECTABLE(v3d, base)) {
- project_short(ar, base->object->obmat[3], &base->sx);
+ ED_view3d_project_short(ar, base->object->obmat[3], &base->sx);
if (base->sx != IS_CLIPPED) {
int dx = base->sx - x;
int dy = base->sy - y;
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index c25bb80bfde..ff518e6ce5b 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -520,7 +520,7 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
/* ********************************** */
-void ED_view3d_calc_clipping(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect)
+void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect)
{
float modelview[4][4];
double xs, ys, p[3];
@@ -569,7 +569,18 @@ void ED_view3d_calc_clipping(BoundBox *bb, float planes[4][4], bglMats *mats, co
}
}
-/* create intersection coordinates in view Z direction at mouse coordinates */
+/**
+ * Calculate a 3d segment from 2d window coordinates.
+ * This ray_start is located at the viewpoint, ray_end is a far point.
+ * ray_start and ray_end are clipped by the view near and far limits
+ * so points along this line are always in view.
+ * In orthographic view all resulting segments will be parallel.
+ * \param ar The region (used for the window width and height).
+ * \param v3d The 3d viewport (used for near and far clipping range).
+ * \param mval The area relative 2d location (such as event->mval, converted into float[2]).
+ * \param ray_start The world-space starting point of the segment.
+ * \param ray_end The world-space end point of the segment.
+ */
void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -604,7 +615,17 @@ void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2]
}
}
-/* create intersection ray in view Z direction at mouse coordinates */
+/**
+ * Calculate a 3d viewpoint and direction vector from 2d window coordinates.
+ * This ray_start is located at the viewpoint, ray_normal is the direction towards mval.
+ * ray_start is clipped by the view near limit so points in front of it are always in view.
+ * In orthographic view the resulting ray_normal will match the view vector.
+ * \param ar The region (used for the window width and height).
+ * \param v3d The 3d viewport (used for near clipping value).
+ * \param mval The area relative 2d location (such as event->mval, converted into float[2]).
+ * \param ray_start The world-space starting point of the segment.
+ * \param ray_normal The normalized world-space direction of towards mval.
+ */
void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3])
{
float ray_end[3];
@@ -614,6 +635,13 @@ void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float r
normalize_v3(ray_normal);
}
+/**
+ * Calculate a normalized 3d direction vector from the viewpoint towards a global location.
+ * In orthographic view the resulting vector will match the view vector.
+ * \param rv3d The region (used for the window width and height).
+ * \param coord The world-space location.
+ * \param vec The resulting normalized vector.
+ */
void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float vec[3])
{
if (rv3d->is_persp) {
@@ -660,6 +688,13 @@ int initgrabz(RegionView3D *rv3d, float x, float y, float z)
return flip;
}
+/**
+ * Calculate a 3d location from 2d window coordinates.
+ * \param ar The region (used for the window width and height).
+ * \param depth_pt The reference location used to calculate the Z depth.
+ * \param mval The area relative location (such as event->mval converted to floats).
+ * \param out The resulting world-space location.
+ */
void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[2], float out[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -690,8 +725,14 @@ void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[
}
}
-/* always call initgrabz */
-/* only to detect delta motion */
+/**
+ * Calculate a 3d difference vector from 2d window offset.
+ * note that initgrabz() must be called first to determine
+ * the depth used to calculate the delta.
+ * \param ar The region (used for the window width and height).
+ * \param mval The area relative 2d difference (such as event->mval[0] - other_x).
+ * \param out The resulting world-space delta.
+ */
void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -705,9 +746,19 @@ void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3])
out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy);
}
-/* doesn't rely on initgrabz */
-/* for perspective view, get the vector direction to
- * the mouse cursor as a normalized vector */
+/**
+ * Calculate a 3d direction vector from 2d window coordinates.
+ * This direction vector starts and the view in the direction of the 2d window coordinates.
+ * In orthographic view all window coordinates yield the same vector.
+ *
+ * \note doesn't rely on initgrabz
+ * for perspective view, get the vector direction to
+ * the mouse cursor as a normalized vector.
+ *
+ * \param ar The region (used for the window width and height).
+ * \param mval The area relative 2d location (such as event->mval converted to floats).
+ * \param out The resulting normalized world-space direction vector.
+ */
void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -754,7 +805,7 @@ void ED_view3d_ob_project_mat_get(RegionView3D *rv3d, Object *ob, float pmat[4][
/* Uses window coordinates (x,y) and depth component z to find a point in
* modelspace */
-void view3d_unproject(bglMats *mats, float out[3], const short x, const short y, const float z)
+void ED_view3d_unproject(bglMats *mats, float out[3], const float x, const float y, const float z)
{
double ux, uy, uz;
@@ -766,44 +817,44 @@ void view3d_unproject(bglMats *mats, float out[3], const short x, const short y,
out[2] = uz;
}
-/* use view3d_get_object_project_mat to get projecting mat */
-void ED_view3d_project_float_v2(const ARegion *ar, const float vec[3], float adr[2], float mat[4][4])
+/* use #ED_view3d_ob_project_mat_get to get projecting mat */
+void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r_co[2], float mat[4][4])
{
float vec4[4];
- copy_v3_v3(vec4, vec);
+ copy_v3_v3(vec4, co);
vec4[3] = 1.0;
- /* adr[0]= IS_CLIPPED; */ /* always overwritten */
+ /* r_co[0] = IS_CLIPPED; */ /* always overwritten */
mul_m4_v4(mat, vec4);
if (vec4[3] > FLT_EPSILON) {
- adr[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
- adr[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
+ r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
+ r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
}
else {
- adr[0] = adr[1] = 0.0f;
+ zero_v2(r_co);
}
}
-/* use view3d_get_object_project_mat to get projecting mat */
-void ED_view3d_project_float_v3(ARegion *ar, const float vec[3], float adr[3], float mat[4][4])
+/* use #ED_view3d_ob_project_mat_get to get projecting mat */
+void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3], float mat[4][4])
{
float vec4[4];
copy_v3_v3(vec4, vec);
vec4[3] = 1.0;
- /* adr[0]= IS_CLIPPED; */ /* always overwritten */
+ /* r_co[0] = IS_CLIPPED; */ /* always overwritten */
mul_m4_v4(mat, vec4);
if (vec4[3] > FLT_EPSILON) {
- adr[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
- adr[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
- adr[2] = vec4[2] / vec4[3];
+ r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
+ r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
+ r_co[2] = vec4[2] / vec4[3];
}
else {
- zero_v3(adr);
+ zero_v3(r_co);
}
}
@@ -842,24 +893,24 @@ int ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[][4], BoundBox *bb)
return 0;
}
-void project_short(ARegion *ar, const float vec[3], short adr[2]) /* clips */
+void ED_view3d_project_short(ARegion *ar, const float co[3], short r_co[2]) /* clips */
{
RegionView3D *rv3d = ar->regiondata;
float fx, fy, vec4[4];
- adr[0] = IS_CLIPPED;
+ r_co[0] = IS_CLIPPED;
if (rv3d->rflag & RV3D_CLIPPING) {
- if (ED_view3d_clipping_test(rv3d, vec, FALSE)) {
+ if (ED_view3d_clipping_test(rv3d, co, FALSE)) {
return;
}
}
- copy_v3_v3(vec4, vec);
+ copy_v3_v3(vec4, co);
vec4[3] = 1.0;
mul_m4_v4(rv3d->persmat, vec4);
- if (vec4[3] > (float)BL_NEAR_CLIP) { /* 0.001 is the NEAR clipping cutoff for picking */
+ if (vec4[3] > (float)BL_NEAR_CLIP) {
fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
if (fx > 0 && fx < ar->winx) {
@@ -867,44 +918,44 @@ void project_short(ARegion *ar, const float vec[3], short adr[2]) /* clips */
fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
if (fy > 0.0f && fy < (float)ar->winy) {
- adr[0] = (short)floor(fx);
- adr[1] = (short)floor(fy);
+ r_co[0] = (short)floor(fx);
+ r_co[1] = (short)floor(fy);
}
}
}
}
-void project_int(ARegion *ar, const float vec[3], int adr[2])
+void ED_view3d_project_int(ARegion *ar, const float co[3], int r_co[2])
{
RegionView3D *rv3d = ar->regiondata;
float fx, fy, vec4[4];
- copy_v3_v3(vec4, vec);
+ copy_v3_v3(vec4, co);
vec4[3] = 1.0;
- adr[0] = (int)2140000000.0f;
+ r_co[0] = (int)2140000000.0f;
mul_m4_v4(rv3d->persmat, vec4);
- if (vec4[3] > (float)BL_NEAR_CLIP) { /* 0.001 is the NEAR clipping cutoff for picking */
+ if (vec4[3] > (float)BL_NEAR_CLIP) {
fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
if (fx > -2140000000.0f && fx < 2140000000.0f) {
fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
if (fy > -2140000000.0f && fy < 2140000000.0f) {
- adr[0] = (int)floor(fx);
- adr[1] = (int)floor(fy);
+ r_co[0] = (int)floor(fx);
+ r_co[1] = (int)floor(fy);
}
}
}
}
-void project_int_noclip(ARegion *ar, const float vec[3], int adr[2])
+void ED_view3d_project_int_noclip(ARegion *ar, const float co[3], int r_co[2])
{
RegionView3D *rv3d = ar->regiondata;
float fx, fy, vec4[4];
- copy_v3_v3(vec4, vec);
+ copy_v3_v3(vec4, co);
vec4[3] = 1.0;
mul_m4_v4(rv3d->persmat, vec4);
@@ -913,27 +964,27 @@ void project_int_noclip(ARegion *ar, const float vec[3], int adr[2])
fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
- adr[0] = (int)floor(fx);
- adr[1] = (int)floor(fy);
+ r_co[0] = (int)floor(fx);
+ r_co[1] = (int)floor(fy);
}
else {
- adr[0] = ar->winx / 2;
- adr[1] = ar->winy / 2;
+ r_co[0] = ar->winx / 2;
+ r_co[1] = ar->winy / 2;
}
}
-void project_short_noclip(ARegion *ar, const float vec[3], short adr[2])
+void ED_view3d_project_short_noclip(ARegion *ar, const float co[3], short r_co[2])
{
RegionView3D *rv3d = ar->regiondata;
float fx, fy, vec4[4];
- copy_v3_v3(vec4, vec);
+ copy_v3_v3(vec4, co);
vec4[3] = 1.0;
- adr[0] = IS_CLIPPED;
+ r_co[0] = IS_CLIPPED;
mul_m4_v4(rv3d->persmat, vec4);
- if (vec4[3] > (float)BL_NEAR_CLIP) { /* 0.001 is the NEAR clipping cutoff for picking */
+ if (vec4[3] > (float)BL_NEAR_CLIP) {
fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
if (fx > -32700 && fx < 32700) {
@@ -941,53 +992,48 @@ void project_short_noclip(ARegion *ar, const float vec[3], short adr[2])
fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
if (fy > -32700.0f && fy < 32700.0f) {
- adr[0] = (short)floor(fx);
- adr[1] = (short)floor(fy);
+ r_co[0] = (short)floor(fx);
+ r_co[1] = (short)floor(fy);
}
}
}
}
-void apply_project_float(float persmat[4][4], int winx, int winy, const float vec[3], float adr[2])
+void ED_view3d_project_float(ARegion *ar, const float co[3], float r_co[2])
{
+ RegionView3D *rv3d = ar->regiondata;
+
float vec4[4];
- copy_v3_v3(vec4, vec);
+ copy_v3_v3(vec4, co);
vec4[3] = 1.0;
- adr[0] = IS_CLIPPED;
+ r_co[0] = IS_CLIPPED;
- mul_m4_v4(persmat, vec4);
+ mul_m4_v4(rv3d->persmat, vec4);
if (vec4[3] > (float)BL_NEAR_CLIP) {
- adr[0] = (float)(winx / 2.0f) + (winx / 2.0f) * vec4[0] / vec4[3];
- adr[1] = (float)(winy / 2.0f) + (winy / 2.0f) * vec4[1] / vec4[3];
+ r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
+ r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
}
}
-void project_float(ARegion *ar, const float vec[3], float adr[2])
-{
- RegionView3D *rv3d = ar->regiondata;
-
- apply_project_float(rv3d->persmat, ar->winx, ar->winy, vec, adr);
-}
-
-void project_float_noclip(ARegion *ar, const float vec[3], float adr[2])
+void ED_view3d_project_float_noclip(ARegion *ar, const float co[3], float r_co[2])
{
RegionView3D *rv3d = ar->regiondata;
float vec4[4];
- copy_v3_v3(vec4, vec);
+ copy_v3_v3(vec4, co);
vec4[3] = 1.0;
mul_m4_v4(rv3d->persmat, vec4);
if (fabs(vec4[3]) > BL_NEAR_CLIP) {
- adr[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
- adr[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
+ r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
+ r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
}
else {
- adr[0] = ar->winx / 2.0f;
- adr[1] = ar->winy / 2.0f;
+ r_co[0] = ar->winx / 2.0f;
+ r_co[1] = ar->winy / 2.0f;
}
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index a3fb4e851e2..ee5d50c7aba 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -126,11 +126,11 @@ static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy)
{
float divx, divy;
- divx = BLI_RCT_SIZE_X(&v2d->mask);
- divy = BLI_RCT_SIZE_Y(&v2d->mask);
+ divx = BLI_rcti_size_x(&v2d->mask);
+ divy = BLI_rcti_size_y(&v2d->mask);
- r_vec[0] = BLI_RCT_SIZE_X(&v2d->cur) * dx / divx;
- r_vec[1] = BLI_RCT_SIZE_Y(&v2d->cur) * dy / divy;
+ r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx;
+ r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy;
r_vec[2] = 0.0f;
}
@@ -139,11 +139,11 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
float divx, divy;
float mulx, muly;
- divx = BLI_RCT_SIZE_X(&v2d->mask);
- divy = BLI_RCT_SIZE_Y(&v2d->mask);
+ divx = BLI_rcti_size_x(&v2d->mask);
+ divy = BLI_rcti_size_y(&v2d->mask);
- mulx = BLI_RCT_SIZE_X(&v2d->cur);
- muly = BLI_RCT_SIZE_Y(&v2d->cur);
+ mulx = BLI_rctf_size_x(&v2d->cur);
+ muly = BLI_rctf_size_y(&v2d->cur);
/* difference with convertViewVec2D */
/* clamp w/h, mask only */
@@ -226,7 +226,7 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2])
{
if (t->spacetype == SPACE_VIEW3D) {
if (t->ar->regiontype == RGN_TYPE_WINDOW)
- project_int_noclip(t->ar, vec, adr);
+ ED_view3d_project_int_noclip(t->ar, vec, adr);
}
else if (t->spacetype == SPACE_IMAGE) {
SpaceImage *sima = t->sa->spacedata.first;
@@ -344,7 +344,7 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
case SPACE_VIEW3D:
{
if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- project_float_noclip(t->ar, vec, adr);
+ ED_view3d_project_float_noclip(t->ar, vec, adr);
return;
}
break;
@@ -820,9 +820,6 @@ int transformEvent(TransInfo *t, wmEvent *event)
t->redraw |= handleMouseInput(t, &t->mouse, event);
if (event->type == MOUSEMOVE) {
- if (t->modifiers & MOD_CONSTRAINT_SELECT)
- t->con.mode |= CON_SELECT;
-
copy_v2_v2_int(t->mval, event->mval);
// t->redraw |= TREDRAW_SOFT; /* Use this for soft redraw. Might cause flicker in object mode */
@@ -1963,6 +1960,9 @@ void transformApply(bContext *C, TransInfo *t)
t->context = C;
if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) {
+ if (t->modifiers & MOD_CONSTRAINT_SELECT)
+ t->con.mode |= CON_SELECT;
+
selectConstraint(t);
if (t->transform) {
t->transform(t, t->mval); // calls recalcData()
@@ -2195,7 +2195,6 @@ static void constraintTransLim(TransInfo *t, TransData *td)
for (con = td->con; con; con = con->next) {
bConstraintTypeInfo *cti = NULL;
ListBase targets = {NULL, NULL};
- float tmat[4][4];
/* only consider constraint if enabled */
if (con->flag & CONSTRAINT_DISABLE) continue;
@@ -2221,8 +2220,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
/* do space conversions */
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
/* just multiply by td->mtx (this should be ok) */
- copy_m4_m4(tmat, cob.matrix);
- mul_m4_m3m4(cob.matrix, td->mtx, tmat);
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
}
else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
/* skip... incompatable spacetype */
@@ -2237,9 +2235,8 @@ static void constraintTransLim(TransInfo *t, TransData *td)
/* convert spaces again */
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- copy_m4_m4(tmat, cob.matrix);
- mul_m4_m3m4(cob.matrix, td->smtx, tmat);
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
}
/* free targets list */
@@ -2287,18 +2284,17 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
bConstraintOb cob;
bConstraint *con;
int do_limit = FALSE;
-
+
/* Evaluate valid constraints */
for (con = td->con; con; con = con->next) {
/* only consider constraint if enabled */
if (con->flag & CONSTRAINT_DISABLE) continue;
if (con->enforce == 0.0f) continue;
-
+
/* we're only interested in Limit-Rotation constraints */
if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
bRotLimitConstraint *data = con->data;
- float tmat[4][4];
-
+
/* only use it if it's tagged for this purpose */
if ((data->flag2 & LIMIT_TRANSFORM) == 0)
continue;
@@ -2312,12 +2308,11 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
constraintob_from_transdata(&cob, td);
do_limit = TRUE;
}
-
+
/* do space conversions */
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
/* just multiply by td->mtx (this should be ok) */
- copy_m4_m4(tmat, cob.matrix);
- mul_m4_m3m4(cob.matrix, td->mtx, tmat);
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
}
/* do constraint */
@@ -2325,9 +2320,8 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
/* convert spaces again */
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- copy_m4_m4(tmat, cob.matrix);
- mul_m4_m3m4(cob.matrix, td->smtx, tmat);
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
}
}
}
@@ -2382,7 +2376,6 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
/* we're only interested in Limit-Scale constraints */
if (con->type == CONSTRAINT_TYPE_SIZELIMIT) {
bSizeLimitConstraint *data = con->data;
- float tmat[4][4];
/* only use it if it's tagged for this purpose */
if ((data->flag2 & LIMIT_TRANSFORM) == 0)
@@ -2391,11 +2384,10 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
/* do space conversions */
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
/* just multiply by td->mtx (this should be ok) */
- copy_m4_m4(tmat, cob.matrix);
- mul_m4_m3m4(cob.matrix, td->mtx, tmat);
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
}
else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
- /* skip... incompatable spacetype */
+ /* skip... incompatible spacetype */
continue;
}
@@ -2404,13 +2396,12 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
/* convert spaces again */
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- copy_m4_m4(tmat, cob.matrix);
- mul_m4_m3m4(cob.matrix, td->smtx, tmat);
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
}
}
}
-
+
/* copy results from cob->matrix */
if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
/* scale val and reset size */
@@ -2420,7 +2411,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
/* Reset val if SINGLESIZE but using a constraint */
if (td->flag & TD_SINGLESIZE)
return;
-
+
mat4_to_size(td->ext->size, cob.matrix);
}
}
@@ -2852,11 +2843,11 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
if (t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) {
float obsizemat[3][3];
- // Reorient the size mat to fit the oriented object.
+ /* Reorient the size mat to fit the oriented object. */
mul_m3_m3m3(obsizemat, tmat, td->axismtx);
- //print_m3("obsizemat", obsizemat);
+ /* print_m3("obsizemat", obsizemat); */
TransMat3ToSize(obsizemat, td->axismtx, fsize);
- //print_v3("fsize", fsize);
+ /* print_v3("fsize", fsize); */
}
else {
mat3_to_size(fsize, tmat);
@@ -2864,7 +2855,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
protectedSizeBits(td->protectflag, fsize);
- if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't resize objects itself
+ if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */
if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
/* scale val and reset size */
*td->val = td->ival * (1 + (fsize[0] - 1) * td->factor);
@@ -4100,9 +4091,9 @@ void initMaskShrinkFatten(TransInfo *t)
int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
{
- TransData *td = t->data;
+ TransData *td;
float ratio;
- int i;
+ int i, initial_feather = FALSE;
char str[50];
ratio = t->values[0];
@@ -4116,13 +4107,30 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c);
- sprintf(str, "Shrink/Fatten: %s", c);
+ sprintf(str, "Feather Shrink/Fatten: %s", c);
}
else {
- sprintf(str, "Shrink/Fatten: %3f", ratio);
+ sprintf(str, "Feather Shrink/Fatten: %3f", ratio);
}
- for (i = 0; i < t->total; i++, td++) {
+ /* detect if no points have feather yet */
+ if (ratio > 1.0f) {
+ initial_feather = TRUE;
+
+ for (td = t->data, i = 0; i < t->total; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (td->ival >= 0.001f)
+ initial_feather = FALSE;
+ }
+ }
+
+ /* apply shrink/fatten */
+ for (td = t->data, i = 0; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
@@ -4130,7 +4138,11 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
continue;
if (td->val) {
- *td->val = td->ival * ratio;
+ if (initial_feather)
+ *td->val = td->ival + (ratio - 1.0f) * 0.01f;
+ else
+ *td->val = td->ival * ratio;
+
/* apply PET */
*td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
if (*td->val <= 0.0f) *td->val = 0.001f;
@@ -4774,7 +4786,7 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo
sv->edge_len = len_v3v3(dw_p, up_p);
mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co);
- project_float_noclip(t->ar, v_proj, v_proj);
+ ED_view3d_project_float_noclip(t->ar, v_proj, v_proj);
dist = len_squared_v2v2(mval, v_proj);
if (dist < min_dist) {
@@ -5040,19 +5052,19 @@ static int createSlideVerts(TransInfo *t)
j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
if (sv_array[j].down) {
- ED_view3d_project_float_v3(ar, sv_array[j].down->co, vec1, projectMat);
+ ED_view3d_project_float_v3_m4(ar, sv_array[j].down->co, vec1, projectMat);
}
else {
add_v3_v3v3(vec1, v->co, sv_array[j].downvec);
- ED_view3d_project_float_v3(ar, vec1, vec1, projectMat);
+ ED_view3d_project_float_v3_m4(ar, vec1, vec1, projectMat);
}
if (sv_array[j].up) {
- ED_view3d_project_float_v3(ar, sv_array[j].up->co, vec2, projectMat);
+ ED_view3d_project_float_v3_m4(ar, sv_array[j].up->co, vec2, projectMat);
}
else {
add_v3_v3v3(vec2, v->co, sv_array[j].upvec);
- ED_view3d_project_float_v3(ar, vec2, vec2, projectMat);
+ ED_view3d_project_float_v3_m4(ar, vec2, vec2, projectMat);
}
/* global direction */
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 181f9fe6036..022e9177a4a 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -1773,9 +1773,6 @@ void flushTransParticles(TransInfo *t)
/* ********************* mesh ****************** */
-/* proportional distance based on connectivity */
-#define THRESHOLDFACTOR (1.0f - 0.0001f)
-
/* I did this wrong, it should be a breadth-first search
* but instead it's a depth-first search, fudged
* to report shortest distances. I have no idea how fast
@@ -5170,7 +5167,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* Depending on the lock status, draw necessary views */
// fixme... some of this stuff is not good
if (ob) {
- if (ob->pose || ob_get_key(ob))
+ if (ob->pose || BKE_key_from_object(ob))
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
else
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -5554,8 +5551,8 @@ static void createTransObject(bContext *C, TransInfo *t)
static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
{
/* hold original location */
- float locxy[2] = {BLI_RCT_CENTER_X(&node->totr),
- BLI_RCT_CENTER_Y(&node->totr)};
+ float locxy[2] = {BLI_rctf_cent_x(&node->totr),
+ BLI_rctf_cent_y(&node->totr)};
copy_v2_v2(td2d->loc, locxy);
td2d->loc[2] = 0.0f;
@@ -5722,10 +5719,9 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
unit_m3(td->smtx);
}
-static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d,
+static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d,
TransDataTracking *tdt, MovieTrackingTrack *track, float aspx, float aspy)
{
- int framenr = ED_space_clip_get_clip_frame_number(sc);
MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
tdt->flag = marker->flag;
@@ -5777,7 +5773,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
MovieClip *clip = ED_space_clip_get_clip(sc);
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
MovieTrackingTrack *track;
- MovieTrackingMarker *marker;
TransDataTracking *tdt;
int framenr = ED_space_clip_get_clip_frame_number(sc);
float aspx, aspy;
@@ -5788,8 +5783,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
track = tracksbase->first;
while (track) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- marker = BKE_tracking_marker_get(track, framenr);
-
t->total++; /* offset */
if (track->flag & SELECT)
@@ -5820,9 +5813,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
track = tracksbase->first;
while (track) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- marker = BKE_tracking_marker_get(track, framenr);
-
- trackToTransData(sc, td, td2d, tdt, track, aspx, aspy);
+ trackToTransData(framenr, td, td2d, tdt, track, aspx, aspy);
/* offset */
td++;
@@ -5845,12 +5836,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
td += 2;
td2d += 2;
tdt += 2;
-
- if (marker->flag & MARKER_DISABLED) {
- td += 3;
- td2d += 3;
- tdt += 3;
- };
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index b88ae68e00b..1d75be05534 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -315,7 +315,7 @@ void applyProject(TransInfo *t)
copy_v3_v3(iloc, td->ob->obmat[3]);
}
- project_float(t->ar, iloc, mval);
+ ED_view3d_project_float(t->ar, iloc, mval);
if (snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect)) {
// if (t->flag & (T_EDIT|T_POSE)) {
@@ -601,7 +601,7 @@ int updateSelectedSnapPoint(TransInfo *t)
int dx, dy;
int dist;
- project_int(t->ar, p->co, screen_loc);
+ ED_view3d_project_int(t->ar, p->co, screen_loc);
dx = t->mval[0] - screen_loc[0];
dy = t->mval[1] - screen_loc[1];
@@ -960,8 +960,8 @@ static void TargetSnapOffset(TransInfo *t, TransData *td)
if (t->spacetype == SPACE_NODE && td != NULL) {
bNode *node = td->extra;
char border = t->tsnap.snapNodeBorder;
- float width = BLI_RCT_SIZE_X(&node->totr);
- float height = BLI_RCT_SIZE_Y(&node->totr);
+ float width = BLI_rctf_size_x(&node->totr);
+ float height = BLI_rctf_size_y(&node->totr);
if (border & NODE_LEFT)
t->tsnap.snapTarget[0] -= 0.5f * width;
@@ -1164,7 +1164,7 @@ static int snapFace(ARegion *ar, float v1co[3], float v2co[3], float v3co[3], fl
new_depth = len_v3v3(location, ray_start);
- project_int(ar, location, screen_loc);
+ ED_view3d_project_int(ar, location, screen_loc);
new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]);
if (new_dist <= *dist && new_depth < *depth) {
@@ -1232,7 +1232,7 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh
new_depth = len_v3v3(location, ray_start);
- project_int(ar, location, screen_loc);
+ ED_view3d_project_int(ar, location, screen_loc);
new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]);
/* 10% threshold if edge is closer but a bit further
@@ -1289,7 +1289,7 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[][4],
new_depth = len_v3v3(location, ray_start);
- project_int(ar, location, screen_loc);
+ ED_view3d_project_int(ar, location, screen_loc);
new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]);
if (new_dist <= *r_dist && new_depth < *r_depth) {
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index c95b2e85248..7c06fbd2a9d 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -242,7 +242,7 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em,
key = (ParamKey)efa;
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ // tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); // UNUSED
if (efa->len == 3 || efa->len == 4) {
/* for quads let parametrize split, it can make better decisions
diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt
new file mode 100644
index 00000000000..0bbccd0fca4
--- /dev/null
+++ b/source/blender/freestyle/CMakeLists.txt
@@ -0,0 +1,45 @@
+# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+file(GLOB_RECURSE SRC *.cpp *.h)
+
+set(INC
+ ../blenkernel ../blenloader ../blenlib ../imbuf ../makesdna ../makesrna
+ ../python ../python/intern
+ ../render/extern/include ../render/intern/include ../include ../src
+ ../../../extern/glew/include ../../../intern/guardedalloc ../freestyle
+)
+
+set(INC_SYS
+ ${PYTHON_INCLUDE_DIRS}
+ ${PNG_INC}
+)
+
+if(WIN32)
+ set(INC_SYS ${INC_SYS} ${PTHREADS_INC})
+endif(WIN32)
+
+blender_add_lib(bf_freestyle "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h
new file mode 100644
index 00000000000..f23f167b3a0
--- /dev/null
+++ b/source/blender/freestyle/FRS_freestyle.h
@@ -0,0 +1,86 @@
+/* FRS_freestyle.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef FRS_FREESTYLE_H
+#define FRS_FREESTYLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "DNA_listBase.h"
+ #include "DNA_scene_types.h"
+
+ #include "BKE_context.h"
+ #include "BKE_object.h"
+
+ struct Render;
+
+ extern Scene *freestyle_scene;
+ extern float freestyle_viewpoint[3];
+ extern float freestyle_mv[4][4];
+ extern float freestyle_proj[4][4];
+ extern int freestyle_viewport[4];
+
+ // Rendering
+ void FRS_initialize(void);
+ void FRS_set_context(bContext* C);
+ void FRS_read_file(bContext* C);
+ int FRS_is_freestyle_enabled(struct SceneRenderLayer* srl);
+ void FRS_init_stroke_rendering(struct Render* re);
+ struct Render* FRS_do_stroke_rendering(struct Render* re, struct SceneRenderLayer* srl);
+ void FRS_finish_stroke_rendering(struct Render* re);
+ void FRS_composite_result(struct Render* re, struct SceneRenderLayer* srl, struct Render* freestyle_render);
+ void FRS_exit(void);
+
+ // Panel configuration
+ void FRS_add_module(FreestyleConfig *config);
+ void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+ void FRS_move_module_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+ void FRS_move_module_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+
+ FreestyleLineSet *FRS_add_lineset(FreestyleConfig *config);
+ void FRS_copy_active_lineset(FreestyleConfig *config);
+ void FRS_paste_active_lineset(FreestyleConfig *config);
+ void FRS_delete_active_lineset(FreestyleConfig *config);
+ void FRS_move_active_lineset_up(FreestyleConfig *config);
+ void FRS_move_active_lineset_down(FreestyleConfig *config);
+
+ FreestyleLineSet *FRS_get_active_lineset(FreestyleConfig *config);
+ short FRS_get_active_lineset_index(FreestyleConfig *config);
+ void FRS_set_active_lineset_index(FreestyleConfig *config, short index);
+
+ void FRS_unlink_target_object(FreestyleConfig *config, struct Object *ob);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/freestyle/FRS_freestyle_config.h b/source/blender/freestyle/FRS_freestyle_config.h
new file mode 100644
index 00000000000..86a05d1aa22
--- /dev/null
+++ b/source/blender/freestyle/FRS_freestyle_config.h
@@ -0,0 +1,17 @@
+#ifndef FRS_FREESTYLE_CONFIG_H
+#define FRS_FREESTYLE_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "DNA_scene_types.h"
+
+ void FRS_add_freestyle_config( SceneRenderLayer* srl );
+ void FRS_free_freestyle_config( SceneRenderLayer* srl );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/freestyle/SConscript b/source/blender/freestyle/SConscript
new file mode 100644
index 00000000000..4ad790f53e5
--- /dev/null
+++ b/source/blender/freestyle/SConscript
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+import sys
+Import ('env')
+
+sources = []
+defs = []
+incs = ''
+
+incs += '../blenkernel ../blenloader ../blenlib ../imbuf ../makesdna ../makesrna'
+incs += ' ../python ../python/intern'
+incs += ' ../render/extern/include ../render/intern/include ../include ../src'
+incs += ' #/extern/glew/include #/intern/guardedalloc ../freestyle'
+incs += ' ' + env['BF_PYTHON_INC']
+incs += ' ' + env['BF_PNG_INC']
+
+
+if env['OURPLATFORM'] == 'linux2':
+ cflags='-pthread'
+ incs += ' ../../../extern/binreloc/include'
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
+ incs += ' ' + env['BF_PTHREADS_INC']
+
+########################################################
+# folders sources
+########################################################
+
+# system
+prefix = 'intern/system'
+system_sources = env.Glob(prefix + '/*.cpp')
+
+# image
+prefix = 'intern/image'
+image_sources = env.Glob(prefix + '/*.cpp')
+
+# geometry
+prefix = 'intern/geometry'
+geometry_sources = env.Glob(prefix + '/*.cpp')
+
+# scene_graph
+prefix = 'intern/scene_graph'
+scene_graph_sources = env.Glob(prefix + '/*.cpp')
+
+# winged_edge
+prefix = 'intern/winged_edge'
+winged_edge_sources = env.Glob(prefix + '/*.cpp')
+
+# view_map
+prefix = 'intern/view_map'
+view_map_sources = env.Glob(prefix + '/*.cpp')
+
+# stroke
+prefix = 'intern/stroke'
+stroke_sources = env.Glob(prefix + '/*.cpp')
+
+# application
+prefix = 'intern/application'
+application_sources = env.Glob(prefix + '/*.cpp')
+
+# blender_interface
+prefix = 'intern/blender_interface'
+interface_sources = env.Glob(prefix + '/*.cpp')
+
+# Python
+prefix = 'intern/python'
+python_sources = env.Glob(prefix + '/*.cpp') \
+ + env.Glob(prefix + '/*/*.cpp') \
+ + env.Glob(prefix + '/*/*/*.cpp') \
+ + env.Glob(prefix + '/*/*/*/*.cpp')
+
+sources = system_sources + image_sources + geometry_sources + scene_graph_sources \
+ + winged_edge_sources + view_map_sources + stroke_sources \
+ + application_sources + interface_sources + python_sources
+
+env.BlenderLib (libname="bf_freestyle",
+ sources=sources,
+ includes=Split(incs),
+ defines=defs,
+ libtype=['core'],
+ priority = [370] # bf_python is 361
+ )
+
diff --git a/source/blender/freestyle/intern/application/AppCanvas.cpp b/source/blender/freestyle/intern/application/AppCanvas.cpp
new file mode 100755
index 00000000000..ec83d2d9ff8
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppCanvas.cpp
@@ -0,0 +1,198 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Controller.h"
+#include "AppView.h"
+#include "../image/Image.h"
+#include "../system/TimeStamp.h"
+#include "../stroke/StrokeRenderer.h"
+#include "AppCanvas.h"
+#include "AppConfig.h"
+#include "../stroke/StyleModule.h"
+
+#include "../system/StringUtils.h"
+
+AppCanvas::AppCanvas()
+:Canvas()
+{
+ _pViewer = 0;
+ _MapsPath = StringUtils::toAscii( Config::Path::getInstance()->getMapsDir() ).c_str();
+}
+
+AppCanvas::AppCanvas(AppView* iViewer)
+:Canvas()
+{
+ _pViewer = iViewer;
+}
+
+AppCanvas::AppCanvas(const AppCanvas& iBrother)
+:Canvas(iBrother)
+{
+ _pViewer = iBrother._pViewer;
+}
+
+AppCanvas::~AppCanvas()
+{
+ _pViewer = 0;
+}
+
+void AppCanvas::setViewer(AppView *iViewer)
+{
+ _pViewer = iViewer;
+}
+
+int AppCanvas::width() const
+{
+ return _pViewer->width();
+}
+
+int AppCanvas::height() const
+{
+ return _pViewer->height();
+}
+
+BBox<Vec2i> AppCanvas::border() const
+{
+ return _pViewer->border();
+}
+
+float AppCanvas::thickness() const
+{
+ return _pViewer->thickness();
+}
+
+BBox<Vec3r> AppCanvas::scene3DBBox() const
+{
+ return _pViewer->scene3DBBox();
+}
+
+void AppCanvas::preDraw()
+{
+ Canvas::preDraw();
+}
+
+void AppCanvas::init()
+{
+
+ // static bool firsttime = true;
+ // if (firsttime) {
+ //
+ // _Renderer = new BlenderStrokeRenderer;
+ // if(!StrokeRenderer::loadTextures())
+ // {
+ // cerr << "unable to load stroke textures" << endl;
+ // return;
+ // }
+ // }
+}
+
+void AppCanvas::postDraw()
+{
+ for (unsigned i = 0; i < _StyleModules.size(); i++) {
+ if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
+ continue;
+ _Layers[i]->ScaleThickness(thickness());
+ }
+ Canvas::postDraw();
+}
+
+void AppCanvas::Erase()
+{
+ Canvas::Erase();
+}
+
+// Abstract
+
+void AppCanvas::readColorPixels(int x,int y,int w, int h, RGBImage& oImage) const
+{
+ float *rgb = new float[3*w*h];
+ memset(rgb, 0, sizeof(float) * 3 * w * h);
+ int xsch = width();
+ int ysch = height();
+ if (_pass_diffuse.buf) {
+ int xmin = border().getMin().x();
+ int ymin = border().getMin().y();
+ int xmax = border().getMax().x();
+ int ymax = border().getMax().y();
+ int rectx = _pass_z.width;
+ int recty = _pass_z.height;
+ float xfac = ((float)rectx) / ((float)(xmax - xmin));
+ float yfac = ((float)recty) / ((float)(ymax - ymin));
+ //printf("readColorPixels %d x %d @ (%d, %d) in %d x %d [%d x %d] -- %d x %d @ %d%%\n", w, h, x, y, xsch, ysch, xmax - xmin, ymax - ymin, rectx, recty, (int)(xfac * 100.0f));
+ int ii, jj;
+ for (int j = 0; j < h; j++) {
+ jj = (int)((y - ymin + j) * yfac);
+ if (jj < 0 || jj >= recty)
+ continue;
+ for (int i = 0; i < w; i++) {
+ ii = (int)((x - xmin + i) * xfac);
+ if (ii < 0 || ii >= rectx)
+ continue;
+ memcpy(rgb + (w * j + i) * 3, _pass_diffuse.buf + (rectx * jj + ii) * 3, sizeof(float) * 3);
+ }
+ }
+ }
+ oImage.setArray(rgb, xsch, ysch, w, h, x, y, false);
+}
+
+void AppCanvas::readDepthPixels(int x,int y,int w, int h, GrayImage& oImage) const
+{
+ float *z = new float[w*h];
+ memset(z, 0, sizeof(float) * w * h);
+ int xsch = width();
+ int ysch = height();
+ if (_pass_z.buf) {
+ int xmin = border().getMin().x();
+ int ymin = border().getMin().y();
+ int xmax = border().getMax().x();
+ int ymax = border().getMax().y();
+ int rectx = _pass_z.width;
+ int recty = _pass_z.height;
+ float xfac = ((float)rectx) / ((float)(xmax - xmin));
+ float yfac = ((float)recty) / ((float)(ymax - ymin));
+ //printf("readDepthPixels %d x %d @ (%d, %d) in %d x %d [%d x %d] -- %d x %d @ %d%%\n", w, h, x, y, xsch, ysch, xmax - xmin, ymax - ymin, rectx, recty, (int)(xfac * 100.0f));
+ int ii, jj;
+ for (int j = 0; j < h; j++) {
+ jj = (int)((y - ymin + j) * yfac);
+ if (jj < 0 || jj >= recty)
+ continue;
+ for (int i = 0; i < w; i++) {
+ ii = (int)((x - xmin + i) * xfac);
+ if (ii < 0 || ii >= rectx)
+ continue;
+ z[w * j + i] = _pass_z.buf[rectx * jj + ii];
+ }
+ }
+ }
+ oImage.setArray(z, xsch, ysch, w, h, x, y, false);
+}
+
+void AppCanvas::RenderStroke(Stroke *iStroke) {
+
+ if(_basic)
+ iStroke->RenderBasic(_Renderer);
+ else
+ iStroke->Render(_Renderer);
+}
+
+
+void AppCanvas::update() {}
+
diff --git a/source/blender/freestyle/intern/application/AppCanvas.h b/source/blender/freestyle/intern/application/AppCanvas.h
new file mode 100755
index 00000000000..59ed2af3bdd
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppCanvas.h
@@ -0,0 +1,71 @@
+#ifndef ARTCANVAS_H
+#define ARTCANVAS_H
+
+#include "../stroke/Canvas.h"
+#include "AppView.h"
+
+class AppCanvas : public Canvas
+{
+
+public:
+ AppCanvas();
+ AppCanvas(AppView *iViewer);
+ AppCanvas(const AppCanvas& iBrother);
+ virtual ~AppCanvas();
+
+ /*! operations that need to be done before a draw */
+ virtual void preDraw();
+
+ /*! operations that need to be done after a draw */
+ virtual void postDraw();
+
+ /*! Erases the layers and clears the canvas */
+ virtual void Erase();
+
+ /* init the canvas */
+ virtual void init();
+
+ /*! Reads a pixel area from the canvas */
+ virtual void readColorPixels(int x,int y,int w, int h, RGBImage& oImage) const;
+ /*! Reads a depth pixel area from the canvas */
+ virtual void readDepthPixels(int x,int y,int w, int h, GrayImage& oImage) const;
+
+ virtual BBox<Vec3r> scene3DBBox() const ;
+
+ // abstract
+ virtual void RenderStroke(Stroke*);
+ virtual void update();
+
+
+ /*! accessors */
+ virtual int width() const ;
+ virtual int height() const ;
+ virtual BBox<Vec2i> border() const ;
+ virtual float thickness() const ;
+
+ AppView *_pViewer;
+ inline const AppView * viewer() const {return _pViewer;}
+
+ /*! modifiers */
+ void setViewer(AppView *iViewer) ;
+
+ // soc
+ void setPassDiffuse(float *buf, int width, int height) {
+ _pass_diffuse.buf = buf;
+ _pass_diffuse.width = width;
+ _pass_diffuse.height = height;
+ }
+ void setPassZ(float *buf, int width, int height) {
+ _pass_z.buf = buf;
+ _pass_z.width = width;
+ _pass_z.height = height;
+ }
+private:
+ struct {
+ float *buf;
+ int width, height;
+ } _pass_diffuse, _pass_z;
+};
+
+
+#endif
diff --git a/source/blender/freestyle/intern/application/AppConfig.cpp b/source/blender/freestyle/intern/application/AppConfig.cpp
new file mode 100755
index 00000000000..fe6a8fb5e53
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppConfig.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "AppConfig.h"
+#include <iostream>
+
+#include "../system/StringUtils.h"
+using namespace std;
+
+extern "C" {
+ #include "BLI_path_util.h"
+}
+
+namespace Config {
+Path* Path::_pInstance = 0;
+Path::Path() {
+ // get the root directory
+ //soc
+ setRootDir( BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL) );
+
+ _pInstance = this;
+}
+void Path::setRootDir(const string& iRootDir) {
+ _ProjectDir = iRootDir + string(DIR_SEP.c_str()) + "freestyle";
+ _ModelsPath = "";
+ _PatternsPath = _ProjectDir + string(DIR_SEP.c_str()) + "data"
+ + string(DIR_SEP.c_str()) + "textures" + string(DIR_SEP.c_str())
+ + "variation_patterns" + string(DIR_SEP.c_str());
+ _BrushesPath = _ProjectDir + string(DIR_SEP.c_str()) + "data"
+ + string(DIR_SEP.c_str()) + "textures" + string(DIR_SEP.c_str())
+ + "brushes" + string(DIR_SEP.c_str());
+ _PythonPath = _ProjectDir + string(DIR_SEP.c_str())
++ "style_modules" + string(DIR_SEP.c_str()) ;
+ if (getenv("PYTHONPATH")) {
+ _PythonPath += string(PATH_SEP.c_str()) + string(getenv("PYTHONPATH"));
+ }
+#ifdef WIN32
+ _BrowserCmd = "C:\\Program Files\\Internet Explorer\\iexplore.exe %s";
+#else
+ _BrowserCmd = "mozilla %s";
+#endif
+ _HelpIndexPath = _ProjectDir + string(DIR_SEP.c_str()) + "doc"
+ + string(DIR_SEP.c_str()) + "html" + string(DIR_SEP.c_str())
+ + "index.html";
+ _EnvMapDir = _ProjectDir + string(DIR_SEP.c_str()) + "data"
+ + string(DIR_SEP.c_str()) + "env_map" + string(DIR_SEP.c_str());
+ _MapsDir = _ProjectDir + string(DIR_SEP.c_str()) + "data"
+ + string(DIR_SEP.c_str()) + "maps" + string(DIR_SEP.c_str());
+}
+void Path::setHomeDir(const string& iHomeDir) {
+ _HomeDir = iHomeDir;
+}
+Path::~Path() {
+ _pInstance = 0;
+}
+Path* Path::getInstance() {
+ return _pInstance;
+}
+string Path::getEnvVar(const string& iEnvVarName) {
+ string value;
+ if (!getenv(StringUtils::toAscii(iEnvVarName).c_str() ) ) {
+ cerr << "Warning: You may want to set the $"
+ << StringUtils::toAscii(iEnvVarName)
+ << " environment variable to use Freestyle." << endl
+ << " Otherwise, the current directory will be used instead."
+ << endl;
+ value = ".";
+ } else {
+ value = getenv(StringUtils::toAscii(iEnvVarName).c_str() );
+ }
+ return value;
+}
+
+} // End of namepace Config
+
diff --git a/source/blender/freestyle/intern/application/AppConfig.h b/source/blender/freestyle/intern/application/AppConfig.h
new file mode 100755
index 00000000000..59e85ca2e17
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppConfig.h
@@ -0,0 +1,105 @@
+//
+// Filename : AppConfig.h
+// Author : Emmanuel Turquin
+// Purpose : Configuration file
+// Date of creation : 26/02/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef APP_CONFIG_H
+# define APP_CONFIG_H
+
+# include <string>
+# include "../system/FreestyleConfig.h"
+# include "../system/Precision.h"
+
+using namespace std;
+
+namespace Config {
+
+ class Path{
+ protected:
+ static Path * _pInstance;
+ string _ProjectDir;
+ string _ModelsPath;
+ string _PatternsPath;
+ string _BrushesPath;
+ string _PythonPath;
+ string _BrowserCmd;
+ string _HelpIndexPath;
+ string _EnvMapDir;
+ string _MapsDir;
+ string _HomeDir;
+ public:
+ Path();
+ virtual ~Path();
+ static Path* getInstance();
+
+ void setRootDir(const string& iRootDir) ;
+ void setHomeDir(const string& iHomeDir) ;
+
+ const string& getProjectDir() const {return _ProjectDir;}
+ const string& getModelsPath() const {return _ModelsPath;}
+ const string& getPatternsPath() const {return _PatternsPath;}
+ const string& getBrushesPath() const {return _BrushesPath;}
+ const string& getPythonPath() const {return _PythonPath;}
+ const string& getBrowserCmd() const {return _BrowserCmd;}
+ const string& getHelpIndexpath() const {return _HelpIndexPath;}
+ const string& getEnvMapDir() const {return _EnvMapDir;}
+ const string& getMapsDir() const {return _MapsDir;}
+ const string& getHomeDir() const {return _HomeDir;}
+
+ static string getEnvVar(const string& iEnvVarName);
+
+ };
+
+ //
+ // Configuration, default values
+ //
+ //////////////////////////////////////////////////////////////
+
+ // Application
+ static const string APPLICATION_NAME("APPNAME");
+ static const string APPLICATION_VERSION("APPVERSION");
+
+ // ViewMap
+ static const string VIEWMAP_EXTENSION("vm");
+ static const string VIEWMAP_MAGIC("ViewMap File");
+ static const string VIEWMAP_VERSION("1.9");
+
+ // Style modules
+ static const string STYLE_MODULE_EXTENSION("py");
+ static const string STYLE_MODULES_LIST_EXTENSION("sml");
+
+ // Options
+ static const string OPTIONS_DIR("." + APPLICATION_NAME);
+ static const string OPTIONS_FILE("options.xml");
+ static const string OPTIONS_CURRENT_DIRS_FILE("current_dirs.xml");
+ static const string OPTIONS_QGLVIEWER_FILE("qglviewer.xml");
+
+ // Default options
+ static const real DEFAULT_SPHERE_RADIUS = 1.0;
+ static const real DEFAULT_DKR_EPSILON = 0.0;
+
+} // End of namepace Config
+
+#endif // APP_CONFIG_H
diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp
new file mode 100644
index 00000000000..8541122ef0d
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppView.cpp
@@ -0,0 +1,179 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" {
+#include "BLI_jitter.h"
+}
+
+#include "Controller.h"
+#include <iostream>
+#include "../stroke/Canvas.h"
+#include "AppView.h"
+#include "../scene_graph/NodeLight.h"
+#include "../view_map/Silhouette.h"
+#include "../view_map/ViewMap.h"
+#include "../scene_graph/LineRep.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/VertexRep.h"
+#include "AppConfig.h"
+
+#include "../system/StringUtils.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#if 1 // FRS_antialiasing
+#include "BKE_global.h"
+#include "DNA_scene_types.h"
+#endif
+
+#include "../../FRS_freestyle.h"
+
+}
+
+AppView::AppView(const char *iName)
+{
+ _Fovy = 30.f * M_PI / 180.0;
+ _ModelRootNode = new NodeDrawingStyle;
+ _SilhouetteRootNode = new NodeDrawingStyle;
+ _DebugRootNode = new NodeDrawingStyle;
+
+ _RootNode.AddChild(_ModelRootNode);
+ _SilhouetteRootNode->setStyle(DrawingStyle::LINES);
+ _SilhouetteRootNode->setLightingEnabled(false);
+ _SilhouetteRootNode->setLineWidth(2.f);
+ _SilhouetteRootNode->setPointSize(3.f);
+
+ _RootNode.AddChild(_SilhouetteRootNode);
+
+ _DebugRootNode->setStyle(DrawingStyle::LINES);
+ _DebugRootNode->setLightingEnabled(false);
+ _DebugRootNode->setLineWidth(1.f);
+
+ _RootNode.AddChild(_DebugRootNode);
+
+ _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0],
+ _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0],
+ _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox));
+ _minAbs = __min(rabs(_minBBox), rabs(_maxBBox));
+
+ _p2DSelectionNode = new NodeDrawingStyle;
+ _p2DSelectionNode->setLightingEnabled(false);
+ _p2DSelectionNode->setStyle(DrawingStyle::LINES);
+ _p2DSelectionNode->setLineWidth(5.f);
+
+ _p2DNode.AddChild(_p2DSelectionNode);
+
+
+ NodeLight *light = new NodeLight;
+ _Light.AddChild(light);
+}
+
+AppView::~AppView()
+{
+ int ref = _RootNode.destroy();
+
+ _Light.destroy();
+ ref = _p2DNode.destroy();
+
+}
+
+real AppView::distanceToSceneCenter() {
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+
+ Vec3r v( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+ v -= 0.5 * (bbox.getMin() + bbox.getMax());
+
+ return v.norm();
+}
+
+
+real AppView::znear() {
+
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+ Vec3r u = bbox.getMin();
+ Vec3r v = bbox.getMax();
+ Vec3r cameraCenter( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+
+ Vec3r w1( u[0], u[1], u[2] );
+ Vec3r w2( v[0], u[1], u[2] );
+ Vec3r w3( u[0], v[1], u[2] );
+ Vec3r w4( v[0], v[1], u[2] );
+ Vec3r w5( u[0], u[1], v[2] );
+ Vec3r w6( v[0], u[1], v[2] );
+ Vec3r w7( u[0], v[1], v[2] );
+ Vec3r w8( v[0], v[1], v[2] );
+
+ real _znear = __min( (w1-cameraCenter).norm(),
+ __min( (w2-cameraCenter).norm(),
+ __min( (w3-cameraCenter).norm(),
+ __min( (w4-cameraCenter).norm(),
+ __min( (w5-cameraCenter).norm(),
+ __min( (w6-cameraCenter).norm(),
+ __min( (w7-cameraCenter).norm(),
+ (w8-cameraCenter).norm() )))))));
+
+ return __max(_znear, 0.001);
+
+ }
+
+ real AppView::zfar() {
+
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+ Vec3r u = bbox.getMin();
+ Vec3r v = bbox.getMax();
+ Vec3r cameraCenter( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+
+ Vec3r w1( u[0], u[1], u[2] );
+ Vec3r w2( v[0], u[1], u[2] );
+ Vec3r w3( u[0], v[1], u[2] );
+ Vec3r w4( v[0], v[1], u[2] );
+ Vec3r w5( u[0], u[1], v[2] );
+ Vec3r w6( v[0], u[1], v[2] );
+ Vec3r w7( u[0], v[1], v[2] );
+ Vec3r w8( v[0], v[1], v[2] );
+
+ real _zfar = __max( (w1-cameraCenter).norm(),
+ __max( (w2-cameraCenter).norm(),
+ __max( (w3-cameraCenter).norm(),
+ __max( (w4-cameraCenter).norm(),
+ __max( (w5-cameraCenter).norm(),
+ __max( (w6-cameraCenter).norm(),
+ __max( (w7-cameraCenter).norm(),
+ (w8-cameraCenter).norm() )))))));
+
+ return _zfar;
+
+ }
+
+ real AppView::GetFocalLength()
+ {
+ real Near = __max(0.1,(real)(-2.f*_maxAbs+ distanceToSceneCenter() ));
+ return Near;
+ }
+
+
diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h
new file mode 100644
index 00000000000..d9b53019a93
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppView.h
@@ -0,0 +1,229 @@
+#ifndef APPVIEW_H
+# define APPVIEW_H
+
+# if !defined(WIN32) || defined(__GNUC__)
+# include <algorithm>
+using namespace std;
+# define __min(x,y) (min(x,y))
+# define __max(x,y) (max(x,y))
+# endif // WIN32
+
+# include "../geometry/Geom.h"
+# include "../geometry/BBox.h"
+# include "../scene_graph/NodeDrawingStyle.h"
+# include "../system/Precision.h"
+# include "AppConfig.h"
+
+using namespace Geometry;
+
+class AppView
+{
+
+public:
+
+ AppView(const char *iName = 0);
+ virtual ~AppView();
+
+public:
+
+ //inherited
+ inline unsigned int width() { return _width; }
+ inline unsigned int height() { return _height; }
+ inline BBox<Vec2i> border() { return _border; }
+ inline float thickness() { return _thickness; }
+ inline void setWidth( unsigned int width ) { _width = width; }
+ inline void setHeight( unsigned int height ) { _height = height; }
+ inline void setBorder( int xmin, int ymin, int xmax, int ymax ) {
+ _border = BBox<Vec2i>(Vec2i(xmin, ymin), Vec2i(xmax, ymax));
+ }
+ inline void setThickness( float thickness ) { _thickness = thickness; }
+
+protected:
+ unsigned int _width, _height;
+ BBox<Vec2i> _border;
+ float _thickness;
+
+public:
+
+ /*! Sets the model to draw in the viewer
+ * iModel
+ * The Root Node of the model
+ */
+ inline void setModel(NodeGroup *iModel)
+ {
+ if(0 != _ModelRootNode->numberOfChildren())
+ {
+ _ModelRootNode->DetachChildren();
+ _ModelRootNode->clearBBox();
+ }
+
+ AddModel(iModel);
+ }
+
+ /*! Adds a model for displaying in the viewer */
+ inline void AddModel(NodeGroup *iModel)
+ {
+ _ModelRootNode->AddChild(iModel);
+
+ _ModelRootNode->UpdateBBox();
+
+ _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0],
+ _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0],
+ _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox));
+
+ _minAbs = __min(rabs(_minBBox), rabs(_maxBBox));
+
+ }
+
+ inline void AddSilhouette(NodeGroup* iSilhouette)
+ {
+ _SilhouetteRootNode->AddChild(iSilhouette);
+ }
+
+ inline void Add2DSilhouette(NodeGroup *iSilhouette)
+ {
+ //_pFENode->AddChild(iSilhouette);
+ }
+
+ inline void Add2DVisibleSilhouette(NodeGroup *iVSilhouette)
+ {
+ //_pVisibleSilhouetteNode->AddChild(iVSilhouette);
+ }
+
+ inline void setDebug(NodeGroup* iDebug)
+ {
+ if(0 != _DebugRootNode->numberOfChildren())
+ {
+ _DebugRootNode->DetachChildren();
+ _DebugRootNode->clearBBox();
+ }
+
+ AddDebug(iDebug);
+ }
+
+ inline void AddDebug(NodeGroup* iDebug)
+ {
+ _DebugRootNode->AddChild(iDebug);
+ }
+
+ inline void DetachModel(Node *iModel)
+ {
+ _ModelRootNode->DetachChild(iModel);
+ _ModelRootNode->UpdateBBox();
+
+ _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0],
+ _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0],
+ _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox));
+ _minAbs = __min(rabs(_minBBox), rabs(_maxBBox));
+ }
+
+ inline void DetachModel()
+ {
+ _ModelRootNode->DetachChildren();
+ _ModelRootNode->clearBBox();
+
+ // 2D Scene
+ //_p2DNode.DetachChildren();
+ //_pFENode->DetachChildren();
+ //_pVisibleSilhouetteNode->DetachChildren();
+
+ }
+
+ inline void DetachSilhouette()
+ {
+ _SilhouetteRootNode->DetachChildren();
+ //_pFENode->DetachChildren();
+ //_pVisibleSilhouetteNode->DetachChildren();
+ _p2DSelectionNode->destroy();
+ }
+
+ inline void DetachVisibleSilhouette()
+ {
+ //_pVisibleSilhouetteNode->DetachChildren();
+ _p2DSelectionNode->destroy();
+ }
+
+ inline void DetachDebug()
+ {
+ _DebugRootNode->DetachChildren();
+ }
+
+
+
+ real distanceToSceneCenter();
+ real GetFocalLength();
+
+ inline real GetAspect() const
+ {
+ return ((real) _width/(real) _height);
+ }
+
+ void setHorizontalFov( float hfov )
+{
+ _Fovy = 2.0 * atan (tan(hfov / 2.0) / GetAspect());
+}
+ inline real GetFovyRadian() const
+ {
+ return _Fovy;
+ }
+
+ inline real GetFovyDegrees() const
+ {
+ return _Fovy * 180.0 / M_PI;
+ }
+
+ BBox<Vec3r> scene3DBBox() const { return _ModelRootNode->bbox(); }
+
+ real znear();
+ real zfar();
+
+
+public:
+ /*! Core scene drawing */
+ void DrawScene(SceneVisitor *iRenderer);
+
+ /*! 2D Scene Drawing */
+ void Draw2DScene(SceneVisitor *iRenderer);
+
+
+protected:
+
+ /*! fabs or abs */
+ inline int rabs(int x) {return abs(x);}
+ inline real rabs(real x) {return fabs(x);}
+
+
+protected:
+ float _Fovy;
+
+ //The root node container
+ NodeGroup _RootNode;
+ NodeDrawingStyle *_ModelRootNode;
+ NodeDrawingStyle *_SilhouetteRootNode;
+ NodeDrawingStyle *_DebugRootNode;
+
+ NodeGroup _Light;
+
+ real _minBBox;
+ real _maxBBox;
+ real _maxAbs;
+ real _minAbs;
+
+ // 2D Scene
+ bool _Draw2DScene;
+ bool _Draw3DScene; NodeGroup _p2DNode;
+ NodeDrawingStyle *_p2DSelectionNode;
+
+};
+
+#endif // APPVIEW_H
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
new file mode 100755
index 00000000000..d7f91d3d7c2
--- /dev/null
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -0,0 +1,979 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Must be included before any QT header, because of moc
+#include "../system/PythonInterpreter.h"
+
+#include <string>
+#include <fstream>
+#include <float.h>
+
+#include "AppView.h"
+#include "AppCanvas.h"
+#include "AppConfig.h"
+
+
+#include "../system/StringUtils.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/NodeTransform.h"
+#include "../scene_graph/NodeDrawingStyle.h"
+#include "../winged_edge/WingedEdgeBuilder.h"
+#include "../winged_edge/WEdge.h"
+#include "../scene_graph/VertexRep.h"
+#include "../winged_edge/WXEdgeBuilder.h"
+#include "../scene_graph/ScenePrettyPrinter.h"
+
+#include "../view_map/ViewMapTesselator.h"
+#include "../stroke/StrokeTesselator.h"
+#include "../view_map/ViewMapIO.h"
+#include "Controller.h"
+#include "../view_map/ViewMap.h"
+#include "../winged_edge/Curvature.h"
+#include "../image/Image.h"
+#include "../view_map/SteerableViewMap.h"
+#include "../stroke/PSStrokeRenderer.h"
+#include "../stroke/TextStrokeRenderer.h"
+#include "../stroke/StyleModule.h"
+
+#include "../system/StringUtils.h"
+
+#include "../blender_interface/BlenderFileLoader.h"
+#include "../blender_interface/BlenderStrokeRenderer.h"
+#include "../blender_interface/BlenderStyleModule.h"
+
+#include "DNA_freestyle_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "../../FRS_freestyle.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+Controller::Controller()
+{
+
+ const string sep(Config::DIR_SEP.c_str());
+ //const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR + sep + Config::OPTIONS_CURRENT_DIRS_FILE;
+ //_current_dirs = new ConfigIO(filename, Config::APPLICATION_NAME + "CurrentDirs", true);
+
+ _RootNode = new NodeGroup;
+ _RootNode->addRef();
+
+ _SilhouetteNode = NULL;
+ //_ProjectedSilhouette = NULL;
+ //_VisibleProjectedSilhouette = NULL;
+
+ _DebugNode = new NodeGroup;
+ _DebugNode->addRef();
+
+ _winged_edge = NULL;
+
+ _pView = NULL;
+ _pRenderMonitor = NULL;
+
+ _edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE);
+
+ _ProgressBar = new ProgressBar;
+ _SceneNumFaces = 0;
+ _minEdgeSize = DBL_MAX;
+ _EPSILON = 1e-6;
+ _bboxDiag = 0;
+
+ _ViewMap = 0;
+
+ _Canvas = 0;
+
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
+ //_VisibilityAlgo = ViewMapBuilder::ray_casting;
+
+ _Canvas = new AppCanvas;
+
+ _inter = new PythonInterpreter();
+ _EnableQI = true;
+ _EnableFaceSmoothness = false;
+ _ComputeRidges = true;
+ _ComputeSteerableViewMap = false;
+ _ComputeSuggestive = true;
+ _ComputeMaterialBoundaries = true;
+ _sphereRadius = 1.0;
+ _creaseAngle = 134.43;
+
+ init_options();
+}
+
+Controller::~Controller()
+{
+ if(NULL != _RootNode)
+ {
+ int ref = _RootNode->destroy();
+ if(0 == ref)
+ delete _RootNode;
+ }
+
+ if(NULL != _SilhouetteNode)
+ {
+ int ref = _SilhouetteNode->destroy();
+ if(0 == ref)
+ delete _SilhouetteNode;
+ }
+
+ if(NULL != _DebugNode)
+ {
+ int ref = _DebugNode->destroy();
+ if(0 == ref)
+ delete _DebugNode;
+ }
+
+ if(_winged_edge) {
+ delete _winged_edge;
+ _winged_edge = NULL;
+ }
+
+ if(0 != _ViewMap)
+ {
+ delete _ViewMap;
+ _ViewMap = 0;
+ }
+
+ if(0 != _Canvas)
+ {
+ delete _Canvas;
+ _Canvas = 0;
+ }
+
+ if (_inter) {
+ delete _inter;
+ _inter = NULL;
+ }
+
+ //delete _current_dirs;
+}
+
+void Controller::setView(AppView *iView)
+{
+ if(NULL == iView)
+ return;
+
+ _pView = iView;
+ _Canvas->setViewer(_pView);
+}
+
+void Controller::setRenderMonitor(RenderMonitor *iRenderMonitor)
+{
+ _pRenderMonitor = iRenderMonitor;
+}
+
+void Controller::setPassDiffuse(float *buf, int width, int height)
+{
+ AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
+ assert(app_canvas != 0);
+ app_canvas->setPassDiffuse(buf, width, height);
+}
+
+void Controller::setPassZ(float *buf, int width, int height)
+{
+ AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
+ assert(app_canvas != 0);
+ app_canvas->setPassZ(buf, width, height);
+}
+
+void Controller::setContext(bContext *C)
+{
+ PythonInterpreter* py_inter = dynamic_cast<PythonInterpreter*>(_inter);
+ assert(py_inter != 0);
+ py_inter->setContext(C);
+}
+
+int Controller::LoadMesh(Render *re, SceneRenderLayer* srl)
+{
+
+ BlenderFileLoader loader(re, srl);
+
+ loader.setRenderMonitor(_pRenderMonitor);
+
+ _Chrono.start();
+
+ NodeGroup *blenderScene = loader.Load();
+
+ if (blenderScene == NULL) {
+ cout << "Cannot load scene" << endl;
+ return 1;
+ }
+
+ if( blenderScene->numberOfChildren() < 1) {
+ cout << "Empty scene" << endl;
+ blenderScene->destroy();
+ delete blenderScene;
+ return 1;
+ }
+
+ cout << "Scene loaded" << endl;
+ printf("Mesh cleaning : %lf\n", _Chrono.stop());
+ _SceneNumFaces += loader.numFacesRead();
+
+ if(loader.minEdgeSize() < _minEdgeSize)
+ {
+ _minEdgeSize = loader.minEdgeSize();
+ }
+
+ // DEBUG
+ // ScenePrettyPrinter spp;
+ // blenderScene->accept(spp);
+
+ _RootNode->AddChild(blenderScene);
+ _RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox
+
+ _pView->setModel(_RootNode);
+ //_pView->FitBBox();
+
+ if (_pRenderMonitor->testBreak())
+ return 0;
+
+
+ _Chrono.start();
+
+
+ WXEdgeBuilder wx_builder;
+ wx_builder.setRenderMonitor(_pRenderMonitor);
+ blenderScene->accept(wx_builder);
+ _winged_edge = wx_builder.getWingedEdge();
+
+ printf("WEdge building : %lf\n", _Chrono.stop());
+
+ //
+ // _pView->setDebug(_DebugNode);
+
+ //delete stuff
+ // if(0 != ws_builder)
+ // {
+ // delete ws_builder;
+ // ws_builder = 0;
+ // }
+
+ //soc QFileInfo qfi(iFileName);
+ //soc string basename((const char*)qfi.fileName().toAscii().data());
+ // char cleaned[FILE_MAX];
+ // BLI_strncpy(cleaned, iFileName, FILE_MAX);
+ // BLI_cleanup_file(NULL, cleaned);
+ // string basename = StringUtils::toAscii( string(cleaned) );
+
+ _ListOfModels.push_back("Blender_models");
+
+ cout << "Triangles nb : " << _SceneNumFaces << endl;
+ _bboxDiag = (_RootNode->bbox().getMax()-_RootNode->bbox().getMin()).norm();
+ cout << "Bounding Box : " << _bboxDiag << endl;
+
+ ClearRootNode();
+
+ return 0;
+}
+
+void Controller::CloseFile()
+{
+ WShape::setCurrentId(0);
+ _ListOfModels.clear();
+
+ // We deallocate the memory:
+ ClearRootNode();
+ DeleteWingedEdge();
+ DeleteViewMap();
+
+ // clears the canvas
+ _Canvas->Clear();
+
+ // soc: reset passes
+ setPassDiffuse(NULL, 0, 0);
+ setPassZ(NULL, 0, 0);
+}
+
+void Controller::ClearRootNode()
+{
+ _pView->DetachModel();
+ if(NULL != _RootNode)
+ {
+ int ref = _RootNode->destroy();
+ if(0 == ref)
+ _RootNode->addRef();
+ _RootNode->clearBBox();
+ }
+}
+
+void Controller::DeleteWingedEdge()
+{
+ if(_winged_edge)
+ {
+ delete _winged_edge;
+ _winged_edge = NULL;
+ }
+
+ // clears the grid
+ _Grid.clear();
+ _SceneNumFaces = 0;
+ _minEdgeSize = DBL_MAX;
+}
+
+void Controller::DeleteViewMap()
+{
+ _pView->DetachSilhouette();
+ if (NULL != _SilhouetteNode)
+ {
+ int ref = _SilhouetteNode->destroy();
+ if(0 == ref) {
+ delete _SilhouetteNode;
+ _SilhouetteNode = NULL;
+ }
+ }
+
+ // if(NULL != _ProjectedSilhouette)
+ // {
+ // int ref = _ProjectedSilhouette->destroy();
+ // if(0 == ref)
+ // {
+ // delete _ProjectedSilhouette;
+ // _ProjectedSilhouette = NULL;
+ // }
+ // }
+ // if(NULL != _VisibleProjectedSilhouette)
+ // {
+ // int ref = _VisibleProjectedSilhouette->destroy();
+ // if(0 == ref)
+ // {
+ // delete _VisibleProjectedSilhouette;
+ // _VisibleProjectedSilhouette = NULL;
+ // }
+ // }
+
+ _pView->DetachDebug();
+ if(NULL != _DebugNode) {
+ int ref = _DebugNode->destroy();
+ if(0 == ref)
+ _DebugNode->addRef();
+ }
+
+ if(NULL != _ViewMap) {
+ delete _ViewMap;
+ _ViewMap = 0;
+ }
+}
+
+void Controller::ComputeViewMap()
+{
+
+ if (!_ListOfModels.size())
+ return;
+
+ if(NULL != _ViewMap)
+ {
+ delete _ViewMap;
+ _ViewMap = 0;
+ }
+
+ _pView->DetachDebug();
+ if(NULL != _DebugNode)
+ {
+ int ref = _DebugNode->destroy();
+ if(0 == ref)
+ _DebugNode->addRef();
+ }
+
+
+ _pView->DetachSilhouette();
+ if (NULL != _SilhouetteNode)
+ {
+ int ref = _SilhouetteNode->destroy();
+ if(0 == ref)
+ delete _SilhouetteNode;
+ }
+ // if(NULL != _ProjectedSilhouette)
+ // {
+ // int ref = _ProjectedSilhouette->destroy();
+ // if(0 == ref)
+ // delete _ProjectedSilhouette;
+ // }
+ // if(NULL != _VisibleProjectedSilhouette)
+ // {
+ // int ref = _VisibleProjectedSilhouette->destroy();
+ // if(0 == ref)
+ // {
+ // delete _VisibleProjectedSilhouette;
+ // _VisibleProjectedSilhouette = 0;
+ // }
+ // }
+
+ // retrieve the 3D viewpoint and transformations information
+ //----------------------------------------------------------
+ // Save the viewpoint context at the view level in order
+ // to be able to restore it later:
+
+ // Restore the context of view:
+ // we need to perform all these operations while the
+ // 3D context is on.
+ Vec3r vp( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+
+ //cout << "mv" << endl;
+ real mv[4][4];
+ for( int i= 0; i < 4; i++) {
+ for( int j= 0; j < 4; j++) {
+ mv[i][j] = freestyle_mv[i][j];
+ //cout << mv[i][j] << " ";
+ }
+ // cout << endl;
+ }
+
+ //cout << "\nproj" << endl;
+ real proj[4][4];
+ for( int i= 0; i < 4; i++) {
+ for( int j= 0; j < 4; j++) {
+ proj[i][j] = freestyle_proj[i][j];
+ //cout << proj[i][j] << " ";
+ }
+ //cout << endl;
+ }
+
+ int viewport[4];
+ for( int i= 0; i < 4; i++)
+ viewport[i] = freestyle_viewport[i];
+
+ //cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl;
+
+
+
+ // Flag the WXEdge structure for silhouette edge detection:
+ //----------------------------------------------------------
+
+ cout << "\n=== Detecting silhouette edges ===" << endl;
+ _Chrono.start();
+
+ edgeDetector.setViewpoint(Vec3r(vp));
+ edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0);
+ edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
+ edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
+ edgeDetector.enableMaterialBoundaries(_ComputeMaterialBoundaries);
+ edgeDetector.enableFaceSmoothness(_EnableFaceSmoothness);
+ edgeDetector.setCreaseAngle(_creaseAngle);
+ edgeDetector.setSphereRadius(_sphereRadius);
+ edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon);
+ edgeDetector.setRenderMonitor(_pRenderMonitor);
+ edgeDetector.processShapes(*_winged_edge);
+
+ real duration = _Chrono.stop();
+ printf("Feature lines : %lf\n", duration);
+
+ if (_pRenderMonitor->testBreak())
+ return;
+
+ // Builds the view map structure from the flagged WSEdge structure:
+ //----------------------------------------------------------
+ ViewMapBuilder vmBuilder;
+ vmBuilder.setEnableQI(_EnableQI);
+ vmBuilder.setViewpoint(Vec3r(vp));
+ vmBuilder.setTransform( mv, proj,viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
+ vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
+ vmBuilder.setGrid(&_Grid);
+ vmBuilder.setRenderMonitor(_pRenderMonitor);
+
+ // Builds a tesselated form of the silhouette for display purpose:
+ //---------------------------------------------------------------
+ ViewMapTesselator3D sTesselator3d;
+ //ViewMapTesselator2D sTesselator2d;
+ //sTesselator2d.setNature(_edgeTesselationNature);
+ sTesselator3d.setNature(_edgeTesselationNature);
+
+ cout << "\n=== Building the view map ===" << endl;
+ _Chrono.start();
+ // Build View Map
+ _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON, _RootNode->bbox(), _SceneNumFaces);
+ _ViewMap->setScene3dBBox(_RootNode->bbox());
+
+ printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size() );
+
+ //Tesselate the 3D edges:
+ _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
+ _SilhouetteNode->addRef();
+
+ // Tesselate 2D edges
+ // _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
+ // _ProjectedSilhouette->addRef();
+
+ duration = _Chrono.stop();
+ printf("ViewMap building : %lf\n", duration);
+
+
+ _pView->AddSilhouette(_SilhouetteNode);
+ //_pView->AddSilhouette(_WRoot);
+ //_pView->Add2DSilhouette(_ProjectedSilhouette);
+ //_pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);
+ _pView->AddDebug(_DebugNode);
+
+ // Draw the steerable density map:
+ //--------------------------------
+ if(_ComputeSteerableViewMap){
+ ComputeSteerableViewMap();
+ }
+ // Reset Style modules modification flags
+ resetModified(true);
+
+ DeleteWingedEdge();
+}
+
+void Controller::ComputeSteerableViewMap(){
+//soc
+ // if((!_Canvas) || (!_ViewMap))
+ // return;
+ //
+ // // Build 4 nodes containing the edges in the 4 directions
+ // NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP];
+ // unsigned i;
+ // real c = 32.f/255.f; // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32.
+ // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){
+ // ng[i] = new NodeGroup;
+ // }
+ // NodeShape *completeNS = new NodeShape;
+ // completeNS->material().setDiffuse(c,c,c,1);
+ // ng[Canvas::NB_STEERABLE_VIEWMAP-1]->AddChild(completeNS);
+ // SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ // svm->Reset();
+ //
+ // ViewMap::fedges_container& fedges = _ViewMap->FEdges();
+ // LineRep * fRep;
+ // NodeShape *ns;
+ // for(ViewMap::fedges_container::iterator f=fedges.begin(), fend=fedges.end();
+ // f!=fend;
+ // ++f){
+ // if((*f)->viewedge()->qi() != 0)
+ // continue;
+ // fRep = new LineRep((*f)->vertexA()->point2d(),(*f)->vertexB()->point2d()) ;
+ // completeNS->AddRep(fRep); // add to the complete map anyway
+ // double *oweights = svm->AddFEdge(*f);
+ // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP-1; ++i){
+ // ns = new NodeShape;
+ // double wc = oweights[i]*c;
+ // if(oweights[i] == 0)
+ // continue;
+ // ns->material().setDiffuse(wc, wc, wc, 1);
+ // ns->AddRep(fRep);
+ // ng[i]->AddChild(ns);
+ // }
+ // }
+ //
+ // GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP];
+ // //#ifdef WIN32
+ // QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height());
+ // QPixmap pm;
+ // QImage qimg;
+ // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){
+ // offscreenBuffer.AddNode(ng[i]);
+ // //img[i] = new GrayImage(_pView->width(), _pView->height());
+ // //offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray());
+ // pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height());
+ //
+ // if(pm.isNull())
+ // cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl;
+ // //pm.save(QString("steerable")+QString::number(i)+QString(".bmp"), "BMP");
+ // // FIXME!! Lost of time !
+ // qimg = pm.toImage();
+ // // FIXME !! again!
+ // img[i] = new GrayImage(_pView->width(), _pView->height());
+ // for(unsigned y=0;y<img[i]->height();++y){
+ // for(unsigned x=0;x<img[i]->width();++x){
+ // //img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y))/255.f);
+ // img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y)));
+ // // float c = qGray(qimg.pixel(x,y));
+ // // img[i]->setPixel(x,y,qGray(qimg.pixel(x,y)));
+ // }
+ // }
+ // offscreenBuffer.DetachNode(ng[i]);
+ // ng[i]->destroy();
+ // delete ng[i];
+ // // check
+ // // qimg = QImage(_pView->width(), _pView->height(), 32);
+ // // for(y=0;y<img[i]->height();++y){
+ // // for(unsigned x=0;x<img[i]->width();++x){
+ // // float v = img[i]->pixel(x,y);
+ // // qimg.setPixel(x,y,qRgb(v,v,v));
+ // // }
+ // // }
+ // // qimg.save(QString("newsteerable")+QString::number(i)+QString(".bmp"), "BMP");
+ // }
+ //
+ //
+ // svm->buildImagesPyramids(img,false,0,1.f);
+}
+
+void Controller::saveSteerableViewMapImages(){
+ SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ if(!svm){
+ cerr << "the Steerable ViewMap has not been computed yet" << endl;
+ return;
+ }
+ svm->saveSteerableViewMap();
+}
+
+void Controller::toggleVisibilityAlgo()
+{
+ if(_VisibilityAlgo == ViewMapBuilder::ray_casting) {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
+ }
+ else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
+ }
+ else {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting;
+ }
+}
+
+void Controller::setVisibilityAlgo(int algo)
+{
+ switch (algo) {
+ case FREESTYLE_ALGO_REGULAR:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting;
+ break;
+ case FREESTYLE_ALGO_FAST:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
+ break;
+ case FREESTYLE_ALGO_VERYFAST:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
+ break;
+ case FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_traditional;
+ break;
+ case FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
+ break;
+ case FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_cumulative;
+ break;
+ case FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_cumulative;
+ break;
+ }
+}
+
+int Controller::getVisibilityAlgo()
+{
+ switch (_VisibilityAlgo) {
+ case ViewMapBuilder::ray_casting:
+ return FREESTYLE_ALGO_REGULAR;
+ case ViewMapBuilder::ray_casting_fast:
+ return FREESTYLE_ALGO_FAST;
+ case ViewMapBuilder::ray_casting_very_fast:
+ return FREESTYLE_ALGO_VERYFAST;
+ case ViewMapBuilder::ray_casting_culled_adaptive_traditional:
+ return FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL;
+ case ViewMapBuilder::ray_casting_adaptive_traditional:
+ return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
+ case ViewMapBuilder::ray_casting_culled_adaptive_cumulative:
+ return FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE;
+ case ViewMapBuilder::ray_casting_adaptive_cumulative:
+ return FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE;
+ }
+
+ // ray_casting_adaptive_traditional is the most exact replacement
+ // for legacy code
+ return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
+}
+
+void Controller::setQuantitativeInvisibility(bool iBool)
+{
+ _EnableQI = iBool;
+}
+
+bool Controller::getQuantitativeInvisibility() const
+{
+ return _EnableQI;
+}
+
+void Controller::setFaceSmoothness(bool iBool)
+{
+ _EnableFaceSmoothness = iBool;
+}
+
+bool Controller::getFaceSmoothness() const
+{
+ return _EnableFaceSmoothness;
+}
+
+void Controller::setComputeRidgesAndValleysFlag(bool iBool){
+ _ComputeRidges = iBool;
+}
+
+bool Controller::getComputeRidgesAndValleysFlag() const {
+ return _ComputeRidges;
+}
+
+void Controller::setComputeSuggestiveContoursFlag(bool b){
+ _ComputeSuggestive = b;
+}
+
+bool Controller::getComputeSuggestiveContoursFlag() const {
+ return _ComputeSuggestive;
+}
+
+void Controller::setComputeMaterialBoundariesFlag(bool b){
+ _ComputeMaterialBoundaries = b;
+}
+
+bool Controller::getComputeMaterialBoundariesFlag() const {
+ return _ComputeMaterialBoundaries;
+}
+
+void Controller::setComputeSteerableViewMapFlag(bool iBool){
+ _ComputeSteerableViewMap = iBool;
+}
+
+bool Controller::getComputeSteerableViewMapFlag() const {
+ return _ComputeSteerableViewMap;
+}
+
+void Controller::DrawStrokes()
+{
+ if(_ViewMap == 0)
+ return;
+
+ cout << "\n=== Stroke drawing ===" << endl;
+ _Chrono.start();
+ _Canvas->Draw();
+ real d = _Chrono.stop();
+ cout << "Strokes generation : " << d << endl;
+ cout << "Stroke count : " << _Canvas->stroke_count << endl;
+ resetModified();
+ DeleteViewMap();
+}
+
+void Controller::ResetRenderCount()
+{
+ _render_count = 0;
+}
+
+Render* Controller::RenderStrokes(Render *re) {
+ _Chrono.start();
+ BlenderStrokeRenderer* blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
+ _Canvas->Render( blenderRenderer );
+ Render* freestyle_render = blenderRenderer->RenderScene(re);
+ real d = _Chrono.stop();
+ cout << "Stroke rendering : " << d << endl;
+ delete blenderRenderer;
+
+ return freestyle_render;
+}
+
+void Controller::InsertStyleModule(unsigned index, const char *iFileName)
+{
+ if( !BLI_testextensie(iFileName, ".py") ) {
+ cerr << "Error: Cannot load \"" << StringUtils::toAscii( string(iFileName) )
+ << "\", unknown extension" << endl;
+ return;
+ }
+
+ StyleModule* sm = new StyleModule(iFileName, _inter);
+ _Canvas->InsertStyleModule(index, sm);
+
+}
+
+void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText)
+{
+ StyleModule* sm = new BlenderStyleModule(iText, iName, _inter);
+ _Canvas->InsertStyleModule(index, sm);
+}
+
+void Controller::AddStyleModule(const char *iFileName)
+{
+ //_pStyleWindow->Add(iFileName);
+}
+
+void Controller::RemoveStyleModule(unsigned index)
+{
+ _Canvas->RemoveStyleModule(index);
+}
+
+void Controller::Clear()
+{
+ _Canvas->Clear();
+}
+
+void Controller::ReloadStyleModule(unsigned index, const char * iFileName)
+{
+ StyleModule* sm = new StyleModule(iFileName, _inter);
+ _Canvas->ReplaceStyleModule(index, sm);
+}
+
+void Controller::SwapStyleModules(unsigned i1, unsigned i2)
+{
+ _Canvas->SwapStyleModules(i1, i2);
+}
+
+
+void Controller::toggleLayer(unsigned index, bool iDisplay)
+{
+ _Canvas->setVisible(index, iDisplay);
+}
+
+void Controller::setModified(unsigned index, bool iMod)
+{
+ //_pStyleWindow->setModified(index, iMod);
+ _Canvas->setModified(index, iMod);
+ updateCausalStyleModules(index + 1);
+}
+
+void Controller::updateCausalStyleModules(unsigned index) {
+ vector<unsigned> vec;
+ _Canvas->causalStyleModules(vec, index);
+ for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) {
+ //_pStyleWindow->setModified(*it, true);
+ _Canvas->setModified(*it, true);
+ }
+}
+
+void Controller::resetModified(bool iMod)
+{
+ //_pStyleWindow->resetModified(iMod);
+ _Canvas->resetModified(iMod);
+}
+
+NodeGroup * Controller::BuildRep(vector<ViewEdge*>::iterator vedges_begin,
+ vector<ViewEdge*>::iterator vedges_end)
+{
+ ViewMapTesselator2D tesselator2D;
+ FrsMaterial mat;
+ mat.setDiffuse(1,1,0.3,1);
+ tesselator2D.setFrsMaterial(mat);
+
+ return (tesselator2D.Tesselate(vedges_begin, vedges_end));
+}
+
+void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
+{
+ _edgeTesselationNature ^= (iNature);
+ ComputeViewMap();
+}
+
+void Controller::setModelsDir(const string& dir) {
+ //_current_dirs->setValue("models/dir", dir);
+}
+
+string Controller::getModelsDir() const {
+ string dir = ".";
+ //_current_dirs->getValue("models/dir", dir);
+ return dir;
+}
+
+void Controller::setModulesDir(const string& dir) {
+ //_current_dirs->setValue("modules/dir", dir);
+}
+
+string Controller::getModulesDir() const {
+ string dir = ".";
+ //_current_dirs->getValue("modules/dir", dir);
+ return dir;
+}
+
+void Controller::setHelpIndex(const string& index) {
+ _help_index = index;
+}
+
+string Controller::getHelpIndex() const {
+ return _help_index;
+}
+
+void Controller::setBrowserCmd(const string& cmd) {
+ _browser_cmd = cmd;
+}
+
+string Controller::getBrowserCmd() const {
+ return _browser_cmd;
+}
+
+void Controller::resetInterpreter() {
+ if (_inter)
+ _inter->reset();
+}
+
+
+void Controller::displayDensityCurves(int x, int y){
+ SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ if(!svm)
+ return;
+
+ unsigned i,j;
+ typedef vector<Vec3r> densityCurve;
+ vector<densityCurve> curves(svm->getNumberOfOrientations()+1);
+ vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels());
+
+ // collect the curves values
+ unsigned nbCurves = svm->getNumberOfOrientations()+1;
+ unsigned nbPoints = svm->getNumberOfPyramidLevels();
+ if(!nbPoints)
+ return;
+
+ // build the density/nbLevels curves for each orientation
+ for(i=0;i<nbCurves; ++i){
+ for(j=0; j<nbPoints; ++j){
+ curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0));
+ }
+ }
+ // build the density/nbOrientations curves for each level
+ for(i=0;i<nbPoints; ++i){
+ for(j=0; j<nbCurves; ++j){
+ curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0));
+ }
+ }
+
+ // display the curves
+ // for(i=0; i<nbCurves; ++i)
+ // _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0,0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
+ // for(i=1; i<=8; ++i)
+ // _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0,0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density");
+ // _pDensityCurvesWindow->show();
+}
+
+void Controller::init_options(){
+// from AppOptionsWindow.cpp
+// Default init options
+
+ Config::Path * cpath = Config::Path::getInstance();
+
+ // Directories
+ ViewMapIO::Options::setModelsPath( StringUtils::toAscii( cpath->getModelsPath() ) );
+ PythonInterpreter::Options::setPythonPath( StringUtils::toAscii( cpath->getPythonPath() ) );
+ TextureManager::Options::setPatternsPath( StringUtils::toAscii( cpath->getPatternsPath() ) );
+ TextureManager::Options::setBrushesPath( StringUtils::toAscii( cpath->getModelsPath() ) );
+
+ // ViewMap Format
+ ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS);
+ ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS);
+ setComputeSteerableViewMapFlag( false );
+
+ // Visibility
+ setQuantitativeInvisibility(true);
+
+ // soc: initialize canvas
+ _Canvas->init();
+
+ // soc: initialize passes
+ setPassDiffuse(NULL, 0, 0);
+ setPassZ(NULL, 0, 0);
+}
diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h
new file mode 100755
index 00000000000..6119e14f7b7
--- /dev/null
+++ b/source/blender/freestyle/intern/application/Controller.h
@@ -0,0 +1,253 @@
+//
+// Filename : Controller.h
+// Author : Stephane Grabli
+// Purpose : The spinal tap of the system
+// Date of creation : 01/07/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef CONTROLLER_H
+# define CONTROLLER_H
+
+# include "../view_map/ViewMapBuilder.h"
+# include <string>
+//# include "ConfigIO.h"
+# include "../geometry/FastGrid.h"
+# include "../system/TimeUtils.h"
+# include "../system/ProgressBar.h"
+# include "../system/Precision.h"
+# include "../system/Interpreter.h"
+# include "../system/RenderMonitor.h"
+# include "../view_map/FEdgeXDetector.h"
+
+class AppView;
+class NodeGroup;
+class WShape;
+class SShape;
+class ViewMap;
+class ViewEdge;
+class AppCanvas;
+class InteractiveShader;
+class Shader;
+class StrokeRenderer;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "render_types.h"
+ #include "DNA_scene_types.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+class Controller
+{
+public:
+ Controller() ;
+ ~Controller() ;
+
+ void setView(AppView *iView);
+ void setRenderMonitor(RenderMonitor *iRenderMonitor);
+ void setPassDiffuse(float *buf, int width, int height);
+ void setPassZ(float *buf, int width, int height);
+ void setContext(bContext *C);
+
+ //soc
+ void init_options();
+
+ int LoadMesh( Render *re, SceneRenderLayer* srl );
+ int Load3DSFile(const char *iFileName);
+ void CloseFile();
+ void ComputeViewMap();
+ void ComputeSteerableViewMap();
+ void saveSteerableViewMapImages();
+ void toggleEdgeTesselationNature(Nature::EdgeNature iNature);
+ void DrawStrokes();
+ void ResetRenderCount();
+ Render* RenderStrokes(Render *re);
+ void SwapStyleModules(unsigned i1, unsigned i2);
+ void InsertStyleModule(unsigned index, const char *iFileName);
+ void InsertStyleModule(unsigned index, const char *iName, struct Text *iText);
+ void AddStyleModule(const char *iFileName);
+ void RemoveStyleModule(unsigned index);
+ void ReloadStyleModule(unsigned index, const char * iFileName);
+ void Clear();
+ void ClearRootNode();
+ void DeleteWingedEdge();
+ void DeleteViewMap();
+ void toggleLayer(unsigned index, bool iDisplay);
+ void setModified(unsigned index, bool iMod);
+ void resetModified(bool iMod=false);
+ void updateCausalStyleModules(unsigned index);
+ void displayDensityCurves(int x, int y);
+
+
+ ViewEdge * SelectViewEdge(real x, real y);
+ FEdge * SelectFEdge(real x, real y);
+ NodeGroup* BuildRep(vector<ViewEdge*>::iterator vedges_begin,
+ vector<ViewEdge*>::iterator vedges_end) ;
+
+ //NodeGroup* debugNode() {return _DebugNode;}
+ //AppView * view() {return _pView;}
+ //NodeGroup* debugScene() {return _DebugNode;}
+ //Grid& grid() {return _Grid;}
+
+ void toggleVisibilityAlgo();
+ void setVisibilityAlgo(int algo);
+ int getVisibilityAlgo();
+
+ void setQuantitativeInvisibility(bool iBool); // if true, we compute quantitativeInvisibility
+ bool getQuantitativeInvisibility() const;
+ void setFaceSmoothness(bool iBool);
+ bool getFaceSmoothness() const;
+
+ void setComputeRidgesAndValleysFlag(bool b);
+ bool getComputeRidgesAndValleysFlag() const ;
+ void setComputeSuggestiveContoursFlag(bool b);
+ bool getComputeSuggestiveContoursFlag() const ;
+ void setComputeMaterialBoundariesFlag(bool b);
+ bool getComputeMaterialBoundariesFlag() const ;
+
+ void setComputeSteerableViewMapFlag(bool iBool);
+ bool getComputeSteerableViewMapFlag() const;
+ void setCreaseAngle(real angle){_creaseAngle=angle;}
+ real getCreaseAngle() const {return _creaseAngle;}
+ void setSphereRadius(real s){_sphereRadius=s;}
+ real getSphereRadius() const {return _sphereRadius;}
+ void setSuggestiveContourKrDerivativeEpsilon(real dkr){_suggestiveContourKrDerivativeEpsilon=dkr;}
+ real getSuggestiveContourKrDerivativeEpsilon() const {return _suggestiveContourKrDerivativeEpsilon;}
+
+ void setModelsDir(const string& dir);
+ string getModelsDir() const;
+ void setModulesDir(const string& dir);
+ string getModulesDir() const;
+ void setHelpIndex(const string& dir);
+ string getHelpIndex() const;
+ void setBrowserCmd(const string& cmd);
+ string getBrowserCmd() const;
+
+ void resetInterpreter();
+
+public:
+ // Viewmap data structure
+ ViewMap * _ViewMap;
+
+ // Canvas
+ AppCanvas *_Canvas;
+
+private:
+
+ // Main Window:
+ //AppMainWindow *_pMainWindow;
+
+ // List of models currently loaded
+ vector<string> _ListOfModels;
+
+ // Current directories
+ //ConfigIO* _current_dirs;
+
+
+
+ //View
+ // 3D
+ AppView *_pView;
+
+ // 2D
+ //Viewer2DWindow *_pView2DWindow;
+ //Viewer2D *_pView2D;
+
+ RenderMonitor *_pRenderMonitor;
+
+ //Model
+ // Drawing Structure
+ NodeGroup *_RootNode;
+
+ // Winged-Edge structure
+ WingedEdge* _winged_edge;
+
+ // Silhouette structure:
+ //std::vector<SShape*> _SShapes;
+ //NodeGroup *_SRoot;
+
+ // Silhouette
+ NodeGroup *_SilhouetteNode;
+ NodeGroup *_ProjectedSilhouette;
+ NodeGroup *_VisibleProjectedSilhouette;
+
+ // more Debug info
+ NodeGroup *_DebugNode;
+
+ // debug
+ // NodeUser<ViewMap> *_ViewMapNode; // FIXME
+
+ // Chronometer:
+ Chronometer _Chrono;
+
+ // Progress Bar
+ ProgressBar *_ProgressBar;
+
+ // edges tesselation nature
+ int _edgeTesselationNature;
+
+ FastGrid _Grid;
+ //HashGrid _Grid;
+
+ unsigned int _SceneNumFaces;
+ real _minEdgeSize;
+ real _EPSILON;
+ real _bboxDiag;
+
+ int _render_count;
+
+ //AppStyleWindow *_pStyleWindow;
+ //AppOptionsWindow *_pOptionsWindow;
+ //AppDensityCurvesWindow *_pDensityCurvesWindow;
+
+ ViewMapBuilder::visibility_algo _VisibilityAlgo;
+
+ // Script Interpreter
+ Interpreter* _inter;
+
+ string _help_index;
+ string _browser_cmd;
+
+ bool _EnableQI;
+ bool _EnableFaceSmoothness;
+ bool _ComputeRidges;
+ bool _ComputeSuggestive;
+ bool _ComputeMaterialBoundaries;
+ real _creaseAngle;
+ real _sphereRadius;
+ real _suggestiveContourKrDerivativeEpsilon;
+
+ bool _ComputeSteerableViewMap;
+
+ FEdgeXDetector edgeDetector;
+};
+
+extern Controller *g_pController;
+
+#endif // CONTROLLER_H
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
new file mode 100644
index 00000000000..2b2e92f57dd
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -0,0 +1,666 @@
+#include "BlenderFileLoader.h"
+
+#include <assert.h>
+
+BlenderFileLoader::BlenderFileLoader(Render *re, SceneRenderLayer* srl)
+{
+ _re = re;
+ _srl = srl;
+ _Scene = NULL;
+ _numFacesRead = 0;
+ _minEdgeSize = DBL_MAX;
+ _smooth = (srl->freestyleConfig.flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) != 0;
+}
+
+BlenderFileLoader::~BlenderFileLoader()
+{
+ _Scene = NULL;
+}
+
+NodeGroup* BlenderFileLoader::Load()
+{
+ ObjectInstanceRen *obi;
+
+ cout << "\n=== Importing triangular meshes into Blender ===" << endl;
+
+ // creation of the scene root node
+ _Scene = new NodeGroup;
+
+ _viewplane_left= _re->viewplane.xmin;
+ _viewplane_right= _re->viewplane.xmax;
+ _viewplane_bottom= _re->viewplane.ymin;
+ _viewplane_top= _re->viewplane.ymax;
+ _z_near= -_re->clipsta;
+ _z_far= -_re->clipend;
+#if 0
+ cout << "Frustum: l " << _viewplane_left << " r " << _viewplane_right
+ << " b " << _viewplane_bottom << " t " << _viewplane_top
+ << " n " << _z_near << " f " << _z_far << endl;
+#endif
+
+ int id = 0;
+ for(obi= (ObjectInstanceRen *) _re->instancetable.first; obi; obi=obi->next) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+ if (!(obi->lay & _srl->lay))
+ continue;
+ char *name = obi->ob->id.name;
+ //cout << name[0] << name[1] << ":" << (name+2) <<;
+ //print_m4("obi->mat", obi->mat);
+
+ if( obi->obr->totvlak > 0)
+ insertShapeNode(obi, ++id);
+ else
+ cout << "Warning: " << (name+2) << " is not a vlak-based object (ignored)" << endl;
+ }
+
+ //Returns the built scene.
+ return _Scene;
+}
+
+#define CLIPPED_BY_NEAR -1
+#define NOT_CLIPPED 0
+#define CLIPPED_BY_FAR 1
+
+// check if each vertex of a triangle (V1, V2, V3) is clipped by the near/far plane
+// and calculate the number of triangles to be generated by clipping
+int BlenderFileLoader::countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3])
+{
+ float *v[3];
+ int numClipped, sum, numTris;
+
+ v[0] = v1;
+ v[1] = v2;
+ v[2] = v3;
+ numClipped = sum = 0;
+ for (int i = 0; i < 3; i++) {
+ if (v[i][2] > _z_near) {
+ clip[i] = CLIPPED_BY_NEAR;
+ numClipped++;
+ } else if (v[i][2] < _z_far) {
+ clip[i] = CLIPPED_BY_FAR;
+ numClipped++;
+ } else {
+ clip[i] = NOT_CLIPPED;
+ }
+// printf("%d %s\n", i, (clip[i] == NOT_CLIPPED) ? "not" : (clip[i] == CLIPPED_BY_NEAR) ? "near" : "far");
+ sum += clip[i];
+ }
+ switch (numClipped) {
+ case 0:
+ numTris = 1; // triangle
+ break;
+ case 1:
+ numTris = 2; // tetragon
+ break;
+ case 2:
+ if (sum == 0)
+ numTris = 3; // pentagon
+ else
+ numTris = 1; // triangle
+ break;
+ case 3:
+ if (sum == 3 || sum == -3)
+ numTris = 0;
+ else
+ numTris = 2; // tetragon
+ break;
+ }
+ return numTris;
+}
+
+// find the intersection point C between the line segment from V1 to V2 and
+// a clipping plane at depth Z (i.e., the Z component of C is known, while
+// the X and Y components are unknown).
+void BlenderFileLoader::clipLine(float v1[3], float v2[3], float c[3], float z)
+{
+ // Order v1 and v2 by Z values to make sure that clipLine(P, Q, c, z)
+ // and clipLine(Q, P, c, z) gives exactly the same numerical result.
+ float *p, *q;
+ if (v1[2] < v2[2]) {
+ p = v1;
+ q = v2;
+ } else {
+ p = v2;
+ q = v1;
+ }
+ double d[3];
+ for (int i = 0; i < 3; i++)
+ d[i] = q[i] - p[i];
+ double t = (z - p[2]) / d[2];
+ c[0] = p[0] + t * d[0];
+ c[1] = p[1] + t * d[1];
+ c[2] = z;
+}
+
+// clip the triangle (V1, V2, V3) by the near and far clipping plane and
+// obtain a set of vertices after the clipping. The number of vertices
+// is at most 5.
+void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3],
+ float triNormals[][3], float n1[3], float n2[3], float n3[3],
+ bool edgeMarks[], bool em1, bool em2, bool em3, int clip[3])
+{
+ float *v[3], *n[3];
+ bool em[3];
+ int i, j, k;
+
+ v[0] = v1; n[0] = n1;
+ v[1] = v2; n[1] = n2;
+ v[2] = v3; n[2] = n3;
+ em[0] = em1; /* edge mark of the edge between v1 and v2 */
+ em[1] = em2; /* edge mark of the edge between v2 and v3 */
+ em[2] = em3; /* edge mark of the edge between v3 and v1 */
+ k = 0;
+ for (i = 0; i < 3; i++) {
+ j = (i + 1) % 3;
+ if (clip[i] == NOT_CLIPPED) {
+ copy_v3_v3(triCoords[k], v[i]);
+ copy_v3_v3(triNormals[k], n[i]);
+ edgeMarks[k] = em[i];
+ k++;
+ if (clip[j] != NOT_CLIPPED) {
+ clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ copy_v3_v3(triNormals[k], n[j]);
+ edgeMarks[k] = false;
+ k++;
+ }
+ } else if (clip[i] != clip[j]) {
+ if (clip[j] == NOT_CLIPPED) {
+ clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ copy_v3_v3(triNormals[k], n[i]);
+ edgeMarks[k] = em[i];
+ k++;
+ } else {
+ clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ copy_v3_v3(triNormals[k], n[i]);
+ edgeMarks[k] = em[i];
+ k++;
+ clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ copy_v3_v3(triNormals[k], n[j]);
+ edgeMarks[k] = false;
+ k++;
+ }
+ }
+ }
+ assert (k == 2 + numTris);
+}
+
+void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3],
+ float n1[3], float n2[3], float n3[3],
+ bool fm, bool em1, bool em2, bool em3)
+{
+ float *fv[3], *fn[3], len;
+ unsigned i, j;
+ IndexedFaceSet::FaceEdgeMark marks = 0;
+
+ // initialize the bounding box by the first vertex
+ if (ls->currentIndex == 0) {
+ copy_v3_v3(ls->minBBox, v1);
+ copy_v3_v3(ls->maxBBox, v1);
+ }
+
+ fv[0] = v1; fn[0] = n1;
+ fv[1] = v2; fn[1] = n2;
+ fv[2] = v3; fn[2] = n3;
+ for (i = 0; i < 3; i++) {
+
+ copy_v3_v3(ls->pv, fv[i]);
+ copy_v3_v3(ls->pn, fn[i]);
+
+ // update the bounding box
+ for (j = 0; j < 3; j++)
+ {
+ if (ls->minBBox[j] > ls->pv[j])
+ ls->minBBox[j] = ls->pv[j];
+
+ if (ls->maxBBox[j] < ls->pv[j])
+ ls->maxBBox[j] = ls->pv[j];
+ }
+
+ len = len_v3v3(fv[i], fv[(i + 1) % 3]);
+ if (_minEdgeSize > len)
+ _minEdgeSize = len;
+
+ *ls->pvi = ls->currentIndex;
+ *ls->pni = ls->currentIndex;
+ *ls->pmi = ls->currentMIndex;
+
+ ls->currentIndex +=3;
+ ls->pv += 3;
+ ls->pn += 3;
+
+ ls->pvi++;
+ ls->pni++;
+ ls->pmi++;
+ }
+ if (fm) marks |= IndexedFaceSet::FACE_MARK;
+ if (em1) marks |= IndexedFaceSet::EDGE_MARK_V1V2;
+ if (em2) marks |= IndexedFaceSet::EDGE_MARK_V2V3;
+ if (em3) marks |= IndexedFaceSet::EDGE_MARK_V3V1;
+ *ls->pm++ = marks;
+}
+
+// With A, B and P indicating the three vertices of a given triangle, returns:
+// 1 if points A and B are in the same position in the 3D space;
+// 2 if the distance between point P and line segment AB is zero; and
+// zero otherwise.
+int BlenderFileLoader::testDegenerateTriangle(float v1[3], float v2[3], float v3[3])
+{
+ //float area = area_tri_v3(v1, v2, v3);
+ //bool verbose = (area < 1e-6);
+
+ if (equals_v3v3(v1, v2) || equals_v3v3(v2, v3) || equals_v3v3(v1, v3)) {
+ //if (verbose) printf("BlenderFileLoader::testDegenerateTriangle = 1\n");
+ return 1;
+ }
+ if (dist_to_line_segment_v3(v1, v2, v3) < 1e-6 ||
+ dist_to_line_segment_v3(v2, v1, v3) < 1e-6 ||
+ dist_to_line_segment_v3(v3, v1, v2) < 1e-6) {
+ //if (verbose) printf("BlenderFileLoader::testDegenerateTriangle = 2\n");
+ return 2;
+ }
+ //if (verbose) printf("BlenderFileLoader::testDegenerateTriangle = 0\n");
+ return 0;
+}
+
+// Checks if edge rotation (if necessary) can prevent the given quad from
+// being decomposed into a degenerate triangle
+bool BlenderFileLoader::testEdgeRotation(float v1[3], float v2[3], float v3[3], float v4[3])
+{
+ if (testDegenerateTriangle(v1, v2, v3) == 2 || testDegenerateTriangle(v1, v3, v4) == 2) {
+ if (testDegenerateTriangle(v1, v2, v4) == 2 || testDegenerateTriangle(v2, v3, v4) == 2) {
+ //printf("BlenderFileLoader::testEdgeRotation: edge rotation is unsuccessful.\n");
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
+{
+ ObjectRen *obr = obi->obr;
+ char *name = obi->ob->id.name+2;
+
+ // We parse vlak nodes and count the number of faces after the clipping by
+ // the near and far view planes is applied (Note: mesh vertices are in the
+ // camera coordinate system).
+ VlakRen *vlr;
+ unsigned numFaces = 0;
+ float v1[3], v2[3], v3[3], v4[3];
+ float n1[3], n2[3], n3[3], n4[3], facenormal[3];
+ int clip_1[3], clip_2[3];
+ int wire_material = 0;
+ for(int a=0; a < obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
+ else vlr++;
+ if (vlr->mat->material_type == MA_TYPE_WIRE) {
+ wire_material = 1;
+ continue;
+ }
+ copy_v3_v3(v1, vlr->v1->co);
+ copy_v3_v3(v2, vlr->v2->co);
+ copy_v3_v3(v3, vlr->v3->co);
+ if (vlr->v4) copy_v3_v3(v4, vlr->v4->co);
+ if (obi->flag & R_TRANSFORMED) {
+ mul_m4_v3(obi->mat, v1);
+ mul_m4_v3(obi->mat, v2);
+ mul_m4_v3(obi->mat, v3);
+ if (vlr->v4) mul_m4_v3(obi->mat, v4);
+ }
+// print_v3("v1", v1);
+// print_v3("v2", v2);
+// print_v3("v3", v3);
+// if (vlr->v4) print_v3("v4", v4);
+ if (!vlr->v4 || !testEdgeRotation(v1, v2, v3, v4)) {
+ numFaces += countClippedFaces(v1, v2, v3, clip_1);
+ if (vlr->v4)
+ numFaces += countClippedFaces(v1, v3, v4, clip_2);
+ } else {
+ numFaces += countClippedFaces(v1, v2, v4, clip_1);
+ numFaces += countClippedFaces(v2, v3, v4, clip_2);
+ }
+ }
+ if (wire_material)
+ printf("Warning: Object %s has wire materials (ignored)\n", name);
+// cout <<"numFaces " <<numFaces<<endl;
+ if (numFaces == 0)
+ return;
+
+ // We allocate memory for the meshes to be imported
+ NodeTransform *currentMesh = new NodeTransform;
+ NodeShape * shape = new NodeShape;
+
+ unsigned vSize = 3*3*numFaces;
+ float *vertices = new float[vSize];
+ unsigned nSize = vSize;
+ float *normals = new float[nSize];
+ unsigned *numVertexPerFaces = new unsigned[numFaces];
+ vector<FrsMaterial> meshFrsMaterials;
+
+ IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces];
+ unsigned i;
+ for (i = 0; i <numFaces; i++) {
+ faceStyle[i] = IndexedFaceSet::TRIANGLES;
+ numVertexPerFaces[i] = 3;
+ }
+
+ IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = new IndexedFaceSet::FaceEdgeMark[numFaces];
+
+ unsigned viSize = 3*numFaces;
+ unsigned *VIndices = new unsigned[viSize];
+ unsigned niSize = viSize;
+ unsigned *NIndices = new unsigned[niSize];
+ unsigned *MIndices = new unsigned[viSize]; // Material Indices
+
+ struct LoaderState ls;
+ ls.pv = vertices;
+ ls.pn = normals;
+ ls.pm = faceEdgeMarks;
+ ls.pvi = VIndices;
+ ls.pni = NIndices;
+ ls.pmi = MIndices;
+ ls.currentIndex = 0;
+ ls.currentMIndex = 0;
+
+ FrsMaterial tmpMat;
+
+ // We parse the vlak nodes again and import meshes while applying the clipping
+ // by the near and far view planes.
+ int p;
+ for(p=0; p < obr->totvlak; ++p) // we parse the faces of the mesh
+ {
+ // Lib3dsFace *f=&mesh->faceL[p];
+ // Lib3dsMaterial *mat=0;
+ if((p & 255)==0) vlr = obr->vlaknodes[p>>8].vlak;
+ else vlr++;
+ copy_v3_v3(v1, vlr->v1->co);
+ copy_v3_v3(v2, vlr->v2->co);
+ copy_v3_v3(v3, vlr->v3->co);
+ if (vlr->v4) copy_v3_v3(v4, vlr->v4->co);
+ if (obi->flag & R_TRANSFORMED) {
+ mul_m4_v3(obi->mat, v1);
+ mul_m4_v3(obi->mat, v2);
+ mul_m4_v3(obi->mat, v3);
+ if (vlr->v4) mul_m4_v3(obi->mat, v4);
+ }
+ if (_smooth && (vlr->flag & R_SMOOTH)) {
+ copy_v3_v3(n1, vlr->v1->n);
+ copy_v3_v3(n2, vlr->v2->n);
+ copy_v3_v3(n3, vlr->v3->n);
+ if (vlr->v4) copy_v3_v3(n4, vlr->v4->n);
+ if (obi->flag & R_TRANSFORMED) {
+ mul_m3_v3(obi->nmat, n1);
+ mul_m3_v3(obi->nmat, n2);
+ mul_m3_v3(obi->nmat, n3);
+ normalize_v3(n1);
+ normalize_v3(n2);
+ normalize_v3(n3);
+ if (vlr->v4) {
+ mul_m3_v3(obi->nmat, n4);
+ normalize_v3(n4);
+ }
+ }
+ } else {
+ RE_vlakren_get_normal(_re, obi, vlr, facenormal);
+ copy_v3_v3(n1, facenormal);
+ copy_v3_v3(n2, facenormal);
+ copy_v3_v3(n3, facenormal);
+ if (vlr->v4) copy_v3_v3(n4, facenormal);
+ }
+
+ unsigned numTris_1, numTris_2;
+ bool edge_rotation;
+ if (!vlr->v4 || !testEdgeRotation(v1, v2, v3, v4)) {
+ numTris_1 = countClippedFaces(v1, v2, v3, clip_1);
+ numTris_2 = (!vlr->v4) ? 0 : countClippedFaces(v1, v3, v4, clip_2);
+ edge_rotation = false;
+ } else {
+ numTris_1 = countClippedFaces(v1, v2, v4, clip_1);
+ numTris_2 = countClippedFaces(v2, v3, v4, clip_2);
+ edge_rotation = true;
+ printf("BlenderFileLoader::insertShapeNode: edge rotation is performed.\n");
+ }
+ if (numTris_1 == 0 && numTris_2 == 0)
+ continue;
+ bool fm, em1, em2, em3, em4;
+ fm = (vlr->flag & ME_FREESTYLE_FACE) != 0;
+ em1= (vlr->freestyle_edge_mark & R_EDGE_V1V2) != 0;
+ em2= (vlr->freestyle_edge_mark & R_EDGE_V2V3) != 0;
+ if (!vlr->v4) {
+ em3= (vlr->freestyle_edge_mark & R_EDGE_V3V1) != 0;
+ em4= false;
+ } else {
+ em3= (vlr->freestyle_edge_mark & R_EDGE_V3V4) != 0;
+ em4= (vlr->freestyle_edge_mark & R_EDGE_V4V1) != 0;
+ }
+
+ Material *mat = vlr->mat;
+
+ if (mat)
+ {
+ tmpMat.setDiffuse( mat->r, mat->g, mat->b, mat->alpha );
+ tmpMat.setSpecular( mat->specr, mat->specg, mat->specb, mat->spectra);
+ float s = 1.0 * (mat->har + 1) / 4 ; // in Blender: [1;511] => in OpenGL: [0;128]
+ if(s > 128.f)
+ s = 128.f;
+ tmpMat.setShininess(s);
+ }
+
+ if(meshFrsMaterials.empty())
+ {
+ meshFrsMaterials.push_back(tmpMat);
+ shape->setFrsMaterial(tmpMat);
+ } else {
+ // find if the material is aleady in the list
+ unsigned i=0;
+ bool found = false;
+
+ for(vector<FrsMaterial>::iterator it=meshFrsMaterials.begin(), itend=meshFrsMaterials.end();
+ it!=itend;
+ ++it){
+ if(*it == tmpMat){
+ ls.currentMIndex = i;
+ found = true;
+ break;
+ }
+ ++i;
+ }
+
+ if(!found){
+ meshFrsMaterials.push_back(tmpMat);
+ ls.currentMIndex = meshFrsMaterials.size()-1;
+ }
+ }
+
+ float triCoords[5][3], triNormals[5][3];
+ bool edgeMarks[5]; // edgeMarks[i] is for the edge between i-th and (i+1)-th vertices
+
+ if (numTris_1 > 0) {
+ if (!edge_rotation)
+ clipTriangle(numTris_1, triCoords, v1, v2, v3, triNormals, n1, n2, n3,
+ edgeMarks, em1, em2, (!vlr->v4) ? em3 : false, clip_1);
+ else
+ clipTriangle(numTris_1, triCoords, v1, v2, v4, triNormals, n1, n2, n4,
+ edgeMarks, em1, false, em4, clip_1);
+ for (i = 0; i < numTris_1; i++) {
+ addTriangle(&ls, triCoords[0], triCoords[i+1], triCoords[i+2],
+ triNormals[0], triNormals[i+1], triNormals[i+2],
+ fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i+1],
+ (i == numTris_1 - 1) ? edgeMarks[i+2] : false);
+ _numFacesRead++;
+ }
+ }
+
+ if (numTris_2 > 0) {
+ if (!edge_rotation)
+ clipTriangle(numTris_2, triCoords, v1, v3, v4, triNormals, n1, n3, n4,
+ edgeMarks, false, em3, em4, clip_2);
+ else
+ clipTriangle(numTris_2, triCoords, v2, v3, v4, triNormals, n2, n3, n4,
+ edgeMarks, em2, em3, false, clip_2);
+ for (i = 0; i < numTris_2; i++) {
+ addTriangle(&ls, triCoords[0], triCoords[i+1], triCoords[i+2],
+ triNormals[0], triNormals[i+1], triNormals[i+2],
+ fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i+1],
+ (i == numTris_2 - 1) ? edgeMarks[i+2] : false);
+ _numFacesRead++;
+ }
+ }
+ }
+
+ // We might have several times the same vertex. We want a clean
+ // shape with no real-vertex. Here, we are making a cleaning
+ // pass.
+ real *cleanVertices = NULL;
+ unsigned cvSize;
+ unsigned *cleanVIndices = NULL;
+
+ GeomCleaner::CleanIndexedVertexArray(
+ vertices, vSize,
+ VIndices, viSize,
+ &cleanVertices, &cvSize,
+ &cleanVIndices);
+
+ real *cleanNormals = NULL;
+ unsigned cnSize;
+ unsigned *cleanNIndices = NULL;
+
+ GeomCleaner::CleanIndexedVertexArray(
+ normals, nSize,
+ NIndices, niSize,
+ &cleanNormals, &cnSize,
+ &cleanNIndices);
+
+ // format materials array
+ FrsMaterial** marray = new FrsMaterial*[meshFrsMaterials.size()];
+ unsigned mindex=0;
+ for(vector<FrsMaterial>::iterator m=meshFrsMaterials.begin(), mend=meshFrsMaterials.end();
+ m!=mend;
+ ++m){
+ marray[mindex] = new FrsMaterial(*m);
+ ++mindex;
+ }
+ // deallocates memory:
+ delete [] vertices;
+ delete [] normals;
+ delete [] VIndices;
+ delete [] NIndices;
+
+ // Fix for degenerated triangles
+ // A degenerate triangle is a triangle such that
+ // 1) A and B are in the same position in the 3D space; or
+ // 2) the distance between point P and line segment AB is zero.
+ // Only those degenerate triangles in the second form are resolved here
+ // by adding a small offset to P, whereas those in the first form are
+ // addressed later in WShape::MakeFace().
+ vector<detri_t> detriList;
+ Vec3r zero(0.0, 0.0, 0.0);
+ unsigned vi0, vi1, vi2;
+ for (i = 0; i < viSize; i += 3) {
+ detri_t detri;
+ vi0 = cleanVIndices[i];
+ vi1 = cleanVIndices[i+1];
+ vi2 = cleanVIndices[i+2];
+ Vec3r v0(cleanVertices[vi0], cleanVertices[vi0+1], cleanVertices[vi0+2]);
+ Vec3r v1(cleanVertices[vi1], cleanVertices[vi1+1], cleanVertices[vi1+2]);
+ Vec3r v2(cleanVertices[vi2], cleanVertices[vi2+1], cleanVertices[vi2+2]);
+ if (v0 == v1 || v0 == v2 || v1 == v2) {
+ continue; // do nothing for now
+ }
+ else if (GeomUtils::distPointSegment<Vec3r>(v0, v1, v2) < 1e-6) {
+ detri.viP = vi0; detri.viA = vi1; detri.viB = vi2;
+ }
+ else if (GeomUtils::distPointSegment<Vec3r>(v1, v0, v2) < 1e-6) {
+ detri.viP = vi1; detri.viA = vi0; detri.viB = vi2;
+ }
+ else if (GeomUtils::distPointSegment<Vec3r>(v2, v0, v1) < 1e-6) {
+ detri.viP = vi2; detri.viA = vi0; detri.viB = vi1;
+ }
+ else {
+ continue;
+ }
+ detri.v = zero;
+ detri.n = 0;
+ for (unsigned j = 0; j < viSize; j += 3) {
+ if (i == j)
+ continue;
+ vi0 = cleanVIndices[j];
+ vi1 = cleanVIndices[j+1];
+ vi2 = cleanVIndices[j+2];
+ Vec3r v0(cleanVertices[vi0], cleanVertices[vi0+1], cleanVertices[vi0+2]);
+ Vec3r v1(cleanVertices[vi1], cleanVertices[vi1+1], cleanVertices[vi1+2]);
+ Vec3r v2(cleanVertices[vi2], cleanVertices[vi2+1], cleanVertices[vi2+2]);
+ if (detri.viP == vi0 && (detri.viA == vi1 || detri.viB == vi1)) {
+ detri.v += (v2 - v0);
+ detri.n++;
+ } else if (detri.viP == vi0 && (detri.viA == vi2 || detri.viB == vi2)) {
+ detri.v += (v1 - v0);
+ detri.n++;
+ } else if (detri.viP == vi1 && (detri.viA == vi0 || detri.viB == vi0)) {
+ detri.v += (v2 - v1);
+ detri.n++;
+ } else if (detri.viP == vi1 && (detri.viA == vi2 || detri.viB == vi2)) {
+ detri.v += (v0 - v1);
+ detri.n++;
+ } else if (detri.viP == vi2 && (detri.viA == vi0 || detri.viB == vi0)) {
+ detri.v += (v1 - v2);
+ detri.n++;
+ } else if (detri.viP == vi2 && (detri.viA == vi1 || detri.viB == vi1)) {
+ detri.v += (v0 - v2);
+ detri.n++;
+ }
+ }
+ if (detri.n > 0) {
+ detri.v.normalizeSafe();
+ }
+ detriList.push_back(detri);
+ }
+ if (detriList.size() > 0) {
+ vector<detri_t>::iterator v;
+ for (v = detriList.begin(); v != detriList.end(); v++) {
+ detri_t detri = (*v);
+ if (detri.n == 0) {
+ cleanVertices[detri.viP] = cleanVertices[detri.viA];
+ cleanVertices[detri.viP+1] = cleanVertices[detri.viA+1];
+ cleanVertices[detri.viP+2] = cleanVertices[detri.viA+2];
+ } else if (detri.v.norm() > 0.0) {
+ cleanVertices[detri.viP] += 1e-5 * detri.v.x();
+ cleanVertices[detri.viP+1] += 1e-5 * detri.v.y();
+ cleanVertices[detri.viP+2] += 1e-5 * detri.v.z();
+ }
+ }
+ printf("Warning: Object %s contains %d degenerate triangle%s (strokes may be incorrect)\n",
+ name, detriList.size(), (detriList.size() > 1) ? "s" : "");
+ }
+
+ // Create the IndexedFaceSet with the retrieved attributes
+ IndexedFaceSet *rep;
+ rep = new IndexedFaceSet(cleanVertices, cvSize,
+ cleanNormals, cnSize,
+ marray, meshFrsMaterials.size(),
+ 0, 0,
+ numFaces, numVertexPerFaces, faceStyle,
+ faceEdgeMarks,
+ cleanVIndices, viSize,
+ cleanNIndices, niSize,
+ MIndices, viSize,
+ 0,0,
+ 0);
+ // sets the id of the rep
+ rep->setId(Id(id, 0));
+ rep->setName(obi->ob->id.name+2);
+
+ const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]),
+ Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2]));
+ rep->setBBox(bbox);
+ shape->AddRep(rep);
+
+ Matrix44r meshMat = Matrix44r::identity();
+ currentMesh->setMatrix(meshMat);
+ currentMesh->Translate(0,0,0);
+
+ currentMesh->AddChild(shape);
+ _Scene->AddChild(currentMesh);
+
+}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
new file mode 100644
index 00000000000..c5c06567c41
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
@@ -0,0 +1,104 @@
+#ifndef BLENDER_FILE_LOADER_H
+# define BLENDER_FILE_LOADER_H
+
+# include <string.h>
+# include <float.h>
+
+# include "../system/FreestyleConfig.h"
+# include "../system/RenderMonitor.h"
+# include "../scene_graph/NodeGroup.h"
+# include "../scene_graph/NodeTransform.h"
+# include "../scene_graph/NodeShape.h"
+# include "../scene_graph/IndexedFaceSet.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+# include "../geometry/GeomCleaner.h"
+# include "../geometry/GeomUtils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "DNA_material_types.h"
+ #include "DNA_meshdata_types.h"
+ #include "DNA_scene_types.h"
+ #include "render_types.h"
+ #include "renderdatabase.h"
+
+ #include "BKE_mesh.h"
+ #include "BKE_scene.h"
+ #include "BLI_math.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+class NodeGroup;
+
+struct LoaderState {
+ float *pv;
+ float *pn;
+ IndexedFaceSet::FaceEdgeMark *pm;
+ unsigned *pvi;
+ unsigned *pni;
+ unsigned *pmi;
+ unsigned currentIndex;
+ unsigned currentMIndex;
+ float minBBox[3];
+ float maxBBox[3];
+};
+
+class LIB_SCENE_GRAPH_EXPORT BlenderFileLoader
+{
+public:
+ /*! Builds a MaxFileLoader */
+ BlenderFileLoader(Render *re, SceneRenderLayer* srl);
+ virtual ~BlenderFileLoader();
+
+ /*! Loads the 3D scene and returns a pointer to the scene root node */
+ NodeGroup * Load();
+
+ /*! Gets the number of read faces */
+ inline unsigned int numFacesRead() {return _numFacesRead;}
+
+ /*! Gets the smallest edge size read */
+ inline real minEdgeSize() {return _minEdgeSize;}
+
+ /*! Modifiers */
+ inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {_pRenderMonitor = iRenderMonitor;}
+
+protected:
+ void insertShapeNode(ObjectInstanceRen *obi, int id);
+ int testDegenerateTriangle(float v1[3], float v2[3], float v3[3]);
+ bool testEdgeRotation(float v1[3], float v2[3], float v3[3], float v4[3]);
+ int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]);
+ void clipLine(float v1[3], float v2[3], float c[3], float z);
+ void clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3],
+ float triNormals[][3], float n1[3], float n2[3], float n3[3],
+ bool edgeMarks[5], bool em1, bool em2, bool em3, int clip[3]);
+ void addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3],
+ float n1[3], float n2[3], float n3[3], bool fm, bool em1, bool em2, bool em3);
+
+protected:
+ struct detri_t {
+ unsigned viA, viB, viP; // 0 <= viA, viB, viP < viSize
+ Vec3r v;
+ unsigned n;
+ };
+ Render* _re;
+ SceneRenderLayer* _srl;
+ NodeGroup* _Scene;
+ unsigned _numFacesRead;
+ real _minEdgeSize;
+ bool _smooth; /* if true, face smoothness is taken into account */
+ float _viewplane_left;
+ float _viewplane_right;
+ float _viewplane_bottom;
+ float _viewplane_top;
+ float _z_near, _z_far;
+
+ RenderMonitor *_pRenderMonitor;
+};
+
+#endif // BLENDER_FILE_LOADER_H
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
new file mode 100644
index 00000000000..e7f43f71ade
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -0,0 +1,421 @@
+# include "BlenderStrokeRenderer.h"
+# include "../stroke/Canvas.h"
+# include "../application/AppConfig.h"
+
+# include "BlenderTextureManager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_library.h" /* free_libblock */
+#include "BKE_material.h"
+#include "BKE_main.h" /* struct Main */
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
+
+#include "RE_pipeline.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+BlenderStrokeRenderer::BlenderStrokeRenderer(Render* re, int render_count)
+:StrokeRenderer(){
+
+ // TEMPORARY - need a texture manager
+ _textureManager = new BlenderTextureManager;
+ _textureManager->load();
+
+ _width = re->winx; _height = re->winy; // for stroke mesh generation
+
+ // Scene.New("FreestyleStrokes")
+ old_scene = re->scene;
+
+ char name[22];
+ snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name+2);
+ freestyle_scene = BKE_scene_add(name);
+ freestyle_scene->r.cfra = old_scene->r.cfra;
+ freestyle_scene->r.mode= old_scene->r.mode &
+ ~( R_EDGE_FRS | R_SHADOW | R_SSS | R_PANORAMA | R_ENVMAP | R_MBLUR | R_BORDER );
+ freestyle_scene->r.xsch= re->rectx; // old_scene->r.xsch
+ freestyle_scene->r.ysch= re->recty; // old_scene->r.ysch
+ freestyle_scene->r.xasp= 1.f; // old_scene->r.xasp;
+ freestyle_scene->r.yasp= 1.f; // old_scene->r.yasp;
+ freestyle_scene->r.xparts= old_scene->r.xparts;
+ freestyle_scene->r.yparts= old_scene->r.yparts;
+ freestyle_scene->r.size= 100; // old_scene->r.size
+ freestyle_scene->r.maximsize= old_scene->r.maximsize;
+ freestyle_scene->r.ocres = old_scene->r.ocres;
+ freestyle_scene->r.color_mgt_flag = 0; // old_scene->r.color_mgt_flag;
+ freestyle_scene->r.scemode= old_scene->r.scemode & ~( R_SINGLE_LAYER );
+ freestyle_scene->r.flag= old_scene->r.flag;
+ freestyle_scene->r.threads= old_scene->r.threads;
+ freestyle_scene->r.border.xmin= old_scene->r.border.xmin;
+ freestyle_scene->r.border.ymin= old_scene->r.border.ymin;
+ freestyle_scene->r.border.xmax= old_scene->r.border.xmax;
+ freestyle_scene->r.border.ymax= old_scene->r.border.ymax;
+ strcpy(freestyle_scene->r.pic, old_scene->r.pic);
+ freestyle_scene->r.safety.xmin= old_scene->r.safety.xmin;
+ freestyle_scene->r.safety.ymin= old_scene->r.safety.ymin;
+ freestyle_scene->r.safety.xmax= old_scene->r.safety.xmax;
+ freestyle_scene->r.safety.ymax= old_scene->r.safety.ymax;
+ freestyle_scene->r.osa= old_scene->r.osa;
+ freestyle_scene->r.filtertype= old_scene->r.filtertype;
+ freestyle_scene->r.gauss= old_scene->r.gauss;
+ freestyle_scene->r.dither_intensity= old_scene->r.dither_intensity;
+ BLI_strncpy(freestyle_scene->r.engine, old_scene->r.engine, sizeof(freestyle_scene->r.engine));
+ freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA;
+ freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG;
+ BKE_scene_set_background( G.main, freestyle_scene );
+
+ // Camera
+ Object* object_camera = BKE_object_add(freestyle_scene, OB_CAMERA);
+
+ Camera* camera = (Camera *) object_camera->data;
+ camera->type = CAM_ORTHO;
+ camera->ortho_scale = max(re->rectx, re->recty);
+ camera->clipsta = 0.1f;
+ camera->clipend = 100.0f;
+
+ _z_delta = 0.00001f;
+ _z = camera->clipsta + _z_delta;
+
+ // test
+ //_z = 999.90f; _z_delta = 0.01f;
+
+ object_camera->loc[0] = re->disprect.xmin + 0.5f * re->rectx;
+ object_camera->loc[1] = re->disprect.ymin + 0.5f * re->recty;
+ object_camera->loc[2] = 1.f;
+
+ freestyle_scene->camera = object_camera;
+
+ // Material
+ material = BKE_material_add("stroke_material");
+ material->mode |= MA_VERTEXCOLP;
+ material->mode |= MA_TRANSP;
+ material->mode |= MA_SHLESS;
+ material->vcol_alpha = 1;
+}
+
+BlenderStrokeRenderer::~BlenderStrokeRenderer(){
+
+ if(0 != _textureManager)
+ {
+ delete _textureManager;
+ _textureManager = 0;
+ }
+
+ // The freestyle_scene object is not released here. Instead,
+ // the scene is released in free_all_freestyle_renders() in
+ // source/blender/render/intern/source/pipeline.c, after the
+ // compositor has finished.
+
+ // release objects and data blocks
+ Base *b = (Base *)freestyle_scene->base.first;
+ while(b) {
+ Object *ob = b->object;
+ void *data = ob->data;
+ char name[24];
+ strcpy(name, ob->id.name);
+ //cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl;
+ switch (ob->type) {
+ case OB_MESH:
+ BKE_libblock_free( &G.main->object, ob );
+ BKE_libblock_free( &G.main->mesh, data );
+ break;
+ case OB_CAMERA:
+ BKE_libblock_free( &G.main->object, ob );
+ BKE_libblock_free( &G.main->camera, data );
+ freestyle_scene->camera = NULL;
+ break;
+ default:
+ cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name+2) << endl;
+ }
+ b = b->next;
+ }
+ BLI_freelistN( &freestyle_scene->base );
+
+ // release material
+ BKE_libblock_free( &G.main->mat, material );
+
+ BKE_scene_set_background( G.main, old_scene );
+}
+
+float BlenderStrokeRenderer::get_stroke_vertex_z(void) const {
+ float z = _z;
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this);
+ if (!(_z < _z_delta * 100000.0f))
+ self->_z_delta *= 10.0f;
+ self->_z += _z_delta;
+ return -z;
+}
+
+void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{
+
+ ////////////////////
+ // Build up scene
+ ////////////////////
+
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ Vec3r color[3];
+ unsigned int vertex_index, edge_index, loop_index;
+ Vec2r p;
+
+ for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
+ s!=send;
+ ++s){
+
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+ int strip_vertex_count = (*s)->sizeStrip();
+ int xl, xu, yl, yu, n, visible_faces, visible_segments;
+ bool visible;
+
+ // iterate over all vertices and count visible faces and strip segments
+ // (note: a strip segment is a series of visible faces, while two strip
+ // segments are separated by one or more invisible faces)
+ v[0] = strip_vertices.begin();
+ v[1] = v[0]; ++(v[1]);
+ v[2] = v[1]; ++(v[2]);
+ visible_faces = visible_segments = 0;
+ visible = false;
+ for (n = 2; n < strip_vertex_count; n++)
+ {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+ xl = xu = yl = yu = 0;
+ for (int j = 0; j < 3; j++) {
+ p = svRep[j]->point2d();
+ if (p[0] < 0.0) xl++; else if (p[0] > _width) xu++;
+ if (p[1] < 0.0) yl++; else if (p[1] > _height) yu++;
+ }
+ if (xl == 3 || xu == 3 || yl == 3 || yu == 3) {
+ visible = false;
+ } else {
+ visible_faces++;
+ if (!visible)
+ visible_segments++;
+ visible = true;
+ }
+ ++v[0]; ++v[1]; ++v[2];
+ }
+ if (visible_faces == 0)
+ continue;
+
+ // me = Mesh.New()
+ Object* object_mesh = BKE_object_add(freestyle_scene, OB_MESH);
+ Mesh* mesh = (Mesh *) object_mesh->data;
+ // MEM_freeN(mesh->bb);
+ // mesh->bb= NULL;
+ // mesh->id.us = 0;
+
+#if 1
+ // me.materials = [mat]
+ mesh->mat = ( Material ** ) MEM_mallocN( 1 * sizeof( Material * ), "MaterialList" );
+ mesh->mat[0] = material;
+ mesh->totcol = 1;
+ test_object_materials( (ID*) mesh );
+#else
+ assign_material(object_mesh, material, object_mesh->totcol+1);
+ object_mesh->actcol= object_mesh->totcol;
+#endif
+
+ // vertices allocation
+ mesh->totvert = visible_faces + visible_segments * 2;
+ mesh->mvert = (MVert*) CustomData_add_layer( &mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+
+ // edges allocation
+ mesh->totedge = visible_faces * 2 + visible_segments;
+ mesh->medge = (MEdge*) CustomData_add_layer( &mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+
+ // faces allocation
+ mesh->totpoly = visible_faces;
+ mesh->mpoly= (MPoly*) CustomData_add_layer( &mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+
+ // loops allocation
+ mesh->totloop = visible_faces * 3;
+ mesh->mloop= (MLoop*) CustomData_add_layer( &mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
+
+ // colors allocation
+ mesh->mloopcol = (MLoopCol *) CustomData_add_layer( &mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop);
+
+ ////////////////////
+ // Data copy
+ ////////////////////
+
+ MVert* vertices = mesh->mvert;
+ MEdge* edges = mesh->medge;
+ MPoly* polys = mesh->mpoly;
+ MLoop* loops = mesh->mloop;
+ MLoopCol* colors = mesh->mloopcol;
+
+ v[0] = strip_vertices.begin();
+ v[1] = v[0]; ++(v[1]);
+ v[2] = v[1]; ++(v[2]);
+
+ vertex_index = edge_index = loop_index = 0;
+ visible = false;
+
+ // Note: Mesh generation in the following loop assumes stroke strips
+ // to be triangle strips.
+ for (n = 2; n < strip_vertex_count; n++)
+ {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+ xl = xu = yl = yu = 0;
+ for (int j = 0; j < 3; j++) {
+ p = svRep[j]->point2d();
+ if (p[0] < 0.0) xl++; else if (p[0] > _width) xu++;
+ if (p[1] < 0.0) yl++; else if (p[1] > _height) yu++;
+ }
+ if (xl == 3 || xu == 3 || yl == 3 || yu == 3) {
+ visible = false;
+ } else {
+ if (!visible) {
+ // first vertex
+ vertices->co[0] = svRep[0]->point2d()[0];
+ vertices->co[1] = svRep[0]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ ++vertices;
+ ++vertex_index;
+
+ // second vertex
+ vertices->co[0] = svRep[1]->point2d()[0];
+ vertices->co[1] = svRep[1]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ ++vertices;
+ ++vertex_index;
+
+ // first edge
+ edges->v1 = vertex_index - 2;
+ edges->v2 = vertex_index - 1;
+ ++edges;
+ ++edge_index;
+ }
+ visible = true;
+
+ // vertex
+ vertices->co[0] = svRep[2]->point2d()[0];
+ vertices->co[1] = svRep[2]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ ++vertices;
+ ++vertex_index;
+
+ // edges
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 3;
+ ++edges;
+ ++edge_index;
+
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 2;
+ ++edges;
+ ++edge_index;
+
+ // poly
+ polys->loopstart = loop_index;
+ polys->totloop = 3;
+ ++polys;
+
+ // loops
+ if (n % 2 == 0) {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 1;
+
+ loops[1].v = vertex_index - 2;
+ loops[1].e = edge_index - 3;
+
+ loops[2].v = vertex_index - 3;
+ loops[2].e = edge_index - 2;
+ } else {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 2;
+
+ loops[1].v = vertex_index - 3;
+ loops[1].e = edge_index - 3;
+
+ loops[2].v = vertex_index - 2;
+ loops[2].e = edge_index - 1;
+ }
+ loops += 3;
+ loop_index += 3;
+
+ // colors
+ if (n % 2 == 0) {
+ colors[0].r = (short)(255.0f*svRep[2]->color()[0]);
+ colors[0].g = (short)(255.0f*svRep[2]->color()[1]);
+ colors[0].b = (short)(255.0f*svRep[2]->color()[2]);
+ colors[0].a = (short)(255.0f*svRep[2]->alpha());
+
+ colors[1].r = (short)(255.0f*svRep[1]->color()[0]);
+ colors[1].g = (short)(255.0f*svRep[1]->color()[1]);
+ colors[1].b = (short)(255.0f*svRep[1]->color()[2]);
+ colors[1].a = (short)(255.0f*svRep[1]->alpha());
+
+ colors[2].r = (short)(255.0f*svRep[0]->color()[0]);
+ colors[2].g = (short)(255.0f*svRep[0]->color()[1]);
+ colors[2].b = (short)(255.0f*svRep[0]->color()[2]);
+ colors[2].a = (short)(255.0f*svRep[0]->alpha());
+ } else {
+ colors[0].r = (short)(255.0f*svRep[2]->color()[0]);
+ colors[0].g = (short)(255.0f*svRep[2]->color()[1]);
+ colors[0].b = (short)(255.0f*svRep[2]->color()[2]);
+ colors[0].a = (short)(255.0f*svRep[2]->alpha());
+
+ colors[1].r = (short)(255.0f*svRep[0]->color()[0]);
+ colors[1].g = (short)(255.0f*svRep[0]->color()[1]);
+ colors[1].b = (short)(255.0f*svRep[0]->color()[2]);
+ colors[1].a = (short)(255.0f*svRep[0]->alpha());
+
+ colors[2].r = (short)(255.0f*svRep[1]->color()[0]);
+ colors[2].g = (short)(255.0f*svRep[1]->color()[1]);
+ colors[2].b = (short)(255.0f*svRep[1]->color()[2]);
+ colors[2].a = (short)(255.0f*svRep[1]->alpha());
+ }
+ colors += 3;
+
+ }
+ ++v[0]; ++v[1]; ++v[2];
+
+ } // loop over strip vertices
+#if 0
+ BKE_mesh_validate(mesh, TRUE);
+#endif
+
+ } // loop over strips
+
+}
+
+Render* BlenderStrokeRenderer::RenderScene( Render *re ) {
+ Camera *camera = (Camera *)freestyle_scene->camera->data;
+ if (camera->clipend < _z)
+ camera->clipend = _z + _z_delta * 100.0f;
+ //cout << "clipsta " << camera->clipsta << ", clipend " << camera->clipend << endl;
+
+ Render *freestyle_render = RE_NewRender(freestyle_scene->id.name);
+
+ RE_RenderFreestyleStrokes(freestyle_render, G.main, freestyle_scene);
+ return freestyle_render;
+}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
new file mode 100644
index 00000000000..b7d8c5b95d7
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
@@ -0,0 +1,45 @@
+#ifndef BLENDERSTROKERENDERER_H
+# define BLENDERSTROKERENDERER_H
+
+# include "../stroke/StrokeRenderer.h"
+# include "../system/FreestyleConfig.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+
+#include "render_types.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+class LIB_STROKE_EXPORT BlenderStrokeRenderer : public StrokeRenderer
+{
+public:
+ BlenderStrokeRenderer(Render *re, int render_count);
+ virtual ~BlenderStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ Render* RenderScene(Render *re);
+
+protected:
+ Scene* old_scene;
+ Scene* freestyle_scene;
+ Material* material;
+ float _width, _height;
+ float _z, _z_delta;
+
+ float get_stroke_vertex_z(void) const;
+};
+
+#endif // BLENDERSTROKERENDERER_H
+
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
new file mode 100644
index 00000000000..93b5f694eb6
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
@@ -0,0 +1,39 @@
+#ifndef BLENDERSTYLEMODULE_H
+#define BLENDERSTYLEMODULE_H
+
+#include "../stroke/StyleModule.h"
+#include "../system/PythonInterpreter.h"
+
+extern "C" {
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_text.h"
+}
+
+class BlenderStyleModule : public StyleModule
+{
+public:
+
+ BlenderStyleModule(struct Text *text, const string &name,
+ Interpreter *inter) : StyleModule(name, inter) {
+ _text = text;
+ }
+
+ virtual ~BlenderStyleModule() {
+ BKE_text_unlink(G.main, _text);
+ BKE_libblock_free(&G.main->text, _text);
+ }
+
+protected:
+
+ virtual int interpret() {
+ PythonInterpreter* py_inter = dynamic_cast<PythonInterpreter*>(_inter);
+ assert(py_inter != 0);
+ return py_inter->interpretText(_text, getFileName());
+ }
+
+private:
+ struct Text *_text;
+};
+
+#endif // BLENDERSTYLEMODULE_H
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp
new file mode 100644
index 00000000000..d731af42d0e
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp
@@ -0,0 +1,71 @@
+#include "BlenderTextureManager.h"
+
+
+BlenderTextureManager::BlenderTextureManager ()
+: TextureManager()
+{
+ //_brushes_path = Config::getInstance()...
+}
+
+BlenderTextureManager::~BlenderTextureManager ()
+{
+}
+
+void BlenderTextureManager::loadStandardBrushes()
+{
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ //_defaultTextureId = getBrushTextureIndex("smoothAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+}
+
+
+unsigned
+BlenderTextureManager::loadBrush(string sname, Stroke::MediumType mediumType)
+{
+// GLuint texId;
+// glGenTextures(1, &texId);
+// bool found = false;
+// vector<string> pathnames;
+// string path; //soc
+// StringUtils::getPathName(TextureManager::Options::getBrushesPath(),
+// sname,
+// pathnames);
+// for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
+// path = j->c_str();
+// //soc if(QFile::exists(path)){
+// if( BLI_exists( const_cast<char *>(path.c_str()) ) ) {
+// found = true;
+// break;
+// }
+// }
+// if(!found)
+// return 0;
+// // Brush texture
+// cout << "Loading brush texture..." << endl;
+// switch(mediumType){
+// case Stroke::DRY_MEDIUM:
+// //soc prepareTextureLuminance((const char*)path.toAscii(), texId);
+// prepareTextureLuminance(StringUtils::toAscii(path), texId);
+// break;
+// case Stroke::HUMID_MEDIUM:
+// case Stroke::OPAQUE_MEDIUM:
+// default:
+// //soc prepareTextureAlpha((const char*)path.toAscii(), texId);
+// prepareTextureAlpha(StringUtils::toAscii(path), texId);
+// break;
+// }
+// cout << "Done." << endl << endl;
+//
+// return texId;
+//
+ return 0;
+}
+
+
+
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h
new file mode 100644
index 00000000000..fac33c139e1
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h
@@ -0,0 +1,23 @@
+#ifndef BLENDERTEXTUREMANAGER_H
+#define BLENDERTEXTUREMANAGER_H
+
+# include "../stroke/StrokeRenderer.h"
+# include "../stroke/StrokeRep.h"
+# include "../system/FreestyleConfig.h"
+
+/*! Class to load textures
+ */
+class LIB_RENDERING_EXPORT BlenderTextureManager : public TextureManager
+{
+ public:
+ BlenderTextureManager ();
+ virtual ~BlenderTextureManager ();
+protected:
+ virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM);
+
+ protected:
+ virtual void loadStandardBrushes();
+
+};
+
+#endif // BLENDERTEXTUREMANAGER_H
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
new file mode 100644
index 00000000000..5dcda3bd69c
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -0,0 +1,740 @@
+#include "../application/Controller.h"
+#include "../application/AppView.h"
+#include "../application/AppConfig.h"
+#include "../application/AppCanvas.h"
+
+#include <iostream>
+#include <map>
+#include <set>
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_text_types.h"
+#include "DNA_group_types.h"
+#include "DNA_freestyle_types.h"
+
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_linestyle.h"
+#include "BKE_main.h"
+#include "BKE_text.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BPY_extern.h"
+
+#include "renderpipeline.h"
+#include "pixelblending.h"
+
+#include "../../FRS_freestyle.h"
+#include "../../FRS_freestyle_config.h"
+
+#define DEFAULT_SPHERE_RADIUS 1.0f
+#define DEFAULT_DKR_EPSILON 0.0f
+
+ // Freestyle configuration
+ static short freestyle_is_initialized = 0;
+ static Config::Path *pathconfig = NULL;
+ static Controller *controller = NULL;
+ static AppView *view = NULL;
+
+ // line set buffer for copy & paste
+ static FreestyleLineSet lineset_buffer;
+ static bool lineset_copied = false;
+
+ // camera information
+ float freestyle_viewpoint[3];
+ float freestyle_mv[4][4];
+ float freestyle_proj[4][4];
+ int freestyle_viewport[4];
+
+ // current scene
+ Scene *freestyle_scene;
+
+ string default_module_path;
+
+ //=======================================================
+ // Initialization
+ //=======================================================
+
+ void FRS_initialize() {
+
+ if( freestyle_is_initialized )
+ return;
+
+ pathconfig = new Config::Path;
+ controller = new Controller();
+ view = new AppView;
+ controller->setView(view);
+ controller->Clear();
+ freestyle_scene = NULL;
+ lineset_copied = false;
+
+ default_module_path = pathconfig->getProjectDir() + Config::DIR_SEP + "style_modules" + Config::DIR_SEP + "contour.py";
+
+ freestyle_is_initialized = 1;
+ }
+
+ void FRS_set_context(bContext* C) {
+ cout << "FRS_set_context: context 0x" << C << " scene 0x" << CTX_data_scene(C) << endl;
+ controller->setContext(C);
+ }
+
+ void FRS_read_file(bContext* C) {
+ lineset_copied = false;
+ }
+
+ void FRS_exit() {
+ delete pathconfig;
+ delete controller;
+ delete view;
+ }
+
+ //=======================================================
+ // Rendering
+ //=======================================================
+
+ static void init_view(Render* re){
+ int width = re->winx;
+ int height = re->winy;
+ int xmin = re->disprect.xmin;
+ int ymin = re->disprect.ymin;
+ int xmax = re->disprect.xmax;
+ int ymax = re->disprect.ymax;
+
+ float thickness = 1.f;
+ switch (re->r.line_thickness_mode) {
+ case R_LINE_THICKNESS_ABSOLUTE:
+ thickness = re->r.unit_line_thickness * (re->r.size / 100.f);
+ break;
+ case R_LINE_THICKNESS_RELATIVE:
+ thickness = height / 480.f;
+ break;
+ }
+
+ freestyle_viewport[0] = freestyle_viewport[1] = 0;
+ freestyle_viewport[2] = width;
+ freestyle_viewport[3] = height;
+
+ view->setWidth( width );
+ view->setHeight( height );
+ view->setBorder( xmin, ymin, xmax, ymax );
+ view->setThickness( thickness );
+
+ cout << "\n=== Dimensions of the 2D image coordinate system ===" << endl;
+ cout << "Width : " << width << endl;
+ cout << "Height : " << height << endl;
+ if (re->r.mode & R_BORDER)
+ cout << "Border : (" << xmin << ", " << ymin << ") - (" << xmax << ", " << ymax << ")" << endl;
+ cout << "Unit line thickness : " << thickness << " pixel(s)" << endl;
+ }
+
+ static void init_camera(Render* re){
+ // It is assumed that imported meshes are in the camera coordinate system.
+ // Therefore, the view point (i.e., camera position) is at the origin, and
+ // the the model-view matrix is simply the identity matrix.
+
+ freestyle_viewpoint[0] = 0.0;
+ freestyle_viewpoint[1] = 0.0;
+ freestyle_viewpoint[2] = 0.0;
+
+ for( int i = 0; i < 4; i++ )
+ for( int j = 0; j < 4; j++ )
+ freestyle_mv[i][j] = (i == j) ? 1.0 : 0.0;
+
+ for( int i = 0; i < 4; i++ )
+ for( int j = 0; j < 4; j++ )
+ freestyle_proj[i][j] = re->winmat[i][j];
+
+ //print_m4("mv", freestyle_mv);
+ //print_m4("proj", freestyle_proj);
+ }
+
+ static char *escape_quotes(char *name)
+ {
+ char *s= (char *)MEM_mallocN(strlen(name) * 2 + 1, "escape_quotes");
+ char *p= s;
+ while (*name) {
+ if (*name == '\'')
+ *p++= '\\';
+ *p++ = *name++;
+ }
+ *p = '\0';
+ return s;
+ }
+
+ static Text *create_lineset_handler(char *layer_name, char *lineset_name)
+ {
+ char *s1= escape_quotes(layer_name);
+ char *s2= escape_quotes(lineset_name);
+ Text *text= BKE_text_add(lineset_name);
+ BKE_text_write(text, "import parameter_editor; parameter_editor.process('");
+ BKE_text_write(text, s1);
+ BKE_text_write(text, "', '");
+ BKE_text_write(text, s2);
+ BKE_text_write(text, "')\n");
+ MEM_freeN(s1);
+ MEM_freeN(s2);
+ return text;
+ }
+
+ struct edge_type_condition {
+ int edge_type, value;
+ };
+
+ // examines the conditions and returns true if the target edge type needs to be computed
+ static bool test_edge_type_conditions(struct edge_type_condition *conditions,
+ int num_edge_types, bool logical_and, int target, bool distinct)
+ {
+ int target_condition = 0;
+ int num_non_target_positive_conditions = 0;
+ int num_non_target_negative_conditions = 0;
+
+ for (int i = 0; i < num_edge_types; i++) {
+ if (conditions[i].edge_type == target)
+ target_condition = conditions[i].value;
+ else if (conditions[i].value > 0)
+ ++num_non_target_positive_conditions;
+ else if (conditions[i].value < 0)
+ ++num_non_target_negative_conditions;
+ }
+ if (distinct) {
+ // In this case, the 'target' edge type is assumed to appear on distinct edge
+ // of its own and never together with other edge types.
+ if (logical_and) {
+ if (num_non_target_positive_conditions > 0)
+ return false;
+ if (target_condition > 0)
+ return true;
+ if (target_condition < 0)
+ return false;
+ if (num_non_target_negative_conditions > 0)
+ return true;
+ } else {
+ if (target_condition > 0)
+ return true;
+ if (num_non_target_negative_conditions > 0)
+ return true;
+ if (target_condition < 0)
+ return false;
+ if (num_non_target_positive_conditions > 0)
+ return false;
+ }
+ } else {
+ // In this case, the 'target' edge type may appear together with other edge types.
+ if (target_condition > 0)
+ return true;
+ if (target_condition < 0)
+ return true;
+ if (logical_and) {
+ if (num_non_target_positive_conditions > 0)
+ return false;
+ if (num_non_target_negative_conditions > 0)
+ return true;
+ } else {
+ if (num_non_target_negative_conditions > 0)
+ return true;
+ if (num_non_target_positive_conditions > 0)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static void prepare(Render* re, SceneRenderLayer* srl ) {
+
+ // load mesh
+ re->i.infostr= "Freestyle: Mesh loading";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr= NULL;
+ if( controller->LoadMesh(re, srl) ) // returns if scene cannot be loaded or if empty
+ return;
+ if( re->test_break(re->tbh) )
+ return;
+
+ // add style modules
+ FreestyleConfig* config = &srl->freestyleConfig;
+
+ cout << "\n=== Rendering options ===" << endl;
+ int layer_count = 0;
+
+ switch (config->mode) {
+ case FREESTYLE_CONTROL_SCRIPT_MODE:
+ cout << "Modules :"<< endl;
+ for (FreestyleModuleConfig* module_conf = (FreestyleModuleConfig *)config->modules.first; module_conf; module_conf = module_conf->next) {
+ if( module_conf->is_displayed ) {
+ cout << " " << layer_count+1 << ": " << module_conf->module_path << endl;
+ controller->InsertStyleModule( layer_count, module_conf->module_path );
+ controller->toggleLayer(layer_count, true);
+ layer_count++;
+ }
+ }
+ cout << endl;
+ controller->setComputeRidgesAndValleysFlag( (config->flags & FREESTYLE_RIDGES_AND_VALLEYS_FLAG) ? true : false);
+ controller->setComputeSuggestiveContoursFlag( (config->flags & FREESTYLE_SUGGESTIVE_CONTOURS_FLAG) ? true : false);
+ controller->setComputeMaterialBoundariesFlag( (config->flags & FREESTYLE_MATERIAL_BOUNDARIES_FLAG) ? true : false);
+ break;
+ case FREESTYLE_CONTROL_EDITOR_MODE:
+ int use_ridges_and_valleys = 0;
+ int use_suggestive_contours = 0;
+ int use_material_boundaries = 0;
+ struct edge_type_condition conditions[] = {
+ {FREESTYLE_FE_SILHOUETTE, 0},
+ {FREESTYLE_FE_BORDER, 0},
+ {FREESTYLE_FE_CREASE, 0},
+ {FREESTYLE_FE_RIDGE_VALLEY, 0},
+ {FREESTYLE_FE_SUGGESTIVE_CONTOUR, 0},
+ {FREESTYLE_FE_MATERIAL_BOUNDARY, 0},
+ {FREESTYLE_FE_CONTOUR, 0},
+ {FREESTYLE_FE_EXTERNAL_CONTOUR, 0},
+ {FREESTYLE_FE_EDGE_MARK, 0}};
+ int num_edge_types = sizeof(conditions) / sizeof(struct edge_type_condition);
+ cout << "Linesets:"<< endl;
+ for (FreestyleLineSet *lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->flags & FREESTYLE_LINESET_ENABLED) {
+ cout << " " << layer_count+1 << ": " << lineset->name << " - " << lineset->linestyle->id.name+2 << endl;
+ Text *text = create_lineset_handler(srl->name, lineset->name);
+ controller->InsertStyleModule( layer_count, lineset->name, text );
+ controller->toggleLayer(layer_count, true);
+ if (!(lineset->selection & FREESTYLE_SEL_EDGE_TYPES) || !lineset->edge_types) {
+ ++use_ridges_and_valleys;
+ ++use_suggestive_contours;
+ ++use_material_boundaries;
+ } else {
+ // conditions for feature edge selection by edge types
+ for (int i = 0; i < num_edge_types; i++) {
+ if (!(lineset->edge_types & conditions[i].edge_type))
+ conditions[i].value = 0; // no condition specified
+ else if (!(lineset->exclude_edge_types & conditions[i].edge_type))
+ conditions[i].value = 1; // condition: X
+ else
+ conditions[i].value = -1; // condition: NOT X
+ }
+ // logical operator for the selection conditions
+ bool logical_and = ((lineset->flags & FREESTYLE_LINESET_FE_AND) != 0);
+ // negation operator
+ if (lineset->flags & FREESTYLE_LINESET_FE_NOT) {
+ // convert an Exclusive condition into an Inclusive equivalent using De Morgan's laws:
+ // NOT (X OR Y) --> (NOT X) AND (NOT Y)
+ // NOT (X AND Y) --> (NOT X) OR (NOT Y)
+ for (int i = 0; i < num_edge_types; i++)
+ conditions[i].value *= -1;
+ logical_and = !logical_and;
+ }
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and, FREESTYLE_FE_RIDGE_VALLEY, true))
+ ++use_ridges_and_valleys;
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and, FREESTYLE_FE_SUGGESTIVE_CONTOUR, true))
+ ++use_suggestive_contours;
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and, FREESTYLE_FE_MATERIAL_BOUNDARY, true))
+ ++use_material_boundaries;
+ }
+ layer_count++;
+ }
+ }
+ controller->setComputeRidgesAndValleysFlag( use_ridges_and_valleys > 0 );
+ controller->setComputeSuggestiveContoursFlag( use_suggestive_contours > 0 );
+ controller->setComputeMaterialBoundariesFlag( use_material_boundaries > 0 );
+ break;
+ }
+
+ // set parameters
+ if (config->flags & FREESTYLE_ADVANCED_OPTIONS_FLAG) {
+ controller->setSphereRadius( config->sphere_radius );
+ controller->setSuggestiveContourKrDerivativeEpsilon( config->dkr_epsilon );
+ } else {
+ controller->setSphereRadius( DEFAULT_SPHERE_RADIUS );
+ controller->setSuggestiveContourKrDerivativeEpsilon( DEFAULT_DKR_EPSILON );
+ }
+ controller->setFaceSmoothness( (config->flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) ? true : false);
+ controller->setCreaseAngle( config->crease_angle );
+ controller->setVisibilityAlgo( config->raycasting_algorithm );
+
+ cout << "Crease angle : " << controller->getCreaseAngle() << endl;
+ cout << "Sphere radius : " << controller->getSphereRadius() << endl;
+ cout << "Face smoothness : " << (controller->getFaceSmoothness() ? "enabled" : "disabled") << endl;
+ cout << "Redges and valleys : " << (controller->getComputeRidgesAndValleysFlag() ? "enabled" : "disabled") << endl;
+ cout << "Suggestive contours : " << (controller->getComputeSuggestiveContoursFlag() ? "enabled" : "disabled") << endl;
+ cout << "Suggestive contour Kr derivative epsilon : " << controller->getSuggestiveContourKrDerivativeEpsilon() << endl;
+ cout << "Material boundaries : " << (controller->getComputeMaterialBoundariesFlag() ? "enabled" : "disabled") << endl;
+ cout << endl;
+
+ // set diffuse and z depth passes
+ RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name);
+ bool diffuse = false, z = false;
+ for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) {
+ switch (rpass->passtype) {
+ case SCE_PASS_DIFFUSE:
+ controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty);
+ diffuse = true;
+ break;
+ case SCE_PASS_Z:
+ controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty);
+ z = true;
+ break;
+ }
+ }
+ cout << "Passes :" << endl;
+ cout << " Diffuse = " << (diffuse ? "enabled" : "disabled") << endl;
+ cout << " Z = " << (z ? "enabled" : "disabled") << endl;
+
+ // compute view map
+ re->i.infostr= "Freestyle: View map creation";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr= NULL;
+ controller->ComputeViewMap();
+ }
+
+ void FRS_composite_result(Render* re, SceneRenderLayer* srl, Render* freestyle_render)
+ {
+ RenderLayer *rl;
+ float *src, *dest, *pixSrc, *pixDest;
+ int x, y, rectx, recty;
+
+ if( freestyle_render == NULL || freestyle_render->result == NULL )
+ return;
+
+ rl = render_get_active_layer( freestyle_render, freestyle_render->result );
+ if( !rl || rl->rectf == NULL) { cout << "Cannot find Freestyle result image" << endl; return; }
+ src = rl->rectf;
+ //cout << "src: " << rl->rectx << " x " << rl->recty << endl;
+
+ rl = RE_GetRenderLayer(re->result, srl->name);
+ if( !rl || rl->rectf == NULL) { cout << "No layer to composite to" << endl; return; }
+ dest = rl->rectf;
+ //cout << "dest: " << rl->rectx << " x " << rl->recty << endl;
+
+ rectx = re->rectx;
+ recty = re->recty;
+ for( y = 0; y < recty; y++) {
+ for( x = 0; x < rectx; x++) {
+ pixSrc = src + 4 * (rectx * y + x);
+ if( pixSrc[3] > 0.0) {
+ pixDest = dest + 4 * (rectx * y + x);
+ addAlphaOverFloat(pixDest, pixSrc);
+ }
+ }
+ }
+ }
+
+ static int displayed_layer_count( SceneRenderLayer* srl ) {
+ int count = 0;
+
+ switch (srl->freestyleConfig.mode) {
+ case FREESTYLE_CONTROL_SCRIPT_MODE:
+ for (FreestyleModuleConfig* module = (FreestyleModuleConfig *)srl->freestyleConfig.modules.first; module; module = module->next) {
+ if( module->is_displayed )
+ count++;
+ }
+ break;
+ case FREESTYLE_CONTROL_EDITOR_MODE:
+ for (FreestyleLineSet *lineset = (FreestyleLineSet *)srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->flags & FREESTYLE_LINESET_ENABLED)
+ count++;
+ }
+ break;
+ }
+ return count;
+ }
+
+ int FRS_is_freestyle_enabled(SceneRenderLayer* srl) {
+ return (!(srl->layflag & SCE_LAY_DISABLE) &&
+ srl->layflag & SCE_LAY_FRS &&
+ displayed_layer_count(srl) > 0);
+ }
+
+ void FRS_init_stroke_rendering(Render* re) {
+
+ cout << "\n#===============================================================" << endl;
+ cout << "# Freestyle" << endl;
+ cout << "#===============================================================" << endl;
+
+ init_view(re);
+ init_camera(re);
+
+ controller->ResetRenderCount();
+ }
+
+ Render* FRS_do_stroke_rendering(Render* re, SceneRenderLayer *srl) {
+
+ Render* freestyle_render = NULL;
+
+ RenderMonitor monitor(re);
+ controller->setRenderMonitor(&monitor);
+
+ cout << "\n----------------------------------------------------------" << endl;
+ cout << "| " << (re->scene->id.name+2) << "|" << srl->name << endl;
+ cout << "----------------------------------------------------------" << endl;
+
+ // prepare Freestyle:
+ // - load mesh
+ // - add style modules
+ // - set parameters
+ // - compute view map
+ prepare(re, srl);
+
+ if( re->test_break(re->tbh) ) {
+ controller->CloseFile();
+ cout << "Break" << endl;
+ return NULL;
+ }
+
+ // render and composite Freestyle result
+ if( controller->_ViewMap ) {
+
+ // render strokes
+ re->i.infostr= "Freestyle: Stroke rendering";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr= NULL;
+ freestyle_scene = re->scene;
+ controller->DrawStrokes();
+ freestyle_render = controller->RenderStrokes(re);
+ controller->CloseFile();
+ freestyle_scene = NULL;
+
+ // composite result
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
+
+ return freestyle_render;
+ }
+
+ void FRS_finish_stroke_rendering(Render* re) {
+ // clear canvas
+ controller->Clear();
+ }
+
+ //=======================================================
+ // Freestyle Panel Configuration
+ //=======================================================
+
+ void FRS_add_freestyle_config( SceneRenderLayer* srl )
+ {
+ FreestyleConfig* config = &srl->freestyleConfig;
+
+ config->mode = FREESTYLE_CONTROL_SCRIPT_MODE;
+
+ config->modules.first = config->modules.last = NULL;
+ config->flags = 0;
+ config->sphere_radius = DEFAULT_SPHERE_RADIUS;
+ config->dkr_epsilon = DEFAULT_DKR_EPSILON;
+ config->crease_angle = 134.43f;
+
+ config->linesets.first = config->linesets.last = NULL;
+
+ config->raycasting_algorithm = FREESTYLE_ALGO_REGULAR;
+ }
+
+ void FRS_free_freestyle_config( SceneRenderLayer* srl )
+ {
+ FreestyleLineSet *lineset;
+
+ for(lineset=(FreestyleLineSet *)srl->freestyleConfig.linesets.first; lineset; lineset=lineset->next) {
+ if (lineset->group) {
+ lineset->group->id.us--;
+ lineset->group = NULL;
+ }
+ lineset->linestyle->id.us--;
+ lineset->linestyle = NULL;
+ }
+ BLI_freelistN( &srl->freestyleConfig.linesets );
+ BLI_freelistN( &srl->freestyleConfig.modules );
+ }
+
+ void FRS_add_module(FreestyleConfig *config)
+ {
+ FreestyleModuleConfig* module_conf = (FreestyleModuleConfig*) MEM_callocN( sizeof(FreestyleModuleConfig), "style module configuration");
+ BLI_addtail(&config->modules, (void*) module_conf);
+
+ strcpy( module_conf->module_path, default_module_path.c_str() );
+ module_conf->is_displayed = 1;
+ }
+
+ void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+ {
+ BLI_freelinkN(&config->modules, module_conf);
+ }
+
+ void FRS_move_module_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+ {
+ BLI_remlink(&config->modules, module_conf);
+ BLI_insertlinkbefore(&config->modules, module_conf->prev, module_conf);
+ }
+
+ void FRS_move_module_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+ {
+ BLI_remlink(&config->modules, module_conf);
+ BLI_insertlinkafter(&config->modules, module_conf->next, module_conf);
+ }
+
+ static void unique_lineset_name(FreestyleConfig *config, FreestyleLineSet *lineset)
+ {
+ BLI_uniquename(&config->linesets, lineset, "FreestyleLineSet", '.', offsetof(FreestyleLineSet, name), sizeof(lineset->name));
+ }
+
+ FreestyleLineSet *FRS_add_lineset(FreestyleConfig *config)
+ {
+ int lineset_index = BLI_countlist(&config->linesets);
+
+ FreestyleLineSet *lineset = (FreestyleLineSet *) MEM_callocN( sizeof(FreestyleLineSet), "Freestyle line set");
+ BLI_addtail(&config->linesets, (void *) lineset);
+ FRS_set_active_lineset_index(config, lineset_index);
+
+ lineset->linestyle = FRS_new_linestyle("LineStyle", NULL);
+ lineset->flags |= FREESTYLE_LINESET_ENABLED;
+ lineset->selection = FREESTYLE_SEL_IMAGE_BORDER;
+ lineset->qi = FREESTYLE_QI_VISIBLE;
+ lineset->qi_start = 0;
+ lineset->qi_end = 100;
+ lineset->edge_types = FREESTYLE_FE_SILHOUETTE | FREESTYLE_FE_BORDER | FREESTYLE_FE_CREASE;
+ lineset->exclude_edge_types = 0;
+ lineset->group = NULL;
+ if (lineset_index > 0)
+ sprintf(lineset->name, "LineSet %i", lineset_index+1);
+ else
+ strcpy(lineset->name, "LineSet");
+ unique_lineset_name(config, lineset);
+
+ return lineset;
+ }
+
+ void FRS_copy_active_lineset(FreestyleConfig *config)
+ {
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config);
+
+ if (lineset) {
+ lineset_buffer.linestyle = lineset->linestyle;
+ lineset_buffer.flags = lineset->flags;
+ lineset_buffer.selection = lineset->selection;
+ lineset_buffer.qi = lineset->qi;
+ lineset_buffer.qi_start = lineset->qi_start;
+ lineset_buffer.qi_end = lineset->qi_end;
+ lineset_buffer.edge_types = lineset->edge_types;
+ lineset_buffer.exclude_edge_types = lineset->exclude_edge_types;
+ lineset_buffer.group = lineset->group;
+ strcpy(lineset_buffer.name, lineset->name);
+ lineset_copied = true;
+ }
+ }
+
+ void FRS_paste_active_lineset(FreestyleConfig *config)
+ {
+ if (!lineset_copied)
+ return;
+
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config);
+
+ if (lineset) {
+ lineset->linestyle->id.us--;
+ lineset->linestyle = lineset_buffer.linestyle;
+ lineset->linestyle->id.us++;
+ lineset->flags = lineset_buffer.flags;
+ lineset->selection = lineset_buffer.selection;
+ lineset->qi = lineset_buffer.qi;
+ lineset->qi_start = lineset_buffer.qi_start;
+ lineset->qi_end = lineset_buffer.qi_end;
+ lineset->edge_types = lineset_buffer.edge_types;
+ lineset->exclude_edge_types = lineset_buffer.exclude_edge_types;
+ if (lineset->group) {
+ lineset->group->id.us--;
+ lineset->group = NULL;
+ }
+ if (lineset_buffer.group) {
+ lineset->group = lineset_buffer.group;
+ lineset->group->id.us++;
+ }
+ strcpy(lineset->name, lineset_buffer.name);
+ unique_lineset_name(config, lineset);
+ lineset->flags |= FREESTYLE_LINESET_CURRENT;
+ }
+ }
+
+ void FRS_delete_active_lineset(FreestyleConfig *config)
+ {
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config);
+
+ if (lineset) {
+ if (lineset->group) {
+ lineset->group->id.us--;
+ lineset->group = NULL;
+ }
+ lineset->linestyle->id.us--;
+ lineset->linestyle = NULL;
+ BLI_remlink(&config->linesets, lineset);
+ MEM_freeN(lineset);
+ FRS_set_active_lineset_index(config, 0);
+ }
+ }
+
+ void FRS_move_active_lineset_up(FreestyleConfig *config)
+ {
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config);
+
+ if (lineset) {
+ BLI_remlink(&config->linesets, lineset);
+ BLI_insertlinkbefore(&config->linesets, lineset->prev, lineset);
+ }
+ }
+
+ void FRS_move_active_lineset_down(FreestyleConfig *config)
+ {
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config);
+
+ if (lineset) {
+ BLI_remlink(&config->linesets, lineset);
+ BLI_insertlinkafter(&config->linesets, lineset->next, lineset);
+ }
+ }
+
+ FreestyleLineSet *FRS_get_active_lineset(FreestyleConfig *config)
+ {
+ FreestyleLineSet *lineset;
+
+ for(lineset=(FreestyleLineSet *)config->linesets.first; lineset; lineset=lineset->next)
+ if(lineset->flags & FREESTYLE_LINESET_CURRENT)
+ return lineset;
+ return NULL;
+ }
+
+ short FRS_get_active_lineset_index(FreestyleConfig *config)
+ {
+ FreestyleLineSet *lineset;
+ short i;
+
+ for(lineset=(FreestyleLineSet *)config->linesets.first, i=0; lineset; lineset=lineset->next, i++)
+ if(lineset->flags & FREESTYLE_LINESET_CURRENT)
+ return i;
+ return 0;
+ }
+
+ void FRS_set_active_lineset_index(FreestyleConfig *config, short index)
+ {
+ FreestyleLineSet *lineset;
+ short i;
+
+ for(lineset=(FreestyleLineSet *)config->linesets.first, i=0; lineset; lineset=lineset->next, i++) {
+ if(i == index)
+ lineset->flags |= FREESTYLE_LINESET_CURRENT;
+ else
+ lineset->flags &= ~FREESTYLE_LINESET_CURRENT;
+ }
+ }
+
+ void FRS_unlink_target_object(FreestyleConfig *config, Object *ob)
+ {
+ FreestyleLineSet *lineset;
+
+ for(lineset=(FreestyleLineSet *)config->linesets.first; lineset; lineset=lineset->next) {
+ FRS_unlink_linestyle_target_object(lineset->linestyle, ob);
+ }
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h
new file mode 100755
index 00000000000..9c46d7918e2
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/BBox.h
@@ -0,0 +1,141 @@
+//
+// Filename : BBox.h
+// Author(s) : Stephane Grabli
+// Purpose : A class to hold a bounding box
+// Date of creation : 22/05/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BBOX_H
+# define BBOX_H
+
+template <class Point>
+class BBox
+{
+ public:
+
+ inline BBox() {
+ _empty = true;
+ }
+
+ template <class T>
+ inline BBox(const T& min_in, const T& max_in) : _min(min_in), _max(max_in) {
+ _empty = false;
+ }
+
+ template <class T>
+ inline BBox(const BBox<T>& b) : _min(b.getMin()), _max(b.getMax()) {
+ _empty = false;
+ }
+
+ template <class T>
+ inline void extendToContain(const T& p) {
+ if (_empty) {
+ _min = p;
+ _max = p;
+ _empty = false;
+ return;
+ }
+ for (unsigned i = 0; i < Point::dim(); i++) {
+ if (p[i] < _min[i])
+ _min[i] = p[i];
+ else if (p[i] > _max[i])
+ _max[i] = p[i];
+ }
+ _empty = false;
+ }
+
+ inline void clear() {
+ _empty = true;
+ }
+
+ inline bool empty() const {
+ return _empty;
+ }
+
+ inline const Point& getMin() const {
+ return _min;
+ }
+
+ inline const Point& getMax() const {
+ return _max;
+ }
+
+ inline BBox<Point>& operator=(const BBox<Point>& b) {
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ return *this;
+ }
+
+ inline BBox<Point>& operator+=(const BBox<Point>& b) {
+ if (_empty) {
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ }
+ else {
+ for (unsigned i = 0; i < Point::dim(); i++) {
+ if (b.getMin()[i] < _min[i])
+ _min[i] = b.getMin()[i];
+ if (b.getMax()[i] > _max[i])
+ _max[i] = b.getMax()[i];
+ }
+ }
+ return *this;
+ }
+
+ inline bool inside(const Point& p){
+ if(empty())
+ return false;
+ for (unsigned i = 0; i < Point::dim(); i++) {
+ if((_min[i]>p[i]) || (_max[i]<p[i]))
+ return false;
+ }
+ return true;
+
+ }
+
+private:
+
+ Point _min;
+ Point _max;
+ bool _empty;
+};
+
+template <class Point>
+BBox<Point>& operator+(const BBox<Point> &b1, const BBox<Point> &b2)
+{
+ Point new_min;
+ Point new_max;
+
+ for (unsigned i = 0; i < Point::dim(); i++) {
+ new_min[i] = b1.getMin()[i] < b2.getMin()[i] ? b1.getMin()[i] : b2.getMin()[i];
+ new_max[i] = b1.getMax()[i] > b2.getMax()[i] ? b1.getMax()[i] : b2.getMax()[i];
+ }
+
+ return BBox<Point>(new_min, new_max);
+}
+
+#endif // BBOX_H
diff --git a/source/blender/freestyle/intern/geometry/Bezier.cpp b/source/blender/freestyle/intern/geometry/Bezier.cpp
new file mode 100755
index 00000000000..8f9771f29d3
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Bezier.cpp
@@ -0,0 +1,118 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Bezier.h"
+#include "FitCurve.h"
+
+using namespace std;
+
+BezierCurveSegment::BezierCurveSegment()
+{
+}
+
+BezierCurveSegment::~BezierCurveSegment()
+{
+}
+
+void BezierCurveSegment::AddControlPoint(const Vec2d& iPoint)
+{
+ _ControlPolygon.push_back(iPoint);
+ if(_ControlPolygon.size() == 4)
+ Build();
+}
+
+void BezierCurveSegment::Build()
+{
+ if(_ControlPolygon.size() != 4)
+ return;
+
+ // Compute the rightmost part of the matrix:
+ vector<Vec2d>::const_iterator p0,p1,p2,p3;
+ p0 = _ControlPolygon.begin();
+ p1 = p0;++p1;
+ p2 = p1;++p2;
+ p3 = p2;++p3;
+ float x[4], y[4];
+
+ x[0] = -p0->x()+3*p1->x()-3*p2->x()+p3->x();
+ x[1] = 3*p0->x()-6*p1->x()+3*p2->x();
+ x[2] = -3*p0->x()+3*p1->x();
+ x[3] = p0->x();
+
+ y[0] = -p0->y()+3*p1->y()-3*p2->y()+p3->y();
+ y[1] = 3*p0->y()-6*p1->y()+3*p2->y();
+ y[2] = -3*p0->y()+3*p1->y();
+ y[3] = p0->y();
+
+ int nvertices = 12;
+ float increment = 1.0/(float)nvertices;
+ float t = 0.f;
+ for(int i=0; i<=nvertices; ++i)
+ {
+ _Vertices.push_back(Vec2d((x[3] + t*(x[2] + t*(x[1] + t*x[0]))),
+ (y[3] + t*(y[2] + t*(y[1] + t*y[0])))));
+ t+=increment;
+ }
+}
+
+BezierCurve::BezierCurve()
+{
+ _currentSegment = new BezierCurveSegment;
+}
+
+BezierCurve::BezierCurve(vector<Vec2d>& iPoints, double error)
+{
+ FitCurveWrapper fitcurve;
+ _currentSegment = new BezierCurveSegment;
+ vector<Vec2d> curve;
+
+ fitcurve.FitCurve(iPoints, curve, error);
+ int i=0;
+ vector<Vec2d>::iterator v,vend;
+ for(v=curve.begin(),vend=curve.end();
+ v!=vend;
+ ++v)
+ {
+ if((i == 0) || (i%4 != 0))
+ AddControlPoint(*v);
+ ++i;
+ }
+}
+
+BezierCurve::~BezierCurve()
+{
+ if(_currentSegment)
+ delete _currentSegment;
+}
+
+void BezierCurve::AddControlPoint(const Vec2d& iPoint)
+{
+ _ControlPolygon.push_back(iPoint);
+ _currentSegment->AddControlPoint(iPoint);
+ if(_currentSegment->size() == 4)
+ {
+ _Segments.push_back(_currentSegment);
+ _currentSegment = new BezierCurveSegment;
+ _currentSegment->AddControlPoint(iPoint);
+ }
+}
+
+
diff --git a/source/blender/freestyle/intern/geometry/Bezier.h b/source/blender/freestyle/intern/geometry/Bezier.h
new file mode 100755
index 00000000000..acae71bbb2c
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Bezier.h
@@ -0,0 +1,73 @@
+//
+// Filename : Bezier.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a Bezier curve of order 4.
+// Date of creation : 04/06/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BEZIER_H
+# define BEZIER_H
+
+#include <vector>
+#include "../system/FreestyleConfig.h"
+#include "Geom.h"
+
+using namespace Geometry;
+
+class LIB_GEOMETRY_EXPORT BezierCurveSegment
+{
+private:
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<Vec2d> _Vertices;
+
+public:
+ BezierCurveSegment();
+ virtual ~BezierCurveSegment();
+
+ void AddControlPoint(const Vec2d& iPoint);
+ void Build();
+ inline int size() const {return _ControlPolygon.size();}
+ inline std::vector<Vec2d>& vertices() {return _Vertices;}
+};
+
+
+class LIB_GEOMETRY_EXPORT BezierCurve
+{
+private:
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<BezierCurveSegment*> _Segments;
+ BezierCurveSegment *_currentSegment;
+
+public:
+ BezierCurve();
+ BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0);
+ virtual ~BezierCurve();
+
+ void AddControlPoint(const Vec2d& iPoint);
+ std::vector<Vec2d>& controlPolygon() {return _ControlPolygon;}
+ std::vector<BezierCurveSegment*>& segments() {return _Segments;}
+};
+
+#endif // BEZIER_H
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.cpp b/source/blender/freestyle/intern/geometry/FastGrid.cpp
new file mode 100755
index 00000000000..325126b4b96
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FastGrid.cpp
@@ -0,0 +1,62 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "FastGrid.h"
+
+void FastGrid::clear() {
+ if(!_cells)
+ return;
+
+ for(unsigned i = 0; i < _cells_size; i++)
+ if (_cells[i])
+ delete _cells[i];
+ delete[] _cells;
+ _cells = NULL;
+ _cells_size = 0;
+
+ Grid::clear();
+}
+
+void FastGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) {
+ Grid::configure(orig, size, nb);
+ _cells_size = _cells_nb[0] * _cells_nb[1] * _cells_nb[2];
+ _cells = new Cell*[_cells_size];
+ memset(_cells, 0, _cells_size * sizeof(*_cells));
+}
+
+Cell* FastGrid::getCell(const Vec3u& p) {
+ //cout << _cells<< " "<< p << " " <<_cells_nb[0]<<"-"<< _cells_nb[1]<<"-"<< _cells_nb[2]<< " "<<_cells_size<< endl;
+ assert(_cells||("_cells is a null pointer"));
+ assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size);
+ assert(p[0]<_cells_nb[0]);
+ assert(p[1]<_cells_nb[1]);
+ assert(p[2]<_cells_nb[2]);
+ return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]];
+}
+
+void FastGrid::fillCell(const Vec3u& p, Cell& cell) {
+ assert(_cells||("_cells is a null pointer"));
+ assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size);
+ assert(p[0]<_cells_nb[0]);
+ assert(p[1]<_cells_nb[1]);
+ assert(p[2]<_cells_nb[2]);
+ _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
+}
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.h b/source/blender/freestyle/intern/geometry/FastGrid.h
new file mode 100755
index 00000000000..e620ff24385
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FastGrid.h
@@ -0,0 +1,85 @@
+//
+// Filename : FastGrid.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a cell grid surrounding the
+// bounding box of the scene
+// Date of creation : 30/07/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef FASTGRID_H
+# define FASTGRID_H
+
+# include "Grid.h"
+# include <cassert>
+/*! Class to define a regular grid used for ray
+ * casting computations
+ * We don't use a hashtable here. The grid is
+ * explicitly stored for faster computations.
+ * However, this might result in significant
+ * increase in memory usage (compared to the regular grid)
+ */
+
+class LIB_GEOMETRY_EXPORT FastGrid : public Grid
+{
+ public:
+
+ FastGrid() : Grid() {
+ _cells = NULL;
+ _cells_size = 0;
+ }
+
+ virtual ~FastGrid() {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable,
+ * resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns the cell whose coordinates are pased as argument */
+ Cell* getCell(const Vec3u& p) ;
+
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u& p, Cell& cell);
+
+protected:
+
+ Cell** _cells;
+ unsigned _cells_size;
+};
+
+#endif // FASTGRID_H
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp
new file mode 100755
index 00000000000..7754fcda32b
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp
@@ -0,0 +1,603 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <cstdlib> // for malloc and free
+#include <stdio.h>
+#include <math.h>
+#include "FitCurve.h"
+
+using namespace std;
+
+typedef Vector2 *BezierCurve;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Forward declarations */
+static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve);
+static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u);
+static Vector2 BezierII(int degree, Vector2 *V, double t);
+static double B0(double u);
+static double B1(double u);
+static double B2(double u);
+static double B3(double u);
+static Vector2 ComputeLeftTangent(Vector2 *d, int end);
+static Vector2 ComputeLeftTangent(Vector2 *d, int end);
+static Vector2 ComputeLeftTangent(Vector2 *d, int end);
+static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint);
+static double *ChordLengthParameterize(Vector2 *d, int first, int last);
+static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2);
+static Vector2 V2AddII(Vector2 a, Vector2 b);
+static Vector2 V2ScaleIII(Vector2 v, double s);
+static Vector2 V2SubII(Vector2 a, Vector2 b);
+
+
+#define MAXPOINTS 1000 /* The most points you can have */
+
+/* returns squared length of input vector */
+double V2SquaredLength(Vector2 *a)
+{ return(((*a)[0] * (*a)[0])+((*a)[1] * (*a)[1]));
+}
+
+/* returns length of input vector */
+double V2Length(Vector2 *a)
+{
+ return(sqrt(V2SquaredLength(a)));
+}
+
+Vector2 *V2Scale(Vector2 *v, double newlen)
+{
+ double len = V2Length(v);
+ if (len != 0.0) { (*v)[0] *= newlen/len; (*v)[1] *= newlen/len; }
+ return(v);
+}
+
+/* return the dot product of vectors a and b */
+double V2Dot(Vector2 *a, Vector2 *b)
+{
+ return(((*a)[0]*(*b)[0])+((*a)[1]*(*b)[1]));
+}
+
+/* return the distance between two points */
+double V2DistanceBetween2Points(Vector2 *a, Vector2 *b)
+{
+double dx = (*a)[0] - (*b)[0];
+double dy = (*a)[1] - (*b)[1];
+ return(sqrt((dx*dx)+(dy*dy)));
+}
+
+/* return vector sum c = a+b */
+Vector2 *V2Add(Vector2 *a, Vector2 *b, Vector2 *c)
+{
+ (*c)[0] = (*a)[0]+(*b)[0]; (*c)[1] = (*a)[1]+(*b)[1];
+ return(c);
+}
+
+/* normalizes the input vector and returns it */
+Vector2 *V2Normalize(Vector2 *v)
+{
+double len = V2Length(v);
+ if (len != 0.0) { (*v)[0] /= len; (*v)[1] /= len; }
+ return(v);
+}
+
+/* negates the input vector and returns it */
+Vector2 *V2Negate(Vector2 *v)
+{
+ (*v)[0] = -(*v)[0]; (*v)[1] = -(*v)[1];
+ return(v);
+}
+
+
+/*
+ * GenerateBezier :
+ * Use least-squares method to find Bezier control points for region.
+ *
+ */
+static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2)
+// Vector2 *d; /* Array of digitized points */
+// int first, last; /* Indices defining region */
+// double *uPrime; /* Parameter values for region */
+// Vector2 tHat1, tHat2; /* Unit tangents at endpoints */
+{
+ int i;
+ Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */
+ int nPts; /* Number of pts in sub-curve */
+ double C[2][2]; /* Matrix C */
+ double X[2]; /* Matrix X */
+ double det_C0_C1, /* Determinants of matrices */
+ det_C0_X,
+ det_X_C1;
+ double alpha_l, /* Alpha values, left and right */
+ alpha_r;
+ Vector2 tmp; /* Utility variable */
+ BezierCurve bezCurve; /* RETURN bezier curve ctl pts */
+
+ bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
+ nPts = last - first + 1;
+
+
+ /* Compute the A's */
+ for (i = 0; i < nPts; i++) {
+ Vector2 v1, v2;
+ v1 = tHat1;
+ v2 = tHat2;
+ V2Scale(&v1, B1(uPrime[i]));
+ V2Scale(&v2, B2(uPrime[i]));
+ A[i][0] = v1;
+ A[i][1] = v2;
+ }
+
+ /* Create the C and X matrices */
+ C[0][0] = 0.0;
+ C[0][1] = 0.0;
+ C[1][0] = 0.0;
+ C[1][1] = 0.0;
+ X[0] = 0.0;
+ X[1] = 0.0;
+
+ for (i = 0; i < nPts; i++) {
+ C[0][0] += V2Dot(&A[i][0], &A[i][0]);
+ C[0][1] += V2Dot(&A[i][0], &A[i][1]);
+/* C[1][0] += V2Dot(&A[i][0], &A[i][1]);*/
+ C[1][0] = C[0][1];
+ C[1][1] += V2Dot(&A[i][1], &A[i][1]);
+
+ tmp = V2SubII(d[first + i],
+ V2AddII(
+ V2ScaleIII(d[first], B0(uPrime[i])),
+ V2AddII(
+ V2ScaleIII(d[first], B1(uPrime[i])),
+ V2AddII(
+ V2ScaleIII(d[last], B2(uPrime[i])),
+ V2ScaleIII(d[last], B3(uPrime[i]))))));
+
+
+ X[0] += V2Dot(&((A[i])[0]), &tmp);
+ X[1] += V2Dot(&((A[i])[1]), &tmp);
+ }
+
+ /* Compute the determinants of C and X */
+ det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
+ det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
+ det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
+
+ /* Finally, derive alpha values */
+ if (det_C0_C1 == 0.0) {
+ det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
+ }
+ alpha_l = det_X_C1 / det_C0_C1;
+ alpha_r = det_C0_X / det_C0_C1;
+
+
+ /* If alpha negative, use the Wu/Barsky heuristic (see text) */
+ /* (if alpha is 0, you get coincident control points that lead to
+ * divide by zero in any subsequent NewtonRaphsonRootFind() call. */
+ if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
+ double dist = V2DistanceBetween2Points(&d[last], &d[first]) /
+ 3.0;
+
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&(bezCurve[0]), V2Scale(&(tHat1), dist), &(bezCurve[1]));
+ V2Add(&(bezCurve[3]), V2Scale(&(tHat2), dist), &(bezCurve[2]));
+ return (bezCurve);
+ }
+
+ /* First and last control points of the Bezier curve are */
+ /* positioned exactly at the first and last data points */
+ /* Control points 1 and 2 are positioned an alpha distance out */
+ /* on the tangent vectors, left and right, respectively */
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]);
+ V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]);
+ return (bezCurve);
+}
+
+
+/*
+ * Reparameterize:
+ * Given set of points and their parameterization, try to find
+ * a better parameterization.
+ *
+ */
+static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve)
+// Vector2 *d; /* Array of digitized points */
+// int first, last; /* Indices defining region */
+// double *u; /* Current parameter values */
+// BezierCurve bezCurve; /* Current fitted curve */
+{
+ int nPts = last-first+1;
+ int i;
+ double *uPrime; /* New parameter values */
+
+ uPrime = (double *)malloc(nPts * sizeof(double));
+ for (i = first; i <= last; i++) {
+ uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i-
+ first]);
+ }
+ return (uPrime);
+}
+
+
+
+/*
+ * NewtonRaphsonRootFind :
+ * Use Newton-Raphson iteration to find better root.
+ */
+static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u)
+// BezierCurve Q; /* Current fitted curve */
+// Vector2 P; /* Digitized point */
+// double u; /* Parameter value for "P" */
+{
+ double numerator, denominator;
+ Vector2 Q1[3], Q2[2]; /* Q' and Q'' */
+ Vector2 Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q'' */
+ double uPrime; /* Improved u */
+ int i;
+
+ /* Compute Q(u) */
+ Q_u = BezierII(3, Q, u);
+
+ /* Generate control vertices for Q' */
+ for (i = 0; i <= 2; i++) {
+ Q1[i][0] = (Q[i+1][0] - Q[i][0]) * 3.0;
+ Q1[i][1] = (Q[i+1][1] - Q[i][1]) * 3.0;
+ }
+
+ /* Generate control vertices for Q'' */
+ for (i = 0; i <= 1; i++) {
+ Q2[i][0] = (Q1[i+1][0] - Q1[i][0]) * 2.0;
+ Q2[i][1] = (Q1[i+1][1] - Q1[i][1]) * 2.0;
+ }
+
+ /* Compute Q'(u) and Q''(u) */
+ Q1_u = BezierII(2, Q1, u);
+ Q2_u = BezierII(1, Q2, u);
+
+ /* Compute f(u)/f'(u) */
+ numerator = (Q_u[0] - P[0]) * (Q1_u[0]) + (Q_u[1] - P[1]) * (Q1_u[1]);
+ denominator = (Q1_u[0]) * (Q1_u[0]) + (Q1_u[1]) * (Q1_u[1]) +
+ (Q_u[0] - P[0]) * (Q2_u[0]) + (Q_u[1] - P[1]) * (Q2_u[1]);
+
+ /* u = u - f(u)/f'(u) */
+ if(denominator == 0) // FIXME
+ return u;
+ uPrime = u - (numerator/denominator);
+ return (uPrime);
+}
+
+
+
+/*
+ * Bezier :
+ * Evaluate a Bezier curve at a particular parameter value
+ *
+ */
+static Vector2 BezierII(int degree, Vector2 *V, double t)
+// int degree; /* The degree of the bezier curve */
+// Vector2 *V; /* Array of control points */
+// double t; /* Parametric value to find point for */
+{
+ int i, j;
+ Vector2 Q; /* Point on curve at parameter t */
+ Vector2 *Vtemp; /* Local copy of control points */
+
+ /* Copy array */
+ Vtemp = (Vector2 *)malloc((unsigned)((degree+1)
+ * sizeof (Vector2)));
+ for (i = 0; i <= degree; i++) {
+ Vtemp[i] = V[i];
+ }
+
+ /* Triangle computation */
+ for (i = 1; i <= degree; i++) {
+ for (j = 0; j <= degree-i; j++) {
+ Vtemp[j][0] = (1.0 - t) * Vtemp[j][0] + t * Vtemp[j+1][0];
+ Vtemp[j][1] = (1.0 - t) * Vtemp[j][1] + t * Vtemp[j+1][1];
+ }
+ }
+
+ Q = Vtemp[0];
+ free((void *)Vtemp);
+ return Q;
+}
+
+
+/*
+ * B0, B1, B2, B3 :
+ * Bezier multipliers
+ */
+static double B0(double u)
+{
+ double tmp = 1.0 - u;
+ return (tmp * tmp * tmp);
+}
+
+
+static double B1(double u)
+{
+ double tmp = 1.0 - u;
+ return (3 * u * (tmp * tmp));
+}
+
+static double B2(double u)
+{
+ double tmp = 1.0 - u;
+ return (3 * u * u * tmp);
+}
+
+static double B3(double u)
+{
+ return (u * u * u);
+}
+
+
+
+/*
+ * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent :
+ *Approximate unit tangents at endpoints and "center" of digitized curve
+ */
+static Vector2 ComputeLeftTangent(Vector2 *d, int end)
+// Vector2 *d; /* Digitized points*/
+// int end; /* Index to "left" end of region */
+{
+ Vector2 tHat1;
+ tHat1 = V2SubII(d[end+1], d[end]);
+ tHat1 = *V2Normalize(&tHat1);
+ return tHat1;
+}
+
+static Vector2 ComputeRightTangent(Vector2 *d, int end)
+// Vector2 *d; /* Digitized points */
+// int end; /* Index to "right" end of region */
+{
+ Vector2 tHat2;
+ tHat2 = V2SubII(d[end-1], d[end]);
+ tHat2 = *V2Normalize(&tHat2);
+ return tHat2;
+}
+
+static Vector2 ComputeCenterTangent(Vector2 *d, int center)
+// Vector2 *d; /* Digitized points */
+// int center; /* Index to point inside region */
+{
+ Vector2 V1, V2, tHatCenter;
+
+ V1 = V2SubII(d[center-1], d[center]);
+ V2 = V2SubII(d[center], d[center+1]);
+ tHatCenter[0] = (V1[0] + V2[0])/2.0;
+ tHatCenter[1] = (V1[1] + V2[1])/2.0;
+ tHatCenter = *V2Normalize(&tHatCenter);
+ return tHatCenter;
+}
+
+
+/*
+ * ChordLengthParameterize :
+ * Assign parameter values to digitized points
+ * using relative distances between points.
+ */
+static double *ChordLengthParameterize(Vector2 *d, int first, int last)
+// Vector2 *d; /* Array of digitized points */
+// int first, last; /* Indices defining region */
+{
+ int i;
+ double *u; /* Parameterization */
+
+ u = (double *)malloc((unsigned)(last-first+1) * sizeof(double));
+
+ u[0] = 0.0;
+ for (i = first+1; i <= last; i++) {
+ u[i-first] = u[i-first-1] +
+ V2DistanceBetween2Points(&d[i], &d[i-1]);
+ }
+
+ for (i = first + 1; i <= last; i++) {
+ u[i-first] = u[i-first] / u[last-first];
+ }
+
+ return(u);
+}
+
+
+
+
+/*
+ * ComputeMaxError :
+ * Find the maximum squared distance of digitized points
+ * to fitted curve.
+*/
+static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint)
+// Vector2 *d; /* Array of digitized points */
+// int first, last; /* Indices defining region */
+// BezierCurve bezCurve; /* Fitted Bezier curve */
+// double *u; /* Parameterization of points */
+// int *splitPoint; /* Point of maximum error */
+{
+ int i;
+ double maxDist; /* Maximum error */
+ double dist; /* Current error */
+ Vector2 P; /* Point on curve */
+ Vector2 v; /* Vector from point to curve */
+
+ *splitPoint = (last - first + 1)/2;
+ maxDist = 0.0;
+ for (i = first + 1; i < last; i++) {
+ P = BezierII(3, bezCurve, u[i-first]);
+ v = V2SubII(P, d[i]);
+ dist = V2SquaredLength(&v);
+ if (dist >= maxDist) {
+ maxDist = dist;
+ *splitPoint = i;
+ }
+ }
+ return (maxDist);
+}
+static Vector2 V2AddII(Vector2 a, Vector2 b)
+{
+ Vector2 c;
+ c[0] = a[0] + b[0]; c[1] = a[1] + b[1];
+ return (c);
+}
+static Vector2 V2ScaleIII(Vector2 v, double s)
+{
+ Vector2 result;
+ result[0] = v[0] * s; result[1] = v[1] * s;
+ return (result);
+}
+
+static Vector2 V2SubII(Vector2 a, Vector2 b)
+{
+ Vector2 c;
+ c[0] = a[0] - b[0]; c[1] = a[1] - b[1];
+ return (c);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+//------------------------- WRAPPER -----------------------------//
+
+FitCurveWrapper::FitCurveWrapper()
+{
+}
+
+FitCurveWrapper::~FitCurveWrapper()
+{
+ _vertices.clear();
+}
+
+void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve )
+{
+ for(int i=0; i<n+1; ++i)
+ _vertices.push_back(curve[i]);
+}
+
+void FitCurveWrapper::FitCurve(vector<Vec2d>& data, vector<Vec2d>& oCurve, double error)
+{
+ int size = data.size();
+ Vector2 *d = new Vector2[size];
+ for(int i=0; i<size; ++i)
+ {
+ d[i][0] = data[i][0];
+ d[i][1] = data[i][1];
+ }
+
+ FitCurve(d,size,error);
+
+ // copy results
+ for(vector<Vector2>::iterator v=_vertices.begin(), vend=_vertices.end();
+ v!=vend;
+ ++v)
+ {
+ oCurve.push_back(Vec2d(v->x(), v->y())) ;
+ }
+
+}
+
+void FitCurveWrapper::FitCurve(Vector2 *d, int nPts, double error)
+{
+ Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */
+
+ tHat1 = ComputeLeftTangent(d, 0);
+ tHat2 = ComputeRightTangent(d, nPts - 1);
+ FitCubic(d, 0, nPts - 1, tHat1, tHat2, error);
+}
+
+void FitCurveWrapper::FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error)
+{
+ BezierCurve bezCurve; /*Control points of fitted Bezier curve*/
+ double *u; /* Parameter values for point */
+ double *uPrime; /* Improved parameter values */
+ double maxError; /* Maximum fitting error */
+ int splitPoint; /* Point to split point set at */
+ int nPts; /* Number of points in subset */
+ double iterationError; /*Error below which you try iterating */
+ int maxIterations = 4; /* Max times to try iterating */
+ Vector2 tHatCenter; /* Unit tangent vector at splitPoint */
+ int i;
+
+ iterationError = error * error;
+ nPts = last - first + 1;
+
+ /* Use heuristic if region only has two points in it */
+ if (nPts == 2) {
+ double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
+
+ bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
+ V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
+ DrawBezierCurve(3, bezCurve);
+ free((void *)bezCurve);
+ return;
+ }
+
+ /* Parameterize points, and attempt to fit curve */
+ u = ChordLengthParameterize(d, first, last);
+ bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
+
+ /* Find max deviation of points to fitted curve */
+ maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
+ if (maxError < error) {
+ DrawBezierCurve(3, bezCurve);
+ free((void *)u);
+ free((void *)bezCurve);
+ return;
+ }
+
+
+ /* If error not too large, try some reparameterization */
+ /* and iteration */
+ if (maxError < iterationError) {
+ for (i = 0; i < maxIterations; i++) {
+ uPrime = Reparameterize(d, first, last, u, bezCurve);
+ bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
+ maxError = ComputeMaxError(d, first, last,
+ bezCurve, uPrime, &splitPoint);
+ if (maxError < error) {
+ DrawBezierCurve(3, bezCurve);
+ free((void *)u);
+ free((void *)bezCurve);
+ return;
+ }
+ free((void *)u);
+ u = uPrime;
+ }
+ }
+
+ /* Fitting failed -- split at max error point and fit recursively */
+ free((void *)u);
+ free((void *)bezCurve);
+ tHatCenter = ComputeCenterTangent(d, splitPoint);
+ FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
+ V2Negate(&tHatCenter);
+ FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
+
+}
+
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.h b/source/blender/freestyle/intern/geometry/FitCurve.h
new file mode 100755
index 00000000000..ed7cbe34780
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FitCurve.h
@@ -0,0 +1,101 @@
+//
+// Filename : FitCurve.h
+// Author(s) : Stephane Grabli
+// Purpose : An Algorithm for Automatically Fitting Digitized Curves
+// by Philip J. Schneider
+// from "Graphics Gems", Academic Press, 1990
+// Date of creation : 06/06/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef FITCURVE_H
+# define FITCURVE_H
+
+#include <vector>
+#include "../system/FreestyleConfig.h"
+#include "Geom.h"
+
+using namespace Geometry;
+
+typedef struct Point2Struct { /* 2d point */
+ double coordinates[2];
+ Point2Struct() {coordinates[0]=0;coordinates[1]=0;}
+ inline double operator[](const int i) const
+ {
+ return coordinates[i];
+ }
+ inline double& operator[](const int i)
+ {
+ return coordinates[i];
+ }
+ inline double x() const {return coordinates[0];}
+ inline double y() const {return coordinates[1];}
+ } Point2;
+
+typedef Point2 Vector2;
+
+
+
+class LIB_GEOMETRY_EXPORT FitCurveWrapper
+{
+private:
+ std::vector<Vector2> _vertices;
+
+public:
+ FitCurveWrapper();
+ ~FitCurveWrapper();
+
+ /*! Fits a set of 2D data points to a set of Bezier Curve segments
+ * data
+ * Input data points
+ * oCurve
+ * Control points of the sets of bezier curve segments.
+ * Each segment is made of 4 points (polynomial degree of curve = 3)
+ * error
+ * max error tolerance between resulting curve and input data
+ */
+ void FitCurve(std::vector<Vec2d>& data, std::vector<Vec2d>& oCurve, double error);
+protected:
+ /* Vec2d *d; Array of digitized points */
+ /* int nPts; Number of digitized points */
+ /* double error; User-defined error squared */
+ void FitCurve(Vector2 *d, int nPts, double error);
+
+ /*! Draws a Bezier curve segment
+ * n
+ * degree of curve (=3)
+ * curve
+ * bezier segments control points
+ */
+ void DrawBezierCurve(int n, Vector2 *curve);
+
+ /* Vec2d *d; Array of digitized points */
+ /* int first, last; Indices of first and last pts in region */
+ /* Vec2d tHat1, tHat2; Unit tangent vectors at endpoints */
+ /* double error; User-defined error squared */
+ void FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error);
+
+};
+
+#endif // FITCURVE_H
diff --git a/source/blender/freestyle/intern/geometry/Geom.h b/source/blender/freestyle/intern/geometry/Geom.h
new file mode 100755
index 00000000000..ac94213fe98
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Geom.h
@@ -0,0 +1,78 @@
+//
+// Filename : Geom.h
+// Author(s) : Sylvain Paris
+// Emmanuel Turquin
+// Stephane Grabli
+// Purpose : Vectors and Matrices (useful type definitions)
+// Date of creation : 20/05/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GEOM_H
+# define GEOM_H
+
+# include "VecMat.h"
+# include "../system/Precision.h"
+
+namespace Geometry {
+
+ typedef VecMat::Vec2<unsigned> Vec2u;
+ typedef VecMat::Vec2<int> Vec2i;
+ typedef VecMat::Vec2<float> Vec2f;
+ typedef VecMat::Vec2<double> Vec2d;
+ typedef VecMat::Vec2<real> Vec2r;
+
+ typedef VecMat::Vec3<unsigned> Vec3u;
+ typedef VecMat::Vec3<int> Vec3i;
+ typedef VecMat::Vec3<float> Vec3f;
+ typedef VecMat::Vec3<double> Vec3d;
+ typedef VecMat::Vec3<real> Vec3r;
+
+ typedef VecMat::HVec3<unsigned> HVec3u;
+ typedef VecMat::HVec3<int> HVec3i;
+ typedef VecMat::HVec3<float> HVec3f;
+ typedef VecMat::HVec3<double> HVec3d;
+ typedef VecMat::HVec3<real> HVec3r;
+
+ typedef VecMat::SquareMatrix<unsigned, 2> Matrix22u;
+ typedef VecMat::SquareMatrix<int, 2> Matrix22i;
+ typedef VecMat::SquareMatrix<float, 2> Matrix22f;
+ typedef VecMat::SquareMatrix<double, 2> Matrix22d;
+ typedef VecMat::SquareMatrix<real, 2> Matrix22r;
+
+ typedef VecMat::SquareMatrix<unsigned, 3> Matrix33u;
+ typedef VecMat::SquareMatrix<int, 3> Matrix33i;
+ typedef VecMat::SquareMatrix<float, 3> Matrix33f;
+ typedef VecMat::SquareMatrix<double, 3> Matrix33d;
+ typedef VecMat::SquareMatrix<real, 3> Matrix33r;
+
+ typedef VecMat::SquareMatrix<unsigned, 4> Matrix44u;
+ typedef VecMat::SquareMatrix<int, 4> Matrix44i;
+ typedef VecMat::SquareMatrix<float, 4> Matrix44f;
+ typedef VecMat::SquareMatrix<double, 4> Matrix44d;
+ typedef VecMat::SquareMatrix<real, 4> Matrix44r;
+
+} // end of namespace Geometry
+
+#endif // GEOM_H
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
new file mode 100755
index 00000000000..c148c521a46
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
@@ -0,0 +1,240 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//#if defined(__GNUC__) && (__GNUC__ >= 3)
+//// hash_map is not part of the C++ standard anymore;
+//// hash_map.h has been kept though for backward compatibility
+//# include <hash_map.h>
+//#else
+//# include <hash_map>
+//#endif
+
+#include <stdio.h>
+#include <list>
+#include <map>
+#include "../system/TimeUtils.h"
+#include "GeomCleaner.h"
+
+using namespace std;
+
+
+void GeomCleaner::SortIndexedVertexArray( const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices,
+ unsigned **oIndices)
+{
+ // First, we build a list of IndexVertex:
+ list<IndexedVertex> indexedVertices;
+ unsigned i;
+ for(i=0; i<iVSize; i+= 3)
+ {
+ indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]), i/3));
+ }
+
+ // q-sort
+ indexedVertices.sort();
+
+ // build the indices mapping array:
+ unsigned *mapIndices = new unsigned[iVSize/3];
+ *oVertices = new real[iVSize];
+ list<IndexedVertex>::iterator iv;
+ unsigned newIndex = 0;
+ unsigned vIndex = 0;
+ for(iv=indexedVertices.begin(); iv!=indexedVertices.end(); iv++)
+ {
+ // Build the final results:
+ (*oVertices)[vIndex] = iv->x();
+ (*oVertices)[vIndex+1] = iv->y();
+ (*oVertices)[vIndex+2] = iv->z();
+
+ mapIndices[iv->index()] = newIndex;
+ newIndex++;
+ vIndex+=3;
+ }
+
+
+ // Build the final index array:
+ *oIndices = new unsigned[iISize];
+ for(i=0; i<iISize; i++)
+ {
+ (*oIndices)[i] = 3*mapIndices[iIndices[i]/3];
+ }
+
+ delete [] mapIndices;
+}
+
+void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices)
+{
+ // First, we build a list of IndexVertex:
+ vector<Vec3r> vertices;
+ unsigned i;
+ for(i=0; i<iVSize; i+= 3)
+ {
+ vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]));
+ }
+
+ unsigned *mapVertex = new unsigned[iVSize];
+ vector<Vec3r>::iterator v = vertices.begin();
+
+ vector<Vec3r> compressedVertices;
+ Vec3r previous = *v;
+ mapVertex[0] = 0;
+ compressedVertices.push_back(vertices.front());
+
+ v++;
+ Vec3r current;
+ i=1;
+ for(; v!=vertices.end(); v++)
+ {
+ current = *v;
+ if(current == previous)
+ mapVertex[i] = compressedVertices.size()-1;
+ else
+ {
+ compressedVertices.push_back(current);
+ mapVertex[i] = compressedVertices.size()-1;
+ }
+ previous = current;
+ i++;
+ }
+
+ // Builds the resulting vertex array:
+ *oVSize = 3*compressedVertices.size();
+ *oVertices = new real [*oVSize];
+ i=0;
+ for(v=compressedVertices.begin(); v!=compressedVertices.end(); v++)
+ {
+ (*oVertices)[i] = (*v)[0];
+ (*oVertices)[i+1] = (*v)[1];
+ (*oVertices)[i+2] = (*v)[2];
+ i += 3;
+ }
+
+ // Map the index array:
+ *oIndices = new unsigned[iISize];
+ for(i=0; i<iISize; i++)
+ {
+ (*oIndices)[i] = 3*mapVertex[iIndices[i]/3];
+ }
+
+ delete [] mapVertex;
+}
+
+void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices)
+{
+
+ // tmp arrays used to store the sorted data:
+ real *tmpVertices;
+ unsigned *tmpIndices;
+
+ Chronometer chrono;
+ // Sort data
+ chrono.start();
+ GeomCleaner::SortIndexedVertexArray(iVertices, iVSize,
+ iIndices, iISize,
+ &tmpVertices, &tmpIndices
+ );
+ printf("Sorting: %lf\n", chrono.stop());
+
+ // compress data
+ chrono.start();
+ GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize,
+ tmpIndices, iISize,
+ oVertices, oVSize,
+ oIndices);
+ printf("Merging: %lf\n", chrono.stop());
+
+ // deallocates memory:
+ delete [] tmpVertices;
+ delete [] tmpIndices;
+}
+
+/*! Defines a hash table used for searching the Cells */
+struct GeomCleanerHasher{
+#define _MUL 950706376UL
+#define _MOD 2147483647UL
+ inline size_t operator() (const Vec3r& p) const {
+ size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
+ }
+};
+
+void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices)
+{
+ typedef map<Vec3r, unsigned> cleanHashTable;
+ vector<Vec3r> vertices;
+ unsigned i;
+ for(i=0; i<iVSize; i+= 3)
+ vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]));
+
+ cleanHashTable ht;
+ vector<unsigned> newIndices;
+ vector<Vec3r> newVertices;
+
+ // elimination of needless points
+ unsigned currentIndex = 0;
+ vector<Vec3r>::const_iterator v = vertices.begin();
+ vector<Vec3r>::const_iterator end = vertices.end();
+ cleanHashTable::const_iterator found;
+ for(; v!=end; v++)
+ {
+ found = ht.find(*v);
+ if(found != ht.end())
+ {
+ // The vertex is already in the new array.
+ newIndices.push_back((*found).second);
+ }
+ else
+ {
+ newVertices.push_back(*v);
+ newIndices.push_back(currentIndex);
+ ht[*v] = currentIndex;
+ currentIndex++;
+ }
+ }
+
+ // creation of oVertices array:
+ *oVSize = 3*newVertices.size();
+ *oVertices = new real[*oVSize];
+ currentIndex = 0;
+ end = newVertices.end();
+ for(v=newVertices.begin(); v!=end ; v++)
+ {
+ (*oVertices)[currentIndex++] = (*v)[0];
+ (*oVertices)[currentIndex++] = (*v)[1];
+ (*oVertices)[currentIndex++] = (*v)[2];
+ }
+
+ // map new indices:
+ *oIndices = new unsigned[iISize];
+ for(i=0; i<iISize; i++)
+ (*oIndices)[i] = 3*newIndices[iIndices[i]/3];
+}
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.h b/source/blender/freestyle/intern/geometry/GeomCleaner.h
new file mode 100755
index 00000000000..5fdfda0162a
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.h
@@ -0,0 +1,219 @@
+//
+// Filename : GeomCleaner.h
+// Author : Stephane Grabli
+// Purpose : Class to define a cleaner of geometry providing
+// a set of useful tools
+// Date of creation : 04/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GEOMCLEANER_H
+# define GEOMCLEANER_H
+
+# include "../system/FreestyleConfig.h"
+# include "Geom.h"
+
+using namespace Geometry;
+
+class LIB_GEOMETRY_EXPORT GeomCleaner
+{
+public:
+
+ inline GeomCleaner() {}
+ inline ~GeomCleaner() {}
+
+ /*! Sorts an array of Indexed vertices
+ * iVertices
+ * Array of vertices to sort. It is organized as a
+ * float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer
+ * to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * Output of sorted vertices. A vertex v1 precedes another one
+ * v2 in this array if v1.x<v2.x, or v1.x=v2.x && v1.y < v2.y
+ * or v1.x=v2.y && v1.y=v2.y && v1.z < v2.z.
+ * The array is organized as a 3-float serie giving
+ * the vertices coordinates: XYZXYZXYZ...
+ * oIndices
+ * Output corresponding to the iIndices array but
+ * reorganized in order to match the sorted vertex array.
+ */
+
+ static void SortIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices,
+ unsigned **oIndices);
+
+ /*! Compress a SORTED indexed vertex array by eliminating
+ * multiple appearing occurences of a single vertex.
+ * iVertices
+ * The SORTED vertex array to compress. It is organized as a
+ * float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer
+ * to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the compression.
+ * The array is organized as a 3-float serie giving
+ * the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the compressed
+ * oVertices array.
+ */
+
+ static void CompressIndexedVertexArray(const real *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices);
+
+ /*! Sorts and compress an array of indexed vertices.
+ * iVertices
+ * The vertex array to sort then compress. It is organized as a
+ * float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer
+ * to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the sorting-compression.
+ * The array is organized as a 3-float serie giving
+ * the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the sorted and compressed
+ * oVertices array.
+ */
+
+ static void SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices);
+
+ /*! Cleans an indexed vertex array. (Identical to
+ * SortAndCompress except that we use here a hash
+ * table to create the new array.)
+ * iVertices
+ * The vertex array to sort then compress. It is organized as a
+ * float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer
+ * to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the sorting-compression.
+ * The array is organized as a 3-float serie giving
+ * the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the sorted and compressed
+ * oVertices array.
+ */
+
+ static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices);
+};
+
+
+/*! Binary operators */
+//inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
+
+/*! Class Indexed Vertex. Used to represent
+ * an indexed vertex by storing the vertex
+ * coordinates as well as its index
+ */
+class IndexedVertex
+{
+public:
+
+private:
+ Vec3r _Vector;
+ unsigned _index;
+public:
+ inline IndexedVertex() {}
+ inline IndexedVertex(Vec3r iVector, unsigned iIndex)
+ {
+ _Vector = iVector;
+ _index = iIndex;
+ }
+ /*! accessors */
+ inline const Vec3r& vector() const {return _Vector;}
+ inline unsigned index() {return _index;}
+ inline real x() {return _Vector[0];}
+ inline real y() {return _Vector[1];}
+ inline real z() {return _Vector[2];}
+
+ /*! modifiers */
+ inline void setVector(const Vec3r& iVector) {_Vector = iVector;}
+ inline void setIndex(unsigned iIndex) {_index = iIndex;}
+
+ /*! operators */
+ IndexedVertex& operator=(const IndexedVertex& iv)
+ {
+ _Vector = iv._Vector;
+ _index = iv._index;
+ return *this;
+ }
+ inline real operator[](const unsigned i) {return _Vector[i];}
+ //friend inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
+ inline bool operator<(const IndexedVertex& v) const
+ {
+ return (_Vector < v._Vector);
+ }
+ inline bool operator==(const IndexedVertex& v)
+ {
+ return (_Vector == v._Vector);
+ }
+};
+
+//bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2)
+//{
+// return iv1.operator<(iv2);
+//}
+
+#endif // GEOMCLEANER_H
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
new file mode 100755
index 00000000000..853f8cf82b5
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
@@ -0,0 +1,753 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "GeomUtils.h"
+
+namespace GeomUtils {
+
+ // This internal procedure is defined below.
+ bool intersect2dSegPoly(Vec2r* seg,
+ Vec2r* poly,
+ unsigned n);
+
+ bool intersect2dSeg2dArea(const Vec2r& min,
+ const Vec2r& max,
+ const Vec2r& A,
+ const Vec2r& B) {
+ Vec2r seg[2];
+ seg[0] = A;
+ seg[1] = B;
+
+ Vec2r poly[5];
+ poly[0][0] = min[0];
+ poly[0][1] = min[1];
+ poly[1][0] = max[0];
+ poly[1][1] = min[1];
+ poly[2][0] = max[0];
+ poly[2][1] = max[1];
+ poly[3][0] = min[0];
+ poly[3][1] = max[1];
+ poly[4][0] = min[0];
+ poly[4][1] = min[1];
+
+ return intersect2dSegPoly(seg, poly, 4);
+ }
+
+ bool include2dSeg2dArea(const Vec2r& min,
+ const Vec2r& max,
+ const Vec2r& A,
+ const Vec2r& B) {
+ if((((max[0] > A[0])&&(A[0] > min[0]))&&((max[0] > B[0])&&(B[0] > min[0])))
+ && (((max[1] > A[1])&&(A[1] > min[1]))&&((max[1] > B[1])&&(B[1] > min[1]))))
+ return true;
+ return false;
+ }
+
+ intersection_test intersect2dSeg2dSeg(const Vec2r& p1,
+ const Vec2r& p2,
+ const Vec2r& p3,
+ const Vec2r& p4,
+ Vec2r& res) {
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real r1, r2, r3, r4; // 'Sign' values
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2
+ // is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute r3 and r4.
+ r3 = a1 * p3[0] + b1 * p3[1] + c1;
+ r4 = a1 * p4[0] + b1 * p4[1] + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on
+ // same side of line 1, the line segments do not intersect.
+ if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Compute r1 and r2
+ r1 = a2 * p1[0] + b2 * p1[1] + c2;
+ r2 = a2 * p2[0] + b2 * p2[1] + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie
+ // on same side of second line segment, the line segments do
+ // not intersect.
+ if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < M_EPSILON)
+ return (COLINEAR);
+
+ num = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
+
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
+
+ return (DO_INTERSECT);
+ }
+
+ intersection_test intersect2dLine2dLine(const Vec2r& p1,
+ const Vec2r& p2,
+ const Vec2r& p3,
+ const Vec2r& p4,
+ Vec2r& res) {
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2
+ // is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < M_EPSILON)
+ return (COLINEAR);
+
+ num = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
+
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
+
+ return (DO_INTERSECT);
+ }
+
+ intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1,
+ const Vec2r& p2,
+ const Vec2r& p3,
+ const Vec2r& p4,
+ real& t,
+ real& u,
+ real epsilon) {
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real r1, r2, r3, r4; // 'Sign' values
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2
+ // is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute r3 and r4.
+ r3 = a1 * p3[0] + b1 * p3[1] + c1;
+ r4 = a1 * p4[0] + b1 * p4[1] + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on
+ // same side of line 1, the line segments do not intersect.
+ if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Compute r1 and r2
+ r1 = a2 * p1[0] + b2 * p1[1] + c2;
+ r2 = a2 * p2[0] + b2 * p2[1] + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie
+ // on same side of second line segment, the line segments do
+ // not intersect.
+ if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < epsilon)
+ return (COLINEAR);
+
+ real d1, d2, e1;
+
+ d1 = p1[1] - p3[1];
+ d2 = p2[1] - p1[1];
+ e1 = p1[0] - p3[0];
+
+ num = -b2 * d1 - a2 * e1;
+ t = num / denom;
+
+ num = -b1 * d1 - a1 * e1;
+ u = num / denom;
+
+ return (DO_INTERSECT);
+ }
+
+ // AABB-triangle overlap test code
+ // by Tomas Akenine-Möller
+ // Function: int triBoxOverlap(real boxcenter[3],
+ // real boxhalfsize[3],real triverts[3][3]);
+ // History:
+ // 2001-03-05: released the code in its first version
+ // 2001-06-18: changed the order of the tests, faster
+ //
+ // Acknowledgement: Many thanks to Pierre Terdiman for
+ // suggestions and discussions on how to optimize code.
+ // Thanks to David Hunt for finding a ">="-bug!
+
+#define X 0
+#define Y 1
+#define Z 2
+
+#define FINDMINMAX(x0, x1, x2, min, max) \
+ min = max = x0; \
+ if(x1<min) min=x1; \
+ if(x1>max) max=x1; \
+ if(x2<min) min=x2; \
+ if(x2>max) max=x2;
+
+ //======================== X-tests ========================//
+#define AXISTEST_X01(a, b, fa, fb) \
+ p0 = a*v0[Y] - b*v0[Z]; \
+ p2 = a*v2[Y] - b*v2[Z]; \
+ if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if(min>rad || max<-rad) return 0;
+
+#define AXISTEST_X2(a, b, fa, fb) \
+ p0 = a*v0[Y] - b*v0[Z]; \
+ p1 = a*v1[Y] - b*v1[Z]; \
+ if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if(min>rad || max<-rad) return 0;
+
+ //======================== Y-tests ========================//
+#define AXISTEST_Y02(a, b, fa, fb) \
+ p0 = -a*v0[X] + b*v0[Z]; \
+ p2 = -a*v2[X] + b*v2[Z]; \
+ if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if(min>rad || max<-rad) return 0;
+
+#define AXISTEST_Y1(a, b, fa, fb) \
+ p0 = -a*v0[X] + b*v0[Z]; \
+ p1 = -a*v1[X] + b*v1[Z]; \
+ if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if(min>rad || max<-rad) return 0;
+
+ //======================== Z-tests ========================//
+#define AXISTEST_Z12(a, b, fa, fb) \
+ p1 = a*v1[X] - b*v1[Y]; \
+ p2 = a*v2[X] - b*v2[Y]; \
+ if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if(min>rad || max<-rad) return 0;
+
+#define AXISTEST_Z0(a, b, fa, fb) \
+ p0 = a*v0[X] - b*v0[Y]; \
+ p1 = a*v1[X] - b*v1[Y]; \
+ if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if(min>rad || max<-rad) return 0;
+
+ // This internal procedure is defined below.
+ bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox);
+
+ // Use separating axis theorem to test overlap between triangle and box
+ // need to test for overlap in these directions:
+ // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
+ // we do not even need to test these)
+ // 2) normal of the triangle
+ // 3) crossproduct(edge from tri, {x,y,z}-directin)
+ // this gives 3x3=9 more tests
+ bool overlapTriangleBox(Vec3r& boxcenter,
+ Vec3r& boxhalfsize,
+ Vec3r triverts[3]) {
+ Vec3r v0, v1, v2, normal, e0, e1, e2;
+ real min, max, d, p0, p1, p2, rad, fex, fey, fez;
+
+ // This is the fastest branch on Sun
+ // move everything so that the boxcenter is in (0, 0, 0)
+ v0 = triverts[0] - boxcenter;
+ v1 = triverts[1] - boxcenter;
+ v2 = triverts[2] - boxcenter;
+
+ // compute triangle edges
+ e0 = v1 - v0;
+ e1 = v2 - v1;
+ e2 = v0 - v2;
+
+ // Bullet 3:
+ // Do the 9 tests first (this was faster)
+ fex = fabs(e0[X]);
+ fey = fabs(e0[Y]);
+ fez = fabs(e0[Z]);
+ AXISTEST_X01(e0[Z], e0[Y], fez, fey);
+ AXISTEST_Y02(e0[Z], e0[X], fez, fex);
+ AXISTEST_Z12(e0[Y], e0[X], fey, fex);
+
+ fex = fabs(e1[X]);
+ fey = fabs(e1[Y]);
+ fez = fabs(e1[Z]);
+ AXISTEST_X01(e1[Z], e1[Y], fez, fey);
+ AXISTEST_Y02(e1[Z], e1[X], fez, fex);
+ AXISTEST_Z0(e1[Y], e1[X], fey, fex);
+
+ fex = fabs(e2[X]);
+ fey = fabs(e2[Y]);
+ fez = fabs(e2[Z]);
+ AXISTEST_X2(e2[Z], e2[Y], fez, fey);
+ AXISTEST_Y1(e2[Z], e2[X], fez, fex);
+ AXISTEST_Z12(e2[Y], e2[X], fey, fex);
+
+ // Bullet 1:
+ // first test overlap in the {x,y,z}-directions
+ // find min, max of the triangle each direction, and test for overlap in
+ // that direction -- this is equivalent to testing a minimal AABB around
+ // the triangle against the AABB
+
+ // test in X-direction
+ FINDMINMAX(v0[X], v1[X], v2[X], min, max);
+ if (min > boxhalfsize[X] || max < -boxhalfsize[X])
+ return false;
+
+ // test in Y-direction
+ FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
+ if (min > boxhalfsize[Y] || max < -boxhalfsize[Y])
+ return false;
+
+ // test in Z-direction
+ FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
+ if(min > boxhalfsize[Z] || max < -boxhalfsize[Z])
+ return false;
+
+ // Bullet 2:
+ // test if the box intersects the plane of the triangle
+ // compute plane equation of triangle: normal * x + d = 0
+ normal = e0 ^ e1;
+ d = -(normal * v0); // plane eq: normal.x + d = 0
+ if (!overlapPlaneBox(normal, d, boxhalfsize))
+ return false;
+
+ return true; // box and triangle overlaps
+ }
+
+ // Fast, Minimum Storage Ray-Triangle Intersection
+ //
+ // Tomas Möller
+ // Prosolvia Clarus AB
+ // Sweden
+ // tompa@clarus.se
+ //
+ // Ben Trumbore
+ // Cornell University
+ // Ithaca, New York
+ // wbt@graphics.cornell.edu
+
+ bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir,
+ const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
+ real& t, real& u, real& v, const real epsilon) {
+ Vec3r edge1, edge2, tvec, pvec, qvec;
+ real det, inv_det;
+
+ // find vectors for two edges sharing v0
+ edge1 = v1 - v0;
+ edge2 = v2 - v0;
+
+ // begin calculating determinant - also used to calculate U parameter
+ pvec = dir ^ edge2;
+
+ // if determinant is near zero, ray lies in plane of triangle
+ det = edge1 * pvec;
+
+ // calculate distance from v0 to ray origin
+ tvec = orig - v0;
+ inv_det = 1.0 / det;
+
+ qvec = tvec ^ edge1;
+
+ if (det > epsilon) {
+ u = tvec * pvec;
+ if (u < 0.0 || u > det)
+ return false;
+
+ // calculate V parameter and test bounds
+ v = dir * qvec;
+ if (v < 0.0 || u + v > det)
+ return false;
+ }
+ else if(det < -epsilon) {
+ // calculate U parameter and test bounds
+ u = tvec * pvec;
+ if (u > 0.0 || u < det)
+ return false;
+
+ // calculate V parameter and test bounds
+ v = dir * qvec;
+ if (v > 0.0 || u + v < det)
+ return false;
+ }
+ else
+ return false; // ray is parallell to the plane of the triangle
+
+ u *= inv_det;
+ v *= inv_det;
+ t = (edge2 * qvec) * inv_det;
+
+ return true;
+ }
+
+ // Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
+ intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir,
+ const Vec3r& norm, const real d,
+ real& t,
+ const real epsilon) {
+ real denom = norm * dir;
+
+ if(fabs(denom) <= epsilon) { // plane and ray are parallel
+ if(fabs((norm * orig) + d) <= epsilon)
+ return COINCIDENT; // plane and ray are coincident
+ else
+ return COLINEAR;
+ }
+
+ t = -(d + (norm * orig)) / denom;
+
+ if (t < 0.0f)
+ return DONT_INTERSECT;
+
+ return DO_INTERSECT;
+ }
+
+ bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+ real t0, real t1,
+ real& tmin, real& tmax, // I0=orig+tmin*dir is the first intersection, I1=orig+tmax*dir is the second intersection
+ real epsilon){
+
+ float tymin, tymax, tzmin, tzmax;
+ Vec3r inv_direction(1.0/dir[0], 1.0/dir[1], 1.0/dir[2]);
+ int sign[3];
+ sign[0] = (inv_direction.x() < 0);
+ sign[1] = (inv_direction.y() < 0);
+ sign[2] = (inv_direction.z() < 0);
+
+ Vec3r bounds[2];
+ bounds[0] = boxMin;
+ bounds[1] = boxMax;
+
+ tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
+ tmax = (bounds[1-sign[0]].x() - orig.x()) * inv_direction.x();
+ tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
+ tymax = (bounds[1-sign[1]].y() - orig.y()) * inv_direction.y();
+ if ( (tmin > tymax) || (tymin > tmax) )
+ return false;
+ if (tymin > tmin)
+ tmin = tymin;
+ if (tymax < tmax)
+ tmax = tymax;
+ tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
+ tzmax = (bounds[1-sign[2]].z() - orig.z()) * inv_direction.z();
+ if ( (tmin > tzmax) || (tzmin > tmax) )
+ return false;
+ if (tzmin > tmin)
+ tmin = tzmin;
+ if (tzmax < tmax)
+ tmax = tzmax;
+ return ( (tmin < t1) && (tmax > t0) );
+ }
+
+ // Checks whether 3D points p lies inside or outside of the triangle ABC
+ bool includePointTriangle(const Vec3r& P,
+ const Vec3r& A,
+ const Vec3r& B,
+ const Vec3r& C) {
+ Vec3r AB(B - A);
+ Vec3r BC(C - B);
+ Vec3r CA(A - C);
+ Vec3r AP(P - A);
+ Vec3r BP(P - B);
+ Vec3r CP(P - C);
+
+ Vec3r N(AB ^ BC); // triangle's normal
+
+ N.normalize();
+
+ Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
+ J.normalize();
+ K.normalize();
+ L.normalize();
+
+ if(J * N < 0)
+ return false; // on the right of AB
+
+ if(K * N < 0)
+ return false; // on the right of BC
+
+ if(L * N < 0)
+ return false; // on the right of CA
+
+ return true;
+ }
+
+ void transformVertex(const Vec3r& vert,
+ const Matrix44r& matrix,
+ Vec3r& res) {
+ HVec3r hvert(vert), res_tmp;
+ real scale;
+ for (unsigned j = 0; j < 4; j++) {
+ scale = hvert[j];
+ for (unsigned i = 0; i < 4; i++)
+ res_tmp[i] += matrix(i, j) * scale;
+ }
+
+ res[0] = res_tmp.x();
+ res[1] = res_tmp.y();
+ res[2] = res_tmp.z();
+ }
+
+ void transformVertices(const vector<Vec3r>& vertices,
+ const Matrix44r& trans,
+ vector<Vec3r>& res) {
+ for (vector<Vec3r>::const_iterator v = vertices.begin();
+ v != vertices.end();
+ v++) {
+ Vec3r *res_tmp = new Vec3r;
+ transformVertex(*v, trans, *res_tmp);
+ res.push_back(*res_tmp);
+ }
+ }
+
+ Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v) {
+ Vec3r res;
+ for (unsigned i = 0; i < 3; i++) {
+ res[i] = 0;
+ for (unsigned j = 0; j < 3; j++)
+ res[i] += mat(i, j) * v[j];
+ }
+ res.normalize();
+ return res;
+ }
+
+ // This internal procedure is defined below.
+ void fromCoordAToCoordB(const Vec3r& p,
+ Vec3r& q,
+ const real transform[4][4]);
+
+ void fromWorldToCamera(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4]) {
+ fromCoordAToCoordB(p, q, model_view_matrix);
+ }
+
+ void fromCameraToRetina(const Vec3r& p,
+ Vec3r& q,
+ const real projection_matrix[4][4]) {
+ fromCoordAToCoordB(p, q, projection_matrix);
+ }
+
+ void fromRetinaToImage(const Vec3r& p,
+ Vec3r& q,
+ const int viewport[4]) {
+ // winX:
+ q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
+
+ // winY:
+ q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
+
+ // winZ:
+ q[2] = (p[2] + 1.0) / 2.0;
+ }
+
+ void fromWorldToImage(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4],
+ const real projection_matrix[4][4],
+ const int viewport[4]) {
+ Vec3r p1, p2;
+ fromWorldToCamera(p, p1, model_view_matrix);
+ fromCameraToRetina(p1, p2, projection_matrix);
+ fromRetinaToImage(p2, q, viewport);
+ q[2] = p1[2];
+ }
+
+ void fromWorldToImage(const Vec3r& p,
+ Vec3r& q,
+ const real transform[4][4],
+ const int viewport[4]) {
+ fromCoordAToCoordB(p, q, transform);
+
+ // winX:
+ q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
+
+ //winY:
+ q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
+ }
+
+ void fromImageToRetina(const Vec3r& p,
+ Vec3r& q,
+ const int viewport[4]) {
+ q = p;
+ q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1;
+ q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1;
+ }
+
+ void fromRetinaToCamera(const Vec3r& p,
+ Vec3r& q,
+ real focal,
+ const real projection_matrix[4][4]) {
+
+ if( projection_matrix[3][3] == 0.0 ) // perspective
+ {
+ q[0] = (-p[0] * focal) / projection_matrix[0][0];
+ q[1] = (-p[1] * focal) / projection_matrix[1][1];
+ q[2] = focal;
+ }
+ else // orthogonal
+ {
+ q[0] = p[0] / projection_matrix[0][0];
+ q[1] = p[1] / projection_matrix[1][1];
+ q[2] = focal;
+ }
+ }
+
+ void fromCameraToWorld(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4]) {
+
+ real translation[3] = { model_view_matrix[0][3],
+ model_view_matrix[1][3],
+ model_view_matrix[2][3] };
+ for (unsigned i = 0; i < 3; i++) {
+ q[i] = 0.0;
+ for (unsigned short j = 0; j < 3; j++)
+ q[i] += model_view_matrix[j][i] * (p[j] - translation[j]);
+ }
+ }
+
+
+ //
+ // Internal code
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ // Copyright 2001, softSurfer (www.softsurfer.com)
+ // This code may be freely used and modified for any purpose
+ // providing that this copyright notice is included with it.
+ // SoftSurfer makes no warranty for this code, and cannot be held
+ // liable for any real or imagined damage resulting from its use.
+ // Users of this code must verify correctness for their application.
+
+#define perp(u,v) ((u)[0] * (v)[1] - (u)[1] * (v)[0]) // 2D perp product
+
+ inline bool intersect2dSegPoly(Vec2r* seg,
+ Vec2r* poly,
+ unsigned n) {
+ if (seg[0] == seg[1])
+ return false;
+
+ real tE = 0; // the maximum entering segment parameter
+ real tL = 1; // the minimum leaving segment parameter
+ real t, N, D; // intersect parameter t = N / D
+ Vec2r dseg; // the segment direction vector
+ dseg = seg[1] - seg[0];
+ Vec2r e; // edge vector
+
+ for (unsigned i = 0; i < n; i++) { // process polygon edge poly[i]poly[i+1]
+ e = poly[i+1] - poly[i];
+ N = perp(e, seg[0] - poly[i]);
+ D = -perp(e, dseg);
+ if (fabs(D) < M_EPSILON) {
+ if (N < 0)
+ return false;
+ else
+ continue;
+ }
+
+ t = N / D;
+ if (D < 0) { // segment seg is entering across this edge
+ if (t > tE) { // new max tE
+ tE = t;
+ if (tE > tL) // seg enters after leaving polygon
+ return false;
+ }
+ }
+ else { // segment seg is leaving across this edge
+ if (t < tL) { // new min tL
+ tL = t;
+ if (tL < tE) // seg leaves before entering polygon
+ return false;
+ }
+ }
+ }
+
+ // tE <= tL implies that there is a valid intersection subsegment
+ return true;
+ }
+
+ inline bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox) {
+ Vec3r vmin, vmax;
+
+ for(unsigned q = X; q <= Z; q++) {
+ if(normal[q] > 0.0f) {
+ vmin[q] = -maxbox[q];
+ vmax[q] = maxbox[q];
+ }
+ else {
+ vmin[q] = maxbox[q];
+ vmax[q] = -maxbox[q];
+ }
+ }
+ if((normal * vmin) + d > 0.0f)
+ return false;
+ if((normal * vmax) + d >= 0.0f)
+ return true;
+ return false;
+ }
+
+ inline void fromCoordAToCoordB(const Vec3r&p,
+ Vec3r& q,
+ const real transform[4][4]) {
+ HVec3r hp(p);
+ HVec3r hq(0, 0, 0, 0);
+
+ for (unsigned i = 0; i < 4; i++)
+ for (unsigned j = 0; j < 4; j++)
+ hq[i] += transform[i][j] * hp[j];
+
+ if(hq[3] == 0) {
+ q = p;
+ return;
+ }
+
+ for (unsigned k = 0; k < 3; k++)
+ q[k] = hq[k] / hq[3];
+ }
+
+} // end of namespace GeomUtils
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.h b/source/blender/freestyle/intern/geometry/GeomUtils.h
new file mode 100755
index 00000000000..bbbf42b5881
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.h
@@ -0,0 +1,310 @@
+//
+// Filename : GeomUtils.h
+// Author(s) : Stephane Grabli
+// Purpose : Various tools for geometry
+// Date of creation : 12/04/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GEOMUTILS_H
+# define GEOMUTILS_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "Geom.h"
+
+using namespace std;
+using namespace Geometry;
+
+namespace GeomUtils {
+
+ //
+ // Templated procedures
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ /*! Computes the distance from a point P to a segment AB */
+ template<class T>
+ real distPointSegment( const T& P, const T& A , const T& B) {
+ T AB, AP, BP;
+ AB = B - A;
+ AP = P - A;
+ BP = P - B;
+
+ real c1(AB * AP);
+ if (c1 <= 0)
+ return AP.norm();
+
+ real c2(AB * AB);
+ if (c2 <= c1)
+ return BP.norm();
+
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
+
+ return PPb.norm();
+ }
+
+ //
+ // Non-templated procedures
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ typedef enum {
+ DONT_INTERSECT,
+ DO_INTERSECT,
+ COLINEAR,
+ COINCIDENT
+ } intersection_test;
+
+ LIB_GEOMETRY_EXPORT
+ intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ Vec2r& res); // found intersection point
+
+ LIB_GEOMETRY_EXPORT
+ intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ Vec2r& res); // found intersection point
+
+ LIB_GEOMETRY_EXPORT
+ intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ real& t, // I = P1 + t * P1P2)
+ real& u, // I = P3 + u * P3P4
+ real epsilon = M_EPSILON);
+
+ /*! check whether a 2D segment intersect a 2D region or not */
+ LIB_GEOMETRY_EXPORT
+ bool intersect2dSeg2dArea(const Vec2r& min,
+ const Vec2r& max,
+ const Vec2r& A,
+ const Vec2r& B);
+
+ /*! check whether a 2D segment is included in a 2D region or not */
+ LIB_GEOMETRY_EXPORT
+ bool include2dSeg2dArea(const Vec2r& min,
+ const Vec2r& max,
+ const Vec2r& A,
+ const Vec2r& B);
+
+ /*! Box-triangle overlap test, adapted from Tomas Akenine-Möller code */
+ LIB_GEOMETRY_EXPORT
+ bool overlapTriangleBox(Vec3r& boxcenter,
+ Vec3r& boxhalfsize,
+ Vec3r triverts[3]);
+
+ /*! Fast, Minimum Storage Ray-Triangle Intersection,
+ * adapted from Tomas Möller and Ben Trumbore code.
+ */
+ LIB_GEOMETRY_EXPORT
+ bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir,
+ const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
+ real& t, // I = orig + t * dir
+ real& u, real& v, // I = (1-u-v)*v0+u*v1+v*v2
+ const real epsilon = M_EPSILON); // the epsilon to use
+
+ /*! Intersection between plane and ray
+ * adapted from Graphics Gems, Didier Badouel
+ */
+ LIB_GEOMETRY_EXPORT
+ intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& norm, const real d, // plane's normal and offset (plane = { P / P.N + d = 0 })
+ real& t, // I = orig + t * dir
+ const real epsilon = M_EPSILON); // the epsilon to use
+
+ /*! Intersection Ray-Bounding box (axis aligned).
+ * Adapted from Williams et al, "An Efficient Robust Ray-Box Intersection Algorithm",
+ * JGT 10:1 (2005), pp. 49-54.
+ * Returns
+ */
+ LIB_GEOMETRY_EXPORT
+ bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+ real t0, real t1, // the interval in which at least on of the intersections must happen
+ real& tmin, real& tmax, // Imin=orig+tmin*dir is the first intersection, Imax=orig+tmax*dir is the second intersection
+ real epsilon = M_EPSILON); // the epsilon to use
+
+
+ /*! Checks whether 3D point P lies inside or outside of the triangle ABC */
+ LIB_GEOMETRY_EXPORT
+ bool includePointTriangle(const Vec3r& P,
+ const Vec3r& A,
+ const Vec3r& B,
+ const Vec3r& C);
+
+ LIB_GEOMETRY_EXPORT
+ void transformVertex(const Vec3r& vert,
+ const Matrix44r& matrix,
+ Vec3r& res);
+
+ LIB_GEOMETRY_EXPORT
+ void transformVertices(const vector<Vec3r>& vertices,
+ const Matrix44r& trans,
+ vector<Vec3r>& res);
+
+ LIB_GEOMETRY_EXPORT
+ Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
+
+ //
+ // Coordinates systems changing procedures
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ /*! From world to image
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromWorldToImage(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4],
+ const real projection_matrix[4][4],
+ const int viewport[4]);
+
+ /*! From world to image
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * transform
+ * The transformation matrix (gathering model view and projection),
+ * expressed in line major order (OpenGL matrices are column major ordered)
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromWorldToImage(const Vec3r& p,
+ Vec3r& q,
+ const real transform[4][4],
+ const int viewport[4]);
+
+ /*! Projects from world coordinates to camera coordinates
+ * Returns the point's coordinates expressed in the camera's
+ * coordinates system.
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromWorldToCamera(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4]);
+
+ /*! Projects from World Coordinates to retina coordinates
+ * Returns the point's coordinates expressed in Retina system.
+ * p
+ * point's coordinates expressed in camera system
+ * q
+ * vector in which the result will be stored
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromCameraToRetina(const Vec3r& p,
+ Vec3r& q,
+ const real projection_matrix[4][4]);
+
+ /*! From retina to image.
+ * Returns the coordinates expressed in Image coorinates system.
+ * p
+ * point's coordinates expressed in retina system
+ * q
+ * vector in which the result will be stored
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromRetinaToImage(const Vec3r& p,
+ Vec3r& q,
+ const int viewport[4]);
+
+ /*! From image to retina
+ * p
+ * point's coordinates expressed in image system
+ * q
+ * vector in which the result will be stored
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromImageToRetina(const Vec3r& p,
+ Vec3r& q,
+ const int viewport[4]);
+
+ /*! computes the coordinates of q in the camera coordinates system,
+ * using the known z coordinates of the 3D point.
+ * That means that this method does not inverse any matrices,
+ * it only computes X and Y from x,y and Z)
+ * p
+ * point's coordinates expressed in retina system
+ * q
+ * vector in which the result will be stored
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromRetinaToCamera(const Vec3r& p,
+ Vec3r& q,
+ real z,
+ const real projection_matrix[4][4]);
+
+ /*! Projects from camera coordinates to world coordinates
+ * Returns the point's coordinates expressed in the world's
+ * coordinates system.
+ * p
+ * point's coordinates expressed in the camera coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromCameraToWorld(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4]);
+
+} // end of namespace GeomUtils
+
+#endif // GEOMUTILS_H
diff --git a/source/blender/freestyle/intern/geometry/Grid.cpp b/source/blender/freestyle/intern/geometry/Grid.cpp
new file mode 100755
index 00000000000..0096297f48b
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Grid.cpp
@@ -0,0 +1,392 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Grid.h"
+#include "BBox.h"
+#include <cassert>
+#include <stdexcept>
+
+// Grid Visitors
+/////////////////
+void allOccludersGridVisitor::examineOccluder(Polygon3r *occ){
+ occluders_.push_back(occ);
+}
+
+bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max){
+ if(((inter.x()>=box_min.x()) && (inter.x() <box_max.x()))
+ && ((inter.y()>=box_min.y()) && (inter.y() <box_max.y()))
+ && ((inter.z()>=box_min.z()) && (inter.z() <box_max.z()))
+ ){
+ return true;
+ }
+ return false;
+}
+void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ){
+
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ Vec3r v1(((occ)->getVertices())[0]);
+ Vec3d normal((occ)->getNormal());
+ //soc unused - double d = -(v1 * normal);
+
+ double tmp_u, tmp_v, tmp_t;
+ if((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)){
+ if (fabs(ray_dir_ * normal) > 0.0001){
+ // Check whether the intersection is in the cell:
+ if(inBox(ray_org_+tmp_t*ray_dir_/ray_dir_.norm(), current_cell_->getOrigin(), current_cell_->getOrigin()+cell_size_)){
+
+ //Vec3d bboxdiag(_scene3d->bbox().getMax()-_scene3d->bbox().getMin());
+ //if ((t>1.0E-06*(min(min(bboxdiag.x(),bboxdiag.y()),bboxdiag.z()))) && (t<raylength)){
+ if(tmp_t < t_){
+ occluder_ = occ;
+ u_ = tmp_u;
+ v_ = tmp_v;
+ t_ = tmp_t;
+ }
+ }else{
+ occ->userdata2 = 0;
+ }
+ }
+ }
+}
+
+bool firstIntersectionGridVisitor::stop(){
+ if(occluder_)
+ return true;
+ return false;
+}
+
+// Grid
+/////////////////
+
+void Grid::clear() {
+ if (_occluders.size() != 0) {
+ for(OccludersSet::iterator it = _occluders.begin();
+ it != _occluders.end();
+ it++) {
+ delete (*it);
+ }
+ _occluders.clear();
+ }
+
+ _size = Vec3r(0, 0, 0);
+ _cell_size = Vec3r(0, 0, 0);
+ _orig = Vec3r(0, 0, 0);
+ _cells_nb = Vec3u(0, 0, 0);
+ //_ray_occluders.clear();
+}
+
+void Grid::configure(const Vec3r& orig,
+ const Vec3r& size,
+ unsigned nb) {
+
+ _orig = orig;
+ Vec3r tmpSize=size;
+ // Compute the volume of the desired grid
+ real grid_vol = size[0] * size[1] * size[2];
+
+ if(grid_vol == 0){
+ double min=DBL_MAX;
+ int index=0;
+ int nzeros=0;
+ for(int i=0;i<3;++i){
+ if(size[i] == 0){
+ ++nzeros;
+ index=i;
+ }
+ if((size[i]!=0) && (min>size[i])){
+ min=size[i];
+ }
+ }
+ if(nzeros>1){
+ throw std::runtime_error("Warning: the 3D grid has more than one null dimension");
+ }
+ tmpSize[index]=min;
+ _orig[index] = _orig[index]-min/2;
+ }
+ // Compute the desired volume of a single cell
+ real cell_vol = grid_vol / nb;
+ // The edge of such a cubic cell is cubic root of cellVolume
+ real edge = pow(cell_vol, 1.0 / 3.0);
+
+ // We compute the number of cells par edge
+ // such as we cover at least the whole box.
+ unsigned i;
+ for (i = 0; i < 3; i++)
+ _cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1;
+
+ _size = tmpSize;
+
+ for(i = 0; i < 3; i++)
+ _cell_size[i] = _size[i] / _cells_nb[i];
+}
+
+void Grid::insertOccluder(Polygon3r* occluder) {
+ const vector<Vec3r> vertices = occluder->getVertices();
+ if (vertices.size() == 0)
+ return;
+
+ // add this occluder to the grid's occluders list
+ addOccluder(occluder);
+
+ // find the bbox associated to this polygon
+ Vec3r min, max;
+ occluder->getBBox(min, max);
+
+ // Retrieve the cell x, y, z cordinates associated with these min and max
+ Vec3u imax, imin;
+ getCellCoordinates(max, imax);
+ getCellCoordinates(min, imin);
+
+ // We are now going to fill in the cells overlapping with the
+ // polygon bbox.
+ // If the polygon is a triangle (most of cases), we also
+ // check for each of these cells if it is overlapping with
+ // the triangle in order to only fill in the ones really overlapping
+ // the triangle.
+
+ unsigned i, x, y, z;
+ vector<Vec3r>::const_iterator it;
+ Vec3u coord;
+
+ if (vertices.size() == 3) { // Triangle case
+ Vec3r triverts[3];
+ i = 0;
+ for(it = vertices.begin();
+ it != vertices.end();
+ it++) {
+ triverts[i] = Vec3r(*it);
+ i++;
+ }
+
+ Vec3r boxmin, boxmax;
+
+ for (z = imin[2]; z <= imax[2]; z++)
+ for (y = imin[1]; y <= imax[1]; y++)
+ for (x = imin[0]; x <= imax[0]; x++) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
+ // We retrieve the box coordinates of the current cell
+ getCellBox(coord, boxmin, boxmax);
+ // We check whether the triangle and the box ovewrlap:
+ Vec3r boxcenter((boxmin + boxmax) / 2.0);
+ Vec3r boxhalfsize(_cell_size / 2.0);
+ if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
+ // We must then create the Cell and add it to the cells list
+ // if it does not exist yet.
+ // We must then add the occluder to the occluders list of this cell.
+ Cell* cell = getCell(coord);
+ if (!cell) {
+ cell = new Cell(boxmin);
+ fillCell(coord, *cell);
+ }
+ cell->addOccluder(occluder);
+ }
+ }
+ }
+ else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
+ for (z = imin[2]; z <= imax[2]; z++)
+ for (y = imin[1]; y <= imax[1]; y++)
+ for (x = imin[0]; x <= imax[0]; x++) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
+ Cell* cell = getCell(coord);
+ if (!cell) {
+ Vec3r orig;
+ getCellOrigin(coord, orig);
+ cell = new Cell(orig);
+ fillCell(coord, *cell);
+ }
+ cell->addOccluder(occluder);
+ }
+ }
+}
+
+bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell) {
+ next_cell = current_cell;
+ real t_min, t;
+ unsigned i;
+
+ t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0.
+ unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z)
+
+
+ // using a parametric equation of
+ // a line : B = A + t u, we find
+ // the tx, ty and tz respectively coresponding
+ // to the intersections with the plans:
+ // x = _cell_size[0], y = _cell_size[1], z = _cell_size[2]
+ for (i = 0; i < 3; i++) {
+ if (_ray_dir[i] == 0)
+ continue;
+ if (_ray_dir[i] > 0)
+ t = (_cell_size[i] - _pt[i]) / _ray_dir[i];
+ else
+ t = -_pt[i] / _ray_dir[i];
+ if (t < t_min) {
+ t_min = t;
+ coord = i;
+ }
+ }
+
+ // We use the parametric line equation and
+ // the found t (tamx) to compute the
+ // B coordinates:
+ Vec3r pt_tmp(_pt);
+ _pt = pt_tmp + t_min * _ray_dir;
+
+ // We express B coordinates in the next cell
+ // coordinates system. We just have to
+ // set the coordinate coord of B to 0
+ // of _CellSize[coord] depending on the sign
+ // of _u[coord]
+ if (_ray_dir[coord] > 0) {
+ next_cell[coord]++;
+ _pt[coord] -= _cell_size[coord];
+ // if we are out of the grid, we must stop
+ if (next_cell[coord] >= _cells_nb[coord])
+ return false;
+ }
+ else {
+ int tmp = next_cell[coord] - 1;
+ _pt[coord] = _cell_size[coord];
+ if (tmp < 0)
+ return false;
+ next_cell[coord]--;
+ }
+
+ _t += t_min;
+ if (_t >= _t_end)
+ return false;
+
+ return true;
+}
+
+void Grid::castRay(const Vec3r& orig,
+ const Vec3r& end,
+ OccludersSet& occluders,
+ unsigned timestamp) {
+ initRay(orig, end, timestamp);
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
+}
+
+void Grid::castInfiniteRay(const Vec3r& orig,
+ const Vec3r& dir,
+ OccludersSet& occluders,
+ unsigned timestamp) {
+ Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
+ bool inter = initInfiniteRay(orig, dir, timestamp);
+ if(!inter)
+ return;
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
+}
+
+Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig,
+ const Vec3r& dir,
+ double& t,
+ double& u,
+ double& v,
+ unsigned timestamp){
+ Polygon3r *occluder = 0;
+ Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
+ bool inter = initInfiniteRay(orig, dir, timestamp);
+ if(!inter){
+ return 0;
+ }
+ firstIntersectionGridVisitor visitor(orig,dir,_cell_size);
+ castRayInternal(visitor);
+ // ARB: This doesn't work, because occluders are unordered within any cell
+ // visitor.occluder() will be an occluder, but we have no guarantee
+ // it will be the *first* occluder.
+ // I assume that is the reason this code is not actually used for FindOccludee.
+ occluder = visitor.occluder();
+ t = visitor.t_;
+ u = visitor.u_;
+ v = visitor.v_;
+ return occluder;
+}
+
+void Grid::initRay (const Vec3r &orig,
+ const Vec3r& end,
+ unsigned timestamp) {
+ _ray_dir = end - orig;
+ _t_end = _ray_dir.norm();
+ _t = 0;
+ _ray_dir.normalize();
+ _timestamp = timestamp;
+
+ for(unsigned i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ //_ray_occluders.clear();
+
+}
+
+bool Grid::initInfiniteRay (const Vec3r &orig,
+ const Vec3r& dir,
+ unsigned timestamp) {
+ _ray_dir = dir;
+ _t_end = FLT_MAX;
+ _t = 0;
+ _ray_dir.normalize();
+ _timestamp = timestamp;
+
+ // check whether the origin is in or out the box:
+ Vec3r boxMin(_orig);
+ Vec3r boxMax(_orig+_size);
+ BBox<Vec3r> box(boxMin, boxMax);
+ if(box.inside(orig)){
+ for(unsigned i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ }else{
+ // is the ray intersecting the box?
+ real tmin(-1.0), tmax(-1.0);
+ if(GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)){
+ assert(tmin != -1.0);
+ Vec3r newOrig = orig + tmin*_ray_dir;
+ for(unsigned i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]);
+ if(_current_cell[i] == _cells_nb[i])
+ _current_cell[i] = _cells_nb[i] - 1;
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+
+ }else{
+ return false;
+ }
+ }
+ //_ray_occluders.clear();
+
+ return true;
+
+}
+
diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h
new file mode 100755
index 00000000000..a490646ff51
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Grid.h
@@ -0,0 +1,392 @@
+//
+// Filename : Grid.h
+// Author(s) : Stephane Grabli
+// Purpose : Base class to define a cell grid surrounding
+// the bounding box of the scene
+// Date of creation : 30/07/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GRID_H
+# define GRID_H
+
+# include <cstring> // for memset
+# include <float.h>
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "GeomUtils.h"
+# include "Geom.h"
+# include "Polygon.h"
+
+using namespace std;
+using namespace Geometry;
+
+typedef vector<Polygon3r*> OccludersSet;
+
+
+//
+// Class to define cells used by the regular grid
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class LIB_GEOMETRY_EXPORT Cell
+{
+ public:
+
+ Cell(Vec3r& orig) {
+ _orig = orig;
+ }
+
+ virtual ~Cell() {}
+
+ inline void addOccluder(Polygon3r* o) {
+ if (o)
+ _occluders.push_back(o);
+ }
+
+ inline const Vec3r& getOrigin() {
+ return _orig;
+ }
+
+ inline OccludersSet& getOccluders() {
+ return _occluders;
+ }
+
+ private:
+
+ Vec3r _orig;
+ OccludersSet _occluders;
+};
+
+
+class GridVisitor{
+public:
+ virtual ~GridVisitor() {}; //soc
+ virtual void discoverCell(Cell *cell) {}
+ virtual void examineOccluder(Polygon3r *occ) {}
+ virtual void finishCell(Cell *cell) {}
+ virtual bool stop() {return false;}
+};
+
+/*! Gathers all the occluders belonging to the cells
+ * traversed by the ray */
+class allOccludersGridVisitor : public GridVisitor{
+public:
+ allOccludersGridVisitor(OccludersSet& occluders)
+ :GridVisitor(), occluders_(occluders){}
+ virtual void examineOccluder(Polygon3r *occ);
+
+ OccludersSet& occluders() {return occluders_;}
+ void clear() {occluders_.clear();}
+
+private:
+ OccludersSet& occluders_;
+};
+
+/*! Finds the first intersection and breaks. The occluder and
+ * the intersection information are stored and accessible.
+ */
+class firstIntersectionGridVisitor : public GridVisitor {
+
+//soc - changed order to remove warnings
+public:
+ double u_, v_, t_;
+private:
+ Polygon3r *occluder_;
+ Vec3r ray_org_, ray_dir_, cell_size_;
+ Cell * current_cell_;
+
+public:
+ firstIntersectionGridVisitor(const Vec3r& ray_org, const Vec3r& ray_dir, const Vec3r& cell_size) :
+ GridVisitor(), u_(0),v_(0),t_(DBL_MAX),
+ occluder_(0),
+ ray_org_(ray_org), ray_dir_(ray_dir), cell_size_(cell_size),
+ current_cell_(0) {}
+ virtual ~firstIntersectionGridVisitor() {}
+
+ virtual void discoverCell(Cell *cell) {current_cell_=cell;}
+ virtual void examineOccluder(Polygon3r *occ);
+ virtual bool stop();
+
+ Polygon3r * occluder() {return occluder_;}
+};
+
+//
+// Class to define a regular grid used for ray casting computations
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class LIB_GEOMETRY_EXPORT Grid
+{
+public:
+
+ /*! Builds a Grid
+ * Must be followed by a call to configure()
+ */
+ Grid() {}
+
+ virtual ~Grid() {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable,
+ * resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns a vector of integer containing the
+ * coordinates of the cell containing the point
+ * passed as argument
+ * p
+ * The point for which we're looking the cell
+ */
+ inline void getCellCoordinates(const Vec3r& p, Vec3u& res) {
+ int tmp;
+ for (int i = 0; i < 3; i++) {
+ tmp = (int)((p[i] - _orig[i]) / _cell_size[i]);
+ if (tmp < 0)
+ res[i] = 0;
+ else if ((unsigned)tmp >= _cells_nb[i])
+ res[i] = _cells_nb[i] - 1;
+ else
+ res[i] = tmp;
+ }
+ }
+
+ /*! Fills the case corresponding to coord with the cell */
+ virtual void fillCell(const Vec3u& coord, Cell& cell) = 0;
+
+ /*! returns the cell whose coordinates
+ * are pased as argument
+ */
+ virtual Cell* getCell(const Vec3u& coord) = 0;
+
+ /*! returns the cell containing the point
+ * passed as argument. If the cell is empty
+ * (contains no occluder), NULL is returned
+ * p
+ * The point for which we're looking the cell
+ */
+ inline Cell* getCell(const Vec3r& p) {
+ Vec3u coord;
+ getCellCoordinates(p, coord);
+ return getCell(coord);
+ }
+
+ /*! Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k)
+ * is passed as argument
+ * cell_coord
+ * i,j,k integer coordinates for the cell
+ * orig
+ * x,y,x vector to be filled in with the cell origin's coordinates
+ */
+ inline void getCellOrigin(const Vec3u& cell_coord, Vec3r& orig) {
+ for (unsigned i = 0; i < 3; i++)
+ orig[i] = _orig[i] + cell_coord[i] * _cell_size[i];
+ }
+
+ /*! Retrieves the box corresponding to the cell whose coordinates
+ * are passed as argument.
+ * cell_coord
+ * i,j,k integer coordinates for the cell
+ * min_out
+ * The min x,y,x vector of the box. Filled in by the method.
+ * max_out
+ * The max x,y,z coordinates of the box. Filled in by the method.
+ */
+ inline void getCellBox(const Vec3u& cell_coord, Vec3r& min_out, Vec3r& max_out) {
+ getCellOrigin(cell_coord, min_out);
+ max_out = min_out + _cell_size;
+ }
+
+ /*! inserts a convex polygon occluder
+ * This method is quite coarse insofar as it
+ * adds all cells intersecting the polygon bounding box
+ * convex_poly
+ * The list of 3D points constituing a convex polygon
+ */
+ void insertOccluder(Polygon3r * convex_poly);
+
+ /*! Adds an occluder to the list of occluders */
+ void addOccluder(Polygon3r* occluder) {
+ _occluders.push_back(occluder);
+ }
+
+ /*! Casts a ray between a starting point and an ending point
+ * Returns the list of occluders contained
+ * in the cells intersected by this ray
+ * Starts with a call to InitRay.
+ */
+ void castRay(const Vec3r& orig,
+ const Vec3r& end,
+ OccludersSet& occluders,
+ unsigned timestamp);
+ // Prepares to cast ray without generating OccludersSet
+ void initAcceleratedRay(const Vec3r& orig,
+ const Vec3r& end,
+ unsigned timestamp);
+
+ /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
+ * Returns the list of occluders contained
+ * in the cells intersected by this ray
+ * Starts with a call to InitRay.
+ */
+ void castInfiniteRay(const Vec3r& orig,
+ const Vec3r& dir,
+ OccludersSet& occluders,
+ unsigned timestamp);
+ // Prepares to cast ray without generating OccludersSet.
+ bool initAcceleratedInfiniteRay(const Vec3r& orig,
+ const Vec3r& dir,
+ unsigned timestamp);
+
+ /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
+ * Returns the first intersection (occluder,t,u,v) or null.
+ * Starts with a call to InitRay.
+ */
+ Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig,
+ const Vec3r& dir,
+ double& t,
+ double& u,
+ double& v,
+ unsigned timestamp);
+
+
+ /*! Init all structures and values for computing
+ * the cells intersected by this new ray
+ */
+ void initRay (const Vec3r &orig,
+ const Vec3r& end,
+ unsigned timestamp);
+
+ /*! Init all structures and values for computing
+ * the cells intersected by this infinite ray.
+ * Returns false if the ray doesn't intersect the
+ * grid.
+ */
+ bool initInfiniteRay (const Vec3r &orig,
+ const Vec3r& dir,
+ unsigned timestamp);
+
+
+ /*! Accessors */
+ inline const Vec3r& getOrigin() const {
+ return _orig;
+ }
+ inline Vec3r gridSize() const {
+ return _size;
+ }
+ inline Vec3r getCellSize() const {
+ return _cell_size;
+ }
+//ARB profiling only:
+ inline OccludersSet* getOccluders() {
+ return &_occluders;
+ }
+
+ void displayDebug() {
+ cerr << "Cells nb : " << _cells_nb << endl;
+ cerr << "Cell size : " << _cell_size << endl;
+ cerr << "Origin : " << _orig << endl;
+ cerr << "Occluders nb : " << _occluders.size() << endl;
+ }
+
+ protected:
+
+ /*! Core of castRay and castInfiniteRay, find occluders
+ * along the given ray
+ */
+ inline void castRayInternal(GridVisitor& visitor) {
+ Cell* current_cell = NULL;
+ do {
+ current_cell = getCell(_current_cell);
+ if (current_cell){
+ visitor.discoverCell(current_cell);
+ OccludersSet& occluders = current_cell->getOccluders(); // FIXME: I had forgotten the ref &
+ for (OccludersSet::iterator it = occluders.begin();
+ it != occluders.end();
+ it++) {
+ if ((unsigned long)(*it)->userdata2 != _timestamp) {
+ (*it)->userdata2 = (void*)_timestamp;
+ visitor.examineOccluder(*it);
+ }
+ }
+ visitor.finishCell(current_cell);
+ }
+ } while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell)));
+ }
+
+
+ /*! returns the cell next to the cell
+ * passed as argument.
+ */
+ bool nextRayCell(Vec3u& current_cell, Vec3u& next_cell);
+
+ unsigned _timestamp;
+
+ Vec3u _cells_nb; // number of cells for x,y,z axis
+ Vec3r _cell_size; // cell x,y,z dimensions
+ Vec3r _size; // grid x,y,x dimensions
+ Vec3r _orig; // grid origin
+
+ Vec3r _ray_dir; // direction vector for the ray
+ Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates)
+ Vec3r _pt; // Points corresponding to the incoming and outgoing intersections
+ // of one cell with the ray
+ real _t_end; // To know when we are at the end of the ray
+ real _t;
+
+ //OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by a ray
+ OccludersSet _occluders; // List of all occluders inserted in the grid
+};
+
+//
+// Class to walk through occluders in grid without building intermediate data structures
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class VirtualOccludersSet {
+ public:
+ VirtualOccludersSet(Grid& _grid) : grid (_grid) {};
+ Polygon3r* begin();
+ Polygon3r* next();
+ Polygon3r* next(bool stopOnNewCell);
+ private:
+ Polygon3r* firstOccluderFromNextCell();
+ Grid& grid;
+ OccludersSet::iterator it, end;
+};
+
+#endif // GRID_H
diff --git a/source/blender/freestyle/intern/geometry/GridHelpers.cpp b/source/blender/freestyle/intern/geometry/GridHelpers.cpp
new file mode 100644
index 00000000000..dcf24a72efb
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GridHelpers.cpp
@@ -0,0 +1,56 @@
+//
+// Filename : GridHelpers.cpp
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2010-12-21
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <math.h>
+#include "GridHelpers.h"
+
+void GridHelpers::getDefaultViewProscenium(real viewProscenium[4]) {
+ // Get proscenium boundary for culling
+ // bufferZone determines the amount by which the area processed
+ // should exceed the actual image area. This is intended to
+ // avoid visible artifacts generated along the proscenium edge.
+ // Perhaps this is no longer needed now that entire view edges
+ // are culled at once, since that theoretically should eliminate
+ // visible artifacts.
+ // To the extent it is still useful, bufferZone should be put into
+ // the UI as configurable percentage value
+ const real bufferZone = 0.05;
+ // borderZone describes a blank border outside the proscenium, but
+ // still inside the image area. Only intended for exposing possible
+ // artifacts along or outside the proscenium edge during debugging.
+ const real borderZone = 0.0;
+ viewProscenium[0] = freestyle_viewport[2] * (borderZone - bufferZone);
+ viewProscenium[1] = freestyle_viewport[2] * (1.0f - borderZone + bufferZone);
+ viewProscenium[2] = freestyle_viewport[3] * (borderZone - bufferZone);
+ viewProscenium[3] = freestyle_viewport[3] * (1.0f - borderZone + bufferZone);
+}
+
+GridHelpers::Transform::~Transform () {}
+
+
diff --git a/source/blender/freestyle/intern/geometry/GridHelpers.h b/source/blender/freestyle/intern/geometry/GridHelpers.h
new file mode 100644
index 00000000000..b079005c1b5
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GridHelpers.h
@@ -0,0 +1,199 @@
+//
+// Filename : GridHelpers.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2010-12-13
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GRIDHELPERS_H
+#define GRIDHELPERS_H
+
+#include <vector>
+#include "Polygon.h"
+#include "../winged_edge/WEdge.h"
+#include "FRS_freestyle.h"
+#include "GeomUtils.h"
+
+namespace GridHelpers {
+
+/*! Computes the distance from a point P to a segment AB */
+template<class T>
+T closestPointToSegment(const T& P, const T& A , const T& B, real& distance) {
+ T AB, AP, BP;
+ AB = B - A;
+ AP = P - A;
+ BP = P - B;
+
+ real c1(AB * AP);
+ if (c1 <= 0) {
+ distance = AP.norm();
+ return A; // A is closest point
+ }
+
+ real c2(AB * AB);
+ if (c2 <= c1) {
+ distance = BP.norm();
+ return B; // B is closest point
+ }
+
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
+
+ distance = PPb.norm();
+ return Pb; // closest point lies on AB
+}
+
+inline Vec3r closestPointOnPolygon(const Vec3r& point, const Polygon3r& poly) {
+ // First cast a ray from the point onto the polygon plane
+ // If the ray intersects the polygon, then the intersection point
+ // is the closest point on the polygon
+ real t, u, v;
+ if ( poly.rayIntersect(point, poly.getNormal(), t, u, v) ) {
+ return point + poly.getNormal() * t;
+ }
+
+ // Otherwise, get the nearest point on each edge, and take the closest
+ real distance;
+ Vec3r closest = closestPointToSegment(point, poly.getVertices()[2], poly.getVertices()[0], distance);
+ for ( unsigned i = 0; i < 2; ++i ) {
+ real t;
+ Vec3r p = closestPointToSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1], t);
+ if ( t < distance ) {
+ distance = t;
+ closest = p;
+ }
+ }
+ return closest;
+}
+
+inline real distancePointToPolygon(const Vec3r& point, const Polygon3r& poly) {
+ // First cast a ray from the point onto the polygon plane
+ // If the ray intersects the polygon, then the intersection point
+ // is the closest point on the polygon
+ real t, u, v;
+ if ( poly.rayIntersect(point, poly.getNormal(), t, u, v) ) {
+ return t > 0.0 ? t : -t;
+ }
+
+ // Otherwise, get the nearest point on each edge, and take the closest
+ real distance = GeomUtils::distPointSegment(point, poly.getVertices()[2], poly.getVertices()[0]);
+ for ( unsigned i = 0; i < 2; ++i ) {
+ real t = GeomUtils::distPointSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1]);
+ if ( t < distance ) {
+ distance = t;
+ }
+ }
+ return distance;
+}
+
+class Transform {
+public:
+ virtual ~Transform () =0;
+ virtual Vec3r operator()(const Vec3r& point) const =0;
+};
+
+inline bool insideProscenium (const real proscenium[4], const Polygon3r& polygon) {
+ // N.B. The bounding box check is redundant for inserting occluders into
+ // cells, because the cell selection code in insertOccluders has already
+ // guaranteed that the bounding boxes will overlap.
+ // First check the viewport edges, since they are the easiest case
+ // Check if the bounding box is entirely outside the proscenium
+ Vec3r bbMin, bbMax;
+ polygon.getBBox(bbMin, bbMax);
+ if ( bbMax[0] < proscenium[0]
+ || bbMin[0] > proscenium[1]
+ || bbMax[1] < proscenium[2]
+ || bbMin[1] > proscenium[3] ) {
+ return false;
+ }
+
+ Vec3r boxCenter(proscenium[0] + (proscenium[1] - proscenium[0]) / 2.0, proscenium[2] + (proscenium[3] - proscenium[2]) / 2.0, 0.0);
+ Vec3r boxHalfSize((proscenium[1] - proscenium[0]) / 2.0, (proscenium[3] - proscenium[2]) / 2.0, 1.0);
+ Vec3r triverts[3] = { Vec3r(polygon.getVertices()[0][0], polygon.getVertices()[0][1], 0.0), Vec3r(polygon.getVertices()[1][0], polygon.getVertices()[1][1], 0.0), Vec3r(polygon.getVertices()[2][0], polygon.getVertices()[2][1], 0.0) };
+ return GeomUtils::overlapTriangleBox(boxCenter, boxHalfSize, triverts);
+}
+
+inline vector<Vec3r> enumerateVertices(const vector<WOEdge*>& fedges) {
+ vector<Vec3r> points;
+ // Iterate over vertices, storing projections in points
+ for(vector<WOEdge*>::const_iterator woe=fedges.begin(), woend=fedges.end(); woe!=woend; woe++) {
+ points.push_back((*woe)->GetaVertex()->GetVertex());
+ }
+
+ return points;
+}
+
+void getDefaultViewProscenium(real viewProscenium[4]);
+
+inline void expandProscenium (real proscenium[4], const Polygon3r& polygon) {
+ Vec3r bbMin, bbMax;
+ polygon.getBBox(bbMin, bbMax);
+
+ const real epsilon = 1.0e-6;
+
+ if ( bbMin[0] <= proscenium[0] ) {
+ proscenium[0] = bbMin[0] - epsilon;
+ }
+
+ if ( bbMin[1] <= proscenium[2] ) {
+ proscenium[2] = bbMin[1] - epsilon;
+ }
+
+ if ( bbMax[0] >= proscenium[1] ) {
+ proscenium[1] = bbMax[0] + epsilon;
+ }
+
+ if ( bbMax[1] >= proscenium[3] ) {
+ proscenium[3] = bbMax[1] + epsilon;
+ }
+}
+
+inline void expandProscenium (real proscenium[4], const Vec3r& point) {
+ const real epsilon = 1.0e-6;
+
+ if ( point[0] <= proscenium[0] ) {
+ proscenium[0] = point[0] - epsilon;
+ }
+
+ if ( point[1] <= proscenium[2] ) {
+ proscenium[2] = point[1] - epsilon;
+ }
+
+ if ( point[0] >= proscenium[1] ) {
+ proscenium[1] = point[0] + epsilon;
+ }
+
+ if ( point[1] >= proscenium[3] ) {
+ proscenium[3] = point[1] + epsilon;
+ }
+}
+
+};
+
+#endif // GRIDHELPERS_H
+
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.cpp b/source/blender/freestyle/intern/geometry/HashGrid.cpp
new file mode 100755
index 00000000000..3cf845d57ef
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/HashGrid.cpp
@@ -0,0 +1,41 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "HashGrid.h"
+
+void HashGrid::clear()
+{
+ if(!_cells.empty()) {
+ for(GridHashTable::iterator it = _cells.begin();
+ it !=_cells.end();
+ it++) {
+ Cell* cell = (*it).second;
+ delete cell;
+ }
+ _cells.clear();
+ }
+
+ Grid::clear();
+}
+
+void HashGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) {
+ Grid::configure(orig, size, nb);
+}
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.h b/source/blender/freestyle/intern/geometry/HashGrid.h
new file mode 100755
index 00000000000..f6605957676
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/HashGrid.h
@@ -0,0 +1,109 @@
+//
+// Filename : HashGrid.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a cell grid surrounding the
+// bounding box of the scene
+// Date of creation : 30/07/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef HASHGRID_H
+# define HASHGRID_H
+
+//# if defined(__GNUC__) && (__GNUC__ >= 3)
+// hash_map is not part of the C++ standard anymore;
+// hash_map.h has been kept though for backward compatibility
+//# include <hash_map.h>
+//# else
+//# include <hash_map>
+//# endif
+
+# include "Grid.h"
+# include <map>
+/*! Defines a hash table used for searching the Cells */
+struct GridHasher{
+#define _MUL 950706376UL
+#define _MOD 2147483647UL
+ inline size_t operator() (const Vec3u& p) const
+ {
+ size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
+ }
+};
+
+/*! Class to define a regular grid used for ray
+ casting computations */
+
+class LIB_GEOMETRY_EXPORT HashGrid : public Grid
+{
+ public:
+
+ typedef map<Vec3u, Cell*> GridHashTable;
+
+ HashGrid() : Grid() {}
+
+ virtual ~HashGrid() {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable,
+ * resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns the cell whose coordinates
+ * are pased as argument
+ */
+ virtual Cell* getCell(const Vec3u& p) {
+ Cell* found_cell = NULL;
+
+ GridHashTable::const_iterator found = _cells.find(p);
+ if (found != _cells.end())
+ found_cell = (*found).second;
+ return found_cell;
+ }
+
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u& p, Cell& cell) {
+ _cells[p] = &cell;
+ }
+
+protected:
+
+ GridHashTable _cells;
+};
+
+#endif // HASHGRID_H
diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp
new file mode 100755
index 00000000000..c9a80adc5ee
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Noise.cpp
@@ -0,0 +1,264 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Noise.h"
+# include <stdlib.h>
+# include <stdio.h>
+# include <math.h>
+#include <time.h>
+
+#define MINX -1000000
+#define MINY MINX
+#define MINZ MINX
+#define SCURVE(a) ((a)*(a)*(3.0-2.0*(a)))
+#define REALSCALE ( 2.0 / 65536.0 )
+#define NREALSCALE ( 2.0 / 4096.0 )
+#define HASH3D(a,b,c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
+#define HASH(a,b,c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
+#define INCRSUM(m,s,x,y,z) ((s)*(RTable[m]*0.5 \
+ + RTable[m+1]*(x) \
+ + RTable[m+2]*(y) \
+ + RTable[m+3]*(z)))
+#define MAXSIZE 500
+#define nrand() ((float)rand()/(float)RAND_MAX)
+#define seednrand(x) srand(x*RAND_MAX)
+
+#define BM 0xff
+
+#define N 0x1000
+#define NP 12 /* 2^N */
+#define NM 0xfff
+
+#define s_curve(t) ( t * t * (3. - 2. * t) )
+
+#define lerp(t, a, b) ( a + t * (b - a) )
+
+#define setup(i,b0,b1,r0,r1)\
+ t = i + N;\
+ b0 = ((int)t) & BM;\
+ b1 = (b0+1) & BM;\
+ r0 = t - (int)t;\
+ r1 = r0 - 1.;
+
+void normalize2(float v[2])
+{
+ float s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+}
+
+void normalize3(float v[3])
+{
+ float s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+ v[2] = v[2] / s;
+}
+
+float Noise::turbulence1(float arg, float freq, float amp, unsigned oct)
+{
+ float t;
+ float vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
+ {
+ vec = freq * arg;
+ t += smoothNoise1(vec) * amp;
+ }
+ return t;
+}
+
+float Noise::turbulence2(Vec2f& v, float freq, float amp, unsigned oct)
+{
+ float t;
+ Vec2f vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
+ {
+ vec.x() = freq * v.x();
+ vec.y() = freq * v.y();
+ t += smoothNoise2(vec) * amp;
+ }
+ return t;
+}
+
+float Noise::turbulence3(Vec3f& v, float freq, float amp, unsigned oct)
+{
+ float t;
+ Vec3f vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
+ {
+ vec.x() = freq * v.x();
+ vec.y() = freq * v.y();
+ vec.z() = freq * v.z();
+ t += smoothNoise3(vec) * amp;
+ }
+ return t;
+}
+
+// Noise functions over 1, 2, and 3 dimensions
+
+float Noise::smoothNoise1(float arg)
+{
+ int bx0, bx1;
+ float rx0, rx1, sx, t, u, v, vec;
+
+ vec = arg;
+ setup(vec, bx0,bx1, rx0,rx1);
+
+ sx = s_curve(rx0);
+
+ u = rx0 * g1[ p[ bx0 ] ];
+ v = rx1 * g1[ p[ bx1 ] ];
+
+ return lerp(sx, u, v);
+}
+
+float Noise::smoothNoise2(Vec2f& vec)
+{
+ int bx0, bx1, by0, by1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
+ register int i, j;
+
+ setup(vec.x(), bx0,bx1, rx0,rx1);
+ setup(vec.y(), by0,by1, ry0,ry1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+ sx = s_curve(rx0);
+ sy = s_curve(ry0);
+
+#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
+
+ q = g2[ b00 ] ; u = at2(rx0,ry0);
+ q = g2[ b10 ] ; v = at2(rx1,ry0);
+ a = lerp(sx, u, v);
+
+ q = g2[ b01 ] ; u = at2(rx0,ry1);
+ q = g2[ b11 ] ; v = at2(rx1,ry1);
+ b = lerp(sx, u, v);
+
+ return lerp(sy, a, b);
+}
+
+float Noise::smoothNoise3(Vec3f& vec)
+{
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
+ register int i, j;
+
+ setup(vec.x(), bx0,bx1, rx0,rx1);
+ setup(vec.y(), by0,by1, ry0,ry1);
+ setup(vec.z(), bz0,bz1, rz0,rz1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+ t = s_curve(rx0);
+ sy = s_curve(ry0);
+ sz = s_curve(rz0);
+
+#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
+
+ q = g3[ b00 + bz0 ] ;
+ u = at3(rx0,ry0,rz0);
+ q = g3[ b10 + bz0 ] ;
+ v = at3(rx1,ry0,rz0);
+ a = lerp(t, u, v);
+
+ q = g3[ b01 + bz0 ] ;
+ u = at3(rx0,ry1,rz0);
+ q = g3[ b11 + bz0 ] ;
+ v = at3(rx1,ry1,rz0);
+ b = lerp(t, u, v);
+
+ c = lerp(sy, a, b);
+
+ q = g3[ b00 + bz1 ] ;
+ u = at3(rx0,ry0,rz1);
+ q = g3[ b10 + bz1 ] ;
+ v = at3(rx1,ry0,rz1);
+ a = lerp(t, u, v);
+
+ q = g3[ b01 + bz1 ] ;
+ u = at3(rx0,ry1,rz1);
+ q = g3[ b11 + bz1 ] ;
+ v = at3(rx1,ry1,rz1);
+ b = lerp(t, u, v);
+
+ d = lerp(sy, a, b);
+
+ return lerp(sz, c, d);
+}
+
+Noise::Noise(long seed)
+{
+ int i, j, k;
+
+ seednrand((seed < 0) ? time(NULL) : seed);
+ for (i = 0 ; i < _Noise_B_ ; i++)
+ {
+ p[i] = i;
+
+ g1[i] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
+
+ for (j = 0 ; j < 2 ; j++)
+ g2[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
+ normalize2(g2[i]);
+
+ for (j = 0 ; j < 3 ; j++)
+ g3[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
+ normalize3(g3[i]);
+ }
+
+ while (--i)
+ {
+ k = p[i];
+ p[i] = p[j = rand() % _Noise_B_];
+ p[j] = k;
+ }
+
+ for (i = 0 ; i < _Noise_B_ + 2 ; i++)
+ {
+ p[_Noise_B_ + i] = p[i];
+ g1[_Noise_B_ + i] = g1[i];
+ for (j = 0 ; j < 2 ; j++)
+ g2[_Noise_B_ + i][j] = g2[i][j];
+ for (j = 0 ; j < 3 ; j++)
+ g3[_Noise_B_ + i][j] = g3[i][j];
+ }
+}
diff --git a/source/blender/freestyle/intern/geometry/Noise.h b/source/blender/freestyle/intern/geometry/Noise.h
new file mode 100755
index 00000000000..f92cf07e914
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Noise.h
@@ -0,0 +1,77 @@
+//
+// Filename : Noise.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Class to define Perlin noise
+// Date of creation : 12/01/2004
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef NOISE_H
+# define NOISE_H
+
+
+# include "../system/FreestyleConfig.h"
+# include "Geom.h"
+
+#define _Noise_B_ 0x100
+
+using namespace Geometry;
+using namespace std;
+
+/*! Class to provide Perlin Noise functionalities */
+class LIB_GEOMETRY_EXPORT Noise
+{
+ public:
+
+ /*! Builds a Noise object */
+ Noise(long seed = -1);
+ /*! Destructor */
+ ~Noise() {}
+
+ /*! Returns a noise value for a 1D element */
+ float turbulence1(float arg, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a noise value for a 2D element */
+ float turbulence2(Vec2f& v, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a noise value for a 3D element */
+ float turbulence3(Vec3f& v, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a smooth noise value for a 1D element */
+ float smoothNoise1(float arg);
+ /*! Returns a smooth noise value for a 2D element */
+ float smoothNoise2(Vec2f& vec);
+ /*! Returns a smooth noise value for a 3D element */
+ float smoothNoise3(Vec3f& vec);
+
+ private:
+
+ int p[ _Noise_B_ + _Noise_B_ + 2];
+ float g3[ _Noise_B_ + _Noise_B_ + 2][3];
+ float g2[ _Noise_B_ + _Noise_B_ + 2][2];
+ float g1[ _Noise_B_ + _Noise_B_ + 2];
+ int start;
+};
+
+#endif // NOISE_H
diff --git a/source/blender/freestyle/intern/geometry/Polygon.h b/source/blender/freestyle/intern/geometry/Polygon.h
new file mode 100755
index 00000000000..911804d80f7
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Polygon.h
@@ -0,0 +1,214 @@
+//
+// Filename : Polygon.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a polygon
+// Date of creation : 30/07/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef POLYGON_H
+# define POLYGON_H
+
+# include <vector>
+# include "Geom.h"
+# include "GeomUtils.h"
+
+using namespace std;
+
+namespace Geometry {
+
+template <class Point>
+class Polygon
+{
+ public:
+
+ inline Polygon() {
+ _id = 0;
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ inline Polygon(const vector<Point>& vertices) {
+ _vertices = vertices;
+ computeBBox();
+ _id = 0;
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ inline Polygon(const Polygon<Point>& poly) {
+ Point p;
+ for(typename vector<Point>::const_iterator it = poly.getVertices().begin();
+ it != poly.getVertices().end();
+ it++) {
+ p = *it;
+ _vertices.push_back(p);
+ }
+
+ _id = poly.getId();
+ poly.getBBox(_min, _max);
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ virtual ~Polygon() {}
+
+ //
+ // Accessors
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline const vector<Point>& getVertices() const {
+ return _vertices;
+ }
+
+ inline void getBBox(Point& min, Point& max) const {
+ min = _min;
+ max = _max;
+ }
+
+ inline Point& getBBoxCenter()
+ {
+ Point result;
+ result = (_min + _max) / 2;
+ return result;
+ }
+
+ inline Point& getCenter() {
+ Point result;
+ for (typename vector<Point>::iterator it = _vertices.begin();
+ it != _vertices.end();
+ it++)
+ result += *it;
+ result /= _vertices.size();
+ return result;
+ }
+
+ inline unsigned getId() const {
+ return _id;
+ }
+
+ //
+ // Modifiers
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline void setVertices(const vector<Point>& vertices) {
+ _vertices.clear();
+ Point p;
+ for (typename vector<Point>::const_iterator it = vertices.begin();
+ it != vertices.end();
+ it++) {
+ p = *it;
+ _vertices.push_back(p);
+ }
+ computeBBox();
+ }
+
+ inline void setId(unsigned id) {
+ _id = id;
+ }
+
+ //
+ // Other methods
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline void computeBBox() {
+ if(_vertices.empty())
+ return;
+
+ _max = _vertices[0];
+ _min = _vertices[0];
+
+ for(typename vector<Point>::iterator it = _vertices.begin();
+ it != _vertices.end();
+ it++) {
+ for(unsigned i = 0; i < Point::dim(); i++) {
+ if((*it)[i] > _max[i])
+ _max[i] = (*it)[i];
+ if((*it)[i] < _min[i])
+ _min[i] = (*it)[i];
+ }
+ }
+ }
+
+ // FIXME Is it possible to get rid of userdatas ?
+ void* userdata;
+ void* userdata2; // Used during ray casting
+
+ protected:
+
+ vector<Point> _vertices;
+ Point _min;
+ Point _max;
+ unsigned _id;
+};
+
+
+//
+// Polygon3r class
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class Polygon3r : public Polygon<Vec3r>
+{
+ public:
+ inline Polygon3r() : Polygon<Vec3r>() {}
+
+ inline Polygon3r(const vector<Vec3r>& vertices,
+ const Vec3r& normal) : Polygon<Vec3r>(vertices) {
+ setNormal(normal);
+ }
+
+ inline Polygon3r(const Polygon3r& poly) : Polygon<Vec3r>(poly), _normal(poly._normal) {}
+
+ virtual ~Polygon3r() {}
+
+ void setNormal(const Vec3r& normal) {
+ _normal = normal;
+ }
+
+ inline Vec3r getNormal() const {
+ return _normal;
+ }
+
+ /*! Check whether the Polygon intersects with the ray or not */
+ inline bool rayIntersect(const Vec3r& orig, const Vec3r& dir,
+ real& t, real& u, real& v, real epsilon = M_EPSILON) const {
+ // if (_vertices.size() < 3)
+ // return false;
+ return GeomUtils::intersectRayTriangle(orig, dir,
+ _vertices[0], _vertices[1], _vertices[2],
+ t, u, v, epsilon);
+ }
+
+ private:
+
+ Vec3r _normal;
+};
+
+} // end of namespace Geometry
+
+#endif // POLYGON_H
diff --git a/source/blender/freestyle/intern/geometry/SweepLine.h b/source/blender/freestyle/intern/geometry/SweepLine.h
new file mode 100755
index 00000000000..deecf3c5485
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/SweepLine.h
@@ -0,0 +1,325 @@
+//
+// Filename : SweepLine.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a Sweep Line
+// Date of creation : 29/08/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SWEEPLINE_H
+# define SWEEPLINE_H
+
+# include <list>
+# include <vector>
+
+/*! Class to define the intersection berween two segments*/
+template<class Edge>
+class Intersection
+{
+public:
+
+ template<class EdgeClass>
+ Intersection(EdgeClass* eA, real ta, EdgeClass* eB, real tb)
+ {
+ EdgeA = eA;
+ EdgeB = eB;
+ tA = ta;
+ tB = tb;
+ userdata = 0;
+ }
+
+ Intersection(const Intersection& iBrother)
+ {
+ EdgeA = iBrother.EdgeA;
+ EdgeB = iBrother.EdgeB;
+ tA = iBrother.tA;
+ tB = iBrother.tB;
+ userdata = 0;
+ }
+
+ /*! returns the parameter giving the
+ * intersection, for the edge iEdge
+ */
+ real getParameter(Edge *iEdge)
+ {
+ if(iEdge == EdgeA)
+ return tA;
+ if(iEdge == EdgeB)
+ return tB;
+ return 0;
+ }
+
+public:
+ void * userdata; // FIXME
+
+ Edge *EdgeA; // first segment
+ Edge *EdgeB; // second segment
+ real tA; // parameter defining the intersection point with respect to the segment EdgeA.
+ real tB; // parameter defining the intersection point with respect to the segment EdgeB.
+};
+
+
+
+
+
+
+
+
+template<class T, class Point>
+class Segment
+{
+ public:
+ Segment()
+ {
+ }
+ Segment(T& s, const Point& iA, const Point& iB)
+ {
+ _edge = s;
+ if(iA < iB)
+ {
+ A = iA;
+ B = iB;
+ _order = true;
+ }
+ else
+ {
+ A = iB;
+ B = iA;
+ _order = false;
+ }
+ }
+
+ Segment(Segment<T,Point>& iBrother)
+ {
+ _edge = iBrother.edge();
+ A = iBrother.A;
+ B = iBrother.B;
+ _Intersections = iBrother._Intersections;
+ _order = iBrother._order;
+ }
+
+ Segment(const Segment<T,Point>& iBrother)
+ {
+ _edge = iBrother._edge;
+ A = iBrother.A;
+ B = iBrother.B;
+ _Intersections = iBrother._Intersections;
+ _order = iBrother._order;
+ }
+
+ ~Segment() {
+ _Intersections.clear();
+ }
+
+ inline Point operator[](const unsigned short int& i) const
+ {
+ return i%2==0 ? A : B;
+ }
+
+ inline bool operator==(const Segment<T,Point>& iBrother)
+ {
+ if(_edge == iBrother._edge)
+ return true;
+
+ return false;
+ }
+
+ /* Adds an intersection for this segment */
+ inline void AddIntersection(Intersection<Segment<T,Point> > *i) {_Intersections.push_back(i);}
+
+ /*! Checks for a common vertex with another edge */
+ inline bool CommonVertex(const Segment<T,Point>& S, Point& CP)
+ {
+ if((A == S[0]) || (A == S[1]))
+ {
+ CP = A;
+ return true;
+ }
+ if((B == S[0]) || (B == S[1]))
+ {
+ CP = B;
+ return true;
+ }
+
+ return false;
+ }
+
+ inline vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;}
+ inline bool order() {return _order;}
+ inline T& edge() {return _edge;}
+
+ private:
+ T _edge;
+ Point A;
+ Point B;
+ std::vector<Intersection<Segment<T,Point> >*> _Intersections; // list of intersections parameters
+ bool _order; // true if A and B are in the same order than _edge.A and _edge.B. false otherwise.
+};
+
+/*! defines a binary function that can be overload
+ * by the user to specify at each condition
+ * the intersection between 2 edges must be computed
+ */
+template<class T1, class T2>
+struct binary_rule
+{
+ binary_rule() {}
+ template<class T3,class T4>
+ binary_rule(const binary_rule<T3,T4>& brother) {}
+ virtual ~binary_rule() {}
+
+ virtual bool operator()(T1&, T2&)
+ {
+ return true;
+ }
+};
+
+
+template<class T,class Point>
+class SweepLine
+{
+public:
+
+ SweepLine() {}
+ ~SweepLine()
+ {
+ for(typename vector<Intersection<Segment<T,Point> >*>::iterator i=_Intersections.begin(),iend=_Intersections.end();
+ i!=iend;
+ i++)
+ {
+ delete (*i);
+ }
+ }
+
+
+ inline void process(Point& p,
+ vector<Segment<T,Point>*>& segments,
+ binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
+ //binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>,Segment<T,Point> >(),
+ real epsilon = M_EPSILON
+ )
+ {
+ // first we remove the segments that need to be removed and then
+ // we add the segments to add
+ vector<Segment<T,Point>*> toadd;
+ typename vector<Segment<T,Point>*>::iterator s, send;
+ for(s=segments.begin(), send=segments.end();
+ s!=send;
+ s++)
+ {
+ if(p == (*(*s))[0])
+ toadd.push_back((*s));
+ else
+ remove((*s));
+ }
+ for(s=toadd.begin(), send=toadd.end();
+ s!=send;
+ s++)
+ {
+ add((*s), binrule, epsilon);
+ }
+ }
+
+ inline void add(Segment<T,Point>* S,
+ binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
+ //binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>, Segment<T,Point> >(),
+ real epsilon
+ )
+ {
+ real t,u;
+ Point CP;
+ Vec2r v0, v1, v2, v3;
+ if(true == S->order())
+ {
+ v0[0] = ((*S)[0])[0];
+ v0[1] = ((*S)[0])[1];
+ v1[0] = ((*S)[1])[0];
+ v1[1] = ((*S)[1])[1];
+ }
+ else
+ {
+ v1[0] = ((*S)[0])[0];
+ v1[1] = ((*S)[0])[1];
+ v0[0] = ((*S)[1])[0];
+ v0[1] = ((*S)[1])[1];
+ }
+ for(typename std::list<Segment<T,Point>* >::iterator s=_set.begin(), send=_set.end();
+ s!=send;
+ s++)
+ {
+ Segment<T,Point>* currentS = (*s);
+ if(true != binrule(*S, *currentS))
+ continue;
+
+ if(true == currentS->order())
+ {
+ v2[0] = ((*currentS)[0])[0];
+ v2[1] = ((*currentS)[0])[1];
+ v3[0] = ((*currentS)[1])[0];
+ v3[1] = ((*currentS)[1])[1];
+ }
+ else
+ {
+ v3[0] = ((*currentS)[0])[0];
+ v3[1] = ((*currentS)[0])[1];
+ v2[0] = ((*currentS)[1])[0];
+ v2[1] = ((*currentS)[1])[1];
+ }
+ if(S->CommonVertex(*currentS, CP))
+ continue; // the two edges have a common vertex->no need to check
+
+ if(GeomUtils::intersect2dSeg2dSegParametric(v0, v1, v2, v3, t, u, epsilon) == GeomUtils::DO_INTERSECT)
+ {
+ // create the intersection
+ Intersection<Segment<T,Point> > * inter = new Intersection<Segment<T,Point> >(S,t,currentS,u);
+ // add it to the intersections list
+ _Intersections.push_back(inter);
+ // add this intersection to the first edge intersections list
+ S->AddIntersection(inter);
+ // add this intersection to the second edge intersections list
+ currentS->AddIntersection(inter);
+ }
+ }
+ // add the added segment to the list of active segments
+ _set.push_back(S);
+ }
+
+ inline void remove(Segment<T,Point>* s)
+ {
+ if(s->intersections().size() > 0)
+ _IntersectedEdges.push_back(s);
+ _set.remove(s);
+ }
+
+ vector<Segment<T,Point>* >& intersectedEdges() {return _IntersectedEdges;}
+ vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;}
+
+
+private:
+ std::list<Segment<T,Point>* > _set; // set of active edges for a given position of the sweep line
+ std::vector<Segment<T,Point>* > _IntersectedEdges; // the list of intersected edges
+ std::vector<Intersection<Segment<T,Point> >*> _Intersections; // the list of all intersections.
+};
+
+#endif // SWEEPLINE_H
diff --git a/source/blender/freestyle/intern/geometry/VecMat.h b/source/blender/freestyle/intern/geometry/VecMat.h
new file mode 100755
index 00000000000..9bbec3b1349
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/VecMat.h
@@ -0,0 +1,899 @@
+//
+// Filename : VecMat.h
+// Author(s) : Sylvain Paris
+// Emmanuel Turquin
+// Stephane Grabli
+// Purpose : Vectors and Matrices definition and manipulation
+// Date of creation : 12/06/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VECMAT_H
+# define VECMAT_H
+
+# include <math.h>
+# include <vector>
+# include <iostream>
+
+namespace VecMat {
+
+ namespace Internal {
+
+ template <bool B>
+ struct is_false {};
+
+ template <>
+ struct is_false<false> {
+ static inline void ensure() {}
+ };
+
+ } // end of namespace Internal
+
+ //
+ // Vector class
+ // - T: value type
+ // - N: dimension
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T, unsigned N>
+ class Vec
+ {
+ public:
+
+ typedef T value_type;
+
+ // constructors
+
+ inline Vec() {
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = 0;
+ }
+
+ ~Vec() {
+ Internal::is_false<(N == 0)>::ensure();
+ }
+
+ template <class U>
+ explicit inline Vec(const U tab[N]) {
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = (T)tab[i];
+ }
+
+ template <class U>
+ explicit inline Vec(const std::vector<U>& tab) {
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = (T)tab[i];
+ }
+
+ template <class U>
+ explicit inline Vec(const Vec<U, N>& v) {
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = (T)v[i];
+ }
+
+ // accessors
+
+ inline value_type operator[](const unsigned i) const {
+ return this->_coord[i];
+ }
+
+ inline value_type& operator[](const unsigned i) {
+ return this->_coord[i];
+ }
+
+ static inline unsigned dim() {
+ return N;
+ }
+
+ // various useful methods
+
+ inline value_type norm() const {
+ return (T)sqrt((float)squareNorm());
+ }
+
+ inline value_type squareNorm() const {
+ return (*this) * (*this);
+ }
+
+ inline Vec<T, N>& normalize() {
+ value_type n = norm();
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] /= n;
+ return *this;
+ }
+
+ inline Vec<T, N>& normalizeSafe() {
+ value_type n = norm();
+ if (n)
+ for (unsigned i=0; i < N; i++)
+ this->_coord[i] /= n;
+ return *this;
+ }
+
+ // classical operators
+ inline Vec<T, N> operator+(const Vec<T, N>& v) const{
+ Vec<T, N> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec<T, N> operator-(const Vec<T,N>& v) const{
+ Vec<T, N> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec<T, N> operator*(const typename Vec<T,N>::value_type r) const{
+ Vec<T, N> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec<T, N> operator/(const typename Vec<T,N>::value_type r) const{
+ Vec<T, N> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec<T, N>& v) const{
+ value_type sum = 0;
+ for (unsigned i = 0; i < N; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator=(const Vec<U, N>& v) {
+ if (this != &v)
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator+=(const Vec<U, N>& v) {
+ for (unsigned i = 0 ; i < N; i++)
+ this->_coord[i] += (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator-=(const Vec<U, N>& v) {
+ for (unsigned i = 0 ; i < N; i++)
+ this->_coord[i] -= (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator*=(const U r) {
+ for (unsigned i = 0 ; i < N; i++)
+ this->_coord[i] *= r;
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator/=(const U r) {
+ if (r)
+ for (unsigned i = 0 ; i < N; i++)
+ this->_coord[i] /= r;
+ return *this;
+ }
+
+
+ inline bool operator==(const Vec<T, N>& v) const {
+ for(unsigned i = 0; i < N; i++)
+ if (this->_coord[i] != v[i])
+ return false;
+ return true;
+ }
+
+ inline bool operator!=(const Vec<T, N>& v) const {
+ for(unsigned i = 0; i < N; i++)
+ if (this->_coord[i] != v[i])
+ return true;
+ return false;
+ }
+
+ inline bool operator<(const Vec<T, N>& v) const {
+ for (unsigned i = 0; i<N; i++) {
+ if (this->_coord[i] < v[i])
+ return true;
+ if (this->_coord[i] > v[i])
+ return false;
+ if (this->_coord[i] == v[i])
+ continue;
+ }
+ return false;
+ }
+
+ inline bool operator>(const Vec<T, N>& v) const {
+ for (unsigned i=0; i<N; i++) {
+ if(this->_coord[i] > v[i])
+ return true;
+ if(this->_coord[i] < v[i])
+ return false;
+ if(this->_coord[i] == v[i])
+ continue;
+ }
+ return false;
+ }
+
+ protected:
+
+ value_type _coord[N];
+ enum {
+ _dim = N,
+ };
+ };
+
+
+ //
+ // Vec2 class (2D Vector)
+ // - T: value type
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class Vec2 : public Vec<T, 2>
+ {
+ public:
+
+ typedef typename Vec<T, 2>::value_type value_type;
+
+ inline Vec2() : Vec<T, 2>() {}
+
+ template <class U>
+ explicit inline Vec2(const U tab[2]) : Vec<T, 2>(tab) {}
+
+ template <class U>
+ explicit inline Vec2(const std::vector<U>& tab) : Vec<T, 2>(tab) {}
+
+ template <class U>
+ inline Vec2(const Vec<U, 2>& v) : Vec<T, 2>(v) {}
+
+ inline Vec2(const value_type x,
+ const value_type y = 0) : Vec<T, 2>() {
+ this->_coord[0] = (T)x;
+ this->_coord[1] = (T)y;
+ }
+
+ inline value_type x() const {
+ return this->_coord[0];
+ }
+
+ inline value_type& x() {
+ return this->_coord[0];
+ }
+
+ inline value_type y() const {
+ return this->_coord[1];
+ }
+
+ inline value_type& y() {
+ return this->_coord[1];
+ }
+
+ inline void setX(const value_type v) {
+ this->_coord[0] = v;
+ }
+
+ inline void setY(const value_type v) {
+ this->_coord[1] = v;
+ }
+
+ // FIXME: hack swig -- no choice
+ inline Vec2<T> operator+(const Vec2<T>& v) const{
+ Vec2<T> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec2<T> operator-(const Vec2<T>& v) const{
+ Vec2<T> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec2<T> operator*(const value_type r) const{
+ Vec2<T> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec2<T> operator/(const value_type r) const{
+ Vec2<T> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec2<T>& v) const{
+ value_type sum = 0;
+ for (unsigned i = 0; i < 2; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+ };
+
+
+ //
+ // HVec3 class (3D Vector in homogeneous coordinates)
+ // - T: value type
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class HVec3 : public Vec<T, 4>
+ {
+ public:
+
+ typedef typename Vec<T, 4>::value_type value_type;
+
+ inline HVec3() : Vec<T, 4>() {}
+
+ template <class U>
+ explicit inline HVec3(const U tab[4]) : Vec<T, 4>(tab) {}
+
+ template <class U>
+ explicit inline HVec3(const std::vector<U>& tab) : Vec<T, 4>(tab) {}
+
+ template<class U>
+ inline HVec3(const Vec<U, 4>& v) : Vec<T, 4>(v) {}
+
+ inline HVec3(const value_type sx,
+ const value_type sy = 0,
+ const value_type sz = 0,
+ const value_type s = 1) {
+ this->_coord[0] = sx;
+ this->_coord[1] = sy;
+ this->_coord[2] = sz;
+ this->_coord[3] = s;
+ }
+
+ template <class U>
+ inline HVec3(const Vec<U, 3>& sv,
+ const U s = 1) {
+ this->_coord[0] = (T)sv[0];
+ this->_coord[1] = (T)sv[1];
+ this->_coord[2] = (T)sv[2];
+ this->_coord[3] = (T)s;
+ }
+
+ inline value_type sx() const {
+ return this->_coord[0];
+ }
+
+ inline value_type& sx() {
+ return this->_coord[0];
+ }
+
+ inline value_type sy() const {
+ return this->_coord[1];
+ }
+
+ inline value_type& sy() {
+ return this->_coord[1];
+ }
+
+ inline value_type sz() const {
+ return this->_coord[2];
+ }
+
+ inline value_type& sz() {
+ return this->_coord[2];
+ }
+
+ inline value_type s() const {
+ return this->_coord[3];
+ }
+
+ inline value_type& s() {
+ return this->_coord[3];
+ }
+
+ // Acces to non-homogeneous coordinates in 3D
+
+ inline value_type x() const {
+ return this->_coord[0] / this->_coord[3];
+ }
+
+ inline value_type y() const {
+ return this->_coord[1] / this->_coord[3];
+ }
+
+ inline value_type z() const {
+ return this->_coord[2] / this->_coord[3];
+ }
+ };
+
+
+ //
+ // Vec3 class (3D Vec)
+ // - T: value type
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class Vec3 : public Vec<T, 3>
+ {
+ public:
+
+ typedef typename Vec<T, 3>::value_type value_type;
+
+ inline Vec3() : Vec<T, 3>() {}
+
+ template <class U>
+ explicit inline Vec3(const U tab[3]) : Vec<T, 3>(tab) {}
+
+ template <class U>
+ explicit inline Vec3(const std::vector<U>& tab) : Vec<T, 3>(tab) {}
+
+ template<class U>
+ inline Vec3(const Vec<U, 3>& v) : Vec<T, 3>(v) {}
+
+ template<class U>
+ inline Vec3(const HVec3<U>& v) {
+ this->_coord[0] = (T)v.x();
+ this->_coord[1] = (T)v.y();
+ this->_coord[2] = (T)v.z();
+ }
+
+ inline Vec3(const value_type x,
+ const value_type y = 0,
+ const value_type z = 0) : Vec<T, 3>() {
+ this->_coord[0] = x;
+ this->_coord[1] = y;
+ this->_coord[2] = z;
+ }
+
+ inline value_type x() const {
+ return this->_coord[0];
+ }
+
+ inline value_type& x() {
+ return this->_coord[0];
+ }
+
+ inline value_type y() const {
+ return this->_coord[1];
+ }
+
+ inline value_type& y() {
+ return this->_coord[1];
+ }
+
+ inline value_type z() const {
+ return this->_coord[2];
+ }
+
+ inline value_type& z() {
+ return this->_coord[2];
+ }
+
+ inline void setX(const value_type v) {
+ this->_coord[0] = v;
+ }
+
+ inline void setY(const value_type v) {
+ this->_coord[1] = v;
+ }
+
+ inline void setZ(const value_type v) {
+ this->_coord[2] = v;
+ }
+
+ // classical operators
+ // FIXME: hack swig -- no choice
+ inline Vec3<T> operator+(const Vec3<T>& v) const{
+ Vec3<T> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec3<T> operator-(const Vec3<T>& v) const{
+ Vec3<T> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec3<T> operator*(const value_type r) const{
+ Vec3<T> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec3<T> operator/(const value_type r) const{
+ Vec3<T> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec3<T>& v) const{
+ value_type sum = 0;
+ for (unsigned i = 0; i < 3; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+
+ // cross product for 3D Vectors
+ // FIXME: hack swig -- no choice
+ inline Vec3<T> operator^(const Vec3<T>& v) const{
+ Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
+ (*this)[2] * v[0] - (*this)[0] * v[2],
+ (*this)[0] * v[1] - (*this)[1] * v[0]);
+ return res;
+ }
+
+ // cross product for 3D Vectors
+ template <typename U>
+ inline Vec3<T> operator^(const Vec<U, 3>& v) const{
+ Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
+ (*this)[2] * v[0] - (*this)[0] * v[2],
+ (*this)[0] * v[1] - (*this)[1] * v[0]);
+ return res;
+ }
+ };
+
+
+ //
+ // Matrix class
+ // - T: value type
+ // - M: rows
+ // - N: cols
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ // Dirty, but icc under Windows needs this
+# define _SIZE (M * N)
+
+ template <class T, unsigned M, unsigned N>
+ class Matrix
+ {
+ public:
+
+ typedef T value_type;
+
+ inline Matrix() {
+ for (unsigned i = 0; i < _SIZE; i++)
+ this->_coord[i] = 0;
+ }
+
+ ~Matrix() {
+ Internal::is_false<(M == 0)>::ensure();
+ Internal::is_false<(N == 0)>::ensure();
+ }
+
+ template <class U>
+ explicit inline Matrix(const U tab[_SIZE]) {
+ for (unsigned i = 0; i < _SIZE; i++)
+ this->_coord[i] = tab[i];
+ }
+
+ template <class U>
+ explicit inline Matrix(const std::vector<U>& tab) {
+ for (unsigned i = 0; i < _SIZE; i++)
+ this->_coord[i] = tab[i];
+ }
+
+ template <class U>
+ inline Matrix(const Matrix<U, M, N>& m) {
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] = (T)m(i, j);
+ }
+
+ inline value_type operator()(const unsigned i, const unsigned j) const {
+ return this->_coord[i * N + j];
+ }
+
+ inline value_type& operator()(const unsigned i, const unsigned j) {
+ return this->_coord[i * N + j];
+ }
+
+ static inline unsigned rows() {
+ return M;
+ }
+
+ static inline unsigned cols() {
+ return N;
+ }
+
+ inline Matrix<T, M, N>& transpose() const {
+ Matrix<T, N, M> res;
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ res(j,i) = this->_coord[i * N + j];
+ return res;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator=(const Matrix<U, M, N>& m) {
+ if (this != &m)
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] = (T)m(i, j);
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator+=(const Matrix<U, M, N>& m) {
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] += (T)m(i, j);
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator-=(const Matrix<U, M, N>& m) {
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] -= (T)m(i, j);
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator*=(const U lambda) {
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] *= lambda;
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator/=(const U lambda) {
+ if (lambda)
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] /= lambda;
+ return *this;
+ }
+
+ protected:
+
+ value_type _coord[_SIZE];
+ };
+
+
+ //
+ // SquareMatrix class
+ // - T: value type
+ // - N: rows & cols
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ // Dirty, but icc under Windows needs this
+# define __SIZE (N * N)
+
+ template <class T, unsigned N>
+ class SquareMatrix : public Matrix<T, N, N>
+ {
+ public:
+
+ typedef T value_type;
+
+ inline SquareMatrix() : Matrix<T, N, N>() {}
+
+ template <class U>
+ explicit inline SquareMatrix(const U tab[__SIZE]) : Matrix<T, N, N>(tab) {}
+
+ template <class U>
+ explicit inline SquareMatrix(const std::vector<U>& tab) : Matrix<T, N, N>(tab) {}
+
+ template <class U>
+ inline SquareMatrix(const Matrix<U, N, N>& m) : Matrix<T, N, N>(m) {}
+
+ static inline SquareMatrix<T, N> identity() {
+ SquareMatrix<T, N> res;
+ for (unsigned i = 0; i < N; i++)
+ res(i, i) = 1;
+ return res;
+ }
+ };
+
+
+ //
+ // Vector external functions
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ // template <class T, unsigned N>
+ // inline Vec<T, N> operator+(const Vec<T, N>& v1,
+ // const Vec<T, N>& v2) {
+ // Vec<T, N> res(v1);
+ // res += v2;
+ // return res;
+ // }
+ //
+ // template <class T, unsigned N>
+ // inline Vec<T, N> operator-(const Vec<T, N>& v1,
+ // const Vec<T, N>& v2) {
+ // Vec<T, N> res(v1);
+ // res -= v2;
+ // return res;
+ // }
+ // template <class T, unsigned N>
+ // inline Vec<T, N> operator*(const Vec<T, N>& v,
+ // const typename Vec<T, N>::value_type r) {
+ // Vec<T, N> res(v);
+ // res *= r;
+ // return res;
+ // }
+
+ template <class T, unsigned N>
+ inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r,
+ const Vec<T, N>& v) {
+ Vec<T, N> res(v);
+ res *= r;
+ return res;
+ }
+ //
+ // template <class T, unsigned N>
+ // inline Vec<T, N> operator/(const Vec<T, N>& v,
+ // const typename Vec<T, N>::value_type r) {
+ // Vec<T, N> res(v);
+ // if (r)
+ // res /= r;
+ // return res;
+ // }
+ //
+ // dot product
+ // template <class T, unsigned N>
+ // inline typename Vec<T, N>::value_type operator*(const Vec<T, N>& v1,
+ // const Vec<T, N>& v2) {
+ // typename Vec<T, N>::value_type sum = 0;
+ // for (unsigned i = 0; i < N; i++)
+ // sum += v1[i] * v2[i];
+ // return sum;
+ // }
+ //
+ // // cross product for 3D Vectors
+ // template <typename T>
+ // inline Vec3<T> operator^(const Vec<T, 3>& v1,
+ // const Vec<T, 3>& v2) {
+ // Vec3<T> res(v1[1] * v2[2] - v1[2] * v2[1],
+ // v1[2] * v2[0] - v1[0] * v2[2],
+ // v1[0] * v2[1] - v1[1] * v2[0]);
+ // return res;
+ // }
+
+ // stream operator
+ template <class T, unsigned N>
+ inline std::ostream& operator<<(std::ostream& s,
+ const Vec<T, N>& v) {
+ unsigned i;
+ s << "[";
+ for (i = 0; i < N - 1; i++)
+ s << v[i] << ", ";
+ s << v[i] << "]";
+ return s;
+ }
+
+
+ //
+ // Matrix external functions
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator+(const Matrix<T, M, N>& m1,
+ const Matrix<T, M, N>& m2) {
+ Matrix<T, M, N> res(m1);
+ res += m2;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator-(const Matrix<T, M, N>& m1,
+ const Matrix<T, M, N>& m2) {
+ Matrix<T, M, N> res(m1);
+ res -= m2;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator*(const Matrix<T, M, N>& m1,
+ const typename Matrix<T, M, N>::value_type lambda) {
+ Matrix<T, M, N> res(m1);
+ res *= lambda;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator*(const typename Matrix<T, M, N>::value_type lambda,
+ const Matrix<T, M, N>& m1) {
+ Matrix<T, M, N> res(m1);
+ res *= lambda;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator/(const Matrix<T, M, N>& m1,
+ const typename Matrix<T, M, N>::value_type lambda) {
+ Matrix<T, M, N> res(m1);
+ res /= lambda;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N, unsigned P>
+ inline Matrix<T, M, P>
+ operator*(const Matrix<T, M, N>& m1,
+ const Matrix<T, N, P>& m2) {
+ unsigned i, j, k;
+ Matrix<T, M, P> res;
+ typename Matrix<T, N, P>::value_type scale;
+
+ for (j = 0; j < P; j++) {
+ for (k = 0; k < N; k++) {
+ scale = m2(k, j);
+ for (i = 0; i < N; i++)
+ res(i, j) += m1(i, k) * scale;
+ }
+ }
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Vec<T, M>
+ operator*(const Matrix<T, M, N>& m,
+ const Vec<T, N>& v) {
+
+ Vec<T, M> res;
+ typename Matrix<T, M, N>::value_type scale;
+
+ for (unsigned j = 0; j < M; j++) {
+ scale = v[j];
+ for (unsigned i = 0; i < N; i++)
+ res[i] += m(i, j) * scale;
+ }
+ return res;
+ }
+
+ // stream operator
+ template <class T, unsigned M, unsigned N>
+ inline std::ostream& operator<<(std::ostream& s,
+ const Matrix<T, M, N>& m) {
+ unsigned i, j;
+ for (i = 0; i < M; i++) {
+ s << "[";
+ for (j = 0; j < N - 1; j++)
+ s << m(i, j) << ", ";
+ s << m(i, j) << "]" << std::endl;
+ }
+ return s;
+ }
+
+} // end of namespace VecMat
+
+#endif // VECMAT_H
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.cpp b/source/blender/freestyle/intern/geometry/matrix_util.cpp
new file mode 100755
index 00000000000..2117b06e62f
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp
@@ -0,0 +1,265 @@
+/*
+ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Note that the GNU General Public License does not permit incorporating
+ * the Software into proprietary programs.
+ */
+
+
+#include "matrix_util.h"
+#include <math.h>
+
+
+
+namespace OGF {
+
+ namespace MatrixUtil {
+
+ static const double EPS = 0.00001 ;
+ static int MAX_ITER = 100 ;
+
+ void semi_definite_symmetric_eigen(
+ const double *mat, int n, double *eigen_vec, double *eigen_val
+ ) {
+ double *a,*v;
+ double a_norm,a_normEPS,thr,thr_nn;
+ int nb_iter = 0;
+ int jj;
+ int i,j,k,ij,ik,l,m,lm,mq,lq,ll,mm,imv,im,iq,ilv,il,nn;
+ int *index;
+ double a_ij,a_lm,a_ll,a_mm,a_im,a_il;
+ double a_lm_2;
+ double v_ilv,v_imv;
+ double x;
+ double sinx,sinx_2,cosx,cosx_2,sincos;
+ double delta;
+
+ // Number of entries in mat
+
+ nn = (n*(n+1))/2;
+
+ // Step 1: Copy mat to a
+
+ a = new double[nn];
+
+ for( ij=0; ij<nn; ij++ ) {
+ a[ij] = mat[ij];
+ }
+
+ // Ugly Fortran-porting trick: indices for a are between 1 and n
+ a--;
+
+ // Step 2 : Init diagonalization matrix as the unit matrix
+ v = new double[n*n];
+
+ ij = 0;
+ for( i=0; i<n; i++ ) {
+ for( j=0; j<n; j++ ) {
+ if( i==j ) {
+ v[ij++] = 1.0;
+ } else {
+ v[ij++] = 0.0;
+ }
+ }
+ }
+
+ // Ugly Fortran-porting trick: indices for v are between 1 and n
+ v--;
+
+ // Step 3 : compute the weight of the non diagonal terms
+ ij = 1 ;
+ a_norm = 0.0;
+ for( i=1; i<=n; i++ ) {
+ for( j=1; j<=i; j++ ) {
+ if( i!=j ) {
+ a_ij = a[ij];
+ a_norm += a_ij*a_ij;
+ }
+ ij++;
+ }
+ }
+
+ if( a_norm != 0.0 ) {
+
+ a_normEPS = a_norm*EPS;
+ thr = a_norm ;
+
+ // Step 4 : rotations
+ while( thr > a_normEPS && nb_iter < MAX_ITER ) {
+
+ nb_iter++;
+ thr_nn = thr / nn;
+
+ for( l=1 ; l< n; l++ ) {
+ for( m=l+1; m<=n; m++ ) {
+
+ // compute sinx and cosx
+
+ lq = (l*l-l)/2;
+ mq = (m*m-m)/2;
+
+ lm = l+mq;
+ a_lm = a[lm];
+ a_lm_2 = a_lm*a_lm;
+
+ if( a_lm_2 < thr_nn ) {
+ continue ;
+ }
+
+ ll = l+lq;
+ mm = m+mq;
+ a_ll = a[ll];
+ a_mm = a[mm];
+
+ delta = a_ll - a_mm;
+
+ if( delta == 0.0 ) {
+ x = - M_PI/4 ;
+ } else {
+ x = - atan( (a_lm+a_lm) / delta ) / 2.0 ;
+ }
+
+ sinx = sin(x) ;
+ cosx = cos(x) ;
+ sinx_2 = sinx*sinx;
+ cosx_2 = cosx*cosx;
+ sincos = sinx*cosx;
+
+ // rotate L and M columns
+
+ ilv = n*(l-1);
+ imv = n*(m-1);
+
+ for( i=1; i<=n;i++ ) {
+ if( (i!=l) && (i!=m) ) {
+ iq = (i*i-i)/2;
+
+ if( i<m ) {
+ im = i + mq;
+ } else {
+ im = m + iq;
+ }
+ a_im = a[im];
+
+ if( i<l ) {
+ il = i + lq;
+ } else {
+ il = l + iq;
+ }
+ a_il = a[il];
+
+ a[il] = a_il*cosx - a_im*sinx;
+ a[im] = a_il*sinx + a_im*cosx;
+ }
+
+ ilv++;
+ imv++;
+
+ v_ilv = v[ilv];
+ v_imv = v[imv];
+
+ v[ilv] = cosx*v_ilv - sinx*v_imv;
+ v[imv] = sinx*v_ilv + cosx*v_imv;
+ }
+
+ x = a_lm*sincos; x+=x;
+
+ a[ll] = a_ll*cosx_2 + a_mm*sinx_2 - x;
+ a[mm] = a_ll*sinx_2 + a_mm*cosx_2 + x;
+ a[lm] = 0.0;
+
+ thr = fabs( thr - a_lm_2 );
+ }
+ }
+ }
+ }
+
+ // Step 5: index conversion and copy eigen values
+
+ // back from Fortran to C++
+ a++;
+
+ for( i=0; i<n; i++ ) {
+ k = i + (i*(i+1))/2;
+ eigen_val[i] = a[k];
+ }
+
+ delete[] a;
+
+ // Step 6: sort the eigen values and eigen vectors
+
+ index = new int[n];
+ for( i=0; i<n; i++ ) {
+ index[i] = i;
+ }
+
+ for( i=0; i<(n-1); i++ ) {
+ x = eigen_val[i];
+ k = i;
+
+ for( j=i+1; j<n; j++ ) {
+ if( x < eigen_val[j] ) {
+ k = j;
+ x = eigen_val[j];
+ }
+ }
+
+ eigen_val[k] = eigen_val[i];
+ eigen_val[i] = x;
+
+ jj = index[k];
+ index[k] = index[i];
+ index[i] = jj;
+ }
+
+
+ // Step 7: save the eigen vectors
+
+ v++; // back from Fortran to to C++
+
+ ij = 0;
+ for( k=0; k<n; k++ ) {
+ ik = index[k]*n;
+ for( i=0; i<n; i++ ) {
+ eigen_vec[ij++] = v[ik++];
+ }
+ }
+
+ delete[] v ;
+ delete[] index;
+ return;
+ }
+
+//_________________________________________________________
+
+ }
+}
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h
new file mode 100755
index 00000000000..a990413c403
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/matrix_util.h
@@ -0,0 +1,69 @@
+/*
+ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Note that the GNU General Public License does not permit incorporating
+ * the Software into proprietary programs.
+ */
+
+#ifndef __MATRIX_UTIL__
+#define __MATRIX_UTIL__
+
+# include "../system/FreestyleConfig.h"
+
+namespace OGF {
+
+ namespace MatrixUtil {
+
+ /**
+ * computes the eigen values and eigen vectors
+ * of a semi definite symmetric matrix
+ *
+ * @param matrix is stored in column symmetric storage, i.e.
+ * matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
+ * size = n(n+1)/2
+ *
+ * @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
+ * where vk = vk0, vk1, ..., vkn
+ * size = n^2, must be allocated by caller
+ *
+ * @param eigen_values (return) are in decreasing order
+ * size = n, must be allocated by caller
+ */
+ LIB_GEOMETRY_EXPORT
+ void semi_definite_symmetric_eigen(
+ const double *mat, int n, double *eigen_vec, double *eigen_val
+ ) ;
+
+ }
+}
+
+#endif
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.cpp b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
new file mode 100755
index 00000000000..3a697d54731
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
@@ -0,0 +1,87 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+#include "normal_cycle.h"
+#include "matrix_util.h"
+
+
+namespace OGF {
+
+//_________________________________________________________
+
+
+ NormalCycle::NormalCycle() {
+ }
+
+ void NormalCycle::begin() {
+ M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0 ;
+ }
+
+ void NormalCycle::end() {
+
+ double eigen_vectors[9] ;
+ MatrixUtil::semi_definite_symmetric_eigen(M_, 3, eigen_vectors, eigen_value_) ;
+
+ axis_[0] = Vec3r(
+ eigen_vectors[0], eigen_vectors[1], eigen_vectors[2]
+ ) ;
+
+ axis_[1] = Vec3r(
+ eigen_vectors[3], eigen_vectors[4], eigen_vectors[5]
+ ) ;
+
+ axis_[2] = Vec3r(
+ eigen_vectors[6], eigen_vectors[7], eigen_vectors[8]
+ ) ;
+
+ // Normalize the eigen vectors
+
+ for(int i=0; i<3; i++) {
+ axis_[i].normalize() ;
+ }
+
+ // Sort the eigen vectors
+
+ i_[0] = 0 ;
+ i_[1] = 1 ;
+ i_[2] = 2 ;
+
+ double l0 = ::fabs(eigen_value_[0]) ;
+ double l1 = ::fabs(eigen_value_[1]) ;
+ double l2 = ::fabs(eigen_value_[2]) ;
+
+ if(l1 > l0) {
+ ogf_swap(l0 , l1 ) ;
+ ogf_swap(i_[0], i_[1]) ;
+ }
+ if(l2 > l1) {
+ ogf_swap(l1 , l2 ) ;
+ ogf_swap(i_[1], i_[2]) ;
+ }
+ if(l1 > l0) {
+ ogf_swap(l0 , l1 ) ;
+ ogf_swap(i_[0],i_[1]) ;
+ }
+
+ }
+
+//_________________________________________________________
+
+}
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h
new file mode 100755
index 00000000000..cdf00a0b4c5
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.h
@@ -0,0 +1,110 @@
+/*
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Note that the GNU General Public License does not permit incorporating
+ * the Software into proprietary programs.
+ */
+
+#ifndef __MESH_TOOLS_MATH_NORMAL_CYCLE__
+#define __MESH_TOOLS_MATH_NORMAL_CYCLE__
+
+# include "../system/FreestyleConfig.h"
+# include "Geom.h"
+using namespace Geometry;
+
+namespace OGF {
+
+template <class T> inline void ogf_swap(T& x, T& y) {
+ T z = x ;
+ x = y ;
+ y = z ;
+ }
+
+//_________________________________________________________
+
+ /**
+ * NormalCycle evaluates the curvature tensor in function
+ * of a set of dihedral angles and associated vectors.
+ * Reference:
+ * Restricted Delaunay Triangulation and Normal Cycle,
+ * D. Cohen-Steiner and J.M. Morvan,
+ * SOCG 2003
+ */
+ class LIB_GEOMETRY_EXPORT NormalCycle {
+ public:
+ NormalCycle() ;
+ void begin() ;
+ void end() ;
+ /**
+ * Note: the specified edge vector needs to be pre-clipped
+ * by the neighborhood.
+ */
+ void accumulate_dihedral_angle(
+ const Vec3r& edge, real angle, real neigh_area = 1.0
+ ) ;
+ const Vec3r& eigen_vector(int i) const { return axis_[i_[i]] ; }
+ real eigen_value(int i) const { return eigen_value_[i_[i]] ; }
+
+ const Vec3r& N() const { return eigen_vector(2) ; }
+ const Vec3r& Kmax() const { return eigen_vector(1) ; }
+ const Vec3r& Kmin() const { return eigen_vector(0) ; }
+
+ real n() const { return eigen_value(2) ; }
+ real kmax() const { return eigen_value(1) ; }
+ real kmin() const { return eigen_value(0) ; }
+
+ private:
+ real center_[3] ;
+ Vec3r axis_[3] ;
+ real eigen_value_[3] ;
+ real M_[6] ;
+ int i_[3] ;
+ } ;
+
+ inline void NormalCycle::accumulate_dihedral_angle(
+ const Vec3r& edge, const double beta, double neigh_area
+ ) {
+ double s = beta * neigh_area / edge.norm();
+
+ M_[0] += s * edge.x() * edge.x() ;
+ M_[1] += s * edge.x() * edge.y() ;
+ M_[2] += s * edge.y() * edge.y() ;
+ M_[3] += s * edge.x() * edge.z() ;
+ M_[4] += s * edge.y() * edge.z() ;
+ M_[5] += s * edge.z() * edge.z() ;
+ }
+
+//_________________________________________________________
+
+}
+
+#endif
diff --git a/source/blender/freestyle/intern/image/GaussianFilter.cpp b/source/blender/freestyle/intern/image/GaussianFilter.cpp
new file mode 100755
index 00000000000..3a79f5f9949
--- /dev/null
+++ b/source/blender/freestyle/intern/image/GaussianFilter.cpp
@@ -0,0 +1,96 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "GaussianFilter.h"
+#include <stdlib.h>
+
+GaussianFilter::GaussianFilter(float iSigma )
+{
+ _sigma = iSigma;
+ _mask = 0;
+ computeMask();
+}
+
+GaussianFilter::GaussianFilter(const GaussianFilter& iBrother)
+{
+ _sigma = iBrother._sigma;
+ _maskSize = iBrother._maskSize;
+ _bound = iBrother._bound;
+ _storedMaskSize = iBrother._storedMaskSize;
+ _mask = new float[_maskSize*_maskSize];
+ memcpy(_mask, iBrother._mask, _maskSize*_maskSize*sizeof(float));
+}
+
+
+GaussianFilter& GaussianFilter::operator= (const GaussianFilter& iBrother)
+{
+ _sigma = iBrother._sigma;
+ _maskSize = iBrother._maskSize;
+ _bound = iBrother._bound;
+ _storedMaskSize = iBrother._storedMaskSize;
+ _mask = new float[_storedMaskSize*_storedMaskSize];
+ memcpy(_mask, iBrother._mask, _storedMaskSize*_storedMaskSize*sizeof(float));
+ return *this;
+}
+
+
+GaussianFilter::~GaussianFilter()
+{
+ if(0!=_mask)
+ {
+ delete [] _mask;
+ }
+}
+
+int GaussianFilter::computeMaskSize(float sigma)
+{
+ int maskSize = (int)floor(4*sigma)+1;
+ if(0 == maskSize%2)
+ ++maskSize;
+
+ return maskSize;
+}
+
+void GaussianFilter::setSigma(float sigma)
+{
+ _sigma = sigma;
+ computeMask();
+}
+
+void GaussianFilter::computeMask()
+{
+ if(0 != _mask){
+ delete [] _mask;
+ }
+
+ _maskSize = computeMaskSize(_sigma);
+ _storedMaskSize = (_maskSize+1)>>1;
+ _bound = _storedMaskSize-1;
+
+ float norm = _sigma*_sigma*2.f*M_PI;
+ float invNorm = 1.0/norm;
+ _mask = new float[_storedMaskSize*_storedMaskSize*sizeof(float)];
+ for(int i=0; i<_storedMaskSize; ++i)
+ for(int j=0; j<_storedMaskSize; ++j)
+ _mask[i*_storedMaskSize+j] = invNorm*exp(-(i*i + j*j)/(2.0*_sigma*_sigma));
+ //_mask[i*_storedMaskSize+j] = exp(-(i*i + j*j)/(2.0*_sigma*_sigma));
+}
+
diff --git a/source/blender/freestyle/intern/image/GaussianFilter.h b/source/blender/freestyle/intern/image/GaussianFilter.h
new file mode 100755
index 00000000000..be0e3e2bada
--- /dev/null
+++ b/source/blender/freestyle/intern/image/GaussianFilter.h
@@ -0,0 +1,146 @@
+//
+// Filename : Image.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to perform gaussian filtering operations on an image
+// Date of creation : 20/05/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GAUSSIANFILTER_H
+# define GAUSSIANFILTER_H
+
+#include <string.h> // for memcpy
+#include <cstdlib> // for abs
+#include "../system/FreestyleConfig.h"
+
+class LIB_IMAGE_EXPORT GaussianFilter{
+protected:
+ /* the mask is a symetrical 2d array (with respect
+ to the middle point).
+ Thus, M(i,j) = M(-i,j) = M(i,-j) = M(-i,-j).
+ For this reason, to represent a NxN array (N odd), we only store
+ a ((N+1)/2)x((N+1)/2) array.
+ */
+ float _sigma;
+ float *_mask;
+ int _bound;
+ int _maskSize; // the real mask size (must be odd)(the size of the mask we store is ((_maskSize+1)/2)*((_maskSize+1)/2))
+ int _storedMaskSize; //(_maskSize+1)/2)
+
+public:
+ GaussianFilter(float iSigma = 1.f) ;
+ GaussianFilter(const GaussianFilter&) ;
+ GaussianFilter& operator= (const GaussianFilter&) ;
+ virtual ~GaussianFilter() ;
+
+ /*! Returns the value for pixel x,y of image "map" after a gaussian blur,
+ * made using the sigma value.
+ * The sigma value determines the mask size (~ 2 x sigma).
+ * \param map
+ * The image we wish to work on. The Map template must implement the
+ * foloowing methods:
+ * - float pixel(unsigned int x,unsigned int y) const;
+ * - unsigned width() const;
+ * - unsigned height() const;
+ * \param x
+ * The abscissa of the pixel where we want to evaluate the gaussian blur.
+ * \param y
+ * The ordinate of the pixel where we want to evaluate the gaussian blur.
+ * \param sigma
+ * The sigma value of the gaussian function.
+ */
+ template<class Map>
+ float getSmoothedPixel(Map * map, int x, int y) ;
+
+ /*! Compute the mask size and returns the REAL mask size ((2*_maskSize)-1)
+ * This method is provided for convenience.
+ */
+ static int computeMaskSize(float sigma) ;
+
+ /*! accessors */
+ inline float sigma() const {return _sigma;}
+ inline int maskSize() const {return _maskSize;}
+ inline int getBound() {return _bound;}
+
+ /*! modifiers */
+ void setSigma(float sigma) ;
+ // void SetMaskSize(int size) {_maskSize = size;_storedMaskSize=(_maskSize+1)>>1;}
+
+
+protected:
+ void computeMask();
+};
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+
+
+#include <math.h>
+
+#ifdef __MACH__
+#define sqrtf(x) (sqrt(x))
+#endif
+
+template<class Map>
+float GaussianFilter::getSmoothedPixel(Map * map, int x, int y)
+{
+ float sum = 0.f;
+ float L=0.f;
+ int w = (int)map->width(); //soc
+ int h = (int)map->height(); //soc
+
+ // Current pixel is x,y
+ // Sum surrounding pixels L value:
+ for(int i=-_bound; i<=_bound; ++i)
+ {
+ if((y+i < 0) || (y+i >= h))
+ continue;
+ for(int j=-_bound; j<=_bound; ++j)
+ {
+ if((x+j < 0) || (x+j >= w))
+ continue;
+
+ float tmpL = map->pixel(x+j,y+i);
+ float m = _mask[abs(i)*_storedMaskSize+abs(j)];
+ L += m*tmpL;
+ sum += m;
+ }
+ }
+ //L /= sum;
+ return L;
+}
+
+
+#endif // GAUSSIANFILTER
diff --git a/source/blender/freestyle/intern/image/Image.h b/source/blender/freestyle/intern/image/Image.h
new file mode 100755
index 00000000000..72affbc1023
--- /dev/null
+++ b/source/blender/freestyle/intern/image/Image.h
@@ -0,0 +1,389 @@
+//
+// Filename : Image.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to encapsulate an array of RGB or Gray level values
+// Date of creation : 20/05/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef IMAGE_H
+# define IMAGE_H
+
+# include <string.h> // for memcpy
+
+//
+// Image base class, for all types of images
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/*! This class allows the storing of part of an image,
+ * while allowing a normal access to its pixel values.
+ * You can for example only a rectangle of sw*sh, whose
+ * lower-left corner is at (ox, oy), of an image of
+ * size w*h, and access these pixels using x,y coordinates
+ * specified in the whole image coordinate system.
+ */
+class FrsImage
+{
+ public:
+
+ /*! Default constructor */
+ FrsImage() {
+ _storedWidth = 0;
+ _storedHeight = 0;
+ _width = 0;
+ _height = 0;
+ _Ox = 0;
+ _Oy = 0;
+ }
+
+ /*! Copy constructor */
+ FrsImage(const FrsImage& brother) {
+ _storedWidth = brother._storedWidth;
+ _storedHeight = brother._storedHeight;
+ _width = brother._width;
+ _height = brother._height;
+ _Ox = brother._Ox;
+ _Oy = brother._Oy;
+ }
+
+ /*! Builds an FrsImage from its width and height.
+ * The memory is allocated consequently.
+ */
+ FrsImage(unsigned w, unsigned h) {
+ _width = w;
+ _height = h;
+ _storedWidth = w;
+ _storedHeight = h;
+ _Ox = 0;
+ _Oy = 0;
+ }
+
+ /*! Builds a partial-storing image.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the rectangle that will actually
+ * be stored.
+ * \param sh
+ * The height of the rectangle that will actually
+ * be stored.
+ * \param ox
+ * The x-abscissa of the origin of the rectangle that will actually
+ * be stored.
+ * \param oy
+ * The x-abscissa of the origin of the rectangle that will actually
+ * be stored.
+ */
+ FrsImage(unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) {
+ _width = w;
+ _height = h;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = ox;
+ _Oy = oy;
+ }
+
+ /*! Operator= */
+ FrsImage& operator=(const FrsImage& brother) {
+ _width = brother._width;
+ _height = brother._height;
+ _storedWidth = brother._storedWidth;
+ _storedHeight = brother._storedHeight;
+ _Ox = brother._Ox;
+ _Oy = brother._Oy;
+ return* this;
+ }
+
+ /*! Destructor */
+ virtual ~FrsImage() {}
+
+ /*! Returns the width of the complete image */
+ inline unsigned width() const {
+ return _width;
+ }
+ /*! Returns the height of the complete image */
+ inline unsigned height() const {
+ return _height;
+ }
+
+ /*! Returns the grey value for pixel x,y */
+ virtual float pixel(unsigned x, unsigned y) const = 0;
+
+ /*! Sets the array.
+ * \param array
+ * The array containing the values we wish to store.
+ * Its size is sw*sh.
+ * \param width
+ * The width of the complete image
+ * \param height
+ * The height of the complete image
+ * \param sw
+ * The width of the rectangle that will actually
+ * be stored.
+ * \param sh
+ * The height of the rectangle that will actually
+ * be stored.
+ * \param ox
+ * The x-abscissa of the origin of the rectangle that will actually
+ * be stored.
+ * \param oy
+ * The x-abscissa of the origin of the rectangle that will actually
+ * be stored.
+ * \param copy
+ * If true, the array is copied, otherwise the pointer is
+ * copied
+ */
+ virtual void setArray(float* array, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) = 0;
+
+ /*! Returns the array containing the pixels values.
+ * Its size is sw*sh, i.e. potentially a smaller
+ * rectangular part of the complete image.
+ */
+ virtual float * getArray() = 0;
+
+ protected:
+
+ unsigned _width;
+ unsigned _height;
+ unsigned _storedWidth;
+ unsigned _storedHeight;
+ unsigned _Ox; // origin of the stored part
+ unsigned _Oy; // origin of the stored part
+};
+
+
+//
+// RGBImage
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class RGBImage : public FrsImage
+{
+ public:
+
+ RGBImage() : FrsImage() {
+ _rgb = 0;
+ }
+
+ RGBImage(const RGBImage& brother) : FrsImage(brother) {
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ RGBImage(unsigned w, unsigned h) : FrsImage(w, h) {
+ _rgb = new float[3 * _width * _height];
+ }
+
+ RGBImage(float* rgb, unsigned w, unsigned h) : FrsImage(w, h) {
+ _rgb = new float[3 * _width * _height];
+ memcpy(_rgb, rgb, 3 * _width * _height * sizeof(float));
+ }
+
+ /*! Builds an RGB partial image from the useful part buffer.
+ * \param rgb
+ * The array of size 3*sw*sh containing the RGB values
+ * of the sw*sh pixels we need to stored.
+ * These sw*sh pixels constitute a rectangular part of
+ * a bigger RGB image containing w*h pixels.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the part of the image we want to store and work on
+ * \param sh
+ * The height of the part of the image we want to store and work on
+ */
+ RGBImage(float* rgb, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : FrsImage(w, h, sw, sh, ox, oy) {
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ RGBImage& operator=(const RGBImage& brother) {
+ dynamic_cast<FrsImage&>(*this) = brother;
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ return* this;
+ }
+
+ virtual ~RGBImage() {
+ if(_rgb)
+ delete[] _rgb;
+ }
+
+ inline float getR(unsigned x, unsigned y) const {
+ return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3];
+ }
+
+ inline float getG(unsigned x, unsigned y) const {
+ return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 1];
+ }
+
+ inline float getB(unsigned x, unsigned y) const {
+ return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 2];
+ }
+
+ virtual void setPixel(unsigned x, unsigned y, float r, float g, float b){
+ float * tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]);
+ *tmp = r;++tmp;
+ *tmp = g;++tmp;
+ *tmp = b;
+ }
+
+ virtual float pixel(unsigned x, unsigned y) const {
+ float res = 0;
+ float* tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]);
+ res += 11 * (*tmp++);
+ res += 16 * (*tmp++);
+ res += 5 * (*tmp);
+ return res / 32;
+ }
+
+ /*! Sets the RGB array.
+ * copy
+ * If true, the array is copied, otherwise the pointer is
+ * copied
+ */
+ virtual void setArray(float* rgb, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) {
+ _width = width;
+ _height = height;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = x;
+ _Oy = y;
+ if(!copy) {
+ _rgb = rgb;
+ return;
+ }
+
+ memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight* sizeof(float));
+ }
+
+ virtual float * getArray() {return _rgb;}
+
+ protected:
+
+ float* _rgb;
+};
+
+
+//
+// GrayImage
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class GrayImage : public FrsImage
+{
+ public:
+
+ GrayImage() : FrsImage() {
+ _lvl = 0;
+ }
+
+ GrayImage(const GrayImage& brother) : FrsImage(brother) {
+ _lvl = new float[_storedWidth*_storedHeight];
+ memcpy(_lvl, brother._lvl, _storedWidth*_storedHeight*sizeof(*_lvl));
+ }
+
+ /*! Builds an empty gray image */
+ GrayImage(unsigned w, unsigned h) : FrsImage(w, h) {
+ _lvl = new float[_width*_height];
+ }
+
+ GrayImage(float* lvl, unsigned w, unsigned h) : FrsImage(w, h) {
+ _lvl = new float[_width*_height];
+ memcpy(_lvl, lvl, _width*_height*sizeof(*_lvl));
+ }
+
+ /*! Builds a partial image from the useful part buffer.
+ * \param lvl
+ * The array of size sw*sh containing the gray values
+ * of the sw*sh pixels we need to stored.
+ * These sw*sh pixels constitute a rectangular part of
+ * a bigger gray image containing w*h pixels.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the part of the image we want to store and work on
+ * \param sh
+ * The height of the part of the image we want to store and work on
+ */
+ GrayImage(float* lvl, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : FrsImage(w, h, sw, sh, ox, oy) {
+ _lvl = new float[_storedWidth*_storedHeight];
+ memcpy(_lvl, lvl, _storedWidth*_storedHeight*sizeof(float));
+ }
+
+ GrayImage& operator=(const GrayImage& brother) {
+ dynamic_cast<FrsImage&>(*this) = brother;
+ _lvl = new float[_storedWidth * _storedHeight];
+ memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(float));
+ return *this;
+ }
+
+ virtual ~GrayImage() {
+ if(_lvl)
+ delete[] _lvl;
+ }
+
+ inline void setPixel(unsigned x, unsigned y, float v){
+ _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)] = v;
+ }
+
+ inline float pixel(unsigned x, unsigned y) const {
+ return _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)];
+ }
+
+ /*! Sets the array.
+ * copy
+ * If true, the array is copie, otherwise the pounsigneder is
+ * copied
+ */
+ void setArray(float *lvl, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) {
+ _width = width;
+ _height = height;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = x;
+ _Oy = y;
+ if(!copy) {
+ _lvl = lvl;
+ return;
+ }
+
+ memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
+ }
+ /*! Returns the array containing the gray values. */
+ virtual float * getArray() {return _lvl;}
+
+ protected:
+
+ float *_lvl;
+};
+
+#endif // IMAGE_H
diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp
new file mode 100755
index 00000000000..542ab7917e3
--- /dev/null
+++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp
@@ -0,0 +1,166 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+#include "ImagePyramid.h"
+#include "Image.h"
+#include "GaussianFilter.h"
+#include <iostream>
+
+using namespace std;
+
+//ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels){
+// //BuildPyramid(level0,nbLevels);
+//}
+
+ImagePyramid::ImagePyramid(const ImagePyramid& iBrother){
+ if(!_levels.empty()){
+ for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end();
+ im!=imend;
+ ++im){
+ _levels.push_back(new GrayImage(**im));
+ }
+ }
+}
+ImagePyramid::~ImagePyramid(){
+ if(!_levels.empty()){
+ for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end();
+ im!=imend;
+ ++im){
+ delete (*im);
+ }
+ _levels.clear();
+ }
+}
+
+GrayImage * ImagePyramid::getLevel(int l){
+ return _levels[l];
+}
+
+float ImagePyramid::pixel(int x, int y, int level){
+ GrayImage *img = _levels[level];
+ if(0 == level){
+ return img->pixel(x,y);
+ }
+ unsigned int i = 1<<level;
+ unsigned int sx = x>>level;
+ unsigned int sy = y>>level;
+ if(sx >= img->width())
+ sx = img->width()-1;
+ if(sy >= img->height())
+ sy = img->height()-1;
+
+ // bilinear interpolation
+ float A = i*(sx+1)-x;
+ float B = x-i*sx;
+ float C = i*(sy+1)-y;
+ float D = y-i*sy;
+
+ float P1(0), P2(0);
+ P1 = A*img->pixel(sx,sy);
+ if(sx < img->width()-1){
+ if(x%i != 0)
+ P1 += B*img->pixel(sx+1,sy);
+ }else{
+ P1 += B*img->pixel(sx,sy);
+ }
+ if(sy<img->height()-1){
+ if(y%i != 0){
+ P2 = A*img->pixel(sx,sy+1);
+ if(sx < img->width()-1){
+ if(x%i != 0)
+ P2 += B*img->pixel(sx+1,sy+1);
+ }else{
+ P2 += B*img->pixel(sx,sy+1);
+ }
+ }
+ }else{
+ P2 = P1;
+ }
+ return (1.f/(float)(1<<2*level))*(C*P1 + D*P2);
+}
+
+int ImagePyramid::width(int level){
+ return _levels[level]->width();
+}
+
+int ImagePyramid::height(int level){
+ return _levels[level]->height();
+}
+
+GaussianPyramid::GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma)
+ : ImagePyramid()
+{
+ _sigma = iSigma;
+ BuildPyramid(level0,nbLevels);
+}
+GaussianPyramid::GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma)
+ : ImagePyramid()
+{
+ _sigma = iSigma;
+ BuildPyramid(level0,nbLevels);
+}
+
+GaussianPyramid::GaussianPyramid(const GaussianPyramid& iBrother)
+: ImagePyramid(iBrother){
+ _sigma = iBrother._sigma;
+}
+void GaussianPyramid::BuildPyramid(const GrayImage& level0, unsigned nbLevels){
+ GrayImage *pLevel = new GrayImage(level0);
+ BuildPyramid(pLevel, nbLevels);
+}
+
+void GaussianPyramid::BuildPyramid(GrayImage* level0, unsigned nbLevels){
+ GrayImage *pLevel = level0;
+ _levels.push_back(pLevel);
+ GaussianFilter gf(_sigma);
+ // build the nbLevels:
+ unsigned w = pLevel->width();
+ unsigned h = pLevel->height();
+ if(nbLevels!=0)
+ {
+ for(unsigned i=0; i<nbLevels; ++i){ //soc
+ w = pLevel->width()>>1;
+ h = pLevel->height()>>1;
+ GrayImage *img = new GrayImage(w,h);
+ for(unsigned y=0; y<h; ++y){
+ for(unsigned x=0; x<w; ++x){
+ float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y);
+ img->setPixel(x,y,v);
+ }
+ }
+ _levels.push_back(img);
+ pLevel = img;
+ }
+ }else{
+ while((w>1) && (h>1)){
+ w = pLevel->width()>>1;
+ h = pLevel->height()>>1;
+ GrayImage *img = new GrayImage(w,h);
+ for(unsigned y=0; y<h; ++y){
+ for(unsigned x=0; x<w; ++x){
+ float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y);
+ img->setPixel(x,y,v);
+ }
+ }
+ _levels.push_back(img);
+ pLevel = img;
+ }
+ }
+}
diff --git a/source/blender/freestyle/intern/image/ImagePyramid.h b/source/blender/freestyle/intern/image/ImagePyramid.h
new file mode 100755
index 00000000000..9e326757f02
--- /dev/null
+++ b/source/blender/freestyle/intern/image/ImagePyramid.h
@@ -0,0 +1,92 @@
+//
+// Filename : ImagePyramid.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a pyramid of images
+// Date of creation : 25/12/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef IMAGEPYRAMID_H
+# define IMAGEPYRAMID_H
+
+#include "../system/FreestyleConfig.h"
+#include <vector>
+
+class GrayImage;
+class LIB_IMAGE_EXPORT ImagePyramid{
+protected:
+ std::vector<GrayImage*> _levels;
+
+public:
+ ImagePyramid(){}
+ ImagePyramid(const ImagePyramid& iBrother);
+ //ImagePyramid(const GrayImage& level0, unsigned nbLevels);
+ virtual ~ImagePyramid();
+
+ /*! Builds the pyramid.
+ * must be overloaded by inherited classes.
+ * if nbLevels==0, the complete pyramid is built
+ */
+ virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels) = 0;
+
+ /*! Builds a pyramid without copying the base level */
+ virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels) = 0;
+
+ virtual GrayImage * getLevel(int l);
+ /*! Returns the pixel x,y using bilinear interpolation.
+ * \param x
+ * the abscissa specified in the finest level coordinate system
+ * \param y
+ * the ordinate specified in the finest level coordinate system
+ * \param level
+ * the level from which we want the pixel to be evaluated
+ */
+ virtual float pixel(int x, int y, int level=0);
+ /*! Returns the width of the level-th level image */
+ virtual int width(int level=0);
+ /*! Returns the height of the level-th level image */
+ virtual int height(int level=0);
+ /*! Returns the number of levels in the pyramid */
+ inline int getNumberOfLevels() const { return _levels.size();}
+};
+
+class LIB_IMAGE_EXPORT GaussianPyramid : public ImagePyramid
+{
+protected:
+ float _sigma;
+public:
+ GaussianPyramid(float iSigma=1.f) : ImagePyramid() {_sigma=iSigma;}
+ GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma=1.f);
+ GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma=1.f);
+ GaussianPyramid(const GaussianPyramid& iBrother);
+ virtual ~GaussianPyramid(){}
+
+ virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels);
+ virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels);
+ /* accessors */
+ inline float getSigma() const {return _sigma;}
+ /* modifiers */
+
+};
+#endif // IMAGEPYRAMID_H
diff --git a/source/blender/freestyle/intern/python/BPy_BBox.cpp b/source/blender/freestyle/intern/python/BPy_BBox.cpp
new file mode 100644
index 00000000000..0acd32bad58
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BBox.cpp
@@ -0,0 +1,100 @@
+#include "BPy_BBox.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BBox_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &BBox_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &BBox_Type );
+ PyModule_AddObject(module, "BBox", (PyObject *)&BBox_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BBox___doc__[] =
+"Class for representing a bounding box.\n";
+
+static int BBox___init__(BPy_BBox *self, PyObject *args, PyObject *kwds)
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->bb = new BBox< Vec3r>();
+ return 0;
+}
+
+static void BBox___dealloc__(BPy_BBox* self)
+{
+ delete self->bb;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * BBox___repr__(BPy_BBox* self)
+{
+ return PyUnicode_FromFormat("BBox - address: %p", self->bb );
+}
+
+/*----------------------BBox instance definitions ----------------------------*/
+static PyMethodDef BPy_BBox_methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_BBox type definition ------------------------------*/
+
+PyTypeObject BBox_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BBox", /* tp_name */
+ sizeof(BPy_BBox), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BBox___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BBox___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BBox___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_BBox_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BBox___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BBox.h b/source/blender/freestyle/intern/python/BPy_BBox.h
new file mode 100644
index 00000000000..f8282187da0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BBox.h
@@ -0,0 +1,38 @@
+#ifndef FREESTYLE_PYTHON_BBOX_H
+#define FREESTYLE_PYTHON_BBOX_H
+
+#include <Python.h>
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BBox_Type;
+
+#define BPy_BBox_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BBox_Type) )
+
+/*---------------------------Python BPy_BBox structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BBox<Vec3r> *bb;
+} BPy_BBox;
+
+/*---------------------------Python BPy_BBox visible prototypes-----------*/
+
+int BBox_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BBOX_H */
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp
new file mode 100644
index 00000000000..693d35b1f60
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp
@@ -0,0 +1,166 @@
+#include "BPy_BinaryPredicate0D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BinaryPredicate0D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &BinaryPredicate0D_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &BinaryPredicate0D_Type );
+ PyModule_AddObject(module, "BinaryPredicate0D", (PyObject *)&BinaryPredicate0D_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BinaryPredicate0D___doc__[] =
+"Base class for binary predicates working on :class:`Interface0D`\n"
+"objects. A BinaryPredicate0D is typically an ordering relation\n"
+"between two Interface0D objects. The predicate evaluates a relation\n"
+"between the two Interface0D instances and returns a boolean value (true\n"
+"or false). It is used by invoking the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Must be overload by inherited classes. It evaluates a relation\n"
+" between two Interface0D objects.\n"
+"\n"
+" :arg inter1: The first Interface0D object.\n"
+" :type inter1: :class:`Interface0D`\n"
+" :arg inter2: The second Interface0D object.\n"
+" :type inter2: :class:`Interface0D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int BinaryPredicate0D___init__(BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->bp0D = new BinaryPredicate0D();
+ self->bp0D->py_bp0D = (PyObject *) self;
+
+ return 0;
+}
+
+static void BinaryPredicate0D___dealloc__(BPy_BinaryPredicate0D* self)
+{
+ if (self->bp0D)
+ delete self->bp0D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * BinaryPredicate0D___repr__(BPy_BinaryPredicate0D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->bp0D->getName().c_str(), self->bp0D );
+}
+
+static char BinaryPredicate0D_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the binary 0D predicate.\n"
+"\n"
+" :return: The name of the binary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * BinaryPredicate0D_getName( BPy_BinaryPredicate0D *self, PyObject *args)
+{
+ return PyUnicode_FromString( self->bp0D->getName().c_str() );
+}
+
+static PyObject * BinaryPredicate0D___call__( BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ BPy_Interface0D *obj1, *obj2;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!O!", &Interface0D_Type, &obj1, &Interface0D_Type, &obj2) )
+ return NULL;
+
+ if( typeid(*(self->bp0D)) == typeid(BinaryPredicate0D) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->bp0D->operator()( *(obj1->if0D) , *(obj2->if0D) ) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->bp0D->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool( self->bp0D->result );
+
+}
+
+/*----------------------BinaryPredicate0D instance definitions ----------------------------*/
+static PyMethodDef BPy_BinaryPredicate0D_methods[] = {
+ {"getName", ( PyCFunction ) BinaryPredicate0D_getName, METH_NOARGS, BinaryPredicate0D_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_BinaryPredicate0D type definition ------------------------------*/
+
+PyTypeObject BinaryPredicate0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BinaryPredicate0D", /* tp_name */
+ sizeof(BPy_BinaryPredicate0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BinaryPredicate0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BinaryPredicate0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)BinaryPredicate0D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BinaryPredicate0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_BinaryPredicate0D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BinaryPredicate0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h
new file mode 100644
index 00000000000..6a9a0775608
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_BINARYPREDICATE0D_H
+#define FREESTYLE_PYTHON_BINARYPREDICATE0D_H
+
+#include <Python.h>
+
+#include "../stroke/Predicates0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BinaryPredicate0D_Type;
+
+#define BPy_BinaryPredicate0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BinaryPredicate0D_Type) )
+
+/*---------------------------Python BPy_BinaryPredicate0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BinaryPredicate0D *bp0D;
+} BPy_BinaryPredicate0D;
+
+/*---------------------------Python BPy_BinaryPredicate0D visible prototypes-----------*/
+
+int BinaryPredicate0D_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BINARYPREDICATE0D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp
new file mode 100644
index 00000000000..e690a6d51c1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp
@@ -0,0 +1,193 @@
+#include "BPy_BinaryPredicate1D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface1D.h"
+
+#include "BinaryPredicate1D/BPy_FalseBP1D.h"
+#include "BinaryPredicate1D/BPy_Length2DBP1D.h"
+#include "BinaryPredicate1D/BPy_SameShapeIdBP1D.h"
+#include "BinaryPredicate1D/BPy_TrueBP1D.h"
+#include "BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BinaryPredicate1D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &BinaryPredicate1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &BinaryPredicate1D_Type );
+ PyModule_AddObject(module, "BinaryPredicate1D", (PyObject *)&BinaryPredicate1D_Type);
+
+ if( PyType_Ready( &FalseBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FalseBP1D_Type );
+ PyModule_AddObject(module, "FalseBP1D", (PyObject *)&FalseBP1D_Type);
+
+ if( PyType_Ready( &Length2DBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Length2DBP1D_Type );
+ PyModule_AddObject(module, "Length2DBP1D", (PyObject *)&Length2DBP1D_Type);
+
+ if( PyType_Ready( &SameShapeIdBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SameShapeIdBP1D_Type );
+ PyModule_AddObject(module, "SameShapeIdBP1D", (PyObject *)&SameShapeIdBP1D_Type);
+
+ if( PyType_Ready( &TrueBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TrueBP1D_Type );
+ PyModule_AddObject(module, "TrueBP1D", (PyObject *)&TrueBP1D_Type);
+
+ if( PyType_Ready( &ViewMapGradientNormBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ViewMapGradientNormBP1D_Type );
+ PyModule_AddObject(module, "ViewMapGradientNormBP1D", (PyObject *)&ViewMapGradientNormBP1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BinaryPredicate1D___doc__[] =
+"Base class for binary predicates working on :class:`Interface1D`\n"
+"objects. A BinaryPredicate1D is typically an ordering relation\n"
+"between two Interface1D objects. The predicate evaluates a relation\n"
+"between the two Interface1D instances and returns a boolean value (true\n"
+"or false). It is used by invoking the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Must be overload by inherited classes. It evaluates a relation\n"
+" between two Interface1D objects.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int BinaryPredicate1D___init__(BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->bp1D = new BinaryPredicate1D();
+ self->bp1D->py_bp1D = (PyObject *) self;
+ return 0;
+}
+
+static void BinaryPredicate1D___dealloc__(BPy_BinaryPredicate1D* self)
+{
+ if (self->bp1D)
+ delete self->bp1D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * BinaryPredicate1D___repr__(BPy_BinaryPredicate1D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->bp1D->getName().c_str(), self->bp1D );
+}
+
+static char BinaryPredicate1D_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the binary 1D predicate.\n"
+"\n"
+" :return: The name of the binary 1D predicate.\n"
+" :rtype: str\n";
+
+static PyObject *BinaryPredicate1D_getName( BPy_BinaryPredicate1D *self, PyObject *args)
+{
+ return PyUnicode_FromString( self->bp1D->getName().c_str() );
+}
+
+static PyObject *BinaryPredicate1D___call__( BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ BPy_Interface1D *obj1, *obj2;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!O!", &Interface1D_Type, &obj1, &Interface1D_Type, &obj2) )
+ return NULL;
+
+ if( typeid(*(self->bp1D)) == typeid(BinaryPredicate1D) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->bp1D->operator()( *(obj1->if1D) , *(obj2->if1D) ) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->bp1D->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool( self->bp1D->result );
+}
+
+/*----------------------BinaryPredicate1D instance definitions ----------------------------*/
+static PyMethodDef BPy_BinaryPredicate1D_methods[] = {
+ {"getName", ( PyCFunction ) BinaryPredicate1D_getName, METH_NOARGS, BinaryPredicate1D_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_BinaryPredicate1D type definition ------------------------------*/
+PyTypeObject BinaryPredicate1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BinaryPredicate1D", /* tp_name */
+ sizeof(BPy_BinaryPredicate1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BinaryPredicate1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BinaryPredicate1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)BinaryPredicate1D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BinaryPredicate1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_BinaryPredicate1D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BinaryPredicate1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h
new file mode 100644
index 00000000000..5a993f84f5b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_BINARYPREDICATE1D_H
+#define FREESTYLE_PYTHON_BINARYPREDICATE1D_H
+
+#include <Python.h>
+
+#include "../stroke/Predicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BinaryPredicate1D_Type;
+
+#define BPy_BinaryPredicate1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BinaryPredicate1D_Type) )
+
+/*---------------------------Python BPy_BinaryPredicate1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BinaryPredicate1D *bp1D;
+} BPy_BinaryPredicate1D;
+
+/*---------------------------Python BPy_BinaryPredicate1D visible prototypes-----------*/
+
+int BinaryPredicate1D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BINARYPREDICATE1D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
new file mode 100644
index 00000000000..5c824981aa3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
@@ -0,0 +1,262 @@
+#include "BPy_ContextFunctions.h"
+#include "BPy_Convert.h"
+
+#include "../stroke/ContextFunctions.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+static char ContextFunctions_GetTimeStampCF___doc__[] =
+".. function:: GetTimeStampCF()\n"
+"\n"
+" Returns the system time stamp.\n"
+"\n"
+" :return: The system time stamp.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_GetTimeStampCF( PyObject* self )
+{
+ return PyLong_FromLong( ContextFunctions::GetTimeStampCF() );
+}
+
+static char ContextFunctions_GetCanvasWidthCF___doc__[] =
+".. method:: GetCanvasWidthCF()\n"
+"\n"
+" Returns the canvas width.\n"
+"\n"
+" :return: The canvas width.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_GetCanvasWidthCF( PyObject* self )
+{
+ return PyLong_FromLong( ContextFunctions::GetCanvasWidthCF() );
+}
+
+static char ContextFunctions_GetCanvasHeightCF___doc__[] =
+".. method:: GetCanvasHeightCF()\n"
+"\n"
+" Returns the canvas height.\n"
+"\n"
+" :return: The canvas height.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_GetCanvasHeightCF( PyObject* self )
+{
+ return PyLong_FromLong( ContextFunctions::GetCanvasHeightCF() );
+}
+
+static char ContextFunctions_LoadMapCF___doc__[] =
+".. function:: LoadMapCF(iFileName, iMapName, iNbLevels=4, iSigma=1.0)\n"
+"\n"
+" Loads an image map for further reading.\n"
+"\n"
+" :arg iFileName: The name of the image file.\n"
+" :type iFileName: str\n"
+" :arg iMapName: The name that will be used to access this image.\n"
+" :type iMapName: str\n"
+" :arg iNbLevels: The number of levels in the map pyramid\n"
+" (default = 4). If iNbLevels == 0, the complete pyramid is\n"
+" built.\n"
+" :type iNbLevels: int\n"
+" :arg iSigma: The sigma value of the gaussian function.\n"
+" :type iSigma: float\n";
+
+static PyObject *
+ContextFunctions_LoadMapCF( PyObject *self, PyObject *args )
+{
+ char *fileName, *mapName;
+ unsigned nbLevels;
+ float sigma;
+
+ if( !PyArg_ParseTuple(args, "ssIf", &fileName, &mapName, &nbLevels, &sigma) )
+ return NULL;
+
+ ContextFunctions::LoadMapCF(fileName, mapName, nbLevels, sigma);
+
+ Py_RETURN_NONE;
+}
+
+static char ContextFunctions_ReadMapPixelCF___doc__[] =
+".. function:: ReadMapPixelCF(iMapName, level, x, y)\n"
+"\n"
+" Reads a pixel in a user-defined map.\n"
+"\n"
+" :arg iMapName: The name of the map.\n"
+" :type iMapName: str\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_ReadMapPixelCF( PyObject *self, PyObject *args )
+{
+ char *mapName;
+ int level;
+ unsigned x, y;
+
+ if( !PyArg_ParseTuple(args, "siII", &mapName, &level, &x, &y) )
+ return NULL;
+
+ float f = ContextFunctions::ReadMapPixelCF(mapName, level, x, y);
+
+ return PyFloat_FromDouble( f );
+}
+
+static char ContextFunctions_ReadCompleteViewMapPixelCF___doc__[] =
+".. function:: ReadCompleteViewMapPixelCF(level, x, y)\n"
+"\n"
+" Reads a pixel in the complete view map.\n"
+"\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_ReadCompleteViewMapPixelCF( PyObject *self, PyObject *args )
+{
+ int level;
+ unsigned x, y;
+
+ if( !PyArg_ParseTuple(args, "iII", &level, &x, &y) )
+ return NULL;
+
+ float f = ContextFunctions::ReadCompleteViewMapPixelCF(level, x, y);
+
+ return PyFloat_FromDouble( f );
+}
+
+static char ContextFunctions_ReadDirectionalViewMapPixelCF___doc__[] =
+".. function:: ReadDirectionalViewMapPixelCF(iOrientation, level, x, y)\n"
+"\n"
+" Reads a pixel in one of the oriented view map images.\n"
+"\n"
+" :arg iOrientation: The number telling which orientation we want to\n"
+" check.\n"
+" :type iOrientation: int\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_ReadDirectionalViewMapPixelCF( PyObject *self, PyObject *args )
+{
+ int orientation, level;
+ unsigned x, y;
+
+ if( !PyArg_ParseTuple(args, "iiII", &orientation, &level, &x, &y) )
+ return NULL;
+
+ float f = ContextFunctions::ReadDirectionalViewMapPixelCF(orientation, level, x, y);
+
+ return PyFloat_FromDouble( f );
+}
+
+static char ContextFunctions_GetSelectedFEdgeCF___doc__[] =
+".. function:: GetSelectedFEdgeCF()\n"
+"\n"
+" Returns the selected FEdge.\n"
+"\n"
+" :return: The selected FEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject *
+ContextFunctions_GetSelectedFEdgeCF( PyObject *self )
+{
+ FEdge *fe = ContextFunctions::GetSelectedFEdgeCF();
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge( *fe );
+
+ Py_RETURN_NONE;
+}
+
+/*-----------------------ContextFunctions module docstring-------------------------------*/
+
+static char module_docstring[] = "The Blender Freestyle.ContextFunctions submodule\n\n";
+
+/*-----------------------ContextFunctions module functions definitions-------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"GetTimeStampCF", (PyCFunction)ContextFunctions_GetTimeStampCF, METH_NOARGS, ContextFunctions_GetTimeStampCF___doc__},
+ {"GetCanvasWidthCF", (PyCFunction)ContextFunctions_GetCanvasWidthCF, METH_NOARGS, ContextFunctions_GetCanvasWidthCF___doc__},
+ {"GetCanvasHeightCF", (PyCFunction)ContextFunctions_GetCanvasHeightCF, METH_NOARGS, ContextFunctions_GetCanvasHeightCF___doc__},
+ {"LoadMapCF", (PyCFunction)ContextFunctions_LoadMapCF, METH_VARARGS, ContextFunctions_LoadMapCF___doc__},
+ {"ReadMapPixelCF", (PyCFunction)ContextFunctions_ReadMapPixelCF, METH_VARARGS, ContextFunctions_ReadMapPixelCF___doc__},
+ {"ReadCompleteViewMapPixelCF", (PyCFunction)ContextFunctions_ReadCompleteViewMapPixelCF, METH_VARARGS, ContextFunctions_ReadCompleteViewMapPixelCF___doc__},
+ {"ReadDirectionalViewMapPixelCF", (PyCFunction)ContextFunctions_ReadDirectionalViewMapPixelCF, METH_VARARGS, ContextFunctions_ReadDirectionalViewMapPixelCF___doc__},
+ {"GetSelectedFEdgeCF", (PyCFunction)ContextFunctions_GetSelectedFEdgeCF, METH_NOARGS, ContextFunctions_GetSelectedFEdgeCF___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------ContextFunctions module definition--------------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle.ContextFunctions",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+//------------------- MODULE INITIALIZATION --------------------------------
+
+int ContextFunctions_Init( PyObject *module )
+{
+ PyObject *m, *d, *f;
+
+ if( module == NULL )
+ return -1;
+
+ m = PyModule_Create(&module_definition);
+ if (m == NULL)
+ return -1;
+ Py_INCREF(m);
+ PyModule_AddObject(module, "ContextFunctions", m);
+
+ // from ContextFunctions import *
+ d = PyModule_GetDict(m);
+ for (PyMethodDef *p = module_functions; p->ml_name; p++) {
+ f = PyDict_GetItemString(d, p->ml_name);
+ Py_INCREF(f);
+ PyModule_AddObject(module, p->ml_name, f);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.h b/source/blender/freestyle/intern/python/BPy_ContextFunctions.h
new file mode 100644
index 00000000000..fafeff3e974
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.h
@@ -0,0 +1,18 @@
+#ifndef FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H
+#define FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------Python BPy_ContextFunctions visible prototypes-----------*/
+
+int ContextFunctions_Init( PyObject *module );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp
new file mode 100644
index 00000000000..01567b18142
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp
@@ -0,0 +1,609 @@
+#include "BPy_Convert.h"
+
+#include "BPy_BBox.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_Id.h"
+#include "BPy_IntegrationType.h"
+#include "BPy_Interface0D.h"
+#include "Interface0D/BPy_CurvePoint.h"
+#include "Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface0D/ViewVertex/BPy_NonTVertex.h"
+#include "Interface0D/ViewVertex/BPy_TVertex.h"
+#include "BPy_Interface1D.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "Interface1D/Curve/BPy_Chain.h"
+#include "Interface1D/FEdge/BPy_FEdgeSharp.h"
+#include "Interface1D/FEdge/BPy_FEdgeSmooth.h"
+#include "BPy_Nature.h"
+#include "BPy_MediumType.h"
+#include "BPy_SShape.h"
+#include "BPy_StrokeAttribute.h"
+#include "BPy_ViewShape.h"
+
+#include "Iterator/BPy_AdjacencyIterator.h"
+#include "Iterator/BPy_ChainPredicateIterator.h"
+#include "Iterator/BPy_ChainSilhouetteIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_CurvePointIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Iterator/BPy_SVertexIterator.h"
+#include "Iterator/BPy_StrokeVertexIterator.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_orientedViewEdgeIterator.h"
+
+#include "../stroke/StrokeRep.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//==============================
+// C++ => Python
+//==============================
+
+
+PyObject * PyBool_from_bool( bool b ){
+ return PyBool_FromLong( b ? 1 : 0);
+}
+
+
+PyObject * Vector_from_Vec2f( Vec2f& vec ) {
+ float vec_data[2]; // because vec->_coord is protected
+
+ vec_data[0] = vec.x(); vec_data[1] = vec.y();
+ return Vector_CreatePyObject( vec_data, 2, Py_NEW, NULL);
+}
+
+PyObject * Vector_from_Vec3f( Vec3f& vec ) {
+ float vec_data[3]; // because vec->_coord is protected
+
+ vec_data[0] = vec.x(); vec_data[1] = vec.y(); vec_data[2] = vec.z();
+ return Vector_CreatePyObject( vec_data, 3, Py_NEW, NULL);
+}
+
+PyObject * Vector_from_Vec3r( Vec3r& vec ) {
+ float vec_data[3]; // because vec->_coord is protected
+
+ vec_data[0] = vec.x(); vec_data[1] = vec.y(); vec_data[2] = vec.z();
+ return Vector_CreatePyObject( vec_data, 3, Py_NEW, NULL);
+}
+
+PyObject * BPy_Id_from_Id( Id& id ) {
+ PyObject *py_id = Id_Type.tp_new( &Id_Type, 0, 0 );
+ ((BPy_Id *) py_id)->id = new Id( id.getFirst(), id.getSecond() );
+
+ return py_id;
+}
+
+PyObject * Any_BPy_Interface0D_from_Interface0D( Interface0D& if0D ) {
+ if (typeid(if0D) == typeid(CurvePoint)) {
+ return BPy_CurvePoint_from_CurvePoint(dynamic_cast<CurvePoint&>(if0D));
+ } else if (typeid(if0D) == typeid(StrokeVertex)) {
+ return BPy_StrokeVertex_from_StrokeVertex(dynamic_cast<StrokeVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(SVertex)) {
+ return BPy_SVertex_from_SVertex(dynamic_cast<SVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(ViewVertex)) {
+ return BPy_ViewVertex_from_ViewVertex(dynamic_cast<ViewVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(NonTVertex)) {
+ return BPy_NonTVertex_from_NonTVertex(dynamic_cast<NonTVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(TVertex)) {
+ return BPy_TVertex_from_TVertex(dynamic_cast<TVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(Interface0D)) {
+ return BPy_Interface0D_from_Interface0D(if0D);
+ }
+ string msg("unexpected type: " + if0D.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject * Any_BPy_Interface1D_from_Interface1D( Interface1D& if1D ) {
+ if (typeid(if1D) == typeid(ViewEdge)) {
+ return BPy_ViewEdge_from_ViewEdge(dynamic_cast<ViewEdge&>(if1D));
+ } else if (typeid(if1D) == typeid(Chain)) {
+ return BPy_Chain_from_Chain(dynamic_cast<Chain&>(if1D));
+ } else if (typeid(if1D) == typeid(Stroke)) {
+ return BPy_Stroke_from_Stroke(dynamic_cast<Stroke&>(if1D));
+ } else if (typeid(if1D) == typeid(FEdgeSharp)) {
+ return BPy_FEdgeSharp_from_FEdgeSharp(dynamic_cast<FEdgeSharp&>(if1D));
+ } else if (typeid(if1D) == typeid(FEdgeSmooth)) {
+ return BPy_FEdgeSmooth_from_FEdgeSmooth(dynamic_cast<FEdgeSmooth&>(if1D));
+ } else if (typeid(if1D) == typeid(FEdge)) {
+ return BPy_FEdge_from_FEdge(dynamic_cast<FEdge&>(if1D));
+ } else if (typeid(if1D) == typeid(Interface1D)) {
+ return BPy_Interface1D_from_Interface1D( if1D );
+ }
+ string msg("unexpected type: " + if1D.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject * Any_BPy_FEdge_from_FEdge( FEdge& fe ) {
+ if (typeid(fe) == typeid(FEdgeSharp)) {
+ return BPy_FEdgeSharp_from_FEdgeSharp( dynamic_cast<FEdgeSharp&>(fe) );
+ } else if (typeid(fe) == typeid(FEdgeSmooth)) {
+ return BPy_FEdgeSmooth_from_FEdgeSmooth( dynamic_cast<FEdgeSmooth&>(fe) );
+ } else if (typeid(fe) == typeid(FEdge)) {
+ return BPy_FEdge_from_FEdge( fe );
+ }
+ string msg("unexpected type: " + fe.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject * Any_BPy_ViewVertex_from_ViewVertex( ViewVertex& vv ) {
+ if (typeid(vv) == typeid(NonTVertex)) {
+ return BPy_NonTVertex_from_NonTVertex( dynamic_cast<NonTVertex&>(vv) );
+ } else if (typeid(vv) == typeid(TVertex)) {
+ return BPy_TVertex_from_TVertex( dynamic_cast<TVertex&>(vv) );
+ } else if (typeid(vv) == typeid(ViewVertex)) {
+ return BPy_ViewVertex_from_ViewVertex( vv );
+ }
+ string msg("unexpected type: " + vv.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject * BPy_Interface0D_from_Interface0D( Interface0D& if0D ) {
+ PyObject *py_if0D = Interface0D_Type.tp_new( &Interface0D_Type, 0, 0 );
+ ((BPy_Interface0D *) py_if0D)->if0D = &if0D;
+ ((BPy_Interface0D *) py_if0D)->borrowed = 1;
+
+ return py_if0D;
+}
+
+PyObject * BPy_Interface1D_from_Interface1D( Interface1D& if1D ) {
+ PyObject *py_if1D = Interface1D_Type.tp_new( &Interface1D_Type, 0, 0 );
+ ((BPy_Interface1D *) py_if1D)->if1D = &if1D;
+ ((BPy_Interface1D *) py_if1D)->borrowed = 1;
+
+ return py_if1D;
+}
+
+PyObject * BPy_SVertex_from_SVertex( SVertex& sv ) {
+ PyObject *py_sv = SVertex_Type.tp_new( &SVertex_Type, 0, 0 );
+ ((BPy_SVertex *) py_sv)->sv = &sv;
+ ((BPy_SVertex *) py_sv)->py_if0D.if0D = ((BPy_SVertex *) py_sv)->sv;
+ ((BPy_SVertex *) py_sv)->py_if0D.borrowed = 1;
+
+ return py_sv;
+}
+
+PyObject * BPy_FEdgeSharp_from_FEdgeSharp( FEdgeSharp& fes ) {
+ PyObject *py_fe = FEdgeSharp_Type.tp_new( &FEdgeSharp_Type, 0, 0 );
+ ((BPy_FEdgeSharp *) py_fe)->fes = &fes;
+ ((BPy_FEdgeSharp *) py_fe)->py_fe.fe = ((BPy_FEdgeSharp *) py_fe)->fes;
+ ((BPy_FEdgeSharp *) py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSharp *) py_fe)->fes;
+ ((BPy_FEdgeSharp *) py_fe)->py_fe.py_if1D.borrowed = 1;
+
+ return py_fe;
+}
+
+PyObject * BPy_FEdgeSmooth_from_FEdgeSmooth( FEdgeSmooth& fes ) {
+ PyObject *py_fe = FEdgeSmooth_Type.tp_new( &FEdgeSmooth_Type, 0, 0 );
+ ((BPy_FEdgeSmooth *) py_fe)->fes = &fes;
+ ((BPy_FEdgeSmooth *) py_fe)->py_fe.fe = ((BPy_FEdgeSmooth *) py_fe)->fes;
+ ((BPy_FEdgeSmooth *) py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSmooth *) py_fe)->fes;
+ ((BPy_FEdgeSmooth *) py_fe)->py_fe.py_if1D.borrowed = 1;
+
+ return py_fe;
+}
+
+PyObject * BPy_FEdge_from_FEdge( FEdge& fe ) {
+ PyObject *py_fe = FEdge_Type.tp_new( &FEdge_Type, 0, 0 );
+ ((BPy_FEdge *) py_fe)->fe = &fe;
+ ((BPy_FEdge *) py_fe)->py_if1D.if1D = ((BPy_FEdge *) py_fe)->fe;
+ ((BPy_FEdge *) py_fe)->py_if1D.borrowed = 1;
+
+ return py_fe;
+}
+
+PyObject * BPy_Nature_from_Nature( unsigned short n ) {
+ PyObject *py_n;
+
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SetItem( args, 0, PyLong_FromLong(n) );
+ py_n = Nature_Type.tp_new(&Nature_Type, args, NULL);
+ Py_DECREF(args);
+
+ return py_n;
+}
+
+PyObject * BPy_Stroke_from_Stroke( Stroke& s ) {
+ PyObject *py_s = Stroke_Type.tp_new( &Stroke_Type, 0, 0 );
+ ((BPy_Stroke *) py_s)->s = &s;
+ ((BPy_Stroke *) py_s)->py_if1D.if1D = ((BPy_Stroke *) py_s)->s;
+ ((BPy_Stroke *) py_s)->py_if1D.borrowed = 1;
+
+ return py_s;
+}
+
+PyObject * BPy_StrokeAttribute_from_StrokeAttribute( StrokeAttribute& sa ) {
+ PyObject *py_sa = StrokeAttribute_Type.tp_new( &StrokeAttribute_Type, 0, 0 );
+ ((BPy_StrokeAttribute *) py_sa)->sa = &sa;
+ ((BPy_StrokeAttribute *) py_sa)->borrowed = 1;
+ return py_sa;
+}
+
+PyObject * BPy_MediumType_from_MediumType( Stroke::MediumType n ) {
+ PyObject *py_mt;
+
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SetItem( args, 0, PyLong_FromLong(n) );
+ py_mt = MediumType_Type.tp_new( &MediumType_Type, args, NULL );
+ Py_DECREF(args);
+
+ return py_mt;
+}
+
+PyObject * BPy_StrokeVertex_from_StrokeVertex( StrokeVertex& sv ) {
+ PyObject *py_sv = StrokeVertex_Type.tp_new( &StrokeVertex_Type, 0, 0 );
+ ((BPy_StrokeVertex *) py_sv)->sv = &sv;
+ ((BPy_StrokeVertex *) py_sv)->py_cp.cp = ((BPy_StrokeVertex *) py_sv)->sv;
+ ((BPy_StrokeVertex *) py_sv)->py_cp.py_if0D.if0D = ((BPy_StrokeVertex *) py_sv)->sv;
+ ((BPy_StrokeVertex *) py_sv)->py_cp.py_if0D.borrowed = 1;
+
+ return py_sv;
+}
+
+PyObject * BPy_ViewVertex_from_ViewVertex( ViewVertex& vv ) {
+ PyObject *py_vv = ViewVertex_Type.tp_new( &ViewVertex_Type, 0, 0 );
+ ((BPy_ViewVertex *) py_vv)->vv = &vv;
+ ((BPy_ViewVertex *) py_vv)->py_if0D.if0D = ((BPy_ViewVertex *) py_vv)->vv;
+ ((BPy_ViewVertex *) py_vv)->py_if0D.borrowed = 1;
+
+ return py_vv;
+}
+
+PyObject * BPy_NonTVertex_from_NonTVertex( NonTVertex& ntv ) {
+ PyObject *py_ntv = NonTVertex_Type.tp_new( &NonTVertex_Type, 0, 0 );
+ ((BPy_NonTVertex *) py_ntv)->ntv = &ntv;
+ ((BPy_NonTVertex *) py_ntv)->py_vv.vv = ((BPy_NonTVertex *) py_ntv)->ntv;
+ ((BPy_NonTVertex *) py_ntv)->py_vv.py_if0D.if0D = ((BPy_NonTVertex *) py_ntv)->ntv;
+ ((BPy_NonTVertex *) py_ntv)->py_vv.py_if0D.borrowed = 1;
+
+ return py_ntv;
+}
+
+PyObject * BPy_TVertex_from_TVertex( TVertex& tv ) {
+ PyObject *py_tv = TVertex_Type.tp_new( &TVertex_Type, 0, 0 );
+ ((BPy_TVertex *) py_tv)->tv = &tv;
+ ((BPy_TVertex *) py_tv)->py_vv.vv = ((BPy_TVertex *) py_tv)->tv;
+ ((BPy_TVertex *) py_tv)->py_vv.py_if0D.if0D = ((BPy_TVertex *) py_tv)->tv;
+ ((BPy_TVertex *) py_tv)->py_vv.py_if0D.borrowed = 1;
+
+ return py_tv;
+}
+
+PyObject * BPy_BBox_from_BBox( BBox< Vec3r > &bb ) {
+ PyObject *py_bb = BBox_Type.tp_new( &BBox_Type, 0, 0 );
+ ((BPy_BBox *) py_bb)->bb = new BBox< Vec3r >( bb );
+
+ return py_bb;
+}
+
+PyObject * BPy_ViewEdge_from_ViewEdge( ViewEdge& ve ) {
+ PyObject *py_ve = ViewEdge_Type.tp_new( &ViewEdge_Type, 0, 0 );
+ ((BPy_ViewEdge *) py_ve)->ve = &ve;
+ ((BPy_ViewEdge *) py_ve)->py_if1D.if1D = ((BPy_ViewEdge *) py_ve)->ve;
+ ((BPy_ViewEdge *) py_ve)->py_if1D.borrowed = 1;
+
+ return py_ve;
+}
+
+PyObject * BPy_Chain_from_Chain( Chain& c ) {
+ PyObject *py_c = Chain_Type.tp_new( &Chain_Type, 0, 0 );
+ ((BPy_Chain *) py_c)->c = &c;
+ ((BPy_Chain *) py_c)->py_c.c = ((BPy_Chain *) py_c)->c;
+ ((BPy_Chain *) py_c)->py_c.py_if1D.if1D = ((BPy_Chain *) py_c)->c;
+ ((BPy_Chain *) py_c)->py_c.py_if1D.borrowed = 1;
+ return py_c;
+}
+
+PyObject * BPy_SShape_from_SShape( SShape& ss ) {
+ PyObject *py_ss = SShape_Type.tp_new( &SShape_Type, 0, 0 );
+ ((BPy_SShape *) py_ss)->ss = &ss;
+ ((BPy_SShape *) py_ss)->borrowed = 1;
+
+ return py_ss;
+}
+
+PyObject * BPy_ViewShape_from_ViewShape( ViewShape& vs ) {
+ PyObject *py_vs = ViewShape_Type.tp_new( &ViewShape_Type, 0, 0 );
+ ((BPy_ViewShape *) py_vs)->vs = &vs;
+ ((BPy_ViewShape *) py_vs)->borrowed = 1;
+
+ return py_vs;
+}
+
+PyObject * BPy_FrsMaterial_from_FrsMaterial( FrsMaterial& m ){
+ PyObject *py_m = FrsMaterial_Type.tp_new( &FrsMaterial_Type, 0, 0 );
+ ((BPy_FrsMaterial*) py_m)->m = &m;
+ ((BPy_FrsMaterial*) py_m)->borrowed = 1;
+
+ return py_m;
+}
+
+PyObject * BPy_IntegrationType_from_IntegrationType( IntegrationType i ) {
+ PyObject *py_it;
+
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SetItem( args, 0, PyLong_FromLong(i) );
+ py_it = IntegrationType_Type.tp_new( &IntegrationType_Type, args, NULL );
+ Py_DECREF(args);
+
+ return py_it;
+}
+
+PyObject * BPy_CurvePoint_from_CurvePoint( CurvePoint& cp ) {
+ PyObject *py_cp = CurvePoint_Type.tp_new( &CurvePoint_Type, 0, 0 );
+ ((BPy_CurvePoint*) py_cp)->cp = &cp;
+ ((BPy_CurvePoint*) py_cp)->py_if0D.if0D = ((BPy_CurvePoint*) py_cp)->cp;
+ ((BPy_CurvePoint*) py_cp)->py_if0D.borrowed = 1;
+
+ return py_cp;
+}
+
+PyObject * BPy_directedViewEdge_from_directedViewEdge( ViewVertex::directedViewEdge& dve ) {
+ PyObject *py_dve = PyTuple_New(2);
+
+ PyTuple_SetItem( py_dve, 0, BPy_ViewEdge_from_ViewEdge(*(dve.first)) );
+ PyTuple_SetItem( py_dve, 1, PyBool_from_bool(dve.second) );
+
+ return py_dve;
+}
+
+//==============================
+// Iterators
+//==============================
+
+PyObject * BPy_AdjacencyIterator_from_AdjacencyIterator( AdjacencyIterator& a_it ) {
+ PyObject *py_a_it = AdjacencyIterator_Type.tp_new( &AdjacencyIterator_Type, 0, 0 );
+ ((BPy_AdjacencyIterator *) py_a_it)->a_it = new AdjacencyIterator( a_it );
+ ((BPy_AdjacencyIterator *) py_a_it)->py_it.it = ((BPy_AdjacencyIterator *) py_a_it)->a_it;
+
+ return py_a_it;
+}
+
+PyObject * BPy_Interface0DIterator_from_Interface0DIterator( Interface0DIterator& if0D_it, int reversed ) {
+ PyObject *py_if0D_it = Interface0DIterator_Type.tp_new( &Interface0DIterator_Type, 0, 0 );
+ ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it = new Interface0DIterator( if0D_it );
+ ((BPy_Interface0DIterator *) py_if0D_it)->py_it.it = ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it;
+ ((BPy_Interface0DIterator *) py_if0D_it)->reversed = reversed;
+
+ return py_if0D_it;
+}
+
+PyObject * BPy_CurvePointIterator_from_CurvePointIterator( CurveInternal::CurvePointIterator& cp_it ) {
+ PyObject *py_cp_it = CurvePointIterator_Type.tp_new( &CurvePointIterator_Type, 0, 0 );
+ ((BPy_CurvePointIterator *) py_cp_it)->cp_it = new CurveInternal::CurvePointIterator( cp_it );
+ ((BPy_CurvePointIterator *) py_cp_it)->py_it.it = ((BPy_CurvePointIterator *) py_cp_it)->cp_it;
+
+ return py_cp_it;
+}
+
+PyObject * BPy_StrokeVertexIterator_from_StrokeVertexIterator( StrokeInternal::StrokeVertexIterator& sv_it, int reversed) {
+ PyObject *py_sv_it = StrokeVertexIterator_Type.tp_new( &StrokeVertexIterator_Type, 0, 0 );
+ ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it = new StrokeInternal::StrokeVertexIterator( sv_it );
+ ((BPy_StrokeVertexIterator *) py_sv_it)->py_it.it = ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it;
+ ((BPy_StrokeVertexIterator *) py_sv_it)->reversed = reversed;
+
+ return py_sv_it;
+}
+
+PyObject * BPy_SVertexIterator_from_SVertexIterator( ViewEdgeInternal::SVertexIterator& sv_it ) {
+ PyObject *py_sv_it = SVertexIterator_Type.tp_new( &SVertexIterator_Type, 0, 0 );
+ ((BPy_SVertexIterator *) py_sv_it)->sv_it = new ViewEdgeInternal::SVertexIterator( sv_it );
+ ((BPy_SVertexIterator *) py_sv_it)->py_it.it = ((BPy_SVertexIterator *) py_sv_it)->sv_it;
+
+ return py_sv_it;
+}
+
+
+PyObject * BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ViewVertexInternal::orientedViewEdgeIterator& ove_it, int reversed ) {
+ PyObject *py_ove_it = orientedViewEdgeIterator_Type.tp_new( &orientedViewEdgeIterator_Type, 0, 0 );
+ ((BPy_orientedViewEdgeIterator *) py_ove_it)->ove_it = new ViewVertexInternal::orientedViewEdgeIterator( ove_it );
+ ((BPy_orientedViewEdgeIterator *) py_ove_it)->py_it.it = ((BPy_orientedViewEdgeIterator *) py_ove_it)->ove_it;
+ ((BPy_orientedViewEdgeIterator *) py_ove_it)->reversed = reversed;
+
+ return py_ove_it;
+}
+
+PyObject * BPy_ViewEdgeIterator_from_ViewEdgeIterator( ViewEdgeInternal::ViewEdgeIterator& ve_it ) {
+ PyObject *py_ve_it = ViewEdgeIterator_Type.tp_new( &ViewEdgeIterator_Type, 0, 0 );
+ ((BPy_ViewEdgeIterator *) py_ve_it)->ve_it = new ViewEdgeInternal::ViewEdgeIterator( ve_it );
+ ((BPy_ViewEdgeIterator *) py_ve_it)->py_it.it = ((BPy_ViewEdgeIterator *) py_ve_it)->ve_it;
+
+ return py_ve_it;
+}
+
+PyObject * BPy_ChainingIterator_from_ChainingIterator( ChainingIterator& c_it ) {
+ PyObject *py_c_it = ChainingIterator_Type.tp_new( &ChainingIterator_Type, 0, 0 );
+ ((BPy_ChainingIterator *) py_c_it)->c_it = new ChainingIterator( c_it );
+ ((BPy_ChainingIterator *) py_c_it)->py_ve_it.py_it.it = ((BPy_ChainingIterator *) py_c_it)->c_it;
+
+ return py_c_it;
+}
+
+PyObject * BPy_ChainPredicateIterator_from_ChainPredicateIterator( ChainPredicateIterator& cp_it ) {
+ PyObject *py_cp_it = ChainPredicateIterator_Type.tp_new( &ChainPredicateIterator_Type, 0, 0 );
+ ((BPy_ChainPredicateIterator *) py_cp_it)->cp_it = new ChainPredicateIterator( cp_it );
+ ((BPy_ChainPredicateIterator *) py_cp_it)->py_c_it.py_ve_it.py_it.it = ((BPy_ChainPredicateIterator *) py_cp_it)->cp_it;
+
+ return py_cp_it;
+}
+
+PyObject * BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator( ChainSilhouetteIterator& cs_it ) {
+ PyObject *py_cs_it = ChainSilhouetteIterator_Type.tp_new( &ChainSilhouetteIterator_Type, 0, 0 );
+ ((BPy_ChainSilhouetteIterator *) py_cs_it)->cs_it = new ChainSilhouetteIterator( cs_it );
+ ((BPy_ChainSilhouetteIterator *) py_cs_it)->py_c_it.py_ve_it.py_it.it = ((BPy_ChainSilhouetteIterator *) py_cs_it)->cs_it;
+
+ return py_cs_it;
+}
+
+
+//==============================
+// Python => C++
+//==============================
+
+bool bool_from_PyBool( PyObject *b ) {
+ return PyObject_IsTrue(b) != 0;
+}
+
+IntegrationType IntegrationType_from_BPy_IntegrationType( PyObject* obj ) {
+ return static_cast<IntegrationType>( PyLong_AsLong(obj) );
+}
+
+Stroke::MediumType MediumType_from_BPy_MediumType( PyObject* obj ) {
+ return static_cast<Stroke::MediumType>( PyLong_AsLong(obj) );
+}
+
+Nature::EdgeNature EdgeNature_from_BPy_Nature( PyObject* obj ) {
+ return static_cast<Nature::EdgeNature>( PyLong_AsLong(obj) );
+}
+
+Vec2f * Vec2f_ptr_from_PyObject( PyObject* obj ) {
+ Vec2f *v;
+ if( (v = Vec2f_ptr_from_Vector( obj )) )
+ return v;
+ if( (v = Vec2f_ptr_from_PyList( obj )) )
+ return v;
+ if( (v = Vec2f_ptr_from_PyTuple( obj )) )
+ return v;
+ return NULL;
+}
+
+Vec3f * Vec3f_ptr_from_PyObject( PyObject* obj ) {
+ Vec3f *v;
+ if( (v = Vec3f_ptr_from_Vector( obj )) )
+ return v;
+ if( (v = Vec3f_ptr_from_PyList( obj )) )
+ return v;
+ if( (v = Vec3f_ptr_from_PyTuple( obj )) )
+ return v;
+ return NULL;
+}
+
+Vec3r * Vec3r_ptr_from_PyObject( PyObject* obj ) {
+ Vec3r *v;
+ if( (v = Vec3r_ptr_from_Vector( obj )) )
+ return v;
+ if( (v = Vec3r_ptr_from_PyList( obj )) )
+ return v;
+ if( (v = Vec3r_ptr_from_PyTuple( obj )) )
+ return v;
+ return NULL;
+}
+
+Vec2f * Vec2f_ptr_from_Vector( PyObject* obj ) {
+ PyObject *v;
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 2)
+ return NULL;
+ v = PyObject_GetAttrString(obj,"x");
+ float x = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"y");
+ float y = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+
+ return new Vec2f(x,y);
+}
+
+Vec3f * Vec3f_ptr_from_Vector( PyObject* obj ) {
+ PyObject *v;
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3)
+ return NULL;
+ v = PyObject_GetAttrString(obj,"x");
+ float x = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"y");
+ float y = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"z");
+ float z = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+
+ return new Vec3f(x,y,z);
+}
+
+Vec3r * Vec3r_ptr_from_Vector( PyObject* obj ) {
+ PyObject *v;
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3)
+ return NULL;
+ v = PyObject_GetAttrString(obj,"x");
+ double x = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"y");
+ double y = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"z");
+ double z = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+
+ return new Vec3r(x,y,z);
+}
+
+Vec2f * Vec2f_ptr_from_PyList( PyObject* obj ) {
+ if( !PyList_Check(obj) || PyList_Size(obj) != 2 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyList_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyList_GetItem(obj, 1));
+ return new Vec2f(x,y);
+}
+
+Vec3f * Vec3f_ptr_from_PyList( PyObject* obj ) {
+ if( !PyList_Check(obj) || PyList_Size(obj) != 3 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyList_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyList_GetItem(obj, 1));
+ float z = PyFloat_AsDouble(PyList_GetItem(obj, 2));
+ return new Vec3f(x,y,z);
+}
+
+Vec3r * Vec3r_ptr_from_PyList( PyObject* obj ) {
+ if( !PyList_Check(obj) || PyList_Size(obj) != 3 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyList_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyList_GetItem(obj, 1));
+ float z = PyFloat_AsDouble(PyList_GetItem(obj, 2));
+ return new Vec3r(x,y,z);
+}
+
+Vec2f * Vec2f_ptr_from_PyTuple( PyObject* obj ) {
+ if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 2 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1));
+ return new Vec2f(x,y);
+}
+
+Vec3f * Vec3f_ptr_from_PyTuple( PyObject* obj ) {
+ if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 3 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1));
+ float z = PyFloat_AsDouble(PyTuple_GetItem(obj, 2));
+ return new Vec3f(x,y,z);
+}
+
+Vec3r * Vec3r_ptr_from_PyTuple( PyObject* obj ) {
+ if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 3 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1));
+ float z = PyFloat_AsDouble(PyTuple_GetItem(obj, 2));
+ return new Vec3r(x,y,z);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.h b/source/blender/freestyle/intern/python/BPy_Convert.h
new file mode 100644
index 00000000000..ef5a64bde3f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Convert.h
@@ -0,0 +1,147 @@
+#ifndef FREESTYLE_PYTHON_CONVERT_H
+#define FREESTYLE_PYTHON_CONVERT_H
+
+#include <Python.h>
+#include <typeinfo>
+
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+// BBox
+#include "../geometry/BBox.h"
+
+// FEdge, FEdgeSharp, FEdgeSmooth, SShape, SVertex, FEdgeInternal::SVertexIterator
+#include "../view_map/Silhouette.h"
+
+// Id
+#include "../system/Id.h"
+
+// Interface0D, Interface0DIteratorNested, Interface0DIterator
+#include "../view_map/Interface0D.h"
+
+// Interface1D
+#include "../view_map/Interface1D.h"
+
+// FrsMaterial
+#include "../scene_graph/FrsMaterial.h"
+
+// Nature::VertexNature, Nature::EdgeNature
+#include "../winged_edge/Nature.h"
+
+// Stroke, StrokeAttribute, StrokeVertex
+#include "../stroke/Stroke.h"
+
+// NonTVertex, TVertex, ViewEdge, ViewMap, ViewShape, ViewVertex
+#include "../view_map/ViewMap.h"
+
+// CurvePoint, Curve
+#include "../stroke/Curve.h"
+
+// Chain
+#include "../stroke/Chain.h"
+
+//====== ITERATORS
+
+// AdjacencyIterator, ChainingIterator, ChainSilhouetteIterator, ChainPredicateIterator
+#include "../stroke/ChainingIterators.h"
+
+// ViewVertexInternal::orientedViewEdgeIterator
+// ViewEdgeInternal::SVertexIterator
+// ViewEdgeInternal::ViewEdgeIterator
+#include "../view_map/ViewMapIterators.h"
+
+// StrokeInternal::StrokeVertexIterator
+#include "../stroke/StrokeIterators.h"
+
+// CurveInternal::CurvePointIterator
+#include "../stroke/CurveIterators.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include "mathutils/mathutils.h"
+
+//==============================
+// C++ => Python
+//==============================
+
+PyObject * PyBool_from_bool( bool b );
+PyObject * Vector_from_Vec2f( Vec2f& v );
+PyObject * Vector_from_Vec3f( Vec3f& v );
+PyObject * Vector_from_Vec3r( Vec3r& v );
+
+PyObject * Any_BPy_Interface0D_from_Interface0D( Interface0D& if0D );
+PyObject * Any_BPy_Interface1D_from_Interface1D( Interface1D& if1D );
+PyObject * Any_BPy_FEdge_from_FEdge( FEdge& fe );
+PyObject * Any_BPy_ViewVertex_from_ViewVertex( ViewVertex& vv );
+
+PyObject * BPy_BBox_from_BBox( BBox< Vec3r > &bb );
+PyObject * BPy_CurvePoint_from_CurvePoint( CurvePoint& cp );
+PyObject * BPy_directedViewEdge_from_directedViewEdge( ViewVertex::directedViewEdge& dve );
+PyObject * BPy_FEdge_from_FEdge( FEdge& fe );
+PyObject * BPy_FEdgeSharp_from_FEdgeSharp( FEdgeSharp& fes );
+PyObject * BPy_FEdgeSmooth_from_FEdgeSmooth( FEdgeSmooth& fes );
+PyObject * BPy_Id_from_Id( Id& id );
+PyObject * BPy_Interface0D_from_Interface0D( Interface0D& if0D );
+PyObject * BPy_Interface1D_from_Interface1D( Interface1D& if1D );
+PyObject * BPy_IntegrationType_from_IntegrationType( IntegrationType i );
+PyObject * BPy_FrsMaterial_from_FrsMaterial( FrsMaterial& m );
+PyObject * BPy_Nature_from_Nature( unsigned short n );
+PyObject * BPy_MediumType_from_MediumType( Stroke::MediumType n );
+PyObject * BPy_SShape_from_SShape( SShape& ss );
+PyObject * BPy_Stroke_from_Stroke( Stroke& s );
+PyObject * BPy_StrokeAttribute_from_StrokeAttribute( StrokeAttribute& sa );
+PyObject * BPy_StrokeVertex_from_StrokeVertex( StrokeVertex& sv );
+PyObject * BPy_SVertex_from_SVertex( SVertex& sv );
+PyObject * BPy_ViewVertex_from_ViewVertex( ViewVertex& vv );
+PyObject * BPy_NonTVertex_from_NonTVertex( NonTVertex& ntv );
+PyObject * BPy_TVertex_from_TVertex( TVertex& tv );
+PyObject * BPy_ViewEdge_from_ViewEdge( ViewEdge& ve );
+PyObject * BPy_Chain_from_Chain( Chain& c );
+PyObject * BPy_ViewShape_from_ViewShape( ViewShape& vs );
+
+PyObject * BPy_AdjacencyIterator_from_AdjacencyIterator( AdjacencyIterator& a_it );
+PyObject * BPy_Interface0DIterator_from_Interface0DIterator( Interface0DIterator& if0D_it, int reversed );
+PyObject * BPy_CurvePointIterator_from_CurvePointIterator( CurveInternal::CurvePointIterator& cp_it );
+PyObject * BPy_StrokeVertexIterator_from_StrokeVertexIterator( StrokeInternal::StrokeVertexIterator& sv_it, int reversed);
+PyObject * BPy_SVertexIterator_from_SVertexIterator( ViewEdgeInternal::SVertexIterator& sv_it );
+PyObject * BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ViewVertexInternal::orientedViewEdgeIterator& ove_it, int reversed );
+PyObject * BPy_ViewEdgeIterator_from_ViewEdgeIterator( ViewEdgeInternal::ViewEdgeIterator& ve_it );
+PyObject * BPy_ChainingIterator_from_ChainingIterator( ChainingIterator& c_it );
+PyObject * BPy_ChainPredicateIterator_from_ChainPredicateIterator( ChainPredicateIterator& cp_it );
+PyObject * BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator( ChainSilhouetteIterator& cs_it );
+
+//==============================
+// Python => C++
+//==============================
+
+bool bool_from_PyBool( PyObject *b );
+IntegrationType IntegrationType_from_BPy_IntegrationType( PyObject* obj );
+Stroke::MediumType MediumType_from_BPy_MediumType( PyObject* obj );
+Nature::EdgeNature EdgeNature_from_BPy_Nature( PyObject* obj );
+Vec2f * Vec2f_ptr_from_PyObject( PyObject* obj );
+Vec3f * Vec3f_ptr_from_PyObject( PyObject* obj );
+Vec3r * Vec3r_ptr_from_PyObject( PyObject* obj );
+Vec2f * Vec2f_ptr_from_Vector( PyObject* obj );
+Vec3f * Vec3f_ptr_from_Vector( PyObject* obj );
+Vec3r * Vec3r_ptr_from_Vector( PyObject* obj );
+Vec2f * Vec2f_ptr_from_PyList( PyObject* obj );
+Vec3f * Vec3f_ptr_from_PyList( PyObject* obj );
+Vec3r * Vec3r_ptr_from_PyList( PyObject* obj );
+Vec2f * Vec2f_ptr_from_PyTuple( PyObject* obj );
+Vec3f * Vec3f_ptr_from_PyTuple( PyObject* obj );
+Vec3r * Vec3r_ptr_from_PyTuple( PyObject* obj );
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CONVERT_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
new file mode 100644
index 00000000000..969eed06933
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
@@ -0,0 +1,509 @@
+#include "BPy_Freestyle.h"
+
+#include "BPy_BBox.h"
+#include "BPy_BinaryPredicate0D.h"
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_ContextFunctions.h"
+#include "BPy_Convert.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_FrsNoise.h"
+#include "BPy_Id.h"
+#include "BPy_IntegrationType.h"
+#include "BPy_Interface0D.h"
+#include "BPy_Interface1D.h"
+#include "BPy_Iterator.h"
+#include "BPy_MediumType.h"
+#include "BPy_Nature.h"
+#include "BPy_Operators.h"
+#include "BPy_SShape.h"
+#include "BPy_StrokeAttribute.h"
+#include "BPy_StrokeShader.h"
+#include "BPy_UnaryFunction0D.h"
+#include "BPy_UnaryFunction1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "BPy_ViewMap.h"
+#include "BPy_ViewShape.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+#include "FRS_freestyle.h"
+#include "RNA_access.h"
+#include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */
+
+static char Freestyle_getCurrentScene___doc__[] =
+".. function:: getCurrentScene()\n"
+"\n"
+" Returns the current scene.\n"
+"\n"
+" :return: The current scene.\n"
+" :rtype: :class:`bpy.types.Scene`\n";
+
+static PyObject *Freestyle_getCurrentScene( PyObject *self )
+{
+ if (!freestyle_scene) {
+ PyErr_SetString(PyExc_TypeError, "current scene not available");
+ return NULL;
+ }
+ PointerRNA ptr_scene;
+ RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &ptr_scene);
+ return pyrna_struct_CreatePyObject(&ptr_scene);
+}
+
+#include "DNA_material_types.h"
+
+static int ramp_blend_type(const char *type)
+{
+ if (!strcmp(type, "MIX")) return MA_RAMP_BLEND;
+ if (!strcmp(type, "ADD")) return MA_RAMP_ADD;
+ if (!strcmp(type, "MULTIPLY")) return MA_RAMP_MULT;
+ if (!strcmp(type, "SUBTRACT")) return MA_RAMP_SUB;
+ if (!strcmp(type, "SCREEN")) return MA_RAMP_SCREEN;
+ if (!strcmp(type, "DIVIDE")) return MA_RAMP_DIV;
+ if (!strcmp(type, "DIFFERENCE")) return MA_RAMP_DIFF;
+ if (!strcmp(type, "DARKEN")) return MA_RAMP_DARK;
+ if (!strcmp(type, "LIGHTEN")) return MA_RAMP_LIGHT;
+ if (!strcmp(type, "OVERLAY")) return MA_RAMP_OVERLAY;
+ if (!strcmp(type, "DODGE")) return MA_RAMP_DODGE;
+ if (!strcmp(type, "BURN")) return MA_RAMP_BURN;
+ if (!strcmp(type, "HUE")) return MA_RAMP_HUE;
+ if (!strcmp(type, "SATURATION")) return MA_RAMP_SAT;
+ if (!strcmp(type, "VALUE")) return MA_RAMP_VAL;
+ if (!strcmp(type, "COLOR")) return MA_RAMP_COLOR;
+ if (!strcmp(type, "SOFT LIGHT")) return MA_RAMP_SOFT;
+ if (!strcmp(type, "LINEAR LIGHT")) return MA_RAMP_LINEAR;
+ return -1;
+}
+
+#include "BKE_material.h" /* ramp_blend() */
+
+static char Freestyle_blendRamp___doc__[] =
+".. function:: blendRamp(type, color1, fac, color2)\n"
+"\n"
+" Blend two colors according to a ramp blend type.\n"
+"\n"
+" :arg type: Ramp blend type.\n"
+" :type type: int\n"
+" :arg color1: 1st color.\n"
+" :type color1: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :arg fac: Blend factor.\n"
+" :type fac: float\n"
+" :arg color2: 1st color.\n"
+" :type color2: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :return: Blended color in RGB format.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *Freestyle_blendRamp( PyObject *self, PyObject *args )
+{
+ PyObject *obj1, *obj2;
+ char *s;
+ int type;
+ Vec3f *v1 = NULL, *v2 = NULL;
+ float a[3], fac, b[3];
+
+ if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2))
+ return NULL;
+ type = ramp_blend_type(s);
+ if (type < 0) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an unknown ramp blend type");
+ goto error;
+ }
+ v1 = Vec3f_ptr_from_PyObject(obj1);
+ if (!v1) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a 3D vector (either a tuple/list of 3 elements or Vector)");
+ goto error;
+ }
+ v2 = Vec3f_ptr_from_PyObject(obj2);
+ if (!v2) {
+ PyErr_SetString(PyExc_TypeError, "argument 4 must be a 3D vector (either a tuple/list of 3 elements or Vector)");
+ goto error;
+ }
+ a[0] = v1->x(); b[0] = v2->x();
+ a[1] = v1->y(); b[1] = v2->y();
+ a[2] = v1->z(); b[2] = v2->z();
+ ramp_blend(type, a, fac, b);
+ delete v1;
+ delete v2;
+ return Vector_CreatePyObject( a, 3, Py_NEW, NULL);
+
+error:
+ if (v1) delete v1;
+ if (v2) delete v2;
+ return NULL;
+}
+
+#include "BKE_texture.h" /* do_colorband() */
+
+static char Freestyle_evaluateColorRamp___doc__[] =
+".. function:: evaluateColorRamp(ramp, in)\n"
+"\n"
+" Evaluate a color ramp at a point in the interval 0 to 1.\n"
+"\n"
+" :arg ramp: Color ramp object.\n"
+" :type ramp: :class:`bpy.types.ColorRamp`\n"
+" :arg in: Value in the interval 0 to 1.\n"
+" :type in: float\n"
+" :return: color in RGBA format.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *Freestyle_evaluateColorRamp( PyObject *self, PyObject *args )
+{
+ BPy_StructRNA *py_srna;
+ ColorBand *coba;
+ float in, out[4];
+
+ if(!( PyArg_ParseTuple(args, "O!f", &pyrna_struct_Type, &py_srna, &in) ))
+ return NULL;
+ if(!RNA_struct_is_a(py_srna->ptr.type, &RNA_ColorRamp)) {
+ PyErr_SetString(PyExc_TypeError, "1st argument is not a ColorRamp object");
+ return NULL;
+ }
+ coba = (ColorBand *)py_srna->ptr.data;
+ if (!do_colorband(coba, in, out)) {
+ PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp");
+ return NULL;
+ }
+ return Vector_CreatePyObject( out, 4, Py_NEW, NULL);
+}
+
+#include "DNA_color_types.h"
+#include "BKE_colortools.h" /* curvemapping_evaluateF() */
+
+static char Freestyle_evaluateCurveMappingF___doc__[] =
+".. function:: evaluateCurveMappingF(cumap, cur, value)\n"
+"\n"
+" Evaluate a curve mapping at a point in the interval 0 to 1.\n"
+"\n"
+" :arg cumap: Curve mapping object.\n"
+" :type cumap: :class:`bpy.types.CurveMapping`\n"
+" :arg cur: Index of the curve to be used (0 <= cur <= 3).\n"
+" :type cur: int\n"
+" :arg value: Input value in the interval 0 to 1.\n"
+" :type value: float\n"
+" :return: Mapped output value.\n"
+" :rtype: float\n";
+
+static PyObject *Freestyle_evaluateCurveMappingF( PyObject *self, PyObject *args )
+{
+ BPy_StructRNA *py_srna;
+ CurveMapping *cumap;
+ int cur;
+ float value;
+
+ if(!( PyArg_ParseTuple(args, "O!if", &pyrna_struct_Type, &py_srna, &cur, &value) ))
+ return NULL;
+ if(!RNA_struct_is_a(py_srna->ptr.type, &RNA_CurveMapping)) {
+ PyErr_SetString(PyExc_TypeError, "1st argument is not a CurveMapping object");
+ return NULL;
+ }
+ if (cur < 0 || cur > 3) {
+ PyErr_SetString(PyExc_ValueError, "2nd argument is out of range");
+ return NULL;
+ }
+ cumap = (CurveMapping *)py_srna->ptr.data;
+ curvemapping_initialize(cumap);
+ /* disable extrapolation if enabled */
+ if ((cumap->cm[cur].flag & CUMA_EXTEND_EXTRAPOLATE)) {
+ cumap->cm[cur].flag &= ~( CUMA_EXTEND_EXTRAPOLATE );
+ curvemapping_changed(cumap, 0);
+ }
+ return PyFloat_FromDouble(curvemapping_evaluateF(cumap, cur, value));
+}
+
+/*-----------------------Freestyle module docstring----------------------------*/
+
+static char module_docstring[] =
+"This module provides classes for defining line drawing rules (such as\n"
+"predicates, functions, chaining iterators, and stroke shaders), as well\n"
+"as helper functions for style module writing.\n"
+"\n"
+"Class hierarchy:\n"
+"\n"
+"- :class:`BBox`\n"
+"- :class:`BinaryPredicate0D`\n"
+"- :class:`BinaryPredicate1D`\n"
+"\n"
+" - :class:`FalseBP1D`\n"
+" - :class:`Length2DBP1D`\n"
+" - :class:`SameShapeIdBP1D`\n"
+" - :class:`TrueBP1D`\n"
+" - :class:`ViewMapGradientNormBP1D`\n"
+"\n"
+"- :class:`Id`\n"
+"- :class:`Interface0D`\n"
+"\n"
+" - :class:`CurvePoint`\n"
+"\n"
+" - :class:`StrokeVertex`\n"
+"\n"
+" - :class:`SVertex`\n"
+" - :class:`ViewVertex`\n"
+"\n"
+" - :class:`NonTVertex`\n"
+" - :class:`TVertex`\n"
+"\n"
+"- :class:`Interface1D`\n"
+"\n"
+" - :class:`Curve`\n"
+"\n"
+" - :class:`Chain`\n"
+"\n"
+" - :class:`FEdge`\n"
+"\n"
+" - :class:`FEdgeSharp`\n"
+" - :class:`FEdgeSmooth`\n"
+"\n"
+" - :class:`Stroke`\n"
+" - :class:`ViewEdge`\n"
+"\n"
+"- :class:`Iterator`\n"
+"\n"
+" - :class:`AdjacencyIterator`\n"
+" - :class:`CurvePointIterator`\n"
+" - :class:`Interface0DIterator`\n"
+" - :class:`SVertexIterator`\n"
+" - :class:`StrokeVertexIterator`\n"
+" - :class:`ViewEdgeIterator`\n"
+"\n"
+" - :class:`ChainingIterator`\n"
+"\n"
+" - :class:`ChainPredicateIterator`\n"
+" - :class:`ChainSilhouetteIterator`\n"
+"\n"
+" - :class:`orientedViewEdgeIterator`\n"
+"\n"
+"- :class:`Material`\n"
+"- :class:`Noise`\n"
+"- :class:`Operators`\n"
+"- :class:`SShape`\n"
+"- :class:`StrokeAttribute`\n"
+"- :class:`StrokeShader`\n"
+"\n"
+" - :class:`BackboneStretcherShader`\n"
+" - :class:`BezierCurveShader`\n"
+" - :class:`CalligraphicShader`\n"
+" - :class:`ColorNoiseShader`\n"
+" - :class:`ColorVariationPatternShader`\n"
+" - :class:`ConstantColorShader`\n"
+" - :class:`ConstantThicknessShader`\n"
+" - :class:`ConstrainedIncreasingThicknessShader`\n"
+" - :class:`GuidingLinesShader`\n"
+" - :class:`IncreasingColorShader`\n"
+" - :class:`IncreasingThicknessShader`\n"
+" - :class:`PolygonalizationShader`\n"
+" - :class:`SamplingShader`\n"
+" - :class:`SmoothingShader`\n"
+" - :class:`SpatialNoiseShader`\n"
+" - :class:`StrokeTextureShader`\n"
+" - :class:`TextureAssignerShader`\n"
+" - :class:`ThicknessNoiseShader`\n"
+" - :class:`ThicknessVariationPatternShader`\n"
+" - :class:`TipRemoverShader`\n"
+" - :class:`fstreamShader`\n"
+" - :class:`streamShader`\n"
+"\n"
+"- :class:`UnaryFunction0D`\n"
+"\n"
+" - :class:`UnaryFunction0DDouble`\n"
+"\n"
+" - :class:`Curvature2DAngleF0D`\n"
+" - :class:`DensityF0D`\n"
+" - :class:`GetProjectedXF0D`\n"
+" - :class:`GetProjectedYF0D`\n"
+" - :class:`GetProjectedZF0D`\n"
+" - :class:`GetXF0D`\n"
+" - :class:`GetYF0D`\n"
+" - :class:`GetZF0D`\n"
+" - :class:`LocalAverageDepthF0D`\n"
+" - :class:`ZDiscontinuityF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DEdgeNature`\n"
+"\n"
+" - :class:`CurveNatureF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DFloat`\n"
+"\n"
+" - :class:`GetCurvilinearAbscissaF0D`\n"
+" - :class:`GetParameterF0D`\n"
+" - :class:`GetViewMapGradientNormF0D`\n"
+" - :class:`ReadCompleteViewMapPixelF0D`\n"
+" - :class:`ReadMapPixelF0D`\n"
+" - :class:`ReadSteerableViewMapPixelF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DId`\n"
+"\n"
+" - :class:`ShapeIdF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DMaterial`\n"
+"\n"
+" - :class:`MaterialF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DUnsigned`\n"
+"\n"
+" - :class:`QuantitativeInvisibilityF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DVec2f`\n"
+"\n"
+" - :class:`Normal2DF0D`\n"
+" - :class:`VertexOrientation2DF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DVec3f`\n"
+"\n"
+" - :class:`VertexOrientation3DF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DVectorViewShape`\n"
+"\n"
+" - :class:`GetOccludersF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DViewShape`\n"
+"\n"
+" - :class:`GetOccludeeF0D`\n"
+" - :class:`GetShapeF0D`\n"
+"\n"
+"- :class:`UnaryFunction1D`\n"
+"\n"
+" - :class:`UnaryFunction1DDouble`\n"
+"\n"
+" - :class:`Curvature2DAngleF1D`\n"
+" - :class:`DensityF1D`\n"
+" - :class:`GetCompleteViewMapDensityF1D`\n"
+" - :class:`GetDirectionalViewMapDensityF1D`\n"
+" - :class:`GetProjectedXF1D`\n"
+" - :class:`GetProjectedYF1D`\n"
+" - :class:`GetProjectedZF1D`\n"
+" - :class:`GetSteerableViewMapDensityF1D`\n"
+" - :class:`GetViewMapGradientNormF1D`\n"
+" - :class:`GetXF1D`\n"
+" - :class:`GetYF1D`\n"
+" - :class:`GetZF1D`\n"
+" - :class:`LocalAverageDepthF1D`\n"
+" - :class:`ZDiscontinuityF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DEdgeNature`\n"
+"\n"
+" - :class:`CurveNatureF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DFloat`\n"
+" - :class:`UnaryFunction1DUnsigned`\n"
+"\n"
+" - :class:`QuantitativeInvisibilityF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DVec2f`\n"
+"\n"
+" - :class:`Normal2DF1D`\n"
+" - :class:`Orientation2DF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DVec3f`\n"
+"\n"
+" - :class:`Orientation3DF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DVectorViewShape`\n"
+"\n"
+" - :class:`GetOccludeeF1D`\n"
+" - :class:`GetOccludersF1D`\n"
+" - :class:`GetShapeF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DVoid`\n"
+"\n"
+" - :class:`ChainingTimeStampF1D`\n"
+" - :class:`IncrementChainingTimeStampF1D`\n"
+" - :class:`TimeStampF1D`\n"
+"\n"
+"- :class:`UnaryPredicate0D`\n"
+"\n"
+" - :class:`FalseUP0D`\n"
+" - :class:`TrueUP0D`\n"
+"\n"
+"- :class:`UnaryPredicate1D`\n"
+"\n"
+" - :class:`ContourUP1D`\n"
+" - :class:`DensityLowerThanUP1D`\n"
+" - :class:`EqualToChainingTimeStampUP1D`\n"
+" - :class:`EqualToTimeStampUP1D`\n"
+" - :class:`ExternalContourUP1D`\n"
+" - :class:`FalseUP1D`\n"
+" - :class:`QuantitativeInvisibilityUP1D`\n"
+" - :class:`ShapeUP1D`\n"
+" - :class:`TrueUP1D`\n"
+"\n"
+"- :class:`ViewMap`\n"
+"- :class:`ViewShape`\n"
+"- :class:`IntegrationType`\n"
+"- :class:`MediumType`\n"
+"- :class:`Nature`\n"
+"\n";
+
+/*-----------------------Freestyle module method def---------------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"getCurrentScene", ( PyCFunction ) Freestyle_getCurrentScene, METH_NOARGS, Freestyle_getCurrentScene___doc__},
+ {"blendRamp", ( PyCFunction ) Freestyle_blendRamp, METH_VARARGS, Freestyle_blendRamp___doc__},
+ {"evaluateColorRamp", ( PyCFunction ) Freestyle_evaluateColorRamp, METH_VARARGS, Freestyle_evaluateColorRamp___doc__},
+ {"evaluateCurveMappingF", ( PyCFunction ) Freestyle_evaluateCurveMappingF, METH_VARARGS, Freestyle_evaluateCurveMappingF___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------Freestyle module definition---------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+//-------------------MODULE INITIALIZATION--------------------------------
+PyObject *Freestyle_Init( void )
+{
+ PyObject *module;
+
+ // initialize modules
+ module = PyModule_Create(&module_definition);
+ if (!module)
+ return NULL;
+ PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module);
+
+ // attach its classes (adding the object types to the module)
+
+ // those classes have to be initialized before the others
+ MediumType_Init( module );
+ Nature_Init( module );
+
+ BBox_Init( module );
+ BinaryPredicate0D_Init( module );
+ BinaryPredicate1D_Init( module );
+ ContextFunctions_Init( module );
+ FrsMaterial_Init( module );
+ FrsNoise_Init( module );
+ Id_Init( module );
+ IntegrationType_Init( module );
+ Interface0D_Init( module );
+ Interface1D_Init( module );
+ Iterator_Init( module );
+ Operators_Init( module );
+ SShape_Init( module );
+ StrokeAttribute_Init( module );
+ StrokeShader_Init( module );
+ UnaryFunction0D_Init( module );
+ UnaryFunction1D_Init( module );
+ UnaryPredicate0D_Init( module );
+ UnaryPredicate1D_Init( module );
+ ViewMap_Init( module );
+ ViewShape_Init( module );
+
+ return module;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.h b/source/blender/freestyle/intern/python/BPy_Freestyle.h
new file mode 100644
index 00000000000..8ade4b5ff4d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Freestyle.h
@@ -0,0 +1,22 @@
+#ifndef FREESTYLE_PYTHON_FREESTYLE_H
+#define FREESTYLE_PYTHON_FREESTYLE_H
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*---------------------------Python BPy_Freestyle visible prototypes-----------*/
+
+PyObject *Freestyle_Init( void );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FREESTYLE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
new file mode 100644
index 00000000000..b33a9096e81
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
@@ -0,0 +1,599 @@
+#include "BPy_FrsMaterial.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int FrsMaterial_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &FrsMaterial_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &FrsMaterial_Type );
+ PyModule_AddObject(module, "Material", (PyObject *)&FrsMaterial_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FrsMaterial___doc__[] =
+"Class defining a material.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(m)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg m: A Material object.\n"
+" :type m: :class:`Material`\n"
+"\n"
+".. method:: __init__(iDiffuse, iAmbiant, iSpecular, iEmission, iShininess)\n"
+"\n"
+" Builds a Material from its diffuse, ambiant, specular, emissive\n"
+" colors and a shininess coefficient.\n"
+"\n"
+" :arg iDiffuse: The diffuse color.\n"
+" :type iDiffuse: :class:`mathutils.Vector`, list of tuple of 4 float values\n"
+" :arg iAmbiant: The ambiant color.\n"
+" :type iAmbiant: :class:`mathutils.Vector`, list of tuple of 4 float values\n"
+" :arg iSpecular: The specular color.\n"
+" :type iSpecular: :class:`mathutils.Vector`, list of tuple of 4 float values\n"
+" :arg iEmission: The emissive color.\n"
+" :type iEmission: :class:`mathutils.Vector`, list of tuple of 4 float values\n"
+" :arg iShininess: The shininess coefficient.\n"
+" :type iShininess: :class:`mathutils.Vector`, list of tuple of 4 float values\n";
+
+static int Vec4(PyObject *obj, float *v)
+{
+ if (VectorObject_Check(obj) && ((VectorObject *)obj)->size == 4) {
+ for (int i = 0; i < 4; i++)
+ v[i] = ((VectorObject *)obj)->vec[i];
+ } else if( PyList_Check(obj) && PyList_Size(obj) == 4 ) {
+ for (int i = 0; i < 4; i++)
+ v[i] = PyFloat_AsDouble(PyList_GetItem(obj, i));
+ } else if( PyTuple_Check(obj) && PyTuple_Size(obj) == 4 ) {
+ for (int i = 0; i < 4; i++)
+ v[i] = PyFloat_AsDouble(PyTuple_GetItem(obj, i));
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static int FrsMaterial___init__(BPy_FrsMaterial *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0;
+ float f1[4], f2[4], f3[4], f4[4], f5 = 0.;
+
+ if (! PyArg_ParseTuple(args, "|OOOOf", &obj1, &obj2, &obj3, &obj4, &f5) )
+ return -1;
+
+ if( !obj1 ){
+ self->m = new FrsMaterial();
+
+ } else if( BPy_FrsMaterial_Check(obj1) && !obj2 ) {
+ FrsMaterial *m = ((BPy_FrsMaterial *) obj1)->m;
+ if( !m ) {
+ PyErr_SetString(PyExc_RuntimeError, "invalid FrsMaterial object");
+ return -1;
+ }
+ self->m = new FrsMaterial( *m );
+
+ } else if( Vec4(obj1, f1) && obj2 && Vec4(obj2, f2) && obj3 && Vec4(obj3, f3) && obj4 && Vec4(obj4, f4) ) {
+ self->m = new FrsMaterial(f1, f2, f3, f4, f5);
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->borrowed = 0;
+
+ return 0;
+}
+
+static void FrsMaterial___dealloc__( BPy_FrsMaterial* self)
+{
+ if( self->m && !self->borrowed )
+ delete self->m;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * FrsMaterial___repr__( BPy_FrsMaterial* self)
+{
+ return PyUnicode_FromFormat("Material - address: %p", self->m );
+}
+
+static char FrsMaterial_diffuse___doc__[] =
+".. method:: diffuse()\n"
+"\n"
+" Returns the diffuse color.\n"
+"\n"
+" :return: The diffuse color.\n"
+" :rtype: Tuple of 4 float values\n";
+
+static PyObject * FrsMaterial_diffuse( BPy_FrsMaterial* self) {
+ const float *diffuse = self->m->diffuse();
+ PyObject *py_diffuse = PyTuple_New(4);
+
+ PyTuple_SetItem( py_diffuse, 0, PyFloat_FromDouble( diffuse[0] ) );
+ PyTuple_SetItem( py_diffuse, 1, PyFloat_FromDouble( diffuse[1] ) );
+ PyTuple_SetItem( py_diffuse, 2, PyFloat_FromDouble( diffuse[2] ) );
+ PyTuple_SetItem( py_diffuse, 3, PyFloat_FromDouble( diffuse[3] ) );
+
+ return py_diffuse;
+}
+
+static char FrsMaterial_diffuseR___doc__[] =
+".. method:: diffuseR()\n"
+"\n"
+" Returns the red component of the diffuse color.\n"
+"\n"
+" :return: The red component of the diffuse color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_diffuseR( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->diffuseR() );
+}
+
+static char FrsMaterial_diffuseG___doc__[] =
+".. method:: diffuseG()\n"
+"\n"
+" Returns the green component of the diffuse color.\n"
+"\n"
+" :return: The green component of the diffuse color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_diffuseG( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->diffuseG() );
+}
+
+static char FrsMaterial_diffuseB___doc__[] =
+".. method:: diffuseB()\n"
+"\n"
+" Returns the blue component of the diffuse color.\n"
+"\n"
+" :return: The blue component of the diffuse color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_diffuseB( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->diffuseB() );
+}
+
+static char FrsMaterial_diffuseA___doc__[] =
+".. method:: diffuseA()\n"
+"\n"
+" Returns the alpha component of the diffuse color.\n"
+"\n"
+" :return: The alpha component of the diffuse color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_diffuseA( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->diffuseA() );
+}
+
+static char FrsMaterial_specular___doc__[] =
+".. method:: specular()\n"
+"\n"
+" Returns the specular color.\n"
+"\n"
+" :return: The specular color.\n"
+" :rtype: Tuple of 4 float values\n";
+
+static PyObject * FrsMaterial_specular( BPy_FrsMaterial* self) {
+ const float *specular = self->m->specular();
+ PyObject *py_specular = PyTuple_New(4);
+
+ PyTuple_SetItem( py_specular, 0, PyFloat_FromDouble( specular[0] ) );
+ PyTuple_SetItem( py_specular, 1, PyFloat_FromDouble( specular[1] ) );
+ PyTuple_SetItem( py_specular, 2, PyFloat_FromDouble( specular[2] ) );
+ PyTuple_SetItem( py_specular, 3, PyFloat_FromDouble( specular[3] ) );
+
+ return py_specular;
+}
+
+static char FrsMaterial_specularR___doc__[] =
+".. method:: specularR()\n"
+"\n"
+" Returns the red component of the specular color.\n"
+"\n"
+" :return: The red component of the specular color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_specularR( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->specularR() );
+}
+
+static char FrsMaterial_specularG___doc__[] =
+".. method:: specularG()\n"
+"\n"
+" Returns the green component of the specular color.\n"
+"\n"
+" :return: The green component of the specular color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_specularG( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->specularG() );
+}
+
+static char FrsMaterial_specularB___doc__[] =
+".. method:: specularB()\n"
+"\n"
+" Returns the blue component of the specular color.\n"
+"\n"
+" :return: The blue component of the specular color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_specularB( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->specularB() );
+}
+
+static char FrsMaterial_specularA___doc__[] =
+".. method:: specularA()\n"
+"\n"
+" Returns the alpha component of the specular color.\n"
+"\n"
+" :return: The alpha component of the specular color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_specularA( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->specularA() );
+}
+
+static char FrsMaterial_ambient___doc__[] =
+".. method:: ambient()\n"
+"\n"
+" Returns the ambiant color.\n"
+"\n"
+" :return: The ambiant color.\n"
+" :rtype: Tuple of 4 float values\n";
+
+static PyObject * FrsMaterial_ambient( BPy_FrsMaterial* self) {
+ const float *ambient = self->m->ambient();
+ PyObject *py_ambient = PyTuple_New(4);
+
+ PyTuple_SetItem( py_ambient, 0, PyFloat_FromDouble( ambient[0] ) );
+ PyTuple_SetItem( py_ambient, 1, PyFloat_FromDouble( ambient[1] ) );
+ PyTuple_SetItem( py_ambient, 2, PyFloat_FromDouble( ambient[2] ) );
+ PyTuple_SetItem( py_ambient, 3, PyFloat_FromDouble( ambient[3] ) );
+
+ return py_ambient;
+}
+
+static char FrsMaterial_ambientR___doc__[] =
+".. method:: ambientR()\n"
+"\n"
+" Returns the red component of the ambiant color.\n"
+"\n"
+" :return: The red component of the ambiant color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_ambientR( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->ambientR() );
+}
+
+static char FrsMaterial_ambientG___doc__[] =
+".. method:: ambientG()\n"
+"\n"
+" Returns the green component of the ambiant color.\n"
+"\n"
+" :return: The green component of the ambiant color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_ambientG( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->ambientG() );
+}
+
+static char FrsMaterial_ambientB___doc__[] =
+".. method:: ambientB()\n"
+"\n"
+" Returns the blue component of the ambiant color.\n"
+"\n"
+" :return: The blue component of the ambiant color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_ambientB( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->ambientB() );
+}
+
+static char FrsMaterial_ambientA___doc__[] =
+".. method:: ambientA()\n"
+"\n"
+" Returns the alpha component of the ambiant color.\n"
+"\n"
+" :return: The alpha component of the ambiant color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_ambientA( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->ambientA() );
+}
+
+static char FrsMaterial_emission___doc__[] =
+".. method:: emission()\n"
+"\n"
+" Returns the emissive color.\n"
+"\n"
+" :return: the emissive color.\n"
+" :rtype: Tuple of 4 float values\n";
+
+static PyObject * FrsMaterial_emission( BPy_FrsMaterial* self) {
+ const float *emission = self->m->emission();
+ PyObject *py_emission = PyTuple_New(4);
+
+ PyTuple_SetItem( py_emission, 0, PyFloat_FromDouble( emission[0] ) );
+ PyTuple_SetItem( py_emission, 1, PyFloat_FromDouble( emission[1] ) );
+ PyTuple_SetItem( py_emission, 2, PyFloat_FromDouble( emission[2] ) );
+ PyTuple_SetItem( py_emission, 3, PyFloat_FromDouble( emission[3] ) );
+
+ return py_emission;
+}
+
+static char FrsMaterial_emissionR___doc__[] =
+".. method:: emissionR()\n"
+"\n"
+" Returns the red component of the emissive color.\n"
+"\n"
+" :return: The red component of the emissive color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_emissionR( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->emissionR() );
+}
+
+static char FrsMaterial_emissionG___doc__[] =
+".. method:: emissionG()\n"
+"\n"
+" Returns the green component of the emissive color.\n"
+"\n"
+" :return: The green component of the emissive color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_emissionG( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->emissionG() );
+}
+
+static char FrsMaterial_emissionB___doc__[] =
+".. method:: emissionB()\n"
+"\n"
+" Returns the blue component of the emissive color.\n"
+"\n"
+" :return: The blue component of the emissive color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_emissionB( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->emissionB() );
+}
+
+static char FrsMaterial_emissionA___doc__[] =
+".. method:: emissionA()\n"
+"\n"
+" Returns the alpha component of the emissive color.\n"
+"\n"
+" :return: The alpha component of the emissive color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_emissionA( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->emissionA() );
+}
+
+static char FrsMaterial_shininess___doc__[] =
+".. method:: shininess()\n"
+"\n"
+" Returns the shininess coefficient.\n"
+"\n"
+" :return: Shininess\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_shininess( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->shininess() );
+}
+
+static char FrsMaterial_setDiffuse___doc__[] =
+".. method:: setDiffuse(r, g, b, a)\n"
+"\n"
+" Sets the diffuse color.\n"
+"\n"
+" :arg r: Red component.\n"
+" :type r: float\n"
+" :arg g: Green component.\n"
+" :type g: float\n"
+" :arg b: Blue component.\n"
+" :type b: float\n"
+" :arg a: Alpha component.\n"
+" :type a: float\n";
+
+static PyObject * FrsMaterial_setDiffuse( BPy_FrsMaterial *self, PyObject *args ) {
+ float f1, f2, f3, f4;
+
+ if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) ))
+ return NULL;
+
+ self->m->setDiffuse(f1, f2, f3, f4);
+
+ Py_RETURN_NONE;
+}
+
+static char FrsMaterial_setSpecular___doc__[] =
+".. method:: setSpecular(r, g, b, a)\n"
+"\n"
+" Sets the specular color.\n"
+"\n"
+" :arg r: Red component.\n"
+" :type r: float\n"
+" :arg g: Green component.\n"
+" :type g: float\n"
+" :arg b: Blue component.\n"
+" :type b: float\n"
+" :arg a: Alpha component.\n"
+" :type a: float\n";
+
+static PyObject * FrsMaterial_setSpecular( BPy_FrsMaterial *self, PyObject *args ) {
+ float f1, f2, f3, f4;
+
+ if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) ))
+ return NULL;
+
+ self->m->setSpecular(f1, f2, f3, f4);
+
+ Py_RETURN_NONE;
+}
+
+static char FrsMaterial_setAmbient___doc__[] =
+".. method:: setAmbient(r, g, b, a)\n"
+"\n"
+" Sets the ambiant color.\n"
+"\n"
+" :arg r: Red component.\n"
+" :type r: float\n"
+" :arg g: Green component.\n"
+" :type g: float\n"
+" :arg b: Blue component.\n"
+" :type b: float\n"
+" :arg a: Alpha component.\n"
+" :type a: float\n";
+
+static PyObject * FrsMaterial_setAmbient( BPy_FrsMaterial *self, PyObject *args ) {
+ float f1, f2, f3, f4;
+
+ if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) ))
+ return NULL;
+
+ self->m->setAmbient(f1, f2, f3, f4);
+
+ Py_RETURN_NONE;
+}
+
+static char FrsMaterial_setEmission___doc__[] =
+".. method:: setEmission(r, g, b, a)\n"
+"\n"
+" Sets the emissive color.\n"
+"\n"
+" :arg r: Red component.\n"
+" :type r: float\n"
+" :arg g: Green component.\n"
+" :type g: float\n"
+" :arg b: Blue component.\n"
+" :type b: float\n"
+" :arg a: Alpha component.\n"
+" :type a: float\n";
+
+static PyObject * FrsMaterial_setEmission( BPy_FrsMaterial *self, PyObject *args ) {
+ float f1, f2, f3, f4;
+
+ if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) ))
+ return NULL;
+
+ self->m->setEmission(f1, f2, f3, f4);
+
+ Py_RETURN_NONE;
+}
+
+static char FrsMaterial_setShininess___doc__[] =
+".. method:: setShininess(s)\n"
+"\n"
+" Sets the shininess.\n"
+"\n"
+" :arg s: Shininess.\n"
+" :type s: float\n";
+
+static PyObject * FrsMaterial_setShininess( BPy_FrsMaterial *self, PyObject *args ) {
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return NULL;
+
+ self->m->setShininess(f);
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------FrsMaterial instance definitions ----------------------------*/
+static PyMethodDef BPy_FrsMaterial_methods[] = {
+ {"diffuse", ( PyCFunction ) FrsMaterial_diffuse, METH_NOARGS, FrsMaterial_diffuse___doc__},
+ {"diffuseR", ( PyCFunction ) FrsMaterial_diffuseR, METH_NOARGS, FrsMaterial_diffuseR___doc__},
+ {"diffuseG", ( PyCFunction ) FrsMaterial_diffuseG, METH_NOARGS, FrsMaterial_diffuseG___doc__},
+ {"diffuseB", ( PyCFunction ) FrsMaterial_diffuseB, METH_NOARGS, FrsMaterial_diffuseB___doc__},
+ {"diffuseA", ( PyCFunction ) FrsMaterial_diffuseA, METH_NOARGS, FrsMaterial_diffuseA___doc__},
+ {"specular", ( PyCFunction ) FrsMaterial_specular, METH_NOARGS, FrsMaterial_specular___doc__},
+ {"specularR", ( PyCFunction ) FrsMaterial_specularR, METH_NOARGS, FrsMaterial_specularR___doc__},
+ {"specularG", ( PyCFunction ) FrsMaterial_specularG, METH_NOARGS, FrsMaterial_specularG___doc__},
+ {"specularB", ( PyCFunction ) FrsMaterial_specularB, METH_NOARGS, FrsMaterial_specularB___doc__},
+ {"specularA", ( PyCFunction ) FrsMaterial_specularA, METH_NOARGS, FrsMaterial_specularA___doc__},
+ {"ambient", ( PyCFunction ) FrsMaterial_ambient, METH_NOARGS, FrsMaterial_ambient___doc__},
+ {"ambientR", ( PyCFunction ) FrsMaterial_ambientR, METH_NOARGS, FrsMaterial_ambientR___doc__},
+ {"ambientG", ( PyCFunction ) FrsMaterial_ambientG, METH_NOARGS, FrsMaterial_ambientG___doc__},
+ {"ambientB", ( PyCFunction ) FrsMaterial_ambientB, METH_NOARGS, FrsMaterial_ambientB___doc__},
+ {"ambientA", ( PyCFunction ) FrsMaterial_ambientA, METH_NOARGS, FrsMaterial_ambientA___doc__},
+ {"emission", ( PyCFunction ) FrsMaterial_emission, METH_NOARGS, FrsMaterial_emission___doc__},
+ {"emissionR", ( PyCFunction ) FrsMaterial_emissionR, METH_NOARGS, FrsMaterial_emissionR___doc__},
+ {"emissionG", ( PyCFunction ) FrsMaterial_emissionG, METH_NOARGS, FrsMaterial_emissionG___doc__},
+ {"emissionB", ( PyCFunction ) FrsMaterial_emissionB, METH_NOARGS, FrsMaterial_emissionB___doc__},
+ {"emissionA", ( PyCFunction ) FrsMaterial_emissionA, METH_NOARGS, FrsMaterial_emissionA___doc__},
+ {"shininess", ( PyCFunction ) FrsMaterial_shininess, METH_NOARGS, FrsMaterial_shininess___doc__},
+ {"setDiffuse", ( PyCFunction ) FrsMaterial_setDiffuse, METH_NOARGS, FrsMaterial_setDiffuse___doc__},
+ {"setSpecular", ( PyCFunction ) FrsMaterial_setSpecular, METH_NOARGS, FrsMaterial_setSpecular___doc__},
+ {"setAmbient", ( PyCFunction ) FrsMaterial_setAmbient, METH_NOARGS, FrsMaterial_setAmbient___doc__},
+ {"setEmission", ( PyCFunction ) FrsMaterial_setEmission, METH_NOARGS, FrsMaterial_setEmission___doc__},
+ {"setShininess", ( PyCFunction ) FrsMaterial_setShininess, METH_NOARGS, FrsMaterial_setShininess___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FrsMaterial type definition ------------------------------*/
+
+PyTypeObject FrsMaterial_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Material", /* tp_name */
+ sizeof(BPy_FrsMaterial), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)FrsMaterial___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)FrsMaterial___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FrsMaterial___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FrsMaterial_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsMaterial___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.h b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h
new file mode 100644
index 00000000000..f541e1bb529
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_FRSMATERIAL_H
+#define FREESTYLE_PYTHON_FRSMATERIAL_H
+
+#include <Python.h>
+
+#include "../scene_graph/FrsMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject FrsMaterial_Type;
+
+#define BPy_FrsMaterial_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsMaterial_Type) )
+
+/*---------------------------Python BPy_FrsMaterial structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ FrsMaterial *m;
+ int borrowed; /* non-zero if *m is a borrowed object */
+} BPy_FrsMaterial;
+
+/*---------------------------Python BPy_FrsMaterial visible prototypes-----------*/
+
+int FrsMaterial_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_FRSMATERIAL_H */
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
new file mode 100644
index 00000000000..d58a37179ac
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
@@ -0,0 +1,280 @@
+#include "BPy_FrsNoise.h"
+#include "BPy_Convert.h"
+
+#include <sstream>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int FrsNoise_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &FrsNoise_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &FrsNoise_Type );
+ PyModule_AddObject(module, "Noise", (PyObject *)&FrsNoise_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FrsNoise___doc__[] =
+"Class to provide Perlin noise functionalities.\n"
+"\n"
+".. method:: __init__(seed = -1)\n"
+"\n"
+" Builds a Noise object. Seed is an optional argument. The seed value is used\n"
+" as a seed for random number generation if it is equal to or greater than zero;\n"
+" otherwise, time is used as a seed.\n"
+"\n"
+" :arg seed: Seed for random number generation.\n"
+" :type seed: int\n";
+
+static int FrsNoise___init__(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ long seed = -1;
+ if(!( PyArg_ParseTuple(args, "|l", &seed) ))
+ return -1;
+ self->n = new Noise(seed);
+ return 0;
+}
+
+static void FrsNoise___dealloc__(BPy_FrsNoise* self)
+{
+ delete self->n;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * FrsNoise___repr__(BPy_FrsNoise* self)
+{
+ return PyUnicode_FromFormat("Noise - address: %p", self->n );
+}
+
+static char FrsNoise_turbulence1___doc__[] =
+".. method:: turbulence1(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 1D element.\n"
+"\n"
+" :arg v: One-dimensional sample point.\n"
+" :type v: float\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_turbulence1( BPy_FrsNoise *self , PyObject *args) {
+ float f1, f2, f3;
+ unsigned int i = 4;
+
+ if(!( PyArg_ParseTuple(args, "fff|I", &f1, &f2, &f3, &i) ))
+ return NULL;
+
+ return PyFloat_FromDouble( self->n->turbulence1(f1, f2, f3, i) );
+}
+
+static char FrsNoise_turbulence2___doc__[] =
+".. method:: turbulence2(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 2D element.\n"
+"\n"
+" :arg v: Two-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_turbulence2( BPy_FrsNoise *self , PyObject *args) {
+ PyObject *obj1;
+ float f2, f3;
+ unsigned int i = 4;
+
+ if(!( PyArg_ParseTuple(args, "Off|I", &obj1, &f2, &f3, &i) ))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->turbulence2(*v, f2, f3, i);
+ delete v;
+ return PyFloat_FromDouble( t );
+}
+
+static char FrsNoise_turbulence3___doc__[] =
+".. method:: turbulence3(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 3D element.\n"
+"\n"
+" :arg v: Three-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_turbulence3( BPy_FrsNoise *self , PyObject *args) {
+ PyObject *obj1;
+ float f2, f3;
+ unsigned int i = 4;
+
+ if(!( PyArg_ParseTuple(args, "Off|I", &obj1, &f2, &f3, &i) ))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->turbulence3(*v, f2, f3, i);
+ delete v;
+ return PyFloat_FromDouble( t );
+}
+
+static char FrsNoise_smoothNoise1___doc__[] =
+".. method:: smoothNoise1(v)\n"
+"\n"
+" Returns a smooth noise value for a 1D element.\n"
+"\n"
+" :arg v: One-dimensional sample point.\n"
+" :type v: float\n"
+" :return: A smooth noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_smoothNoise1( BPy_FrsNoise *self , PyObject *args) {
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return NULL;
+
+ return PyFloat_FromDouble( self->n->smoothNoise1(f) );
+}
+
+static char FrsNoise_smoothNoise2___doc__[] =
+".. method:: smoothNoise2(v)\n"
+"\n"
+" Returns a smooth noise value for a 2D element.\n"
+"\n"
+" :arg v: Two-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"
+" :return: A smooth noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_smoothNoise2( BPy_FrsNoise *self , PyObject *args) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->smoothNoise2(*v);
+ delete v;
+ return PyFloat_FromDouble( t );
+}
+
+static char FrsNoise_smoothNoise3___doc__[] =
+".. method:: smoothNoise3(v)\n"
+"\n"
+" Returns a smooth noise value for a 3D element.\n"
+"\n"
+" :arg v: Three-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :return: A smooth noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_smoothNoise3( BPy_FrsNoise *self , PyObject *args) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->smoothNoise3(*v);
+ delete v;
+ return PyFloat_FromDouble( t );
+}
+
+/*----------------------FrsNoise instance definitions ----------------------------*/
+static PyMethodDef BPy_FrsNoise_methods[] = {
+ {"turbulence1", ( PyCFunction ) FrsNoise_turbulence1, METH_VARARGS, FrsNoise_turbulence1___doc__},
+ {"turbulence2", ( PyCFunction ) FrsNoise_turbulence2, METH_VARARGS, FrsNoise_turbulence2___doc__},
+ {"turbulence3", ( PyCFunction ) FrsNoise_turbulence3, METH_VARARGS, FrsNoise_turbulence3___doc__},
+ {"smoothNoise1", ( PyCFunction ) FrsNoise_smoothNoise1, METH_VARARGS, FrsNoise_smoothNoise1___doc__},
+ {"smoothNoise2", ( PyCFunction ) FrsNoise_smoothNoise2, METH_VARARGS, FrsNoise_smoothNoise2___doc__},
+ {"smoothNoise3", ( PyCFunction ) FrsNoise_smoothNoise3, METH_VARARGS, FrsNoise_smoothNoise3___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FrsNoise type definition ------------------------------*/
+
+PyTypeObject FrsNoise_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Noise", /* tp_name */
+ sizeof(BPy_FrsNoise), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)FrsNoise___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)FrsNoise___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FrsNoise___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FrsNoise_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsNoise___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.h b/source/blender/freestyle/intern/python/BPy_FrsNoise.h
new file mode 100644
index 00000000000..00b4f3375bc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_FRSNOISE_H
+#define FREESTYLE_PYTHON_FRSNOISE_H
+
+#include <Python.h>
+
+#include "../geometry/Noise.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject FrsNoise_Type;
+
+#define BPy_FrsNoise_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsNoise_Type) )
+
+/*---------------------------Python BPy_FrsNoise structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Noise *n;
+} BPy_FrsNoise;
+
+/*---------------------------Python BPy_FrsNoise visible prototypes-----------*/
+
+int FrsNoise_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_FRSNOISE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Id.cpp b/source/blender/freestyle/intern/python/BPy_Id.cpp
new file mode 100644
index 00000000000..9254badd95d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Id.cpp
@@ -0,0 +1,222 @@
+#include "BPy_Id.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Id_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Id_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &Id_Type );
+ PyModule_AddObject(module, "Id", (PyObject *)&Id_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Id___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An Id object.\n"
+" :type iBrother: :class:`Id`\n"
+"\n"
+".. method:: __init__(iFirst)\n"
+"\n"
+" Builds an Id from an integer. The second number is set to 0.\n"
+"\n"
+" :arg iFirst: The first Id number.\n"
+" :type iFirst: int\n"
+"\n"
+".. method:: __init__(iFirst, iSecond)\n"
+"\n"
+" Builds the Id from the two numbers.\n"
+"\n"
+" :arg iFirst: The first Id number.\n"
+" :type iFirst: int\n"
+" :arg iSecond: The second Id number.\n"
+" :type iSecond: int\n";
+
+static int Id___init__(BPy_Id *self, PyObject *args, PyObject *kwds)
+{
+ int first = 0, second = 0;
+ static char *kwlist[] = {"first", "second", NULL};
+
+ if (! PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &first, &second) )
+ return -1;
+
+ self->id = new Id( first, second );
+
+ return 0;
+}
+
+static void Id___dealloc__(BPy_Id* self)
+{
+ delete self->id;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * Id___repr__(BPy_Id* self)
+{
+ return PyUnicode_FromFormat("[ first: %i, second: %i ](BPy_Id)", self->id->getFirst(), self->id->getSecond() );
+}
+
+static char Id_getFirst___doc__[] =
+".. method:: getFirst()\n"
+"\n"
+" Returns the first Id number.\n"
+"\n"
+" :return: The first Id number.\n"
+" :rtype: int\n";
+
+static PyObject *Id_getFirst( BPy_Id *self ) {
+ return PyLong_FromLong( self->id->getFirst() );
+}
+
+static char Id_getSecond___doc__[] =
+".. method:: getSecond()\n"
+"\n"
+" Returns the second Id number.\n"
+"\n"
+" :return: The second Id number.\n"
+" :rtype: int\n";
+
+static PyObject *Id_getSecond( BPy_Id *self) {
+ return PyLong_FromLong( self->id->getSecond() );
+}
+
+static char Id_setFirst___doc__[] =
+".. method:: setFirst(iFirst)\n"
+"\n"
+" Sets the first number constituting the Id.\n"
+"\n"
+" :arg iFirst: The first number constituting the Id.\n"
+" :type iFirst: int\n";
+
+static PyObject *Id_setFirst( BPy_Id *self , PyObject *args) {
+ unsigned int i;
+
+ if( !PyArg_ParseTuple(args, "i", &i) )
+ return NULL;
+
+ self->id->setFirst( i );
+
+ Py_RETURN_NONE;
+}
+
+static char Id_setSecond___doc__[] =
+".. method:: setSecond(iSecond)\n"
+"\n"
+" Sets the second number constituting the Id.\n"
+"\n"
+" :arg iSecond: The second number constituting the Id.\n"
+" :type iSecond: int\n";
+
+static PyObject *Id_setSecond( BPy_Id *self , PyObject *args) {
+ unsigned int i;
+
+ if( !PyArg_ParseTuple(args, "i", &i) )
+ return NULL;
+
+ self->id->setSecond( i );
+
+ Py_RETURN_NONE;
+}
+
+static PyObject * Id_RichCompare(BPy_Id *o1, BPy_Id *o2, int opid) {
+ switch(opid){
+ case Py_LT:
+ return PyBool_from_bool( o1->id->operator<(*(o2->id)) );
+ break;
+ case Py_LE:
+ return PyBool_from_bool( o1->id->operator<(*(o2->id)) || o1->id->operator<(*(o2->id)) );
+ break;
+ case Py_EQ:
+ return PyBool_from_bool( o1->id->operator==(*(o2->id)) );
+ break;
+ case Py_NE:
+ return PyBool_from_bool( o1->id->operator!=(*(o2->id)) );
+ break;
+ case Py_GT:
+ return PyBool_from_bool(!( o1->id->operator<(*(o2->id)) || o1->id->operator<(*(o2->id)) ));
+ break;
+ case Py_GE:
+ return PyBool_from_bool(!( o1->id->operator<(*(o2->id)) ));
+ break;
+ }
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------Id instance definitions ----------------------------*/
+static PyMethodDef BPy_Id_methods[] = {
+ {"getFirst", ( PyCFunction ) Id_getFirst, METH_NOARGS, Id_getFirst___doc__},
+ {"getSecond", ( PyCFunction ) Id_getSecond, METH_NOARGS, Id_getSecond___doc__},
+ {"setFirst", ( PyCFunction ) Id_setFirst, METH_VARARGS, Id_setFirst___doc__},
+ {"setSecond", ( PyCFunction ) Id_setSecond, METH_VARARGS, Id_setSecond___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Id type definition ------------------------------*/
+
+PyTypeObject Id_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Id", /* tp_name */
+ sizeof(BPy_Id), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Id___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Id___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Id___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ (richcmpfunc)Id_RichCompare, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Id_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Id___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Id.h b/source/blender/freestyle/intern/python/BPy_Id.h
new file mode 100644
index 00000000000..10f370f8a80
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Id.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_ID_H
+#define FREESTYLE_PYTHON_ID_H
+
+#include <Python.h>
+#include <iostream>
+using namespace std;
+
+#include "../system/Id.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Id_Type;
+
+#define BPy_Id_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Id_Type) )
+
+/*---------------------------Python BPy_Id structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Id *id;
+} BPy_Id;
+
+/*---------------------------Python BPy_Id visible prototypes-----------*/
+
+int Id_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ID_H */
diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
new file mode 100644
index 00000000000..9ce20632a25
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
@@ -0,0 +1,250 @@
+#include "BPy_IntegrationType.h"
+
+#include "BPy_Convert.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+static char Integrator_integrate___doc__[] =
+".. function:: integrate(fun, it, it_end, integration_type)\n"
+"\n"
+" Returns a single value from a set of values evaluated at each 0D\n"
+" element of this 1D element.\n"
+"\n"
+" :arg fun: The UnaryFunction0D used to compute a value at each\n"
+" Interface0D.\n"
+" :type fun: :class:`UnaryFunction0D`\n"
+" :arg it: The Interface0DIterator used to iterate over the 0D\n"
+" elements of this 1D element. The integration will occur over\n"
+" the 0D elements starting from the one pointed by it.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :arg it_end: The Interface0DIterator pointing the end of the 0D\n"
+" elements of the 1D element.\n"
+" :type it_end: :class:`Interface0DIterator`\n"
+" :arg integration_type: The integration method used to compute a\n"
+" single value from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :return: The single value obtained for the 1D element. The return\n"
+" value type is float if fun is of the :class:`UnaryFunction0DDouble`\n"
+" or :class:`UnaryFunction0DFloat` type, and int if fun is of the\n"
+" :class:`UnaryFunction0DUnsigned` type.\n"
+" :rtype: int or float\n";
+
+static PyObject * Integrator_integrate( PyObject *self, PyObject *args )
+{
+ PyObject *obj1, *obj4 = 0;
+ BPy_Interface0DIterator *obj2, *obj3;
+
+#if 1
+ if(!( PyArg_ParseTuple(args, "O!O!O!|O!", &UnaryFunction0D_Type, &obj1,
+ &Interface0DIterator_Type, &obj2, &Interface0DIterator_Type, &obj3,
+ &IntegrationType_Type, &obj4) ))
+ return NULL;
+#else
+ if(!( PyArg_ParseTuple(args, "OOO|O", &obj1, &obj2, &obj3, &obj4) ))
+ return NULL;
+ if(!BPy_UnaryFunction0D_Check(obj1)) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a UnaryFunction0D object");
+ return NULL;
+ }
+ if(!BPy_Interface0DIterator_Check(obj2)) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a Interface0DIterator object");
+ return NULL;
+ }
+ if(!BPy_Interface0DIterator_Check(obj3)) {
+ PyErr_SetString(PyExc_TypeError, "argument 3 must be a Interface0DIterator object");
+ return NULL;
+ }
+ if(obj4 && !BPy_IntegrationType_Check(obj4)) {
+ PyErr_SetString(PyExc_TypeError, "argument 4 must be a IntegrationType object");
+ return NULL;
+ }
+#endif
+
+ Interface0DIterator it(*(obj2->if0D_it)), it_end(*(obj3->if0D_it));
+ IntegrationType t = ( obj4 ) ? IntegrationType_from_BPy_IntegrationType( obj4 ) : MEAN;
+
+ if( BPy_UnaryFunction0DDouble_Check(obj1) ) {
+ UnaryFunction0D<double> *fun = ((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double;
+ double res = integrate( *fun, it, it_end, t );
+ return PyFloat_FromDouble( res );
+
+ } else if( BPy_UnaryFunction0DFloat_Check(obj1) ) {
+ UnaryFunction0D<float> *fun = ((BPy_UnaryFunction0DFloat *)obj1)->uf0D_float;
+ float res = integrate( *fun, it, it_end, t );
+ return PyFloat_FromDouble( res );
+
+ } else if( BPy_UnaryFunction0DUnsigned_Check(obj1) ) {
+ UnaryFunction0D<unsigned int> *fun = ((BPy_UnaryFunction0DUnsigned *)obj1)->uf0D_unsigned;
+ unsigned int res = integrate( *fun, it, it_end, t );
+ return PyLong_FromLong( res );
+
+ } else {
+ string msg("unsupported function type: " + string(obj1->ob_type->tp_name));
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+ }
+}
+
+/*-----------------------Integrator module docstring---------------------------------------*/
+
+static char module_docstring[] = "The Blender Freestyle.Integrator submodule\n\n";
+
+/*-----------------------Integrator module functions definitions---------------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"integrate", (PyCFunction) Integrator_integrate, METH_VARARGS, Integrator_integrate___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------Integrator module definition--------------------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle.Integrator",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+/*-----------------------BPy_IntegrationType type definition ------------------------------*/
+
+static char IntegrationType___doc__[] =
+"Class hierarchy: int > :class:`IntegrationType`\n"
+"\n"
+"Different integration methods that can be invoked to integrate into a\n"
+"single value the set of values obtained from each 0D element of an 1D\n"
+"element:\n"
+"\n"
+"* IntegrationType.MEAN: The value computed for the 1D element is the\n"
+" mean of the values obtained for the 0D elements.\n"
+"* IntegrationType.MIN: The value computed for the 1D element is the\n"
+" minimum of the values obtained for the 0D elements.\n"
+"* IntegrationType.MAX: The value computed for the 1D element is the\n"
+" maximum of the values obtained for the 0D elements.\n"
+"* IntegrationType.FIRST: The value computed for the 1D element is the\n"
+" first of the values obtained for the 0D elements.\n"
+"* IntegrationType.LAST: The value computed for the 1D element is the\n"
+" last of the values obtained for the 0D elements.\n";
+
+PyTypeObject IntegrationType_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IntegrationType", /* tp_name */
+ sizeof(PyLongObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ IntegrationType___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_IntegrationType instance definitions -------------------------*/
+
+static PyLongObject _IntegrationType_MEAN = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MEAN }
+};
+static PyLongObject _IntegrationType_MIN = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MIN }
+};
+static PyLongObject _IntegrationType_MAX = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MAX }
+};
+static PyLongObject _IntegrationType_FIRST = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { FIRST }
+};
+static PyLongObject _IntegrationType_LAST = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { LAST }
+};
+
+#define BPy_IntegrationType_MEAN ((PyObject *)&_IntegrationType_MEAN)
+#define BPy_IntegrationType_MIN ((PyObject *)&_IntegrationType_MIN)
+#define BPy_IntegrationType_MAX ((PyObject *)&_IntegrationType_MAX)
+#define BPy_IntegrationType_FIRST ((PyObject *)&_IntegrationType_FIRST)
+#define BPy_IntegrationType_LAST ((PyObject *)&_IntegrationType_LAST)
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int IntegrationType_Init( PyObject *module )
+{
+ PyObject *m, *d, *f;
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &IntegrationType_Type ) < 0 )
+ return -1;
+ Py_INCREF( &IntegrationType_Type );
+ PyModule_AddObject(module, "IntegrationType", (PyObject *)&IntegrationType_Type);
+
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "MEAN", BPy_IntegrationType_MEAN);
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "MIN", BPy_IntegrationType_MIN);
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "MAX", BPy_IntegrationType_MAX);
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "FIRST", BPy_IntegrationType_FIRST);
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "LAST", BPy_IntegrationType_LAST);
+
+ m = PyModule_Create(&module_definition);
+ if (m == NULL)
+ return -1;
+ Py_INCREF(m);
+ PyModule_AddObject(module, "Integrator", m);
+
+ // from Integrator import *
+ d = PyModule_GetDict(m);
+ for (PyMethodDef *p = module_functions; p->ml_name; p++) {
+ f = PyDict_GetItemString(d, p->ml_name);
+ Py_INCREF(f);
+ PyModule_AddObject(module, p->ml_name, f);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.h b/source/blender/freestyle/intern/python/BPy_IntegrationType.h
new file mode 100644
index 00000000000..f15ae8309e3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.h
@@ -0,0 +1,28 @@
+#ifndef FREESTYLE_PYTHON_INTEGRATIONTYPE_H
+#define FREESTYLE_PYTHON_INTEGRATIONTYPE_H
+
+#include <Python.h>
+
+#include "../view_map/Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject IntegrationType_Type;
+
+#define BPy_IntegrationType_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IntegrationType_Type) )
+
+/*---------------------------Python BPy_IntegrationType visible prototypes-----------*/
+
+int IntegrationType_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INTEGRATIONTYPE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.cpp b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp
new file mode 100644
index 00000000000..11af30439cf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp
@@ -0,0 +1,354 @@
+#include "BPy_Interface0D.h"
+
+#include "BPy_Convert.h"
+#include "Interface0D/BPy_CurvePoint.h"
+#include "Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface0D/ViewVertex/BPy_NonTVertex.h"
+#include "Interface0D/ViewVertex/BPy_TVertex.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Interface0D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Interface0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Interface0D_Type );
+ PyModule_AddObject(module, "Interface0D", (PyObject *)&Interface0D_Type);
+
+ if( PyType_Ready( &CurvePoint_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CurvePoint_Type );
+ PyModule_AddObject(module, "CurvePoint", (PyObject *)&CurvePoint_Type);
+
+ if( PyType_Ready( &SVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SVertex_Type );
+ PyModule_AddObject(module, "SVertex", (PyObject *)&SVertex_Type);
+
+ if( PyType_Ready( &ViewVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ViewVertex_Type );
+ PyModule_AddObject(module, "ViewVertex", (PyObject *)&ViewVertex_Type);
+
+ if( PyType_Ready( &StrokeVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeVertex_Type );
+ PyModule_AddObject(module, "StrokeVertex", (PyObject *)&StrokeVertex_Type);
+
+ if( PyType_Ready( &NonTVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &NonTVertex_Type );
+ PyModule_AddObject(module, "NonTVertex", (PyObject *)&NonTVertex_Type);
+
+ if( PyType_Ready( &TVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TVertex_Type );
+ PyModule_AddObject(module, "TVertex", (PyObject *)&TVertex_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Interface0D___doc__[] =
+"Base class for any 0D element.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int Interface0D___init__(BPy_Interface0D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->if0D = new Interface0D();
+ self->borrowed = 0;
+ return 0;
+}
+
+static void Interface0D___dealloc__(BPy_Interface0D* self)
+{
+ if( self->if0D && !self->borrowed )
+ delete self->if0D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * Interface0D___repr__(BPy_Interface0D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->if0D->getExactTypeName().c_str(), self->if0D );
+}
+
+static char Interface0D_getExactTypeName___doc__[] =
+".. method:: getExactTypeName()\n"
+"\n"
+" Returns the name of the 0D element.\n"
+"\n"
+" :return: Name of the interface.\n"
+" :rtype: str\n";
+
+static PyObject *Interface0D_getExactTypeName( BPy_Interface0D *self ) {
+ return PyUnicode_FromString( self->if0D->getExactTypeName().c_str() );
+}
+
+static char Interface0D_getX___doc__[] =
+".. method:: getX()\n"
+"\n"
+" Returns the X coordinate of the 3D point of the 0D element.\n"
+"\n"
+" :return: The X coordinate of the 3D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getX( BPy_Interface0D *self ) {
+ double x = self->if0D->getX();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( x );
+}
+
+static char Interface0D_getY___doc__[] =
+".. method:: getY()\n"
+"\n"
+" Returns the Y coordinate of the 3D point of the 0D element.\n"
+"\n"
+" :return: The Y coordinate of the 3D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getY( BPy_Interface0D *self ) {
+ double y = self->if0D->getY();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( y );
+}
+
+static char Interface0D_getZ___doc__[] =
+".. method:: getZ()\n"
+"\n"
+" Returns the Z coordinate of the 3D point of the 0D element.\n"
+"\n"
+" :return: The Z coordinate of the 3D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getZ( BPy_Interface0D *self ) {
+ double z = self->if0D->getZ();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( z );
+}
+
+static char Interface0D_getPoint3D___doc__[] =
+".. method:: getPoint3D()\n"
+"\n"
+" Returns the location of the 0D element in the 3D space.\n"
+"\n"
+" :return: The 3D point of the 0D element.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *Interface0D_getPoint3D( BPy_Interface0D *self ) {
+ Vec3f v( self->if0D->getPoint3D() );
+ if (PyErr_Occurred())
+ return NULL;
+ return Vector_from_Vec3f( v );
+}
+
+static char Interface0D_getProjectedX___doc__[] =
+".. method:: getProjectedX()\n"
+"\n"
+" Returns the X coordinate of the 2D point of the 0D element.\n"
+"\n"
+" :return: The X coordinate of the 2D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getProjectedX( BPy_Interface0D *self ) {
+ double x = self->if0D->getProjectedX();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( x );
+}
+
+static char Interface0D_getProjectedY___doc__[] =
+".. method:: getProjectedY()\n"
+"\n"
+" Returns the Y coordinate of the 2D point of the 0D element.\n"
+"\n"
+" :return: The Y coordinate of the 2D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getProjectedY( BPy_Interface0D *self ) {
+ double y = self->if0D->getProjectedY();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( y );
+}
+
+static char Interface0D_getProjectedZ___doc__[] =
+".. method:: getProjectedZ()\n"
+"\n"
+" Returns the Z coordinate of the 2D point of the 0D element.\n"
+"\n"
+" :return: The Z coordinate of the 2D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getProjectedZ( BPy_Interface0D *self ) {
+ double z = self->if0D->getProjectedZ();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( z );
+}
+
+static char Interface0D_getPoint2D___doc__[] =
+".. method:: getPoint2D()\n"
+"\n"
+" Returns the location of the 0D element in the 2D space.\n"
+"\n"
+" :return: The 2D point of the 0D element.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *Interface0D_getPoint2D( BPy_Interface0D *self ) {
+ Vec2f v( self->if0D->getPoint2D() );
+ if (PyErr_Occurred())
+ return NULL;
+ return Vector_from_Vec2f( v );
+}
+
+static char Interface0D_getFEdge___doc__[] =
+".. method:: getFEdge(inter)\n"
+"\n"
+" Returns the FEdge that lies between this 0D element and the 0D\n"
+" element given as the argument.\n"
+"\n"
+" :arg inter: A 0D element.\n"
+" :type inter: :class:`Interface0D`\n"
+" :return: The FEdge lying between the two 0D elements.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject *Interface0D_getFEdge( BPy_Interface0D *self, PyObject *args ) {
+ PyObject *py_if0D;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Interface0D_Type, &py_if0D) ))
+ return NULL;
+
+ FEdge *fe = self->if0D->getFEdge(*( ((BPy_Interface0D *) py_if0D)->if0D ));
+ if (PyErr_Occurred())
+ return NULL;
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge( *fe );
+
+ Py_RETURN_NONE;
+}
+
+static char Interface0D_getId___doc__[] =
+".. method:: getId()\n"
+"\n"
+" Returns the identifier of the 0D element.\n"
+"\n"
+" :return: The identifier of the 0D element.\n"
+" :rtype: :class:`Id`\n";
+
+static PyObject *Interface0D_getId( BPy_Interface0D *self ) {
+ Id id( self->if0D->getId() );
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Id_from_Id( id );
+}
+
+static char Interface0D_getNature___doc__[] =
+".. method:: getNature()\n"
+"\n"
+" Returns the nature of the 0D element.\n"
+"\n"
+" :return: The nature of the 0D element.\n"
+" :rtype: :class:`Nature`\n";
+
+static PyObject *Interface0D_getNature( BPy_Interface0D *self ) {
+ Nature::VertexNature nature = self->if0D->getNature();
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Nature_from_Nature( nature );
+}
+
+/*----------------------Interface0D instance definitions ----------------------------*/
+static PyMethodDef BPy_Interface0D_methods[] = {
+ {"getExactTypeName", ( PyCFunction ) Interface0D_getExactTypeName, METH_NOARGS, Interface0D_getExactTypeName___doc__},
+ {"getX", ( PyCFunction ) Interface0D_getX, METH_NOARGS, Interface0D_getX___doc__},
+ {"getY", ( PyCFunction ) Interface0D_getY, METH_NOARGS, Interface0D_getY___doc__},
+ {"getZ", ( PyCFunction ) Interface0D_getZ, METH_NOARGS, Interface0D_getZ___doc__},
+ {"getPoint3D", ( PyCFunction ) Interface0D_getPoint3D, METH_NOARGS, Interface0D_getPoint3D___doc__},
+ {"getProjectedX", ( PyCFunction ) Interface0D_getProjectedX, METH_NOARGS, Interface0D_getProjectedX___doc__},
+ {"getProjectedY", ( PyCFunction ) Interface0D_getProjectedY, METH_NOARGS, Interface0D_getProjectedY___doc__},
+ {"getProjectedZ", ( PyCFunction ) Interface0D_getProjectedZ, METH_NOARGS, Interface0D_getProjectedZ___doc__},
+ {"getPoint2D", ( PyCFunction ) Interface0D_getPoint2D, METH_NOARGS, Interface0D_getPoint2D___doc__},
+ {"getFEdge", ( PyCFunction ) Interface0D_getFEdge, METH_VARARGS, Interface0D_getFEdge___doc__},
+ {"getId", ( PyCFunction ) Interface0D_getId, METH_NOARGS, Interface0D_getId___doc__},
+ {"getNature", ( PyCFunction ) Interface0D_getNature, METH_NOARGS, Interface0D_getNature___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Interface0D type definition ------------------------------*/
+
+PyTypeObject Interface0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface0D", /* tp_name */
+ sizeof(BPy_Interface0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Interface0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Interface0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Interface0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Interface0D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0 /* tp_del */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.h b/source/blender/freestyle/intern/python/BPy_Interface0D.h
new file mode 100644
index 00000000000..25134db5352
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface0D.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_INTERFACE0D_H
+#define FREESTYLE_PYTHON_INTERFACE0D_H
+
+#include <Python.h>
+
+#include "../view_map/Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Interface0D_Type;
+
+#define BPy_Interface0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface0D_Type) )
+
+/*---------------------------Python BPy_Interface0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Interface0D *if0D;
+ int borrowed; /* non-zero if *if0D is a borrowed object */
+} BPy_Interface0D;
+
+/*---------------------------Python BPy_Interface0D visible prototypes-----------*/
+
+int Interface0D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INTERFACE0D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.cpp b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp
new file mode 100644
index 00000000000..7b4bdddf70c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp
@@ -0,0 +1,337 @@
+#include "BPy_Interface1D.h"
+
+#include "BPy_Convert.h"
+#include "Interface1D/BPy_FrsCurve.h"
+#include "Interface1D/Curve/BPy_Chain.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/FEdge/BPy_FEdgeSharp.h"
+#include "Interface1D/FEdge/BPy_FEdgeSmooth.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+
+#include "BPy_MediumType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Interface1D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Interface1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Interface1D_Type );
+ PyModule_AddObject(module, "Interface1D", (PyObject *)&Interface1D_Type);
+
+ if( PyType_Ready( &FrsCurve_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FrsCurve_Type );
+ PyModule_AddObject(module, "Curve", (PyObject *)&FrsCurve_Type);
+
+ if( PyType_Ready( &Chain_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Chain_Type );
+ PyModule_AddObject(module, "Chain", (PyObject *)&Chain_Type);
+
+ if( PyType_Ready( &FEdge_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FEdge_Type );
+ PyModule_AddObject(module, "FEdge", (PyObject *)&FEdge_Type);
+
+ if( PyType_Ready( &FEdgeSharp_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FEdgeSharp_Type );
+ PyModule_AddObject(module, "FEdgeSharp", (PyObject *)&FEdgeSharp_Type);
+
+ if( PyType_Ready( &FEdgeSmooth_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FEdgeSmooth_Type );
+ PyModule_AddObject(module, "FEdgeSmooth", (PyObject *)&FEdgeSmooth_Type);
+
+ if( PyType_Ready( &Stroke_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Stroke_Type );
+ PyModule_AddObject(module, "Stroke", (PyObject *)&Stroke_Type);
+
+ PyDict_SetItemString( Stroke_Type.tp_dict, "DRY_MEDIUM", BPy_MediumType_DRY_MEDIUM );
+ PyDict_SetItemString( Stroke_Type.tp_dict, "HUMID_MEDIUM", BPy_MediumType_HUMID_MEDIUM );
+ PyDict_SetItemString( Stroke_Type.tp_dict, "OPAQUE_MEDIUM", BPy_MediumType_OPAQUE_MEDIUM );
+
+ if( PyType_Ready( &ViewEdge_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ViewEdge_Type );
+ PyModule_AddObject(module, "ViewEdge", (PyObject *)&ViewEdge_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Interface1D___doc__[] =
+"Base class for any 1D element.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int Interface1D___init__(BPy_Interface1D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->if1D = new Interface1D();
+ self->borrowed = 0;
+ return 0;
+}
+
+static void Interface1D___dealloc__(BPy_Interface1D* self)
+{
+ if( self->if1D && !self->borrowed )
+ delete self->if1D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * Interface1D___repr__(BPy_Interface1D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->if1D->getExactTypeName().c_str(), self->if1D );
+}
+
+static char Interface1D_getExactTypeName___doc__[] =
+".. method:: getExactTypeName()\n"
+"\n"
+" Returns the string of the name of the 1D element.\n"
+"\n"
+" :return: The name of the 1D element.\n"
+" :rtype: str\n";
+
+static PyObject *Interface1D_getExactTypeName( BPy_Interface1D *self ) {
+ return PyUnicode_FromString( self->if1D->getExactTypeName().c_str() );
+}
+
+#if 0
+static PyObject *Interface1D_getVertices( BPy_Interface1D *self ) {
+ return PyList_New(0);
+}
+
+static PyObject *Interface1D_getPoints( BPy_Interface1D *self ) {
+ return PyList_New(0);
+}
+#endif
+
+static char Interface1D_getLength2D___doc__[] =
+".. method:: getLength2D()\n"
+"\n"
+" Returns the 2D length of the 1D element.\n"
+"\n"
+" :return: The 2D length of the 1D element.\n"
+" :rtype: float\n";
+
+static PyObject *Interface1D_getLength2D( BPy_Interface1D *self ) {
+ return PyFloat_FromDouble( (double) self->if1D->getLength2D() );
+}
+
+static char Interface1D_getId___doc__[] =
+".. method:: getId()\n"
+"\n"
+" Returns the Id of the 1D element .\n"
+"\n"
+" :return: The Id of the 1D element .\n"
+" :rtype: :class:`Id`\n";
+
+static PyObject *Interface1D_getId( BPy_Interface1D *self ) {
+ Id id( self->if1D->getId() );
+ return BPy_Id_from_Id( id );
+}
+
+static char Interface1D_getNature___doc__[] =
+".. method:: getNature()\n"
+"\n"
+" Returns the nature of the 1D element.\n"
+"\n"
+" :return: The nature of the 1D element.\n"
+" :rtype: :class:`Nature`\n";
+
+static PyObject *Interface1D_getNature( BPy_Interface1D *self ) {
+ return BPy_Nature_from_Nature( self->if1D->getNature() );
+}
+
+static char Interface1D_getTimeStamp___doc__[] =
+".. method:: getTimeStamp()\n"
+"\n"
+" Returns the time stamp of the 1D element. Mainly used for selection.\n"
+"\n"
+" :return: The time stamp of the 1D element.\n"
+" :rtype: int\n";
+
+static PyObject *Interface1D_getTimeStamp( BPy_Interface1D *self ) {
+ return PyLong_FromLong( self->if1D->getTimeStamp() );
+}
+
+static char Interface1D_setTimeStamp___doc__[] =
+".. method:: setTimeStamp(iTimeStamp)\n"
+"\n"
+" Sets the time stamp for the 1D element.\n"
+"\n"
+" :arg iTimeStamp: A time stamp.\n"
+" :type iTimeStamp: int\n";
+
+static PyObject *Interface1D_setTimeStamp( BPy_Interface1D *self, PyObject *args) {
+ int timestamp = 0 ;
+
+ if( !PyArg_ParseTuple(args, "i", &timestamp) )
+ return NULL;
+
+ self->if1D->setTimeStamp( timestamp );
+
+ Py_RETURN_NONE;
+}
+
+static char Interface1D_verticesBegin___doc__[] =
+".. method:: verticesBegin()\n"
+"\n"
+" Returns an iterator over the Interface1D vertices, pointing to the\n"
+" first vertex.\n"
+"\n"
+" :return: An Interface0DIterator pointing to the first vertex.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * Interface1D_verticesBegin( BPy_Interface1D *self ) {
+ Interface0DIterator if0D_it( self->if1D->verticesBegin() );
+ return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 0 );
+}
+
+static char Interface1D_verticesEnd___doc__[] =
+".. method:: verticesEnd()\n"
+"\n"
+" Returns an iterator over the Interface1D vertices, pointing after\n"
+" the last vertex.\n"
+"\n"
+" :return: An Interface0DIterator pointing after the last vertex.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * Interface1D_verticesEnd( BPy_Interface1D *self ) {
+ Interface0DIterator if0D_it( self->if1D->verticesEnd() );
+ return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 1 );
+}
+
+static char Interface1D_pointsBegin___doc__[] =
+".. method:: pointsBegin(t=0.0)\n"
+"\n"
+" Returns an iterator over the Interface1D points, pointing to the\n"
+" first point. The difference with verticesBegin() is that here we can\n"
+" iterate over points of the 1D element at a any given sampling.\n"
+" Indeed, for each iteration, a virtual point is created.\n"
+"\n"
+" :arg t: A sampling with which we want to iterate over points of\n"
+" this 1D element.\n"
+" :type t: float\n"
+" :return: An Interface0DIterator pointing to the first point.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * Interface1D_pointsBegin( BPy_Interface1D *self, PyObject *args ) {
+ float f = 0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return NULL;
+
+ Interface0DIterator if0D_it( self->if1D->pointsBegin(f) );
+ return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 0 );
+}
+
+static char Interface1D_pointsEnd___doc__[] =
+".. method:: pointsEnd(t=0.0)\n"
+"\n"
+" Returns an iterator over the Interface1D points, pointing after the\n"
+" last point. The difference with verticesEnd() is that here we can\n"
+" iterate over points of the 1D element at a given sampling. Indeed,\n"
+" for each iteration, a virtual point is created.\n"
+"\n"
+" :arg t: A sampling with which we want to iterate over points of\n"
+" this 1D element.\n"
+" :type t: float\n"
+" :return: An Interface0DIterator pointing after the last point.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * Interface1D_pointsEnd( BPy_Interface1D *self, PyObject *args ) {
+ float f = 0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return NULL;
+
+ Interface0DIterator if0D_it( self->if1D->pointsEnd(f) );
+ return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 1 );
+}
+
+/*----------------------Interface1D instance definitions ----------------------------*/
+static PyMethodDef BPy_Interface1D_methods[] = {
+ {"getExactTypeName", ( PyCFunction ) Interface1D_getExactTypeName, METH_NOARGS, Interface1D_getExactTypeName___doc__},
+#if 0
+ {"getVertices", ( PyCFunction ) Interface1D_getVertices, METH_NOARGS, "Returns the vertices"},
+ {"getPoints", ( PyCFunction ) Interface1D_getPoints, METH_NOARGS, "Returns the points. The difference with getVertices() is that here we can iterate over points of the 1D element at any given sampling. At each call, a virtual point is created."},
+#endif
+ {"getLength2D", ( PyCFunction ) Interface1D_getLength2D, METH_NOARGS, Interface1D_getLength2D___doc__},
+ {"getId", ( PyCFunction ) Interface1D_getId, METH_NOARGS, Interface1D_getId___doc__},
+ {"getNature", ( PyCFunction ) Interface1D_getNature, METH_NOARGS, Interface1D_getNature___doc__},
+ {"getTimeStamp", ( PyCFunction ) Interface1D_getTimeStamp, METH_NOARGS, Interface1D_getTimeStamp___doc__},
+ {"setTimeStamp", ( PyCFunction ) Interface1D_setTimeStamp, METH_VARARGS, Interface1D_setTimeStamp___doc__},
+ {"verticesBegin", ( PyCFunction ) Interface1D_verticesBegin, METH_NOARGS, Interface1D_verticesBegin___doc__},
+ {"verticesEnd", ( PyCFunction ) Interface1D_verticesEnd, METH_NOARGS, Interface1D_verticesEnd___doc__},
+ {"pointsBegin", ( PyCFunction ) Interface1D_pointsBegin, METH_VARARGS, Interface1D_pointsBegin___doc__},
+ {"pointsEnd", ( PyCFunction ) Interface1D_pointsEnd, METH_VARARGS, Interface1D_pointsEnd___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Interface1D type definition ------------------------------*/
+
+PyTypeObject Interface1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface1D", /* tp_name */
+ sizeof(BPy_Interface1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Interface1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Interface1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Interface1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Interface1D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.h b/source/blender/freestyle/intern/python/BPy_Interface1D.h
new file mode 100644
index 00000000000..75eefa1836f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface1D.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_INTERFACE1D_H
+#define FREESTYLE_PYTHON_INTERFACE1D_H
+
+#include <Python.h>
+
+#include "../view_map/Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Interface1D_Type;
+
+#define BPy_Interface1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface1D_Type) )
+
+/*---------------------------Python BPy_Interface1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Interface1D *if1D;
+ int borrowed; /* non-zero if *if1D is a borrowed object */
+} BPy_Interface1D;
+
+/*---------------------------Python BPy_Interface1D visible prototypes-----------*/
+
+int Interface1D_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INTERFACE1D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.cpp b/source/blender/freestyle/intern/python/BPy_Iterator.cpp
new file mode 100644
index 00000000000..dd7d3783d81
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Iterator.cpp
@@ -0,0 +1,229 @@
+#include "BPy_Iterator.h"
+
+#include "BPy_Convert.h"
+#include "Iterator/BPy_AdjacencyIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Iterator/BPy_CurvePointIterator.h"
+#include "Iterator/BPy_StrokeVertexIterator.h"
+#include "Iterator/BPy_SVertexIterator.h"
+#include "Iterator/BPy_orientedViewEdgeIterator.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_ChainPredicateIterator.h"
+#include "Iterator/BPy_ChainSilhouetteIterator.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Iterator_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Iterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Iterator_Type );
+ PyModule_AddObject(module, "Iterator", (PyObject *)&Iterator_Type);
+
+ if( PyType_Ready( &AdjacencyIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &AdjacencyIterator_Type );
+ PyModule_AddObject(module, "AdjacencyIterator", (PyObject *)&AdjacencyIterator_Type);
+
+ if( PyType_Ready( &Interface0DIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Interface0DIterator_Type );
+ PyModule_AddObject(module, "Interface0DIterator", (PyObject *)&Interface0DIterator_Type);
+
+ if( PyType_Ready( &CurvePointIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CurvePointIterator_Type );
+ PyModule_AddObject(module, "CurvePointIterator", (PyObject *)&CurvePointIterator_Type);
+
+ if( PyType_Ready( &StrokeVertexIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeVertexIterator_Type );
+ PyModule_AddObject(module, "StrokeVertexIterator", (PyObject *)&StrokeVertexIterator_Type);
+
+ if( PyType_Ready( &SVertexIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SVertexIterator_Type );
+ PyModule_AddObject(module, "SVertexIterator", (PyObject *)&SVertexIterator_Type);
+
+ if( PyType_Ready( &orientedViewEdgeIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &orientedViewEdgeIterator_Type );
+ PyModule_AddObject(module, "orientedViewEdgeIterator", (PyObject *)&orientedViewEdgeIterator_Type);
+
+ if( PyType_Ready( &ViewEdgeIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ViewEdgeIterator_Type );
+ PyModule_AddObject(module, "ViewEdgeIterator", (PyObject *)&ViewEdgeIterator_Type);
+
+ if( PyType_Ready( &ChainingIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ChainingIterator_Type );
+ PyModule_AddObject(module, "ChainingIterator", (PyObject *)&ChainingIterator_Type);
+
+ if( PyType_Ready( &ChainPredicateIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ChainPredicateIterator_Type );
+ PyModule_AddObject(module, "ChainPredicateIterator", (PyObject *)&ChainPredicateIterator_Type);
+
+ if( PyType_Ready( &ChainSilhouetteIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ChainSilhouetteIterator_Type );
+ PyModule_AddObject(module, "ChainSilhouetteIterator", (PyObject *)&ChainSilhouetteIterator_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Iterator___doc__[] =
+"Base class to define iterators.\n";
+
+static void Iterator___dealloc__(BPy_Iterator* self)
+{
+ if (self->it)
+ delete self->it;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * Iterator___repr__(BPy_Iterator* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->it->getExactTypeName().c_str(), self->it );
+}
+
+static char Iterator_getExactTypeName___doc__[] =
+".. method:: getExactTypeName()\n"
+"\n"
+" Returns the name of the iterator.\n"
+"\n"
+" :return: The name of the iterator.\n"
+" :rtype: str\n";
+
+static PyObject * Iterator_getExactTypeName(BPy_Iterator* self) {
+ return PyUnicode_FromString( self->it->getExactTypeName().c_str() );
+}
+
+static char Iterator_increment___doc__[] =
+".. method:: increment()\n"
+"\n"
+" Makes the iterator point the next element.\n";
+
+static PyObject * Iterator_increment(BPy_Iterator* self) {
+ if (self->it->isEnd()) {
+ PyErr_SetString(PyExc_RuntimeError , "cannot increment any more");
+ return NULL;
+ }
+ self->it->increment();
+
+ Py_RETURN_NONE;
+}
+
+static char Iterator_decrement___doc__[] =
+".. method:: decrement()\n"
+"\n"
+" Makes the iterator point the previous element.\n";
+
+static PyObject * Iterator_decrement(BPy_Iterator* self) {
+ if (self->it->isBegin()) {
+ PyErr_SetString(PyExc_RuntimeError , "cannot decrement any more");
+ return NULL;
+ }
+ self->it->decrement();
+
+ Py_RETURN_NONE;
+}
+
+static char Iterator_isBegin___doc__[] =
+".. method:: isBegin()\n"
+"\n"
+" Returns true if the interator points the first element.\n"
+"\n"
+" :return: True if the interator points the first element.\n"
+" :rtype: bool\n";
+
+static PyObject * Iterator_isBegin(BPy_Iterator* self) {
+ return PyBool_from_bool( self->it->isBegin() );
+}
+
+static char Iterator_isEnd___doc__[] =
+".. method:: isEnd()\n"
+"\n"
+" Returns true if the interator points the last element.\n"
+"\n"
+" :return: True if the interator points the last element.\n"
+" :rtype: bool\n";
+
+static PyObject * Iterator_isEnd(BPy_Iterator* self) {
+ return PyBool_from_bool( self->it->isEnd() );
+}
+
+/*----------------------Iterator instance definitions ----------------------------*/
+static PyMethodDef BPy_Iterator_methods[] = {
+ {"getExactTypeName", ( PyCFunction ) Iterator_getExactTypeName, METH_NOARGS, Iterator_getExactTypeName___doc__},
+ {"increment", ( PyCFunction ) Iterator_increment, METH_NOARGS, Iterator_increment___doc__},
+ {"decrement", ( PyCFunction ) Iterator_decrement, METH_NOARGS, Iterator_decrement___doc__},
+ {"isBegin", ( PyCFunction ) Iterator_isBegin, METH_NOARGS, Iterator_isBegin___doc__},
+ {"isEnd", ( PyCFunction ) Iterator_isEnd, METH_NOARGS, Iterator_isEnd___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Iterator type definition ------------------------------*/
+
+PyTypeObject Iterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Iterator", /* tp_name */
+ sizeof(BPy_Iterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Iterator___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Iterator___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Iterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Iterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.h b/source/blender/freestyle/intern/python/BPy_Iterator.h
new file mode 100644
index 00000000000..0bdb52ef9a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Iterator.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_ITERATOR_H
+#define FREESTYLE_PYTHON_ITERATOR_H
+
+#include <Python.h>
+
+#include "../system/Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Iterator_Type;
+
+#define BPy_Iterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Iterator_Type) )
+
+/*---------------------------Python BPy_Iterator structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Iterator *it;
+} BPy_Iterator;
+
+/*---------------------------Python BPy_Iterator visible prototypes-----------*/
+
+int Iterator_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.cpp b/source/blender/freestyle/intern/python/BPy_MediumType.cpp
new file mode 100644
index 00000000000..111fb756ba2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_MediumType.cpp
@@ -0,0 +1,99 @@
+#include "BPy_MediumType.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*-----------------------BPy_MediumType type definition ------------------------------*/
+
+static char MediumType___doc__[] =
+"Class hierarchy: int > :class:`MediumType`\n"
+"\n"
+"The different blending modes available to similate the interaction\n"
+"media-medium:\n"
+"\n"
+"* Stroke.DRY_MEDIUM: To simulate a dry medium such as Pencil or Charcoal.\n"
+"* Stroke.HUMID_MEDIUM: To simulate ink painting (color substraction blending).\n"
+"* Stroke.OPAQUE_MEDIUM: To simulate an opaque medium (oil, spray...).\n";
+
+PyTypeObject MediumType_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "MediumType", /* tp_name */
+ sizeof(PyLongObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ MediumType___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_IntegrationType instance definitions -------------------------*/
+
+PyLongObject _BPy_MediumType_DRY_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::DRY_MEDIUM }
+};
+PyLongObject _BPy_MediumType_HUMID_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::HUMID_MEDIUM }
+};
+PyLongObject _BPy_MediumType_OPAQUE_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::OPAQUE_MEDIUM }
+};
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int MediumType_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &MediumType_Type ) < 0 )
+ return -1;
+ Py_INCREF( &MediumType_Type );
+ PyModule_AddObject(module, "MediumType", (PyObject *)&MediumType_Type);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.h b/source/blender/freestyle/intern/python/BPy_MediumType.h
new file mode 100644
index 00000000000..3bc50477295
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_MediumType.h
@@ -0,0 +1,42 @@
+#ifndef FREESTYLE_PYTHON_MEDIUMTYPE_H
+#define FREESTYLE_PYTHON_MEDIUMTYPE_H
+
+#include <Python.h>
+
+#include "../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject MediumType_Type;
+
+#define BPy_MediumType_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &MediumType_Type) )
+
+/*---------------------------Python BPy_MediumType structure definition----------*/
+typedef struct {
+ PyLongObject i;
+} BPy_MediumType;
+
+/*---------------------------Python BPy_MediumType visible prototypes-----------*/
+
+int MediumType_Init( PyObject *module );
+
+// internal constants
+extern PyLongObject _BPy_MediumType_DRY_MEDIUM;
+extern PyLongObject _BPy_MediumType_HUMID_MEDIUM;
+extern PyLongObject _BPy_MediumType_OPAQUE_MEDIUM;
+// public constants
+#define BPy_MediumType_DRY_MEDIUM ((PyObject *)&_BPy_MediumType_DRY_MEDIUM)
+#define BPy_MediumType_HUMID_MEDIUM ((PyObject *)&_BPy_MediumType_HUMID_MEDIUM)
+#define BPy_MediumType_OPAQUE_MEDIUM ((PyObject *)&_BPy_MediumType_OPAQUE_MEDIUM)
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_MEDIUMTYPE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Nature.cpp b/source/blender/freestyle/intern/python/BPy_Nature.cpp
new file mode 100644
index 00000000000..149baa9a7f3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Nature.cpp
@@ -0,0 +1,312 @@
+#include "BPy_Nature.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+static PyObject *BPy_Nature___and__(PyObject *a, PyObject *b);
+static PyObject *BPy_Nature___xor__(PyObject *a, PyObject *b);
+static PyObject *BPy_Nature___or__(PyObject *a, PyObject *b);
+static int BPy_Nature_bool(PyObject *v);
+
+/*-----------------------BPy_Nature number method definitions --------------------*/
+
+PyNumberMethods nature_as_number = {
+ 0, /* binaryfunc nb_add */
+ 0, /* binaryfunc nb_subtract */
+ 0, /* binaryfunc nb_multiply */
+ 0, /* binaryfunc nb_remainder */
+ 0, /* binaryfunc nb_divmod */
+ 0, /* ternaryfunc nb_power */
+ 0, /* unaryfunc nb_negative */
+ 0, /* unaryfunc nb_positive */
+ 0, /* unaryfunc nb_absolute */
+ (inquiry)BPy_Nature_bool, /* inquiry nb_bool */
+ 0, /* unaryfunc nb_invert */
+ 0, /* binaryfunc nb_lshift */
+ 0, /* binaryfunc nb_rshift */
+ (binaryfunc)BPy_Nature___and__, /* binaryfunc nb_and */
+ (binaryfunc)BPy_Nature___xor__, /* binaryfunc nb_xor */
+ (binaryfunc)BPy_Nature___or__, /* binaryfunc nb_or */
+ 0, /* unaryfunc nb_int */
+ 0, /* void *nb_reserved */
+ 0, /* unaryfunc nb_float */
+ 0, /* binaryfunc nb_inplace_add */
+ 0, /* binaryfunc nb_inplace_subtract */
+ 0, /* binaryfunc nb_inplace_multiply */
+ 0, /* binaryfunc nb_inplace_remainder */
+ 0, /* ternaryfunc nb_inplace_power */
+ 0, /* binaryfunc nb_inplace_lshift */
+ 0, /* binaryfunc nb_inplace_rshift */
+ 0, /* binaryfunc nb_inplace_and */
+ 0, /* binaryfunc nb_inplace_xor */
+ 0, /* binaryfunc nb_inplace_or */
+ 0, /* binaryfunc nb_floor_divide */
+ 0, /* binaryfunc nb_true_divide */
+ 0, /* binaryfunc nb_inplace_floor_divide */
+ 0, /* binaryfunc nb_inplace_true_divide */
+ 0, /* unaryfunc nb_index */
+};
+
+/*-----------------------BPy_Nature docstring ------------------------------------*/
+
+static char Nature___doc__[] =
+"Class hierarchy: int > :class:`Nature`\n"
+"\n"
+"Different possible natures of 0D and 1D elements of the ViewMap.\n"
+"\n"
+"Vertex natures:\n"
+"\n"
+"* Nature.POINT: True for any 0D element.\n"
+"* Nature.S_VERTEX: True for SVertex.\n"
+"* Nature.VIEW_VERTEX: True for ViewVertex.\n"
+"* Nature.NON_T_VERTEX: True for NonTVertex.\n"
+"* Nature.T_VERTEX: True for TVertex.\n"
+"* Nature.CUSP: True for CUSP.\n"
+"\n"
+"Edge natures:\n"
+"\n"
+"* Nature.NO_FEATURE: True for non feature edges (always false for 1D\n"
+" elements of the ViewMap).\n"
+"* Nature.SILHOUETTE: True for silhouettes.\n"
+"* Nature.BORDER: True for borders.\n"
+"* Nature.CREASE: True for creases.\n"
+"* Nature.RIDGE: True for ridges.\n"
+"* Nature.VALLEY: True for valleys.\n"
+"* Nature.SUGGESTIVE_CONTOUR: True for suggestive contours.\n"
+"* Nature.MATERIAL_BOUNDARY: True for edges at material boundaries.\n"
+"* Nature.EDGE_MARK: True for edges having user-defined edge marks.\n";
+
+/*-----------------------BPy_Nature type definition ------------------------------*/
+
+PyTypeObject Nature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Nature", /* tp_name */
+ sizeof(PyLongObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ &nature_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Nature___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_Nature instance definitions ----------------------------------*/
+
+static PyLongObject _Nature_POINT = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::POINT }
+};
+static PyLongObject _Nature_S_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::S_VERTEX }
+};
+static PyLongObject _Nature_VIEW_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::VIEW_VERTEX }
+};
+static PyLongObject _Nature_NON_T_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::NON_T_VERTEX }
+};
+static PyLongObject _Nature_T_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::T_VERTEX }
+};
+static PyLongObject _Nature_CUSP = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::CUSP }
+};
+static PyLongObject _Nature_NO_FEATURE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::NO_FEATURE }
+};
+static PyLongObject _Nature_SILHOUETTE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::SILHOUETTE }
+};
+static PyLongObject _Nature_BORDER = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::BORDER }
+};
+static PyLongObject _Nature_CREASE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::CREASE }
+};
+static PyLongObject _Nature_RIDGE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::RIDGE }
+};
+static PyLongObject _Nature_VALLEY = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::VALLEY }
+};
+static PyLongObject _Nature_SUGGESTIVE_CONTOUR = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::SUGGESTIVE_CONTOUR }
+};
+static PyLongObject _Nature_MATERIAL_BOUNDARY = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::MATERIAL_BOUNDARY }
+};
+static PyLongObject _Nature_EDGE_MARK = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::EDGE_MARK }
+};
+
+#define BPy_Nature_POINT ((PyObject *)&_Nature_POINT)
+#define BPy_Nature_S_VERTEX ((PyObject *)&_Nature_S_VERTEX)
+#define BPy_Nature_VIEW_VERTEX ((PyObject *)&_Nature_VIEW_VERTEX)
+#define BPy_Nature_NON_T_VERTEX ((PyObject *)&_Nature_NON_T_VERTEX)
+#define BPy_Nature_T_VERTEX ((PyObject *)&_Nature_T_VERTEX)
+#define BPy_Nature_CUSP ((PyObject *)&_Nature_CUSP)
+#define BPy_Nature_NO_FEATURE ((PyObject *)&_Nature_NO_FEATURE)
+#define BPy_Nature_SILHOUETTE ((PyObject *)&_Nature_SILHOUETTE)
+#define BPy_Nature_BORDER ((PyObject *)&_Nature_BORDER)
+#define BPy_Nature_CREASE ((PyObject *)&_Nature_CREASE)
+#define BPy_Nature_RIDGE ((PyObject *)&_Nature_RIDGE)
+#define BPy_Nature_VALLEY ((PyObject *)&_Nature_VALLEY)
+#define BPy_Nature_SUGGESTIVE_CONTOUR ((PyObject *)&_Nature_SUGGESTIVE_CONTOUR)
+#define BPy_Nature_MATERIAL_BOUNDARY ((PyObject *)&_Nature_MATERIAL_BOUNDARY)
+#define BPy_Nature_EDGE_MARK ((PyObject *)&_Nature_EDGE_MARK)
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Nature_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Nature_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Nature_Type );
+ PyModule_AddObject(module, "Nature", (PyObject *)&Nature_Type);
+
+ // VertexNature
+ PyDict_SetItemString( Nature_Type.tp_dict, "POINT", BPy_Nature_POINT);
+ PyDict_SetItemString( Nature_Type.tp_dict, "S_VERTEX", BPy_Nature_S_VERTEX);
+ PyDict_SetItemString( Nature_Type.tp_dict, "VIEW_VERTEX", BPy_Nature_VIEW_VERTEX );
+ PyDict_SetItemString( Nature_Type.tp_dict, "NON_T_VERTEX", BPy_Nature_NON_T_VERTEX );
+ PyDict_SetItemString( Nature_Type.tp_dict, "T_VERTEX", BPy_Nature_T_VERTEX );
+ PyDict_SetItemString( Nature_Type.tp_dict, "CUSP", BPy_Nature_CUSP );
+
+ // EdgeNature
+ PyDict_SetItemString( Nature_Type.tp_dict, "NO_FEATURE", BPy_Nature_NO_FEATURE );
+ PyDict_SetItemString( Nature_Type.tp_dict, "SILHOUETTE", BPy_Nature_SILHOUETTE );
+ PyDict_SetItemString( Nature_Type.tp_dict, "BORDER", BPy_Nature_BORDER );
+ PyDict_SetItemString( Nature_Type.tp_dict, "CREASE", BPy_Nature_CREASE );
+ PyDict_SetItemString( Nature_Type.tp_dict, "RIDGE", BPy_Nature_RIDGE );
+ PyDict_SetItemString( Nature_Type.tp_dict, "VALLEY", BPy_Nature_VALLEY );
+ PyDict_SetItemString( Nature_Type.tp_dict, "SUGGESTIVE_CONTOUR", BPy_Nature_SUGGESTIVE_CONTOUR );
+ PyDict_SetItemString( Nature_Type.tp_dict, "MATERIAL_BOUNDARY", BPy_Nature_MATERIAL_BOUNDARY );
+ PyDict_SetItemString( Nature_Type.tp_dict, "EDGE_MARK", BPy_Nature_EDGE_MARK );
+
+ return 0;
+}
+
+static PyObject *
+BPy_Nature_bitwise(PyObject *a, int op, PyObject *b)
+{
+ BPy_Nature *result;
+
+ if (!BPy_Nature_Check(a) || !BPy_Nature_Check(b)) {
+ PyErr_SetString(PyExc_TypeError, "operands must be a Nature object");
+ return NULL;
+ }
+ if (Py_SIZE(a) != 1) {
+ stringstream msg;
+ msg << "operand 1: unexpected Nature byte length: " << Py_SIZE(a);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ if (Py_SIZE(b) != 1) {
+ stringstream msg;
+ msg << "operand 2: unexpected Nature byte length: " << Py_SIZE(b);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ result = PyObject_NewVar(BPy_Nature, &Nature_Type, 1);
+ if (!result)
+ return NULL;
+ if (Py_SIZE(result) != 1) {
+ stringstream msg;
+ msg << "unexpected Nature byte length: " << Py_SIZE(result);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ switch (op) {
+ case '&':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) & (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ case '^':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) ^ (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ case '|':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) | (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ }
+ return (PyObject *)result;
+}
+
+static PyObject *
+BPy_Nature___and__(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '&', b);
+}
+
+static PyObject *
+BPy_Nature___xor__(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '^', b);
+}
+
+static PyObject *
+BPy_Nature___or__(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '|', b);
+}
+
+static int
+BPy_Nature_bool(PyObject *v)
+{
+ return ((PyLongObject *)v)->ob_digit[0] != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_Nature.h b/source/blender/freestyle/intern/python/BPy_Nature.h
new file mode 100644
index 00000000000..8c38415242e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Nature.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_NATURE_H
+#define FREESTYLE_PYTHON_NATURE_H
+
+#include <Python.h>
+
+#include "../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Nature_Type;
+
+#define BPy_Nature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Nature_Type) )
+
+/*---------------------------Python BPy_Nature structure definition----------*/
+typedef struct {
+ PyLongObject i;
+} BPy_Nature;
+
+/*---------------------------Python BPy_Nature visible prototypes-----------*/
+
+int Nature_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NATURE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp
new file mode 100644
index 00000000000..7d660054335
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp
@@ -0,0 +1,682 @@
+#include "BPy_Operators.h"
+
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "BPy_StrokeShader.h"
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Operators_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Operators_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &Operators_Type );
+ PyModule_AddObject(module, "Operators", (PyObject *)&Operators_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Operators___doc__[] =
+"Class defining the operators used in a style module. There are five\n"
+"types of operators: Selection, chaining, splitting, sorting and\n"
+"creation. All these operators are user controlled through functors,\n"
+"predicates and shaders that are taken as arguments.\n";
+
+static void Operators___dealloc__(BPy_Operators* self)
+{
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static char Operators_select___doc__[] =
+".. staticmethod:: select(pred)\n"
+"\n"
+" Selects the ViewEdges of the ViewMap verifying a specified\n"
+" condition.\n"
+"\n"
+" :arg pred: The predicate expressing this condition.\n"
+" :type pred: UnaryPredicate1D\n";
+
+static PyObject * Operators_select(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if ( !PyArg_ParseTuple(args, "O!", &UnaryPredicate1D_Type, &obj) )
+ return NULL;
+ if ( !((BPy_UnaryPredicate1D *) obj)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.select(): 1st argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+
+ if (Operators::select(*( ((BPy_UnaryPredicate1D *) obj)->up1D )) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.select() failed");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_chain___doc__[] =
+".. staticmethod:: chain(it, pred, modifier)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list starts a new chain. The chaining\n"
+" operator then iterates over the ViewEdges of the ViewMap using the\n"
+" user specified iterator. This operator only iterates using the\n"
+" increment operator and is therefore unidirectional.\n"
+"\n"
+" :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
+" the chaining rule.\n"
+" :type it: :class:`ViewEdgeIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg modifier: A function that takes a ViewEdge as argument and\n"
+" that is used to modify the processed ViewEdge state (the\n"
+" timestamp incrementation is a typical illustration of such a\n"
+" modifier).\n"
+" :type modifier: :class:`UnaryFunction1DVoid`\n"
+"\n"
+".. staticmethod:: chain(it, pred)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list starts a new chain. The chaining\n"
+" operator then iterates over the ViewEdges of the ViewMap using the\n"
+" user specified iterator. This operator only iterates using the\n"
+" increment operator and is therefore unidirectional. This chaining\n"
+" operator is different from the previous one because it doesn't take\n"
+" any modifier as argument. Indeed, the time stamp (insuring that a\n"
+" ViewEdge is processed one time) is automatically managed in this\n"
+" case.\n"
+"\n"
+" :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
+" the chaining rule. \n"
+" :type it: :class:`ViewEdgeIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`\n";
+
+// CHANGE: first parameter is a chaining iterator, not just a view
+
+static PyObject * Operators_chain(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+
+ if ( !PyArg_ParseTuple(args, "O!O!|O!", &ChainingIterator_Type, &obj1,
+ &UnaryPredicate1D_Type, &obj2,
+ &UnaryFunction1DVoid_Type, &obj3) )
+ return NULL;
+ if ( !((BPy_ChainingIterator *) obj1)->c_it ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 1st argument: invalid ChainingIterator object");
+ return NULL;
+ }
+ if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+
+ if( !obj3 ) {
+
+ if (Operators::chain( *( ((BPy_ChainingIterator *) obj1)->c_it ),
+ *( ((BPy_UnaryPredicate1D *) obj2)->up1D ) ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
+ return NULL;
+ }
+
+ } else {
+
+ if ( !((BPy_UnaryFunction1DVoid *) obj3)->uf1D_void ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 3rd argument: invalid UnaryFunction1DVoid object");
+ return NULL;
+ }
+ if (Operators::chain( *( ((BPy_ChainingIterator *) obj1)->c_it ),
+ *( ((BPy_UnaryPredicate1D *) obj2)->up1D ),
+ *( ((BPy_UnaryFunction1DVoid *) obj3)->uf1D_void ) ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
+ return NULL;
+ }
+
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_bidirectionalChain___doc__[] =
+".. staticmethod:: bidirectionalChain(it, pred)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list potentially starts a new chain. The\n"
+" chaining operator then iterates over the ViewEdges of the ViewMap\n"
+" using the user specified iterator. This operator iterates both using\n"
+" the increment and decrement operators and is therefore bidirectional.\n"
+" This operator works with a ChainingIterator which contains the\n"
+" chaining rules. It is this last one which can be told to chain only\n"
+" edges that belong to the selection or not to process twice a ViewEdge\n"
+" during the chaining. Each time a ViewEdge is added to a chain, its\n"
+" chaining time stamp is incremented. This allows you to keep track of\n"
+" the number of chains to which a ViewEdge belongs to.\n"
+"\n"
+" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
+" contains the chaining rule.\n"
+" :type it: :class:`ChainingIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+"\n"
+".. staticmethod:: bidirectionalChain(it)\n"
+"\n"
+" The only difference with the above bidirectional chaining algorithm\n"
+" is that we don't need to pass a stopping criterion. This might be\n"
+" desirable when the stopping criterion is already contained in the\n"
+" iterator definition. Builds a set of chains from the current set of\n"
+" ViewEdges. Each ViewEdge of the current list potentially starts a new\n"
+" chain. The chaining operator then iterates over the ViewEdges of the\n"
+" ViewMap using the user specified iterator. This operator iterates\n"
+" both using the increment and decrement operators and is therefore\n"
+" bidirectional. This operator works with a ChainingIterator which\n"
+" contains the chaining rules. It is this last one which can be told to\n"
+" chain only edges that belong to the selection or not to process twice\n"
+" a ViewEdge during the chaining. Each time a ViewEdge is added to a\n"
+" chain, its chaining time stamp is incremented. This allows you to\n"
+" keep track of the number of chains to which a ViewEdge belongs to.\n"
+"\n"
+" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
+" contains the chaining rule.\n"
+" :type it: :class:`ChainingIterator`\n";
+
+static PyObject * Operators_bidirectionalChain(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if( !PyArg_ParseTuple(args, "O!|O!", &ChainingIterator_Type, &obj1, &UnaryPredicate1D_Type, &obj2) )
+ return NULL;
+ if ( !((BPy_ChainingIterator *) obj1)->c_it ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.bidirectionalChain(): 1st argument: invalid ChainingIterator object");
+ return NULL;
+ }
+
+ if( !obj2 ) {
+
+ if (Operators::bidirectionalChain( *( ((BPy_ChainingIterator *) obj1)->c_it ) ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectionalChain() failed");
+ return NULL;
+ }
+
+ } else {
+
+ if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.bidirectionalChain(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if (Operators::bidirectionalChain( *( ((BPy_ChainingIterator *) obj1)->c_it ),
+ *( ((BPy_UnaryPredicate1D *) obj2)->up1D ) ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectionalChain() failed");
+ return NULL;
+ }
+
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_sequentialSplit___doc__[] =
+".. staticmethod:: sequentialSplit(startingPred, stoppingPred, sampling=0.0)\n"
+"\n"
+" Splits each chain of the current set of chains in a sequential way.\n"
+" The points of each chain are processed (with a specified sampling)\n"
+" sequentially. Each time a user specified starting condition is\n"
+" verified, a new chain begins and ends as soon as a user-defined\n"
+" stopping predicate is verified. This allows chains overlapping rather\n"
+" than chains partitioning. The first point of the initial chain is the\n"
+" first point of one of the resulting chains. The splitting ends when\n"
+" no more chain can start.\n"
+"\n"
+" :arg startingPred: The predicate on a point that expresses the\n"
+" starting condition.\n"
+" :type startingPred: :class:`UnaryPredicate0D`\n"
+" :arg stoppingPred: The predicate on a point that expresses the\n"
+" stopping condition.\n"
+" :type stoppingPred: :class:`UnaryPredicate0D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled;\n"
+" a virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n"
+"\n"
+".. staticmethod:: sequentialSplit(pred, sampling=0.0)\n"
+"\n"
+" Splits each chain of the current set of chains in a sequential way.\n"
+" The points of each chain are processed (with a specified sampling)\n"
+" sequentially and each time a user specified condition is verified,\n"
+" the chain is split into two chains. The resulting set of chains is a\n"
+" partition of the initial chain\n"
+"\n"
+" :arg pred: The predicate on a point that expresses the splitting\n"
+" condition.\n"
+" :type pred: :class:`UnaryPredicate0D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicate evaluation. (The chain is not actually resampled; a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n";
+
+static PyObject * Operators_sequentialSplit(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+ float f = 0.0;
+
+ if( !PyArg_ParseTuple(args, "O!|Of", &UnaryPredicate0D_Type, &obj1, &obj2, &f) )
+ return NULL;
+ if ( !((BPy_UnaryPredicate0D *) obj1)->up0D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): 1st argument: invalid UnaryPredicate0D object");
+ return NULL;
+ }
+
+ if( obj2 && BPy_UnaryPredicate0D_Check(obj2) ) {
+
+ if ( !((BPy_UnaryPredicate0D *) obj2)->up0D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): 2nd argument: invalid UnaryPredicate0D object");
+ return NULL;
+ }
+ if (Operators::sequentialSplit( *( ((BPy_UnaryPredicate0D *) obj1)->up0D ),
+ *( ((BPy_UnaryPredicate0D *) obj2)->up0D ),
+ f ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sequentialSplit() failed");
+ return NULL;
+ }
+
+ } else {
+
+ if ( obj2 ) {
+ if ( !PyFloat_Check(obj2) ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): invalid 2nd argument");
+ return NULL;
+ }
+ f = PyFloat_AsDouble(obj2);
+ }
+ if (Operators::sequentialSplit( *( ((BPy_UnaryPredicate0D *) obj1)->up0D ), f ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sequentialSplit() failed");
+ return NULL;
+ }
+
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_recursiveSplit___doc__[] =
+".. staticmethod:: recursiveSplit(func, pred, sampling=0.0)\n"
+"\n"
+" Splits the current set of chains in a recursive way. We process the\n"
+" points of each chain (with a specified sampling) to find the point\n"
+" minimizing a specified function. The chain is split in two at this\n"
+" point and the two new chains are processed in the same way. The\n"
+" recursivity level is controlled through a predicate 1D that expresses\n"
+" a stopping condition on the chain that is about to be processed.\n"
+"\n"
+" :arg func: The Unary Function evaluated at each point of the chain.\n"
+" The splitting point is the point minimizing this function.\n"
+" :type func: :class:`UnaryFunction0DDouble`\n"
+" :arg pred: The Unary Predicate expressing the recursivity stopping\n"
+" condition. This predicate is evaluated for each curve before it\n"
+" actually gets split. If pred(chain) is true, the curve won't be\n"
+" split anymore.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled, a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n"
+"\n"
+".. staticmethod:: recursiveSplit(func, pred0d, pred, sampling=0.0)\n"
+"\n"
+" Splits the current set of chains in a recursive way. We process the\n"
+" points of each chain (with a specified sampling) to find the point\n"
+" minimizing a specified function. The chain is split in two at this\n"
+" point and the two new chains are processed in the same way. The user\n"
+" can specify a 0D predicate to make a first selection on the points\n"
+" that can potentially be split. A point that doesn't verify the 0D\n"
+" predicate won't be candidate in realizing the min. The recursivity\n"
+" level is controlled through a predicate 1D that expresses a stopping\n"
+" condition on the chain that is about to be processed.\n"
+"\n"
+" :arg func: The Unary Function evaluated at each point of the chain.\n"
+" The splitting point is the point minimizing this function.\n"
+" :type func: :class:`UnaryFunction0DDouble`\n"
+" :arg pred0d: The Unary Predicate 0D used to select the candidate\n"
+" points where the split can occur. For example, it is very likely\n"
+" that would rather have your chain splitting around its middle\n"
+" point than around one of its extremities. A 0D predicate working\n"
+" on the curvilinear abscissa allows to add this kind of constraints.\n"
+" :type pred0d: :class:`UnaryPredicate0D`\n"
+" :arg pred: The Unary Predicate expressing the recursivity stopping\n"
+" condition. This predicate is evaluated for each curve before it\n"
+" actually gets split. If pred(chain) is true, the curve won't be\n"
+" split anymore.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled; a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n";
+
+static PyObject * Operators_recursiveSplit(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+ float f = 0.0;
+
+ if ( !PyArg_ParseTuple(args, "O!O|Of", &UnaryFunction0DDouble_Type, &obj1, &obj2, &obj3, &f) )
+ return NULL;
+ if ( !((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): 1st argument: invalid UnaryFunction0DDouble object");
+ return NULL;
+ }
+
+ if ( BPy_UnaryPredicate1D_Check(obj2) ) {
+
+ if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if ( obj3 ) {
+ if ( !PyFloat_Check(obj3) ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 3rd argument");
+ return NULL;
+ }
+ f = PyFloat_AsDouble(obj3);
+ }
+ if (Operators::recursiveSplit( *( ((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ),
+ *( ((BPy_UnaryPredicate1D *) obj2)->up1D ),
+ f ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.recursiveSplit() failed");
+ return NULL;
+ }
+
+ } else {
+
+ if ( !BPy_UnaryPredicate0D_Check(obj2) || !((BPy_UnaryPredicate0D *) obj2)->up0D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 2nd argument");
+ return NULL;
+ }
+ if ( !BPy_UnaryPredicate1D_Check(obj3) || !((BPy_UnaryPredicate1D *) obj3)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 3rd argument");
+ return NULL;
+ }
+ if (Operators::recursiveSplit( *( ((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ),
+ *( ((BPy_UnaryPredicate0D *) obj2)->up0D ),
+ *( ((BPy_UnaryPredicate1D *) obj3)->up1D ),
+ f ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.recursiveSplit() failed");
+ return NULL;
+ }
+
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_sort___doc__[] =
+".. staticmethod:: sort(pred)\n"
+"\n"
+" Sorts the current set of chains (or viewedges) according to the\n"
+" comparison predicate given as argument.\n"
+"\n"
+" :arg pred: The binary predicate used for the comparison.\n"
+" :type pred: BinaryPredicate1D\n";
+
+static PyObject * Operators_sort(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if ( !PyArg_ParseTuple(args, "O!", &BinaryPredicate1D_Type, &obj) )
+ return NULL;
+ if ( !((BPy_BinaryPredicate1D *) obj)->bp1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sort(): 1st argument: invalid BinaryPredicate1D object");
+ return NULL;
+ }
+
+ if (Operators::sort(*( ((BPy_BinaryPredicate1D *) obj)->bp1D )) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sort() failed");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static char Operators_create___doc__[] =
+".. staticmethod:: create(pred, shaders)\n"
+"\n"
+" Creates and shades the strokes from the current set of chains. A\n"
+" predicate can be specified to make a selection pass on the chains.\n"
+"\n"
+" :arg pred: The predicate that a chain must verify in order to be\n"
+" transform as a stroke.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg shaders: The list of shaders used to shade the strokes.\n"
+" :type shaders: List of StrokeShader objects\n";
+
+static PyObject * Operators_create(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if ( !PyArg_ParseTuple(args, "O!O!", &UnaryPredicate1D_Type, &obj1, &PyList_Type, &obj2) )
+ return NULL;
+ if ( !((BPy_UnaryPredicate1D *) obj1)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.create(): 1st argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+
+ vector<StrokeShader *> shaders;
+ for( int i = 0; i < PyList_Size(obj2); i++) {
+ PyObject *py_ss = PyList_GetItem(obj2,i);
+
+ if ( !BPy_StrokeShader_Check(py_ss) ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.create() 2nd argument must be a list of StrokeShader objects");
+ return NULL;
+ }
+ shaders.push_back( ((BPy_StrokeShader *) py_ss)->ss );
+ }
+
+ if (Operators::create( *( ((BPy_UnaryPredicate1D *) obj1)->up1D ), shaders) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.create() failed");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_getViewEdgeFromIndex___doc__[] =
+".. staticmethod:: getViewEdgeFromIndex()\n"
+"\n"
+" Returns the ViewEdge at the index in the current set of ViewEdges.\n"
+"\n"
+" :arg i: index (0 <= i < Operators.getViewEdgesSize()).\n"
+" :type i: int\n"
+" :return: The ViewEdge object.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * Operators_getViewEdgeFromIndex(BPy_Operators* self, PyObject *args) {
+ unsigned int i;
+
+ if (!PyArg_ParseTuple(args, "I", &i))
+ return NULL;
+ if (i >= Operators::getViewEdgesSize()) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return NULL;
+ }
+ return BPy_ViewEdge_from_ViewEdge(*(Operators::getViewEdgeFromIndex(i)));
+}
+
+static char Operators_getChainFromIndex___doc__[] =
+".. staticmethod:: getChainFromIndex()\n"
+"\n"
+" Returns the Chain at the index in the current set of Chains.\n"
+"\n"
+" :arg i: index (0 <= i < Operators.getChainsSize()).\n"
+" :type i: int\n"
+" :return: The Chain object.\n"
+" :rtype: :class:`Chain`\n";
+
+static PyObject * Operators_getChainFromIndex(BPy_Operators* self, PyObject *args) {
+ unsigned int i;
+
+ if (!PyArg_ParseTuple(args, "I", &i))
+ return NULL;
+ if (i >= Operators::getChainsSize()) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return NULL;
+ }
+ return BPy_Chain_from_Chain(*(Operators::getChainFromIndex(i)));
+}
+
+static char Operators_getStrokeFromIndex___doc__[] =
+".. staticmethod:: getStrokeFromIndex()\n"
+"\n"
+" Returns the Stroke at the index in the current set of Strokes.\n"
+"\n"
+" :arg i: index (0 <= i < Operators.getStrokesSize()).\n"
+" :type i: int\n"
+" :return: The Stroke object.\n"
+" :rtype: :class:`Stroke`\n";
+
+static PyObject * Operators_getStrokeFromIndex(BPy_Operators* self, PyObject *args) {
+ unsigned int i;
+
+ if (!PyArg_ParseTuple(args, "I", &i))
+ return NULL;
+ if (i >= Operators::getStrokesSize()) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return NULL;
+ }
+ return BPy_Stroke_from_Stroke(*(Operators::getStrokeFromIndex(i)));
+}
+
+static char Operators_getViewEdgesSize___doc__[] =
+".. staticmethod:: getViewEdgesSize()\n"
+"\n"
+" Returns the number of ViewEdges.\n"
+"\n"
+" :return: The number of ViewEdges.\n"
+" :rtype: int\n";
+
+static PyObject * Operators_getViewEdgesSize( BPy_Operators* self) {
+ return PyLong_FromLong( Operators::getViewEdgesSize() );
+}
+
+static char Operators_getChainsSize___doc__[] =
+".. staticmethod:: getChainsSize()\n"
+"\n"
+" Returns the number of Chains.\n"
+"\n"
+" :return: The number of Chains.\n"
+" :rtype: int\n";
+
+static PyObject * Operators_getChainsSize( BPy_Operators* self ) {
+ return PyLong_FromLong( Operators::getChainsSize() );
+}
+
+static char Operators_getStrokesSize___doc__[] =
+".. staticmethod:: getStrokesSize()\n"
+"\n"
+" Returns the number of Strokes.\n"
+"\n"
+" :return: The number of Strokes.\n"
+" :rtype: int\n";
+
+static PyObject * Operators_getStrokesSize( BPy_Operators* self) {
+ return PyLong_FromLong( Operators::getStrokesSize() );
+}
+
+/*----------------------Operators instance definitions ----------------------------*/
+static PyMethodDef BPy_Operators_methods[] = {
+ {"select", ( PyCFunction ) Operators_select, METH_VARARGS | METH_STATIC, Operators_select___doc__},
+ {"chain", ( PyCFunction ) Operators_chain, METH_VARARGS | METH_STATIC, Operators_chain___doc__},
+ {"bidirectionalChain", ( PyCFunction ) Operators_bidirectionalChain, METH_VARARGS | METH_STATIC, Operators_bidirectionalChain___doc__},
+ {"sequentialSplit", ( PyCFunction ) Operators_sequentialSplit, METH_VARARGS | METH_STATIC, Operators_sequentialSplit___doc__},
+ {"recursiveSplit", ( PyCFunction ) Operators_recursiveSplit, METH_VARARGS | METH_STATIC, Operators_recursiveSplit___doc__},
+ {"sort", ( PyCFunction ) Operators_sort, METH_VARARGS | METH_STATIC, Operators_sort___doc__},
+ {"create", ( PyCFunction ) Operators_create, METH_VARARGS | METH_STATIC, Operators_create___doc__},
+ {"getViewEdgeFromIndex", ( PyCFunction ) Operators_getViewEdgeFromIndex, METH_VARARGS | METH_STATIC, Operators_getViewEdgeFromIndex___doc__},
+ {"getChainFromIndex", ( PyCFunction ) Operators_getChainFromIndex, METH_VARARGS | METH_STATIC, Operators_getChainFromIndex___doc__},
+ {"getStrokeFromIndex", ( PyCFunction ) Operators_getStrokeFromIndex, METH_VARARGS | METH_STATIC, Operators_getStrokeFromIndex___doc__},
+ {"getViewEdgesSize", ( PyCFunction ) Operators_getViewEdgesSize, METH_NOARGS | METH_STATIC, Operators_getViewEdgesSize___doc__},
+ {"getChainsSize", ( PyCFunction ) Operators_getChainsSize, METH_NOARGS | METH_STATIC, Operators_getChainsSize___doc__},
+ {"getStrokesSize", ( PyCFunction ) Operators_getStrokesSize, METH_NOARGS | METH_STATIC, Operators_getStrokesSize___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Operators type definition ------------------------------*/
+
+PyTypeObject Operators_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Operators", /* tp_name */
+ sizeof(BPy_Operators), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Operators___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Operators___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Operators_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.h b/source/blender/freestyle/intern/python/BPy_Operators.h
new file mode 100644
index 00000000000..5e01d6bb1fe
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Operators.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_OPERATORS_H
+#define FREESTYLE_PYTHON_OPERATORS_H
+
+#include <Python.h>
+
+#include "../stroke/Operators.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Operators_Type;
+
+#define BPy_Operators_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Operators_Type) )
+
+/*---------------------------Python BPy_Operators structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+} BPy_Operators;
+
+/*---------------------------Python BPy_Operators visible prototypes-----------*/
+
+int Operators_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_OPERATORS_H */
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp
new file mode 100644
index 00000000000..65951182f10
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp
@@ -0,0 +1,330 @@
+#include "BPy_SShape.h"
+
+#include "BPy_Convert.h"
+#include "BPy_BBox.h"
+#include "BPy_Id.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int SShape_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &SShape_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &SShape_Type );
+ PyModule_AddObject(module, "SShape", (PyObject *)&SShape_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SShape___doc__[] =
+"Class to define a feature shape. It is the gathering of feature\n"
+"elements from an identified input shape.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An SShape object.\n"
+" :type iBrother: :class:`SShape`\n";
+
+static int SShape___init__(BPy_SShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj = NULL;
+
+ if (! PyArg_ParseTuple(args, "|O!", &SShape_Type, &obj) )
+ return -1;
+
+ if( !obj ) {
+ self->ss = new SShape();
+
+ } else {
+ self->ss = new SShape(*( ((BPy_SShape *) obj)->ss ));
+ }
+ self->borrowed = 0;
+
+ return 0;
+}
+
+static void SShape___dealloc__(BPy_SShape *self)
+{
+ if( self->ss && !self->borrowed )
+ delete self->ss;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * SShape___repr__(BPy_SShape *self)
+{
+ return PyUnicode_FromFormat("SShape - address: %p", self->ss );
+}
+
+static char SShape_AddEdge___doc__[] =
+".. method:: AddEdge(iEdge)\n"
+"\n"
+" Adds an FEdge to the list of FEdges.\n"
+"\n"
+" :arg iEdge: An FEdge object.\n"
+" :type iEdge: :class:`FEdge`\n";
+
+static PyObject * SShape_AddEdge( BPy_SShape *self , PyObject *args) {
+ PyObject *py_fe = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->ss->AddEdge( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_AddNewVertex___doc__[] =
+".. method:: AddNewVertex(iv)\n"
+"\n"
+" Adds an SVertex to the list of SVertex of this Shape. The SShape\n"
+" attribute of the SVertex is also set to this SShape.\n"
+"\n"
+" :arg iv: An SVertex object.\n"
+" :type iv: :class:`SVertex`\n";
+
+static PyObject * SShape_AddNewVertex( BPy_SShape *self , PyObject *args) {
+ PyObject *py_sv = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->ss->AddNewVertex( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_setBBox___doc__[] =
+".. method:: setBBox(iBBox)\n"
+"\n"
+" Sets the bounding box of the SShape.\n"
+"\n"
+" :arg iBBox: The bounding box of the SShape.\n"
+" :type iBBox: :class:`BBox`\n";
+
+static PyObject * SShape_setBBox( BPy_SShape *self , PyObject *args) {
+ PyObject *py_bb = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &BBox_Type, &py_bb) ))
+ return NULL;
+
+ self->ss->setBBox(*( ((BPy_BBox*) py_bb)->bb ));
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_ComputeBBox___doc__[] =
+".. method:: ComputeBBox()\n"
+"\n"
+" Compute the bbox of the SShape.\n";
+
+static PyObject * SShape_ComputeBBox( BPy_SShape *self ) {
+ self->ss->ComputeBBox();
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_bbox___doc__[] =
+".. method:: bbox()\n"
+"\n"
+" Returns the bounding box of the SShape.\n"
+"\n"
+" :return: the bounding box of the SShape.\n"
+" :rtype: :class:`BBox`\n";
+
+static PyObject * SShape_bbox( BPy_SShape *self ) {
+ BBox<Vec3r> bb( self->ss->bbox() );
+ return BPy_BBox_from_BBox( bb );
+}
+
+static char SShape_getVertexList___doc__[] =
+".. method:: getVertexList()\n"
+"\n"
+" Returns the list of vertices of the SShape.\n"
+"\n"
+" :return: The list of vertices objects.\n"
+" :rtype: List of :class:`SVertex` objects\n";
+
+static PyObject * SShape_getVertexList( BPy_SShape *self ) {
+ PyObject *py_vertices = PyList_New(0);
+
+ vector< SVertex * > vertices = self->ss->getVertexList();
+ vector< SVertex * >::iterator it;
+
+ for( it = vertices.begin(); it != vertices.end(); it++ ) {
+ PyList_Append( py_vertices, BPy_SVertex_from_SVertex(*( *it )) );
+ }
+
+ return py_vertices;
+}
+
+static char SShape_getEdgeList___doc__[] =
+".. method:: getEdgeList()\n"
+"\n"
+" Returns the list of edges of the SShape.\n"
+"\n"
+" :return: The list of edges of the SShape.\n"
+" :rtype: List of :class:`FEdge` objects\n";
+
+static PyObject * SShape_getEdgeList( BPy_SShape *self ) {
+ PyObject *py_edges = PyList_New(0);
+
+ vector< FEdge * > edges = self->ss->getEdgeList();
+ vector< FEdge * >::iterator it;
+
+ for( it = edges.begin(); it != edges.end(); it++ ) {
+ PyList_Append( py_edges, Any_BPy_FEdge_from_FEdge(*( *it )) );
+ }
+
+ return py_edges;
+}
+
+static char SShape_getId___doc__[] =
+".. method:: getId()\n"
+"\n"
+" Returns the Id of the SShape.\n"
+"\n"
+" :return: The Id of the SShape.\n"
+" :rtype: :class:`Id`\n";
+
+static PyObject * SShape_getId( BPy_SShape *self ) {
+ Id id( self->ss->getId() );
+ return BPy_Id_from_Id( id );
+}
+
+static char SShape_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the Id of the SShape.\n"
+"\n"
+" :arg id: The Id of the SShape.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject * SShape_setId( BPy_SShape *self , PyObject *args) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ self->ss->setId(*( ((BPy_Id *) py_id)->id ));
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the SShape.\n"
+"\n"
+" :return: The name string.\n"
+" :rtype: str\n";
+
+static PyObject * SShape_getName( BPy_SShape *self ) {
+ return PyUnicode_FromString( self->ss->getName().c_str() );
+}
+
+static char SShape_setName___doc__[] =
+".. method:: setName(name)\n"
+"\n"
+" Sets the name of the SShape.\n"
+"\n"
+" :arg name: A name string.\n"
+" :type name: str\n";
+
+static PyObject * SShape_setName( BPy_SShape *self , PyObject *args) {
+ char *s;
+
+ if(!( PyArg_ParseTuple(args, "s", &s) ))
+ return NULL;
+
+ self->ss->setName(s);
+
+ Py_RETURN_NONE;
+}
+
+// const Material & material (unsigned i) const
+// const vector< Material > & materials () const
+// void SetMaterials (const vector< Material > &iMaterials)
+
+/*----------------------SShape instance definitions ----------------------------*/
+static PyMethodDef BPy_SShape_methods[] = {
+ {"AddEdge", ( PyCFunction ) SShape_AddEdge, METH_VARARGS, SShape_AddEdge___doc__},
+ {"AddNewVertex", ( PyCFunction ) SShape_AddNewVertex, METH_VARARGS, SShape_AddNewVertex___doc__},
+ {"setBBox", ( PyCFunction ) SShape_setBBox, METH_VARARGS, SShape_setBBox___doc__},
+ {"ComputeBBox", ( PyCFunction ) SShape_ComputeBBox, METH_NOARGS, SShape_ComputeBBox___doc__},
+ {"bbox", ( PyCFunction ) SShape_bbox, METH_NOARGS, SShape_bbox___doc__},
+ {"getVertexList", ( PyCFunction ) SShape_getVertexList, METH_NOARGS, SShape_getVertexList___doc__},
+ {"getEdgeList", ( PyCFunction ) SShape_getEdgeList, METH_NOARGS, SShape_getEdgeList___doc__},
+ {"getId", ( PyCFunction ) SShape_getId, METH_NOARGS, SShape_getId___doc__},
+ {"setId", ( PyCFunction ) SShape_setId, METH_VARARGS, SShape_setId___doc__},
+ {"getName", ( PyCFunction ) SShape_getName, METH_NOARGS, SShape_getName___doc__},
+ {"setName", ( PyCFunction ) SShape_setName, METH_VARARGS, SShape_setName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_SShape type definition ------------------------------*/
+
+PyTypeObject SShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SShape", /* tp_name */
+ sizeof(BPy_SShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)SShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.h b/source/blender/freestyle/intern/python/BPy_SShape.h
new file mode 100644
index 00000000000..e8d631f0538
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_SShape.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_SSHAPE_H
+#define FREESTYLE_PYTHON_SSHAPE_H
+
+#include <Python.h>
+
+#include "../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject SShape_Type;
+
+#define BPy_SShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SShape_Type) )
+
+/*---------------------------Python BPy_SShape structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ SShape *ss;
+ int borrowed; /* non-zero if *ss is a borrowed object */
+} BPy_SShape;
+
+/*---------------------------Python BPy_SShape visible prototypes-----------*/
+
+int SShape_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
new file mode 100644
index 00000000000..e68cc3fd28b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
@@ -0,0 +1,658 @@
+#include "BPy_StrokeAttribute.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int StrokeAttribute_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &StrokeAttribute_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeAttribute_Type );
+ PyModule_AddObject(module, "StrokeAttribute", (PyObject *)&StrokeAttribute_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeAttribute___doc__[] =
+"Class to define a set of attributes associated with a :class:`StrokeVertex`.\n"
+"The attribute set stores the color, alpha and thickness values for a Stroke\n"
+"Vertex.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A StrokeAttribute object.\n"
+" :type iBrother: :class:`StrokeAttribute`\n"
+"\n"
+".. method:: __init__(iRColor, iGColor, iBColor, iAlpha, iRThickness, iLThickness)\n"
+"\n"
+" Builds a stroke vertex attribute from a set of parameters.\n"
+"\n"
+" :arg iRColor: Red component of a stroke color.\n"
+" :type iRColor: float\n"
+" :arg iGColor: Green component of a stroke color.\n"
+" :type iGColor: float\n"
+" :arg iBColor: Blue component of a stroke color.\n"
+" :type iBColor: float\n"
+" :arg iAlpha: Alpha component of a stroke color.\n"
+" :type iAlpha: float\n"
+" :arg iRThickness: Stroke thickness on the right.\n"
+" :type iRThickness: float\n"
+" :arg iLThickness: Stroke thickness on the left.\n"
+" :type iLThickness: float\n"
+"\n"
+".. method:: __init__(a1, a2, t)\n"
+"\n"
+" Interpolation constructor. Builds a StrokeAttribute from two\n"
+" StrokeAttribute objects and an interpolation parameter.\n"
+"\n"
+" :arg a1: The first StrokeAttribute object.\n"
+" :type a1: :class:`StrokeAttribute`\n"
+" :arg a2: The second StrokeAttribute object.\n"
+" :type a2: :class:`StrokeAttribute`\n"
+" :arg t: The interpolation parameter.\n"
+" :type t: float\n";
+
+static int StrokeAttribute___init__(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0, *obj4 = 0, *obj5 = 0 , *obj6 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOOOOO", &obj1, &obj2, &obj3, &obj4, &obj5, &obj6) )
+ return -1;
+
+ if( !obj1 || !obj2 || !obj3 ){
+
+ self->sa = new StrokeAttribute();
+
+ } else if( BPy_StrokeAttribute_Check(obj1) &&
+ BPy_StrokeAttribute_Check(obj2) &&
+ PyFloat_Check(obj3) ) {
+
+ self->sa = new StrokeAttribute( *( ((BPy_StrokeAttribute *) obj1)->sa ),
+ *( ((BPy_StrokeAttribute *) obj2)->sa ),
+ PyFloat_AsDouble( obj3 ) );
+
+ } else if( obj4 && obj5 && obj6 ) {
+
+ self->sa = new StrokeAttribute( PyFloat_AsDouble( obj1 ),
+ PyFloat_AsDouble( obj2 ),
+ PyFloat_AsDouble( obj3 ),
+ PyFloat_AsDouble( obj4 ),
+ PyFloat_AsDouble( obj5 ),
+ PyFloat_AsDouble( obj6 ) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid arguments");
+ return -1;
+ }
+
+ self->borrowed = 0;
+
+ return 0;
+
+}
+
+static void StrokeAttribute___dealloc__(BPy_StrokeAttribute* self)
+{
+ if( self->sa && !self->borrowed )
+ delete self->sa;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * StrokeAttribute___repr__(BPy_StrokeAttribute* self)
+{
+ stringstream repr("StrokeAttribute:");
+ repr << " r: " << self->sa->getColorR()
+ << " g: " << self->sa->getColorG()
+ << " b: " << self->sa->getColorB()
+ << " a: " << self->sa->getAlpha()
+ << " - R: " << self->sa->getThicknessR()
+ << " L: " << self->sa->getThicknessL();
+
+ return PyUnicode_FromString( repr.str().c_str() );
+}
+
+
+static char StrokeAttribute_getColorR___doc__[] =
+".. method:: getColorR()\n"
+"\n"
+" Returns the red component of the stroke color.\n"
+"\n"
+" :return: Red component of the stroke color.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getColorR( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getColorR() );
+}
+
+static char StrokeAttribute_getColorG___doc__[] =
+".. method:: getColorG()\n"
+"\n"
+" Returns the green component of the stroke color.\n"
+"\n"
+" :return: Green component of the stroke color.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getColorG( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getColorG() );
+}
+
+static char StrokeAttribute_getColorB___doc__[] =
+".. method:: getColorB()\n"
+"\n"
+" Returns the blue component of the stroke color.\n"
+"\n"
+" :return: Blue component of the stroke color.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getColorB( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getColorB() );
+}
+
+static char StrokeAttribute_getColorRGB___doc__[] =
+".. method:: getColorRGB()\n"
+"\n"
+" Returns the RGB components of the stroke color.\n"
+"\n"
+" :return: RGB components of the stroke color.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *StrokeAttribute_getColorRGB( BPy_StrokeAttribute *self ) {
+ Vec3f v( self->sa->getColorRGB() );
+ return Vector_from_Vec3f( v );
+}
+
+static char StrokeAttribute_getAlpha___doc__[] =
+".. method:: getAlpha()\n"
+"\n"
+" Returns the alpha component of the stroke color.\n"
+"\n"
+" :return: Alpha component of the stroke color.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getAlpha( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getAlpha() );
+}
+
+static char StrokeAttribute_getThicknessR___doc__[] =
+".. method:: getThicknessR()\n"
+"\n"
+" Returns the thickness on the right of the vertex when following\n"
+" the stroke.\n"
+"\n"
+" :return: The thickness on the right of the vertex.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getThicknessR( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getThicknessR() );
+}
+
+static char StrokeAttribute_getThicknessL___doc__[] =
+".. method:: getThicknessL()\n"
+"\n"
+" Returns the thickness on the left of the vertex when following\n"
+" the stroke.\n"
+"\n"
+" :return: The thickness on the left of the vertex.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getThicknessL( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getThicknessL() );
+}
+
+static char StrokeAttribute_getThicknessRL___doc__[] =
+".. method:: getThicknessRL()\n"
+"\n"
+" Returns the thickness on the right and on the left of the vertex\n"
+" when following the stroke.\n"
+"\n"
+" :return: A two-dimensional vector. The first value is the\n"
+" thickness on the right of the vertex when following the stroke,\n"
+" and the second one is the thickness on the left.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *StrokeAttribute_getThicknessRL( BPy_StrokeAttribute *self ) {
+ Vec2f v( self->sa->getThicknessRL() );
+ return Vector_from_Vec2f( v );
+}
+
+static char StrokeAttribute_isVisible___doc__[] =
+".. method:: isVisible()\n"
+"\n"
+" Returns true if the StrokeVertex is visible, false otherwise.\n"
+"\n"
+" :return: True if the StrokeVertex is visible, false otherwise.\n"
+" :rtype: bool\n";
+
+static PyObject *StrokeAttribute_isVisible( BPy_StrokeAttribute *self ) {
+ return PyBool_from_bool( self->sa->isVisible() );
+}
+
+static char StrokeAttribute_getAttributeReal___doc__[] =
+".. method:: getAttributeReal(iName)\n"
+"\n"
+" Returns an attribute of float type.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :return: The attribute value.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getAttributeReal( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ double a = self->sa->getAttributeReal( attr );
+ return PyFloat_FromDouble( a );
+}
+
+static char StrokeAttribute_getAttributeVec2f___doc__[] =
+".. method:: getAttributeVec2f(iName)\n"
+"\n"
+" Returns an attribute of two-dimensional vector type.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :return: The attribute value.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *StrokeAttribute_getAttributeVec2f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ Vec2f a = self->sa->getAttributeVec2f( attr );
+ return Vector_from_Vec2f( a );
+}
+
+static char StrokeAttribute_getAttributeVec3f___doc__[] =
+".. method:: getAttributeVec3f(iName)\n"
+"\n"
+" Returns an attribute of three-dimensional vector type.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :return: The attribute value.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *StrokeAttribute_getAttributeVec3f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ Vec3f a = self->sa->getAttributeVec3f( attr );
+ return Vector_from_Vec3f( a );
+}
+
+static char StrokeAttribute_isAttributeAvailableReal___doc__[] =
+".. method:: isAttributeAvailableReal(iName)\n"
+"\n"
+" Checks whether the attribute iName of float type is available.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n";
+
+static PyObject *StrokeAttribute_isAttributeAvailableReal( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ return PyBool_from_bool( self->sa->isAttributeAvailableReal( attr ) );
+}
+
+static char StrokeAttribute_isAttributeAvailableVec2f___doc__[] =
+".. method:: isAttributeAvailableVec2f(iName)\n"
+"\n"
+" Checks whether the attribute iName of two-dimensional vector type\n"
+" is available.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n";
+
+static PyObject *StrokeAttribute_isAttributeAvailableVec2f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ return PyBool_from_bool( self->sa->isAttributeAvailableVec2f( attr ) );
+}
+
+static char StrokeAttribute_isAttributeAvailableVec3f___doc__[] =
+".. method:: isAttributeAvailableVec3f(iName)\n"
+"\n"
+" Checks whether the attribute iName of three-dimensional vector\n"
+" type is available.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n";
+
+static PyObject *StrokeAttribute_isAttributeAvailableVec3f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ return PyBool_from_bool( self->sa->isAttributeAvailableVec3f( attr ) );
+}
+
+
+static char StrokeAttribute_setColor___doc__[] =
+".. method:: setColor(r, g, b)\n"
+"\n"
+" Sets the stroke color.\n"
+"\n"
+" :arg r: Red component of the stroke color.\n"
+" :type r: float\n"
+" :arg g: Green component of the stroke color.\n"
+" :type g: float\n"
+" :arg b: Blue component of the stroke color.\n"
+" :type b: float\n"
+"\n"
+".. method:: setColor(iRGB)\n"
+"\n"
+" Sets the stroke color.\n"
+"\n"
+" :arg iRGB: The new RGB values.\n"
+" :type iRGB: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * StrokeAttribute_setColor( BPy_StrokeAttribute *self, PyObject *args ) {
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0 ;
+
+ if(!( PyArg_ParseTuple(args, "O|OO", &obj1, &obj2, &obj3) ))
+ return NULL;
+
+ if( obj1 && !obj2 && !obj3 ){
+
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setColor( *v );
+ delete v;
+
+ } else if( obj1 && obj2 && obj3 ){
+
+ self->sa->setColor( PyFloat_AsDouble(obj1),
+ PyFloat_AsDouble(obj2),
+ PyFloat_AsDouble(obj3) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid arguments");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setAlpha___doc__[] =
+".. method:: setAlpha(alpha)\n"
+"\n"
+" Sets the alpha component of the stroke color.\n"
+"\n"
+" :arg alpha: The new alpha value.\n"
+" :type alpha: float\n";
+
+static PyObject * StrokeAttribute_setAlpha( BPy_StrokeAttribute *self, PyObject *args ){
+ float f = 0;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return NULL;
+
+ self->sa->setAlpha( f );
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setThickness___doc__[] =
+".. method:: setThickness(tr, tl)\n"
+"\n"
+" Sets the stroke thickness.\n"
+"\n"
+" :arg tr: The thickness on the right of the vertex when following\n"
+" the stroke.\n"
+" :type tr: float\n"
+" :arg tl: The thickness on the left of the vertex when following\n"
+" the stroke.\n"
+" :type tl: float\n"
+"\n"
+".. method:: setThickness(tRL)\n"
+"\n"
+" Sets the stroke thickness.\n"
+"\n"
+" :arg tRL: The thickness on the right and on the left of the vertex\n"
+" when following the stroke.\n"
+" :type tRL: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n";
+
+static PyObject * StrokeAttribute_setThickness( BPy_StrokeAttribute *self, PyObject *args ) {
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if(!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) ))
+ return NULL;
+
+ if( obj1 && !obj2 ){
+
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setThickness( *v );
+ delete v;
+
+ } else if( obj1 && obj2 ){
+
+ self->sa->setThickness( PyFloat_AsDouble(obj1),
+ PyFloat_AsDouble(obj2) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid arguments");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setVisible___doc__[] =
+".. method:: setVisible(iVisible)\n"
+"\n"
+" Sets the visibility flag. True means the StrokeVertex is visible.\n"
+"\n"
+" :arg iVisible: True if the StrokeVertex is visible.\n"
+" :type iVisible: bool\n";
+
+static PyObject * StrokeAttribute_setVisible( BPy_StrokeAttribute *self, PyObject *args ) {
+ PyObject *py_b;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_b) ))
+ return NULL;
+
+ self->sa->setVisible( bool_from_PyBool(py_b) );
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setAttributeReal___doc__[] =
+".. method:: setAttributeReal(iName, att)\n"
+"\n"
+" Adds a user-defined attribute of float type. If there is no\n"
+" attribute of the given name, it is added. Otherwise, the new value\n"
+" replaces the old one.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :arg att: The attribute value.\n"
+" :type att: float\n";
+
+static PyObject * StrokeAttribute_setAttributeReal( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *s = 0;
+ double d = 0;
+
+ if(!( PyArg_ParseTuple(args, "sd", &s, &d) ))
+ return NULL;
+
+ self->sa->setAttributeReal( s, d );
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setAttributeVec2f___doc__[] =
+".. method:: setAttributeVec2f(iName, att)\n"
+"\n"
+" Adds a user-defined attribute of two-dimensional vector type. If\n"
+" there is no attribute of the given name, it is added. Otherwise,\n"
+" the new value replaces the old one.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :arg att: The attribute value.\n"
+" :type att: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n";
+
+static PyObject * StrokeAttribute_setAttributeVec2f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *s;
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "sO", &s, &obj) ))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setAttributeVec2f( s, *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setAttributeVec3f___doc__[] =
+".. method:: setAttributeVec3f(iName, att)\n"
+"\n"
+" Adds a user-defined attribute of three-dimensional vector type.\n"
+" If there is no attribute of the given name, it is added.\n"
+" Otherwise, the new value replaces the old one.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: str\n"
+" :arg att: The attribute value.\n"
+" :type att: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * StrokeAttribute_setAttributeVec3f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *s;
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "sO", &s, &obj) ))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setAttributeVec3f( s, *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------StrokeAttribute instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeAttribute_methods[] = {
+ {"getColorR", ( PyCFunction ) StrokeAttribute_getColorR, METH_NOARGS, StrokeAttribute_getColorR___doc__},
+ {"getColorG", ( PyCFunction ) StrokeAttribute_getColorG, METH_NOARGS, StrokeAttribute_getColorG___doc__},
+ {"getColorB", ( PyCFunction ) StrokeAttribute_getColorB, METH_NOARGS, StrokeAttribute_getColorB___doc__},
+ {"getColorRGB", ( PyCFunction ) StrokeAttribute_getColorRGB, METH_NOARGS, StrokeAttribute_getColorRGB___doc__},
+ {"getAlpha", ( PyCFunction ) StrokeAttribute_getAlpha, METH_NOARGS, StrokeAttribute_getAlpha___doc__},
+ {"getThicknessR", ( PyCFunction ) StrokeAttribute_getThicknessR, METH_NOARGS, StrokeAttribute_getThicknessR___doc__},
+ {"getThicknessL", ( PyCFunction ) StrokeAttribute_getThicknessL, METH_NOARGS, StrokeAttribute_getThicknessL___doc__},
+ {"getThicknessRL", ( PyCFunction ) StrokeAttribute_getThicknessRL, METH_NOARGS, StrokeAttribute_getThicknessRL___doc__},
+ {"isVisible", ( PyCFunction ) StrokeAttribute_isVisible, METH_NOARGS, StrokeAttribute_isVisible___doc__},
+ {"getAttributeReal", ( PyCFunction ) StrokeAttribute_getAttributeReal, METH_VARARGS, StrokeAttribute_getAttributeReal___doc__},
+ {"getAttributeVec2f", ( PyCFunction ) StrokeAttribute_getAttributeVec2f, METH_VARARGS, StrokeAttribute_getAttributeVec2f___doc__},
+ {"getAttributeVec3f", ( PyCFunction ) StrokeAttribute_getAttributeVec3f, METH_VARARGS, StrokeAttribute_getAttributeVec3f___doc__},
+ {"isAttributeAvailableReal", ( PyCFunction ) StrokeAttribute_isAttributeAvailableReal, METH_VARARGS, StrokeAttribute_isAttributeAvailableReal___doc__},
+ {"isAttributeAvailableVec2f", ( PyCFunction ) StrokeAttribute_isAttributeAvailableVec2f, METH_VARARGS, StrokeAttribute_isAttributeAvailableVec2f___doc__},
+ {"isAttributeAvailableVec3f", ( PyCFunction ) StrokeAttribute_isAttributeAvailableVec3f, METH_VARARGS, StrokeAttribute_isAttributeAvailableVec3f___doc__},
+ {"setColor", ( PyCFunction ) StrokeAttribute_setColor, METH_VARARGS, StrokeAttribute_setColor___doc__},
+ {"setAlpha", ( PyCFunction ) StrokeAttribute_setAlpha, METH_VARARGS, StrokeAttribute_setAlpha___doc__},
+ {"setThickness", ( PyCFunction ) StrokeAttribute_setThickness, METH_VARARGS, StrokeAttribute_setThickness___doc__},
+ {"setVisible", ( PyCFunction ) StrokeAttribute_setVisible, METH_VARARGS, StrokeAttribute_setVisible___doc__},
+ {"setAttributeReal", ( PyCFunction ) StrokeAttribute_setAttributeReal, METH_VARARGS, StrokeAttribute_setAttributeReal___doc__},
+ {"setAttributeVec2f", ( PyCFunction ) StrokeAttribute_setAttributeVec2f, METH_VARARGS, StrokeAttribute_setAttributeVec2f___doc__},
+ {"setAttributeVec3f", ( PyCFunction ) StrokeAttribute_setAttributeVec3f, METH_VARARGS, StrokeAttribute_setAttributeVec3f___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_StrokeAttribute type definition ------------------------------*/
+
+PyTypeObject StrokeAttribute_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeAttribute", /* tp_name */
+ sizeof(BPy_StrokeAttribute), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)StrokeAttribute___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)StrokeAttribute___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeAttribute___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeAttribute_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeAttribute___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h
new file mode 100644
index 00000000000..51e18c0a96f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_STROKEATTRIBUTE_H
+#define FREESTYLE_PYTHON_STROKEATTRIBUTE_H
+
+#include <Python.h>
+
+#include "../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject StrokeAttribute_Type;
+
+#define BPy_StrokeAttribute_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeAttribute_Type) )
+
+/*---------------------------Python BPy_StrokeAttribute structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ StrokeAttribute *sa;
+ int borrowed; /* non-zero if *sa is a borrowed reference */
+} BPy_StrokeAttribute;
+
+/*---------------------------Python BPy_StrokeAttribute visible prototypes-----------*/
+
+int StrokeAttribute_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKEATTRIBUTE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
new file mode 100644
index 00000000000..202e33c3231
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
@@ -0,0 +1,297 @@
+#include "BPy_StrokeShader.h"
+
+#include "BPy_Convert.h"
+#include "Interface1D/BPy_Stroke.h"
+
+#include "StrokeShader/BPy_BackboneStretcherShader.h"
+#include "StrokeShader/BPy_BezierCurveShader.h"
+#include "StrokeShader/BPy_CalligraphicShader.h"
+#include "StrokeShader/BPy_ColorNoiseShader.h"
+#include "StrokeShader/BPy_ColorVariationPatternShader.h"
+#include "StrokeShader/BPy_ConstantColorShader.h"
+#include "StrokeShader/BPy_ConstantThicknessShader.h"
+#include "StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h"
+#include "StrokeShader/BPy_fstreamShader.h"
+#include "StrokeShader/BPy_GuidingLinesShader.h"
+#include "StrokeShader/BPy_IncreasingColorShader.h"
+#include "StrokeShader/BPy_IncreasingThicknessShader.h"
+#include "StrokeShader/BPy_PolygonalizationShader.h"
+#include "StrokeShader/BPy_SamplingShader.h"
+#include "StrokeShader/BPy_SmoothingShader.h"
+#include "StrokeShader/BPy_SpatialNoiseShader.h"
+#include "StrokeShader/BPy_streamShader.h"
+#include "StrokeShader/BPy_StrokeTextureShader.h"
+#include "StrokeShader/BPy_TextureAssignerShader.h"
+#include "StrokeShader/BPy_ThicknessNoiseShader.h"
+#include "StrokeShader/BPy_ThicknessVariationPatternShader.h"
+#include "StrokeShader/BPy_TipRemoverShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int StrokeShader_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &StrokeShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeShader_Type );
+ PyModule_AddObject(module, "StrokeShader", (PyObject *)&StrokeShader_Type);
+
+ if( PyType_Ready( &BackboneStretcherShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &BackboneStretcherShader_Type );
+ PyModule_AddObject(module, "BackboneStretcherShader", (PyObject *)&BackboneStretcherShader_Type);
+
+ if( PyType_Ready( &BezierCurveShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &BezierCurveShader_Type );
+ PyModule_AddObject(module, "BezierCurveShader", (PyObject *)&BezierCurveShader_Type);
+
+ if( PyType_Ready( &CalligraphicShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CalligraphicShader_Type );
+ PyModule_AddObject(module, "CalligraphicShader", (PyObject *)&CalligraphicShader_Type);
+
+ if( PyType_Ready( &ColorNoiseShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ColorNoiseShader_Type );
+ PyModule_AddObject(module, "ColorNoiseShader", (PyObject *)&ColorNoiseShader_Type);
+
+ if( PyType_Ready( &ColorVariationPatternShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ColorVariationPatternShader_Type );
+ PyModule_AddObject(module, "ColorVariationPatternShader", (PyObject *)&ColorVariationPatternShader_Type);
+
+ if( PyType_Ready( &ConstantColorShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ConstantColorShader_Type );
+ PyModule_AddObject(module, "ConstantColorShader", (PyObject *)&ConstantColorShader_Type);
+
+ if( PyType_Ready( &ConstantThicknessShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ConstantThicknessShader_Type );
+ PyModule_AddObject(module, "ConstantThicknessShader", (PyObject *)&ConstantThicknessShader_Type);
+
+ if( PyType_Ready( &ConstrainedIncreasingThicknessShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ConstrainedIncreasingThicknessShader_Type );
+ PyModule_AddObject(module, "ConstrainedIncreasingThicknessShader", (PyObject *)&ConstrainedIncreasingThicknessShader_Type);
+
+ if( PyType_Ready( &fstreamShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &fstreamShader_Type );
+ PyModule_AddObject(module, "fstreamShader", (PyObject *)&fstreamShader_Type);
+
+ if( PyType_Ready( &GuidingLinesShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GuidingLinesShader_Type );
+ PyModule_AddObject(module, "GuidingLinesShader", (PyObject *)&GuidingLinesShader_Type);
+
+ if( PyType_Ready( &IncreasingColorShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &IncreasingColorShader_Type );
+ PyModule_AddObject(module, "IncreasingColorShader", (PyObject *)&IncreasingColorShader_Type);
+
+ if( PyType_Ready( &IncreasingThicknessShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &IncreasingThicknessShader_Type );
+ PyModule_AddObject(module, "IncreasingThicknessShader", (PyObject *)&IncreasingThicknessShader_Type);
+
+ if( PyType_Ready( &PolygonalizationShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &PolygonalizationShader_Type );
+ PyModule_AddObject(module, "PolygonalizationShader", (PyObject *)&PolygonalizationShader_Type);
+
+ if( PyType_Ready( &SamplingShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SamplingShader_Type );
+ PyModule_AddObject(module, "SamplingShader", (PyObject *)&SamplingShader_Type);
+
+ if( PyType_Ready( &SmoothingShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SmoothingShader_Type );
+ PyModule_AddObject(module, "SmoothingShader", (PyObject *)&SmoothingShader_Type);
+
+ if( PyType_Ready( &SpatialNoiseShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SpatialNoiseShader_Type );
+ PyModule_AddObject(module, "SpatialNoiseShader", (PyObject *)&SpatialNoiseShader_Type);
+
+ if( PyType_Ready( &streamShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &streamShader_Type );
+ PyModule_AddObject(module, "streamShader", (PyObject *)&streamShader_Type);
+
+ if( PyType_Ready( &StrokeTextureShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeTextureShader_Type );
+ PyModule_AddObject(module, "StrokeTextureShader", (PyObject *)&StrokeTextureShader_Type);
+
+ if( PyType_Ready( &TextureAssignerShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TextureAssignerShader_Type );
+ PyModule_AddObject(module, "TextureAssignerShader", (PyObject *)&TextureAssignerShader_Type);
+
+ if( PyType_Ready( &ThicknessNoiseShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ThicknessNoiseShader_Type );
+ PyModule_AddObject(module, "ThicknessNoiseShader", (PyObject *)&ThicknessNoiseShader_Type);
+
+ if( PyType_Ready( &ThicknessVariationPatternShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ThicknessVariationPatternShader_Type );
+ PyModule_AddObject(module, "ThicknessVariationPatternShader", (PyObject *)&ThicknessVariationPatternShader_Type);
+
+ if( PyType_Ready( &TipRemoverShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TipRemoverShader_Type );
+ PyModule_AddObject(module, "TipRemoverShader", (PyObject *)&TipRemoverShader_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeShader___doc__[] =
+"Base class for stroke shaders. Any stroke shader must inherit from\n"
+"this class and overload the shade() method. A StrokeShader is\n"
+"designed to modify stroke attributes such as thickness, color,\n"
+"geometry, texture, blending mode, and so on. The basic way for this\n"
+"operation is to iterate over the stroke vertices of the :class:`Stroke`\n"
+"and to modify the :class:`StrokeAttribute` of each vertex. Here is a\n"
+"code example of such an iteration::\n"
+"\n"
+" it = ioStroke.strokeVerticesBegin()\n"
+" while it.isEnd() == 0:\n"
+" att = it.getObject().attribute()\n"
+" ## perform here any attribute modification\n"
+" it.increment()\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int StrokeShader___init__(BPy_StrokeShader *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->ss = new StrokeShader();
+ self->ss->py_ss = (PyObject *) self;
+ return 0;
+}
+
+static void StrokeShader___dealloc__(BPy_StrokeShader* self)
+{
+ if (self->ss)
+ delete self->ss;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * StrokeShader___repr__(BPy_StrokeShader* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->ss->getName().c_str(), self->ss );
+}
+
+static char StrokeShader_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of this stroke shader.\n"
+"\n"
+" :return: The name of this stroke shader.\n"
+" :rtype: str\n";
+
+static PyObject * StrokeShader_getName( BPy_StrokeShader *self, PyObject *args)
+{
+ return PyUnicode_FromString( self->ss->getName().c_str() );
+}
+
+static char StrokeShader_shade___doc__[] =
+".. method:: shade(s)\n"
+"\n"
+" The shading method. Must be overloaded by inherited classes.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static PyObject *StrokeShader_shade( BPy_StrokeShader *self , PyObject *args) {
+ PyObject *py_s = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Stroke_Type, &py_s) ))
+ return NULL;
+
+ if( typeid(*(self->ss)) == typeid(StrokeShader) ) {
+ PyErr_SetString(PyExc_TypeError, "shade method not properly overridden");
+ return NULL;
+ }
+ if (self->ss->shade(*( ((BPy_Stroke *) py_s)->s )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->ss->getName() + " shade method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+/*----------------------StrokeShader instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeShader_methods[] = {
+ {"getName", ( PyCFunction ) StrokeShader_getName, METH_NOARGS, StrokeShader_getName___doc__},
+ {"shade", ( PyCFunction ) StrokeShader_shade, METH_VARARGS, StrokeShader_shade___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_StrokeShader type definition ------------------------------*/
+
+PyTypeObject StrokeShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeShader", /* tp_name */
+ sizeof(BPy_StrokeShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)StrokeShader___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)StrokeShader___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeShader_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.h b/source/blender/freestyle/intern/python/BPy_StrokeShader.h
new file mode 100644
index 00000000000..baa31a3100e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.h
@@ -0,0 +1,40 @@
+#ifndef FREESTYLE_PYTHON_STROKESHADER_H
+#define FREESTYLE_PYTHON_STROKESHADER_H
+
+#include <Python.h>
+
+#include "../system/FreestyleConfig.h"
+
+using namespace std;
+
+#include "../stroke/StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject StrokeShader_Type;
+
+#define BPy_StrokeShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeShader_Type) )
+
+/*---------------------------Python BPy_StrokeShader structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ StrokeShader *ss;
+} BPy_StrokeShader;
+
+/*---------------------------Python BPy_StrokeShader visible prototypes-----------*/
+
+int StrokeShader_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_STROKESHADER_H */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
new file mode 100644
index 00000000000..9cb855f32ae
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
@@ -0,0 +1,126 @@
+#include "BPy_UnaryFunction0D.h"
+
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DId.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryFunction0D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0D_Type );
+ PyModule_AddObject(module, "UnaryFunction0D", (PyObject *)&UnaryFunction0D_Type);
+
+ UnaryFunction0DDouble_Init( module );
+ UnaryFunction0DEdgeNature_Init( module );
+ UnaryFunction0DFloat_Init( module );
+ UnaryFunction0DId_Init( module );
+ UnaryFunction0DMaterial_Init( module );
+ UnaryFunction0DUnsigned_Init( module );
+ UnaryFunction0DVec2f_Init( module );
+ UnaryFunction0DVec3f_Init( module );
+ UnaryFunction0DVectorViewShape_Init( module );
+ UnaryFunction0DViewShape_Init( module );
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0D___doc__[] =
+"Base class for Unary Functions (functors) working on\n"
+":class:`Interface0DIterator`. A unary function will be used by\n"
+"invoking __call__() on an Interface0DIterator. In Python, several\n"
+"different subclasses of UnaryFunction0D are used depending on the\n"
+"types of functors' return values. For example, you would inherit from\n"
+"a :class:`UnaryFunction0DDouble` if you wish to define a function that\n"
+"returns a double value. Available UnaryFunction0D subclasses are:\n"
+"\n"
+"* :class:`UnaryFunction0DDouble`\n"
+"* :class:`UnaryFunction0DEdgeNature`\n"
+"* :class:`UnaryFunction0DFloat`\n"
+"* :class:`UnaryFunction0DId`\n"
+"* :class:`UnaryFunction0DMaterial`\n"
+"* :class:`UnaryFunction0DUnsigned`\n"
+"* :class:`UnaryFunction0DVec2f`\n"
+"* :class:`UnaryFunction0DVec3f`\n"
+"* :class:`UnaryFunction0DVectorViewShape`\n"
+"* :class:`UnaryFunction0DViewShape`\n";
+
+static void UnaryFunction0D___dealloc__(BPy_UnaryFunction0D* self)
+{
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * UnaryFunction0D___repr__(BPy_UnaryFunction0D* self)
+{
+ return PyUnicode_FromString("UnaryFunction0D");
+}
+
+/*-----------------------BPy_UnaryFunction0D type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0D", /* tp_name */
+ sizeof(BPy_UnaryFunction0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h
new file mode 100644
index 00000000000..6d61c336662
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0D_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0D_H
+
+#include <Python.h>
+
+#include "../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryFunction0D_Type;
+
+#define BPy_UnaryFunction0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0D_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ PyObject *py_uf0D;
+} BPy_UnaryFunction0D;
+
+/*---------------------------Python BPy_UnaryFunction0D visible prototypes-----------*/
+
+int UnaryFunction0D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
new file mode 100644
index 00000000000..f4de9edb962
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
@@ -0,0 +1,117 @@
+#include "BPy_UnaryFunction1D.h"
+
+#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryFunction1D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1D_Type );
+ PyModule_AddObject(module, "UnaryFunction1D", (PyObject *)&UnaryFunction1D_Type);
+
+ UnaryFunction1DDouble_Init( module );
+ UnaryFunction1DEdgeNature_Init( module );
+ UnaryFunction1DFloat_Init( module );
+ UnaryFunction1DUnsigned_Init( module );
+ UnaryFunction1DVec2f_Init( module );
+ UnaryFunction1DVec3f_Init( module );
+ UnaryFunction1DVectorViewShape_Init( module );
+ UnaryFunction1DVoid_Init( module );
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1D___doc__[] =
+"Base class for Unary Functions (functors) working on\n"
+":class:`Interface1D`. A unary function will be used by invoking\n"
+"__call__() on an Interface1D. In Python, several different subclasses\n"
+"of UnaryFunction1D are used depending on the types of functors' return\n"
+"values. For example, you would inherit from a\n"
+":class:`UnaryFunction1DDouble` if you wish to define a function that\n"
+"returns a double value. Available UnaryFunction1D subclasses are:\n"
+"\n"
+"* :class:`UnaryFunction1DDouble`\n"
+"* :class:`UnaryFunction1DEdgeNature`\n"
+"* :class:`UnaryFunction1DFloat`\n"
+"* :class:`UnaryFunction1DUnsigned`\n"
+"* :class:`UnaryFunction1DVec2f`\n"
+"* :class:`UnaryFunction1DVec3f`\n"
+"* :class:`UnaryFunction1DVectorViewShape`\n"
+"* :class:`UnaryFunction1DVoid`\n";
+
+static void UnaryFunction1D___dealloc__(BPy_UnaryFunction1D* self)
+{
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1D___repr__(BPy_UnaryFunction1D* self)
+{
+ return PyUnicode_FromString("UnaryFunction1D");
+}
+
+/*-----------------------BPy_UnaryFunction1D type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1D", /* tp_name */
+ sizeof(BPy_UnaryFunction1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h
new file mode 100644
index 00000000000..cb9df18ab75
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1D_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1D_H
+
+#include <Python.h>
+
+#include "../view_map/Functions1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryFunction1D_Type;
+
+#define BPy_UnaryFunction1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1D_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ PyObject *py_uf1D;
+} BPy_UnaryFunction1D;
+
+/*---------------------------Python BPy_UnaryFunction1D visible prototypes-----------*/
+
+int UnaryFunction1D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp
new file mode 100644
index 00000000000..81f39ef7ab7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp
@@ -0,0 +1,184 @@
+#include "BPy_UnaryPredicate0D.h"
+
+#include "BPy_Convert.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "UnaryPredicate0D/BPy_FalseUP0D.h"
+#include "UnaryPredicate0D/BPy_TrueUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryPredicate0D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryPredicate0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryPredicate0D_Type );
+ PyModule_AddObject(module, "UnaryPredicate0D", (PyObject *)&UnaryPredicate0D_Type);
+
+ if( PyType_Ready( &FalseUP0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FalseUP0D_Type );
+ PyModule_AddObject(module, "FalseUP0D", (PyObject *)&FalseUP0D_Type);
+
+ if( PyType_Ready( &TrueUP0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TrueUP0D_Type );
+ PyModule_AddObject(module, "TrueUP0D", (PyObject *)&TrueUP0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryPredicate0D___doc__[] =
+"Base class for unary predicates that work on\n"
+":class:`Interface0DIterator`. A UnaryPredicate0D is a functor that\n"
+"evaluates a condition on an Interface0DIterator and returns true or\n"
+"false depending on whether this condition is satisfied or not. The\n"
+"UnaryPredicate0D is used by invoking its __call__() method. Any\n"
+"inherited class must overload the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Must be overload by inherited classes.\n"
+"\n"
+" :arg it: The Interface0DIterator pointing onto the Interface0D at\n"
+" which we wish to evaluate the predicate.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: True if the condition is satisfied, false otherwise.\n"
+" :rtype: bool\n";
+
+static int UnaryPredicate0D___init__(BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->up0D = new UnaryPredicate0D();
+ self->up0D->py_up0D = (PyObject *) self;
+ return 0;
+}
+
+static void UnaryPredicate0D___dealloc__(BPy_UnaryPredicate0D* self)
+{
+ if (self->up0D)
+ delete self->up0D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * UnaryPredicate0D___repr__(BPy_UnaryPredicate0D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->up0D->getName().c_str(), self->up0D );
+}
+
+static char UnaryPredicate0D_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the UnaryPredicate0D.\n"
+"\n"
+" :return: The name of the UnaryPredicate0D.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryPredicate0D_getName( BPy_UnaryPredicate0D *self )
+{
+ return PyUnicode_FromString( self->up0D->getName().c_str() );
+}
+
+static PyObject * UnaryPredicate0D___call__( BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_if0D_it;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &py_if0D_it) )
+ return NULL;
+
+ Interface0DIterator *if0D_it = ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it;
+
+ if( !if0D_it ) {
+ string msg(self->up0D->getName() + " has no Interface0DIterator");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ return NULL;
+ }
+ if( typeid(*(self->up0D)) == typeid(UnaryPredicate0D) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->up0D->operator()(*if0D_it) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->up0D->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool( self->up0D->result );
+}
+
+/*----------------------UnaryPredicate0D instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryPredicate0D_methods[] = {
+ {"getName", ( PyCFunction ) UnaryPredicate0D_getName, METH_NOARGS, UnaryPredicate0D_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryPredicate0D type definition ------------------------------*/
+
+PyTypeObject UnaryPredicate0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryPredicate0D", /* tp_name */
+ sizeof(BPy_UnaryPredicate0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryPredicate0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryPredicate0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryPredicate0D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryPredicate0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryPredicate0D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryPredicate0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h
new file mode 100644
index 00000000000..9f9bb0c1003
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYPREDICATE0D_H
+#define FREESTYLE_PYTHON_UNARYPREDICATE0D_H
+
+#include <Python.h>
+
+#include "../stroke/Predicates0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryPredicate0D_Type;
+
+#define BPy_UnaryPredicate0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryPredicate0D_Type) )
+
+/*---------------------------Python BPy_UnaryPredicate0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ UnaryPredicate0D *up0D;
+} BPy_UnaryPredicate0D;
+
+/*---------------------------Python BPy_UnaryPredicate0D visible prototypes-----------*/
+
+int UnaryPredicate0D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYPREDICATE0D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp
new file mode 100644
index 00000000000..a0c59484486
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp
@@ -0,0 +1,236 @@
+#include "BPy_UnaryPredicate1D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface1D.h"
+
+#include "UnaryPredicate1D/BPy_ContourUP1D.h"
+#include "UnaryPredicate1D/BPy_DensityLowerThanUP1D.h"
+#include "UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h"
+#include "UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h"
+#include "UnaryPredicate1D/BPy_ExternalContourUP1D.h"
+#include "UnaryPredicate1D/BPy_FalseUP1D.h"
+#include "UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h"
+#include "UnaryPredicate1D/BPy_ShapeUP1D.h"
+#include "UnaryPredicate1D/BPy_TrueUP1D.h"
+#include "UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryPredicate1D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryPredicate1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryPredicate1D_Type );
+ PyModule_AddObject(module, "UnaryPredicate1D", (PyObject *)&UnaryPredicate1D_Type);
+
+ if( PyType_Ready( &ContourUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ContourUP1D_Type );
+ PyModule_AddObject(module, "ContourUP1D", (PyObject *)&ContourUP1D_Type);
+
+ if( PyType_Ready( &DensityLowerThanUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &DensityLowerThanUP1D_Type );
+ PyModule_AddObject(module, "DensityLowerThanUP1D", (PyObject *)&DensityLowerThanUP1D_Type);
+
+ if( PyType_Ready( &EqualToChainingTimeStampUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &EqualToChainingTimeStampUP1D_Type );
+ PyModule_AddObject(module, "EqualToChainingTimeStampUP1D", (PyObject *)&EqualToChainingTimeStampUP1D_Type);
+
+ if( PyType_Ready( &EqualToTimeStampUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &EqualToTimeStampUP1D_Type );
+ PyModule_AddObject(module, "EqualToTimeStampUP1D", (PyObject *)&EqualToTimeStampUP1D_Type);
+
+ if( PyType_Ready( &ExternalContourUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ExternalContourUP1D_Type );
+ PyModule_AddObject(module, "ExternalContourUP1D", (PyObject *)&ExternalContourUP1D_Type);
+
+ if( PyType_Ready( &FalseUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FalseUP1D_Type );
+ PyModule_AddObject(module, "FalseUP1D", (PyObject *)&FalseUP1D_Type);
+
+ if( PyType_Ready( &QuantitativeInvisibilityUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &QuantitativeInvisibilityUP1D_Type );
+ PyModule_AddObject(module, "QuantitativeInvisibilityUP1D", (PyObject *)&QuantitativeInvisibilityUP1D_Type);
+
+ if( PyType_Ready( &ShapeUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ShapeUP1D_Type );
+ PyModule_AddObject(module, "ShapeUP1D", (PyObject *)&ShapeUP1D_Type);
+
+ if( PyType_Ready( &TrueUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TrueUP1D_Type );
+ PyModule_AddObject(module, "TrueUP1D", (PyObject *)&TrueUP1D_Type);
+
+ if( PyType_Ready( &WithinImageBoundaryUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &WithinImageBoundaryUP1D_Type );
+ PyModule_AddObject(module, "WithinImageBoundaryUP1D", (PyObject *)&WithinImageBoundaryUP1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryPredicate1D___doc__[] =
+"Base class for unary predicates that work on :class:`Interface1D`. A\n"
+"UnaryPredicate1D is a functor that evaluates a condition on a\n"
+"Interface1D and returns true or false depending on whether this\n"
+"condition is satisfied or not. The UnaryPredicate1D is used by\n"
+"invoking its __call__() method. Any inherited class must overload the\n"
+"__call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Must be overload by inherited classes.\n"
+"\n"
+" :arg inter: The Interface1D on which we wish to evaluate the predicate.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the condition is satisfied, false otherwise.\n"
+" :rtype: bool\n";
+
+static int UnaryPredicate1D___init__(BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->up1D = new UnaryPredicate1D();
+ self->up1D->py_up1D = (PyObject *) self;
+ return 0;
+}
+
+static void UnaryPredicate1D___dealloc__(BPy_UnaryPredicate1D* self)
+{
+ if (self->up1D)
+ delete self->up1D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * UnaryPredicate1D___repr__(BPy_UnaryPredicate1D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->up1D->getName().c_str(), self->up1D );
+}
+
+static char UnaryPredicate1D_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the string of the name of the UnaryPredicate1D.\n"
+"\n"
+" Reimplemented in TrueUP1D, FalseUP1D, QuantitativeInvisibilityUP1D,\n"
+" ContourUP1D, ExternalContourUP1D, EqualToTimeStampUP1D,\n"
+" EqualToChainingTimeStampUP1D, ShapeUP1D, and DensityLowerThanUP1D.\n"
+"\n"
+" :return: \n"
+" :rtype: str\n";
+
+static PyObject * UnaryPredicate1D_getName( BPy_UnaryPredicate1D *self, PyObject *args)
+{
+ return PyUnicode_FromString( self->up1D->getName().c_str() );
+}
+
+static PyObject * UnaryPredicate1D___call__( BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_if1D;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &py_if1D) )
+ return NULL;
+
+ Interface1D *if1D = ((BPy_Interface1D *) py_if1D)->if1D;
+
+ if( !if1D ) {
+ string msg(self->up1D->getName() + " has no Interface0DIterator");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ return NULL;
+ }
+ if( typeid(*(self->up1D)) == typeid(UnaryPredicate1D) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if( self->up1D->operator()(*if1D) < 0 ) {
+ if (!PyErr_Occurred()) {
+ string msg(self->up1D->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool( self->up1D->result );
+}
+
+/*----------------------UnaryPredicate1D instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryPredicate1D_methods[] = {
+ {"getName", ( PyCFunction ) UnaryPredicate1D_getName, METH_NOARGS, UnaryPredicate1D_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryPredicate1D type definition ------------------------------*/
+
+PyTypeObject UnaryPredicate1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryPredicate1D", /* tp_name */
+ sizeof(BPy_UnaryPredicate1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryPredicate1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryPredicate1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryPredicate1D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryPredicate1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryPredicate1D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryPredicate1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h
new file mode 100644
index 00000000000..75953e7977b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYPREDICATE1D_H
+#define FREESTYLE_PYTHON_UNARYPREDICATE1D_H
+
+#include <Python.h>
+
+#include "../stroke/Predicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryPredicate1D_Type;
+
+#define BPy_UnaryPredicate1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryPredicate1D_Type) )
+
+/*---------------------------Python BPy_UnaryPredicate1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ UnaryPredicate1D *up1D;
+} BPy_UnaryPredicate1D;
+
+/*---------------------------Python BPy_UnaryPredicate1D visible prototypes-----------*/
+
+int UnaryPredicate1D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYPREDICATE1D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.cpp b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp
new file mode 100644
index 00000000000..c9667103e5a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp
@@ -0,0 +1,195 @@
+#include "BPy_ViewMap.h"
+
+#include "BPy_Convert.h"
+#include "BPy_BBox.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int ViewMap_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &ViewMap_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &ViewMap_Type );
+ PyModule_AddObject(module, "ViewMap", (PyObject *)&ViewMap_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewMap___doc__[] =
+"Class defining the ViewMap.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int ViewMap___init__(BPy_ViewMap *self, PyObject *args, PyObject *kwds)
+{
+ self->vm = new ViewMap();
+ return 0;
+}
+
+static void ViewMap___dealloc__(BPy_ViewMap *self)
+{
+ if( self->vm )
+ delete self->vm;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * ViewMap___repr__(BPy_ViewMap *self)
+{
+ return PyUnicode_FromFormat("ViewMap - address: %p", self->vm );
+}
+
+static char ViewMap_getClosestViewEdge___doc__[] =
+".. method:: getClosestViewEdge(x, y)\n"
+"\n"
+" Gets the ViewEdge nearest to the 2D point specified as arguments.\n"
+"\n"
+" :arg x: X coordinate of a 2D point.\n"
+" :type x: float\n"
+" :arg y: Y coordinate of a 2D point.\n"
+" :type y: float\n"
+" :return: The ViewEdge nearest to the specified 2D point.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * ViewMap_getClosestViewEdge( BPy_ViewMap *self , PyObject *args) {
+ double x, y;
+
+ if(!( PyArg_ParseTuple(args, "dd", &x, &y) ))
+ return NULL;
+
+ ViewEdge *ve = const_cast<ViewEdge *>( self->vm->getClosestViewEdge(x,y) );
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+
+ Py_RETURN_NONE;
+}
+
+static char ViewMap_getClosestFEdge___doc__[] =
+".. method:: getClosestFEdge(x, y)\n"
+"\n"
+" Gets the FEdge nearest to the 2D point specified as arguments.\n"
+"\n"
+" :arg x: X coordinate of a 2D point.\n"
+" :type x: float\n"
+" :arg y: Y coordinate of a 2D point.\n"
+" :type y: float\n"
+" :return: The FEdge nearest to the specified 2D point.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * ViewMap_getClosestFEdge( BPy_ViewMap *self , PyObject *args) {
+ double x, y;
+
+ if(!( PyArg_ParseTuple(args, "dd", &x, &y) ))
+ return NULL;
+
+ FEdge *fe = const_cast<FEdge *>( self->vm->getClosestFEdge(x,y) );
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge(*fe);
+
+ Py_RETURN_NONE;
+}
+
+static char ViewMap_getScene3dBBox___doc__[] =
+".. method:: getScene3dBBox()\n"
+"\n"
+" Returns the scene 3D bounding box.\n"
+"\n"
+" :return: The scene 3D bounding box.\n"
+" :rtype: :class:`BBox`\n";
+
+static PyObject * ViewMap_getScene3dBBox( BPy_ViewMap *self , PyObject *args) {
+ BBox<Vec3r> bb( self->vm->getScene3dBBox() );
+ return BPy_BBox_from_BBox( bb );
+}
+
+static char ViewMap_setScene3dBBox___doc__[] =
+".. method:: setScene3dBBox(bbox)\n"
+"\n"
+" Sets the scene 3D bounding box.\n"
+"\n"
+" :arg bbox: The scene 3D bounding box.\n"
+" :type bbox: :class:`BBox`\n";
+
+static PyObject * ViewMap_setScene3dBBox( BPy_ViewMap *self , PyObject *args) {
+ PyObject *py_bb = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &BBox_Type, &py_bb) ))
+ return NULL;
+
+ self->vm->setScene3dBBox(*( ((BPy_BBox *) py_bb)->bb ));
+
+ Py_RETURN_NONE;
+}
+
+// static ViewMap *getInstance ();
+
+/*---------------------- BPy_ViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewMap_methods[] = {
+ {"getClosestViewEdge", ( PyCFunction ) ViewMap_getClosestViewEdge, METH_VARARGS, ViewMap_getClosestViewEdge___doc__},
+ {"getClosestFEdge", ( PyCFunction ) ViewMap_getClosestFEdge, METH_VARARGS, ViewMap_getClosestFEdge___doc__},
+ {"getScene3dBBox", ( PyCFunction ) ViewMap_getScene3dBBox, METH_NOARGS, ViewMap_getScene3dBBox___doc__},
+ {"setScene3dBBox", ( PyCFunction ) ViewMap_setScene3dBBox, METH_VARARGS, ViewMap_setScene3dBBox___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewMap type definition ------------------------------*/
+
+PyTypeObject ViewMap_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewMap", /* tp_name */
+ sizeof(BPy_ViewMap), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ViewMap___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)ViewMap___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewMap___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewMap_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewMap___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.h b/source/blender/freestyle/intern/python/BPy_ViewMap.h
new file mode 100644
index 00000000000..943aeb718fc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewMap.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_VIEWMAP_H
+#define FREESTYLE_PYTHON_VIEWMAP_H
+
+#include <Python.h>
+
+#include "../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject ViewMap_Type;
+
+#define BPy_ViewMap_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewMap_Type) )
+
+/*---------------------------Python BPy_ViewMap structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ ViewMap *vm;
+} BPy_ViewMap;
+
+/*---------------------------Python BPy_ViewMap visible prototypes-----------*/
+
+int ViewMap_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWMAP_H */
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
new file mode 100644
index 00000000000..eebfa88773c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
@@ -0,0 +1,353 @@
+#include "BPy_ViewShape.h"
+
+#include "BPy_Convert.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "BPy_SShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int ViewShape_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &ViewShape_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &ViewShape_Type );
+ PyModule_AddObject(module, "ViewShape", (PyObject *)&ViewShape_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewShape___doc__[] =
+"Class gathering the elements of the ViewMap (i.e., :class:`ViewVertex`\n"
+"and :class:`ViewEdge`) that are issued from the same input shape.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A ViewShape object.\n"
+" :type iBrother: :class:`ViewShape`\n"
+"\n"
+".. method:: __init__(iSShape)\n"
+"\n"
+" Builds a ViewShape from an SShape.\n"
+"\n"
+" :arg iSShape: An SShape object.\n"
+" :type iSShape: :class:`SShape`\n";
+
+static int ViewShape___init__(BPy_ViewShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ) {
+ self->vs = new ViewShape();
+
+ } else if( BPy_SShape_Check(obj) ) {
+ self->vs = new ViewShape( ((BPy_SShape *) obj)->ss );
+
+ } else if( BPy_ViewShape_Check(obj) ) {
+ self->vs = new ViewShape(*( ((BPy_ViewShape *) obj)->vs ));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+ self->borrowed = 0;
+
+ return 0;
+}
+
+static void ViewShape___dealloc__(BPy_ViewShape *self)
+{
+ if( self->vs && !self->borrowed )
+ delete self->vs;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * ViewShape___repr__(BPy_ViewShape *self)
+{
+ return PyUnicode_FromFormat("ViewShape - address: %p", self->vs );
+}
+
+static char ViewShape_sshape___doc__[] =
+".. method:: sshape()\n"
+"\n"
+" Returns the SShape on top of which this ViewShape is built.\n"
+"\n"
+" :return: The SShape on top of which this ViewShape is built.\n"
+" :rtype: :class:`SShape`\n";
+
+static PyObject * ViewShape_sshape( BPy_ViewShape *self ) {
+ return BPy_SShape_from_SShape( *(self->vs->sshape()) );
+}
+
+static char ViewShape_vertices___doc__[] =
+".. method:: vertices()\n"
+"\n"
+" Returns the list of ViewVertex objects contained in this ViewShape.\n"
+"\n"
+" :return: The list of ViewVertex objects.\n"
+" :rtype: List of :class:`ViewVertex` objects\n";
+
+static PyObject * ViewShape_vertices( BPy_ViewShape *self ) {
+ PyObject *py_vertices = PyList_New(0);
+
+ vector< ViewVertex * > vertices = self->vs->vertices();
+ vector< ViewVertex * >::iterator it;
+
+ for( it = vertices.begin(); it != vertices.end(); it++ ) {
+ PyList_Append( py_vertices, Any_BPy_ViewVertex_from_ViewVertex(*( *it )) );
+ }
+
+ return py_vertices;
+}
+
+static char ViewShape_edges___doc__[] =
+".. method:: edges()\n"
+"\n"
+" Returns the list of ViewEdge objects contained in this ViewShape.\n"
+"\n"
+" :return: The list of ViewEdge objects.\n"
+" :rtype: List of :class:`ViewEdge` objects\n";
+
+static PyObject * ViewShape_edges( BPy_ViewShape *self ) {
+ PyObject *py_edges = PyList_New(0);
+
+ vector< ViewEdge * > edges = self->vs->edges();
+ vector< ViewEdge * >::iterator it;
+
+ for( it = edges.begin(); it != edges.end(); it++ ) {
+ PyList_Append( py_edges, BPy_ViewEdge_from_ViewEdge(*( *it )) );
+ }
+
+ return py_edges;
+}
+
+static char ViewShape_getId___doc__[] =
+".. method:: getId()\n"
+"\n"
+" Returns the ViewShape id.\n"
+"\n"
+" :return: An Id object.\n"
+" :rtype: :class:`Id`\n";
+
+static PyObject * ViewShape_getId( BPy_ViewShape *self ) {
+ Id id( self->vs->getId() );
+ return BPy_Id_from_Id( id );
+}
+
+static char ViewShape_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the ViewShape.\n"
+"\n"
+" :return: The name string.\n"
+" :rtype: str\n";
+
+static PyObject * ViewShape_getName( BPy_ViewShape *self ) {
+ return PyUnicode_FromString( self->vs->getName().c_str() );
+}
+
+static char ViewShape_setSShape___doc__[] =
+".. method:: setSShape(iSShape)\n"
+"\n"
+" Sets the SShape on top of which the ViewShape is built.\n"
+"\n"
+" :arg iSShape: An SShape object.\n"
+" :type iSShape: :class:`SShape`\n";
+
+static PyObject * ViewShape_setSShape( BPy_ViewShape *self , PyObject *args) {
+ PyObject *py_ss = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SShape_Type, &py_ss) ))
+ return NULL;
+
+ self->vs->setSShape( ((BPy_SShape *) py_ss)->ss );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewShape_setVertices___doc__[] =
+".. method:: setVertices(iVertices)\n"
+"\n"
+" Sets the list of ViewVertex objects contained in this ViewShape.\n"
+"\n"
+" :arg iVertices: The list of ViewVertex objects.\n"
+" :type iVertices: List of :class:`ViewVertex` objects\n";
+
+static PyObject * ViewShape_setVertices( BPy_ViewShape *self , PyObject *args) {
+ PyObject *list = 0;
+ PyObject *tmp;
+
+ if(!( PyArg_ParseTuple(args, "O!", &PyList_Type, &list) ))
+ return NULL;
+
+ vector< ViewVertex *> v;
+
+ for( int i=0; i < PyList_Size(list); i++ ) {
+ tmp = PyList_GetItem(list, i);
+ if( BPy_ViewVertex_Check(tmp) )
+ v.push_back( ((BPy_ViewVertex *) tmp)->vv );
+ else {
+ PyErr_SetString(PyExc_TypeError, "argument must be list of ViewVertex objects");
+ return NULL;
+ }
+ }
+
+ self->vs->setVertices( v );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewShape_setEdges___doc__[] =
+".. method:: setEdges(iEdges)\n"
+"\n"
+" Sets the list of ViewEdge objects contained in this ViewShape.\n"
+"\n"
+" :arg iEdges: The list of ViewEdge objects.\n"
+" :type iEdges: List of :class:`ViewEdge` objects.\n";
+
+static PyObject * ViewShape_setEdges( BPy_ViewShape *self , PyObject *args) {
+ PyObject *list = 0;
+ PyObject *tmp;
+
+ if(!( PyArg_ParseTuple(args, "O!", &PyList_Type, &list) ))
+ return NULL;
+
+ vector<ViewEdge *> v;
+
+ for( int i=0; i < PyList_Size(list); i++ ) {
+ tmp = PyList_GetItem(list, i);
+ if( BPy_ViewEdge_Check(tmp) )
+ v.push_back( ((BPy_ViewEdge *) tmp)->ve );
+ else {
+ PyErr_SetString(PyExc_TypeError, "argument must be list of ViewEdge objects");
+ return NULL;
+ }
+ }
+
+ self->vs->setEdges( v );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewShape_AddEdge___doc__[] =
+".. method:: AddEdge(iEdge)\n"
+"\n"
+" Adds a ViewEdge to the list of ViewEdge objects.\n"
+"\n"
+" :arg iEdge: A ViewEdge object.\n"
+" :type iEdge: :class:`ViewEdge`\n";
+
+static PyObject * ViewShape_AddEdge( BPy_ViewShape *self , PyObject *args) {
+ PyObject *py_ve = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ self->vs->AddEdge( ((BPy_ViewEdge *) py_ve)->ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewShape_AddVertex___doc__[] =
+".. method:: AddVertex(iVertex)\n"
+"\n"
+" Adds a ViewVertex to the list of the ViewVertex objects.\n"
+"\n"
+" :arg iVertex: A ViewVertex object.\n"
+" :type iVertex: :class:`ViewVertex`\n";
+
+static PyObject * ViewShape_AddVertex( BPy_ViewShape *self , PyObject *args) {
+ PyObject *py_vv = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) ))
+ return NULL;
+
+ self->vs->AddVertex( ((BPy_ViewVertex *) py_vv)->vv );
+
+ Py_RETURN_NONE;
+}
+
+// virtual ViewShape * duplicate ()
+
+/*---------------------- BPy_ViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewShape_methods[] = {
+ {"sshape", ( PyCFunction ) ViewShape_sshape, METH_NOARGS, ViewShape_sshape___doc__},
+ {"vertices", ( PyCFunction ) ViewShape_vertices, METH_NOARGS, ViewShape_vertices___doc__},
+ {"edges", ( PyCFunction ) ViewShape_edges, METH_NOARGS, ViewShape_edges___doc__},
+ {"getId", ( PyCFunction ) ViewShape_getId, METH_NOARGS, ViewShape_getId___doc__},
+ {"getName", ( PyCFunction ) ViewShape_getName, METH_NOARGS, ViewShape_getName___doc__},
+ {"setSShape", ( PyCFunction ) ViewShape_setSShape, METH_VARARGS, ViewShape_setSShape___doc__},
+ {"setVertices", ( PyCFunction ) ViewShape_setVertices, METH_VARARGS, ViewShape_setVertices___doc__},
+ {"setEdges", ( PyCFunction ) ViewShape_setEdges, METH_VARARGS, ViewShape_setEdges___doc__},
+ {"AddEdge", ( PyCFunction ) ViewShape_AddEdge, METH_VARARGS, ViewShape_AddEdge___doc__},
+ {"AddVertex", ( PyCFunction ) ViewShape_AddVertex, METH_VARARGS, ViewShape_AddVertex___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewShape type definition ------------------------------*/
+
+PyTypeObject ViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewShape", /* tp_name */
+ sizeof(BPy_ViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)ViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.h b/source/blender/freestyle/intern/python/BPy_ViewShape.h
new file mode 100644
index 00000000000..1850ec8f13a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_VIEWSHAPE_H
+#define FREESTYLE_PYTHON_VIEWSHAPE_H
+
+#include <Python.h>
+
+#include "../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject ViewShape_Type;
+
+#define BPy_ViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewShape_Type) )
+
+/*---------------------------Python BPy_ViewShape structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ ViewShape *vs;
+ int borrowed; /* non-zero if *vs a borrowed object */
+} BPy_ViewShape;
+
+/*---------------------------Python BPy_ViewShape visible prototypes-----------*/
+
+int ViewShape_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp
new file mode 100644
index 00000000000..ad2885fb95a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp
@@ -0,0 +1,79 @@
+#include "BPy_FalseBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`FalseBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseBP1D___init__( BPy_FalseBP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::FalseBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseBP1D type definition ------------------------------*/
+PyTypeObject FalseBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseBP1D", /* tp_name */
+ sizeof(BPy_FalseBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FalseBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h
new file mode 100644
index 00000000000..a8d4aad88aa
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_FALSEBP1D_H
+#define FREESTYLE_PYTHON_FALSEBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseBP1D_Type;
+
+#define BPy_FalseBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseBP1D_Type) )
+
+/*---------------------------Python BPy_FalseBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_FalseBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FALSEBP1D_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp
new file mode 100644
index 00000000000..1a59091c453
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp
@@ -0,0 +1,81 @@
+#include "BPy_Length2DBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Length2DBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`Length2DBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if the 2D length of inter1 is less than the 2D length\n"
+" of inter2.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int Length2DBP1D___init__( BPy_Length2DBP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::Length2DBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_Length2DBP1D type definition ------------------------------*/
+
+PyTypeObject Length2DBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Length2DBP1D", /* tp_name */
+ sizeof(BPy_Length2DBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Length2DBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Length2DBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h
new file mode 100644
index 00000000000..d5bce5b150d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_LENGTH2DBP1D_H
+#define FREESTYLE_PYTHON_LENGTH2DBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Length2DBP1D_Type;
+
+#define BPy_Length2DBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Length2DBP1D_Type) )
+
+/*---------------------------Python BPy_Length2DBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_Length2DBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_LENGTH2DBP1D_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp
new file mode 100644
index 00000000000..2b479a49fc0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp
@@ -0,0 +1,80 @@
+#include "BPy_SameShapeIdBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SameShapeIdBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`SameShapeIdBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if inter1 and inter2 belong to the same shape.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int SameShapeIdBP1D___init__( BPy_SameShapeIdBP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::SameShapeIdBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_SameShapeIdBP1D type definition ------------------------------*/
+
+PyTypeObject SameShapeIdBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SameShapeIdBP1D", /* tp_name */
+ sizeof(BPy_SameShapeIdBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SameShapeIdBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SameShapeIdBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h
new file mode 100644
index 00000000000..71065d4ceeb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H
+#define FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SameShapeIdBP1D_Type;
+
+#define BPy_SameShapeIdBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SameShapeIdBP1D_Type) )
+
+/*---------------------------Python BPy_SameShapeIdBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_SameShapeIdBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp
new file mode 100644
index 00000000000..090a8232794
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp
@@ -0,0 +1,80 @@
+#include "BPy_TrueBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`TrueBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueBP1D___init__( BPy_TrueBP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::TrueBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueBP1D type definition ------------------------------*/
+
+PyTypeObject TrueBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueBP1D", /* tp_name */
+ sizeof(BPy_TrueBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TrueBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h
new file mode 100644
index 00000000000..7d809e1fe65
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_TRUEBP1D_H
+#define FREESTYLE_PYTHON_TRUEBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueBP1D_Type;
+
+#define BPy_TrueBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueBP1D_Type) )
+
+/*---------------------------Python BPy_TrueBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_TrueBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TRUEBP1D_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp
new file mode 100644
index 00000000000..f5ba9d58d72
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_ViewMapGradientNormBP1D.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+//ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0)
+
+static char ViewMapGradientNormBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`ViewMapGradientNormBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if the evaluation of the Gradient norm Function is\n"
+" higher for inter1 than for inter2.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int ViewMapGradientNormBP1D___init__( BPy_ViewMapGradientNormBP1D* self, PyObject *args )
+{
+ int i;
+ PyObject *obj;
+ float f = 2.0;
+
+ if(!( PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) ))
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_bp1D.bp1D = new Predicates1D::ViewMapGradientNormBP1D(i,t,f);
+ return 0;
+}
+
+/*-----------------------BPy_ViewMapGradientNormBP1D type definition ------------------------------*/
+
+PyTypeObject ViewMapGradientNormBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewMapGradientNormBP1D", /* tp_name */
+ sizeof(BPy_ViewMapGradientNormBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewMapGradientNormBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewMapGradientNormBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h
new file mode 100644
index 00000000000..23d27e118a9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H
+#define FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewMapGradientNormBP1D_Type;
+
+#define BPy_ViewMapGradientNormBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewMapGradientNormBP1D_Type) )
+
+/*---------------------------Python BPy_ViewMapGradientNormBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_ViewMapGradientNormBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H */
diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp
new file mode 100644
index 00000000000..1948da2b6b0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Director.cpp
@@ -0,0 +1,304 @@
+#include "Director.h"
+
+#include "BPy_Convert.h"
+
+#include "BPy_BinaryPredicate0D.h"
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_Id.h"
+#include "BPy_UnaryFunction0D.h"
+#include "BPy_UnaryFunction1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "BPy_StrokeShader.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "BPy_ViewShape.h"
+
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DId.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h"
+
+#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
+
+
+// BinaryPredicate0D: __call__
+int Director_BPy_BinaryPredicate0D___call__( BinaryPredicate0D *bp0D, Interface0D& i1, Interface0D& i2 ) {
+ if (!bp0D->py_bp0D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp0D) not initialized");
+ return -1;
+ }
+ PyObject *arg1 = Any_BPy_Interface0D_from_Interface0D(i1);
+ PyObject *arg2 = Any_BPy_Interface0D_from_Interface0D(i2);
+ if (!arg1 || !arg2) {
+ Py_XDECREF(arg1);
+ Py_XDECREF(arg2);
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod( bp0D->py_bp0D, "__call__", "OO", arg1, arg2 );
+ Py_DECREF(arg1);
+ Py_DECREF(arg2);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ bp0D->result = ret;
+ return 0;
+}
+
+
+// BinaryPredicate1D: __call__
+int Director_BPy_BinaryPredicate1D___call__( BinaryPredicate1D *bp1D, Interface1D& i1, Interface1D& i2 ) {
+ if (!bp1D->py_bp1D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp1D) not initialized");
+ return -1;
+ }
+ PyObject *arg1 = Any_BPy_Interface1D_from_Interface1D(i1);
+ PyObject *arg2 = Any_BPy_Interface1D_from_Interface1D(i2);
+ if (!arg1 || !arg2) {
+ Py_XDECREF(arg1);
+ Py_XDECREF(arg2);
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod( bp1D->py_bp1D, "__call__", "OO", arg1, arg2 );
+ Py_DECREF(arg1);
+ Py_DECREF(arg2);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ bp1D->result = ret;
+ return 0;
+}
+
+
+// UnaryPredicate0D: __call__
+int Director_BPy_UnaryPredicate0D___call__( UnaryPredicate0D *up0D, Interface0DIterator& if0D_it ) {
+ if (!up0D->py_up0D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up0D) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( up0D->py_up0D, "__call__", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ up0D->result = ret;
+ return 0;
+}
+
+
+// UnaryPredicate1D: __call__
+int Director_BPy_UnaryPredicate1D___call__( UnaryPredicate1D *up1D, Interface1D& if1D ) {
+ if (!up1D->py_up1D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up1D) not initialized");
+ return -1;
+ }
+ PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( up1D->py_up1D, "__call__", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ up1D->result = ret;
+ return 0;
+}
+
+
+// StrokeShader: shade
+int Director_BPy_StrokeShader_shade( StrokeShader *ss, Stroke& s ) {
+ if (!ss->py_ss) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_ss) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Stroke_from_Stroke(s);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( ss->py_ss, "shade", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ Py_DECREF(result);
+ return 0;
+}
+
+// ChainingIterator: init, traverse
+int Director_BPy_ChainingIterator_init( ChainingIterator *c_it ) {
+ if (!c_it->py_c_it) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized");
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod( c_it->py_c_it, "init", "");
+ if (!result)
+ return -1;
+ Py_DECREF(result);
+ return 0;
+}
+
+int Director_BPy_ChainingIterator_traverse( ChainingIterator *c_it, AdjacencyIterator& a_it ) {
+ if (!c_it->py_c_it) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_AdjacencyIterator_from_AdjacencyIterator(a_it);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( c_it->py_c_it, "traverse", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ if (BPy_ViewEdge_Check(result)) {
+ c_it->result = ((BPy_ViewEdge *) result)->ve;
+ } else if (result == Py_None) {
+ c_it->result = NULL;
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "traverse method returned a wrong value");
+ Py_DECREF(result);
+ return -1;
+ }
+ Py_DECREF(result);
+ return 0;
+}
+
+
+// BPy_UnaryFunction{0D,1D}: __call__
+int Director_BPy_UnaryFunction0D___call__( void *uf0D, PyObject *obj, Interface0DIterator& if0D_it) {
+
+ if (!obj) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf0D) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( obj, "__call__", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+
+ if( BPy_UnaryFunction0DDouble_Check(obj) ) {
+ ((UnaryFunction0D<double> *) uf0D)->result = PyFloat_AsDouble(result);
+
+ } else if ( BPy_UnaryFunction0DEdgeNature_Check(obj) ) {
+ ((UnaryFunction0D<Nature::EdgeNature> *) uf0D)->result = EdgeNature_from_BPy_Nature(result);
+
+ } else if ( BPy_UnaryFunction0DFloat_Check(obj) ) {
+ ((UnaryFunction0D<float> *) uf0D)->result = PyFloat_AsDouble(result);
+
+ } else if ( BPy_UnaryFunction0DId_Check(obj) ) {
+ ((UnaryFunction0D<Id> *) uf0D)->result = *( ((BPy_Id *) result)->id );
+
+ } else if ( BPy_UnaryFunction0DMaterial_Check(obj) ) {
+ ((UnaryFunction0D<FrsMaterial> *) uf0D)->result = *( ((BPy_FrsMaterial *) result)->m );
+
+ } else if ( BPy_UnaryFunction0DUnsigned_Check(obj) ) {
+ ((UnaryFunction0D<unsigned> *) uf0D)->result = PyLong_AsLong(result);
+
+ } else if ( BPy_UnaryFunction0DVec2f_Check(obj) ) {
+ Vec2f *v = Vec2f_ptr_from_Vector( result );
+ ((UnaryFunction0D<Vec2f> *) uf0D)->result = *v;
+ delete v;
+
+ } else if ( BPy_UnaryFunction0DVec3f_Check(obj) ) {
+ Vec3f *v = Vec3f_ptr_from_Vector( result );
+ ((UnaryFunction0D<Vec3f> *) uf0D)->result = *v;
+ delete v;
+
+ } else if ( BPy_UnaryFunction0DVectorViewShape_Check(obj) ) {
+ vector<ViewShape*> vec;
+ for( int i = 0; i < PyList_Size(result); i++) {
+ ViewShape *b = ( (BPy_ViewShape *) PyList_GetItem(result, i) )->vs;
+ vec.push_back( b );
+ }
+
+ ((UnaryFunction0D< vector<ViewShape*> > *) uf0D)->result = vec;
+
+ } else if ( BPy_UnaryFunction0DViewShape_Check(obj) ) {
+ ((UnaryFunction0D<ViewShape*> *) uf0D)->result = ((BPy_ViewShape *) result)->vs;
+
+ }
+
+ Py_DECREF(result);
+ return 0;
+}
+
+int Director_BPy_UnaryFunction1D___call__( void *uf1D, PyObject *obj, Interface1D& if1D) {
+
+ if (!obj) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf1D) not initialized");
+ return -1;
+ }
+ PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( obj, "__call__", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+
+ if( BPy_UnaryFunction1DDouble_Check(obj) ) {
+ ((UnaryFunction1D<double> *) uf1D)->result = PyFloat_AsDouble(result);
+
+ } else if ( BPy_UnaryFunction1DEdgeNature_Check(obj) ) {
+ ((UnaryFunction1D<Nature::EdgeNature> *) uf1D)->result = EdgeNature_from_BPy_Nature(result);
+
+ } else if ( BPy_UnaryFunction1DFloat_Check(obj) ) {
+ ((UnaryFunction1D<float> *) uf1D)->result = PyFloat_AsDouble(result);
+
+ } else if ( BPy_UnaryFunction1DUnsigned_Check(obj) ) {
+ ((UnaryFunction1D<unsigned> *) uf1D)->result = PyLong_AsLong(result);
+
+ } else if ( BPy_UnaryFunction1DVec2f_Check(obj) ) {
+ Vec2f *v = Vec2f_ptr_from_Vector( result );
+ ((UnaryFunction1D<Vec2f> *) uf1D)->result = *v;
+ delete v;
+
+ } else if ( BPy_UnaryFunction1DVec3f_Check(obj) ) {
+ Vec3f *v = Vec3f_ptr_from_Vector( result );
+ ((UnaryFunction1D<Vec3f> *) uf1D)->result = *v;
+ delete v;
+
+ } else if ( BPy_UnaryFunction1DVectorViewShape_Check(obj) ) {
+ vector<ViewShape*> vec;
+ for( int i = 1; i < PyList_Size(result); i++) {
+ ViewShape *b = ( (BPy_ViewShape *) PyList_GetItem(result, i) )->vs;
+ vec.push_back( b );
+ }
+
+ ((UnaryFunction1D< vector<ViewShape*> > *) uf1D)->result = vec;
+
+ }
+
+ Py_DECREF(result);
+ return 0;
+}
diff --git a/source/blender/freestyle/intern/python/Director.h b/source/blender/freestyle/intern/python/Director.h
new file mode 100644
index 00000000000..667d4a65942
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Director.h
@@ -0,0 +1,49 @@
+#ifndef FREESTYLE_PYTHON_DIRECTOR
+# define FREESTYLE_PYTHON_DIRECTOR
+
+class UnaryPredicate0D;
+class UnaryPredicate1D;
+class BinaryPredicate0D;
+class BinaryPredicate1D;
+class ChainingIterator;
+class AdjacencyIterator;
+class Interface0D;
+class Interface1D;
+class Interface0DIterator;
+class Stroke;
+class StrokeShader;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+// BinaryPredicate0D: __call__
+int Director_BPy_BinaryPredicate0D___call__( BinaryPredicate0D *bp0D, Interface0D& i1, Interface0D& i2 );
+
+// BinaryPredicate1D: __call__
+int Director_BPy_BinaryPredicate1D___call__( BinaryPredicate1D *bp1D, Interface1D& i1, Interface1D& i2 );
+
+// UnaryFunction{0D,1D}: __call__
+int Director_BPy_UnaryFunction0D___call__( void *uf0D, PyObject *obj, Interface0DIterator& if0D_it);
+int Director_BPy_UnaryFunction1D___call__( void *uf1D, PyObject *obj, Interface1D& if1D);
+
+// UnaryPredicate0D: __call__
+int Director_BPy_UnaryPredicate0D___call__( UnaryPredicate0D *up0D, Interface0DIterator& if0D_it );
+
+// UnaryPredicate1D: __call__
+int Director_BPy_UnaryPredicate1D___call__( UnaryPredicate1D *up1D, Interface1D& if1D );
+
+// StrokeShader: shade
+int Director_BPy_StrokeShader_shade( StrokeShader *ss, Stroke& s );
+
+// ChainingIterator: init, traverse
+int Director_BPy_ChainingIterator_init( ChainingIterator *c_it );
+int Director_BPy_ChainingIterator_traverse( ChainingIterator *c_it, AdjacencyIterator& a_it );
+
+#endif // FREESTYLE_PYTHON_DIRECTOR
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
new file mode 100644
index 00000000000..e213edd5c79
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -0,0 +1,278 @@
+#include "BPy_CurvePoint.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurvePoint___doc__[] =
+"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint`\n"
+"\n"
+"Class to represent a point of a curve. A CurvePoint can be any point\n"
+"of a 1D curve (it doesn't have to be a vertex of the curve). Any\n"
+":class:`Interface1D` is built upon ViewEdges, themselves built upon\n"
+"FEdges. Therefore, a curve is basically a polyline made of a list of\n"
+":class:`SVertex` objects. Thus, a CurvePoint is built by linearly\n"
+"interpolating two :class:`SVertex` instances. CurvePoint can be used\n"
+"as virtual points while querying 0D information along a curve at a\n"
+"given resolution.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Defult constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A CurvePoint object.\n"
+" :type iBrother: :class:`CurvePoint`\n"
+"\n"
+".. method:: __init__(iA, iB, t2d)\n"
+"\n"
+" Builds a CurvePoint from two SVertex and an interpolation parameter.\n"
+"\n"
+" :arg iA: The first SVertex.\n"
+" :type iA: :class:`SVertex`\n"
+" :arg iB: The second SVertex.\n"
+" :type iB: :class:`SVertex`\n"
+" :arg t2d: A 2D interpolation parameter used to linearly interpolate\n"
+" iA and iB.\n"
+" :type t2d: float\n"
+"\n"
+".. method:: __init__(iA, iB, t2d)\n"
+"\n"
+" Builds a CurvePoint from two CurvePoint and an interpolation\n"
+" parameter.\n"
+"\n"
+" :arg iA: The first CurvePoint.\n"
+" :type iA: :class:`CurvePoint`\n"
+" :arg iB: The second CurvePoint.\n"
+" :type iB: :class:`CurvePoint`\n"
+" :arg t2d: The 2D interpolation parameter used to linearly\n"
+" interpolate iA and iB.\n"
+" :type t2d: float\n";
+
+static int CurvePoint___init__(BPy_CurvePoint *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3) )
+ return -1;
+
+ if( !obj1 ){
+ self->cp = new CurvePoint();
+
+ } else if( !obj2 && BPy_CurvePoint_Check(obj1) ) {
+ self->cp = new CurvePoint( *(((BPy_CurvePoint *) obj1)->cp) );
+
+ } else if( obj3 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->cp = new CurvePoint( ((BPy_SVertex *) obj1)->sv,
+ ((BPy_SVertex *) obj2)->sv,
+ PyFloat_AsDouble( obj3 ) );
+
+ } else if( obj3 && BPy_CurvePoint_Check(obj1) && BPy_CurvePoint_Check(obj2) ) {
+ CurvePoint *cp1 = ((BPy_CurvePoint *) obj1)->cp;
+ CurvePoint *cp2 = ((BPy_CurvePoint *) obj2)->cp;
+ if( !cp1 || cp1->A() == 0 || cp1->B() == 0 ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object");
+ return -1;
+ }
+ if( !cp2 || cp2->A() == 0 || cp2->B() == 0 ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid CurvePoint object");
+ return -1;
+ }
+ self->cp = new CurvePoint( cp1, cp2, PyFloat_AsDouble( obj3 ) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if0D.if0D = self->cp;
+ self->py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static char CurvePoint_A___doc__[] =
+".. method:: A()\n"
+"\n"
+" Returns the first SVertex upon which the CurvePoint is built.\n"
+"\n"
+" :return: The first SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * CurvePoint_A( BPy_CurvePoint *self ) {
+ SVertex *A = self->cp->A();
+ if( A )
+ return BPy_SVertex_from_SVertex( *A );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_B___doc__[] =
+".. method:: B()\n"
+"\n"
+" Returns the second SVertex upon which the CurvePoint is built.\n"
+"\n"
+" :return: The second SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * CurvePoint_B( BPy_CurvePoint *self ) {
+ SVertex *B = self->cp->B();
+ if( B )
+ return BPy_SVertex_from_SVertex( *B );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_t2d___doc__[] =
+".. method:: t2d()\n"
+"\n"
+" Returns the 2D interpolation parameter.\n"
+"\n"
+" :return: The 2D interpolation parameter.\n"
+" :rtype: float\n";
+
+static PyObject * CurvePoint_t2d( BPy_CurvePoint *self ) {
+ return PyFloat_FromDouble( self->cp->t2d() );
+}
+
+static char CurvePoint_setA___doc__[] =
+".. method:: setA(iA)\n"
+"\n"
+" Sets the first SVertex upon which to build the CurvePoint.\n"
+"\n"
+" :arg iA: The first SVertex.\n"
+" :type iA: :class:`SVertex`\n";
+
+static PyObject *CurvePoint_setA( BPy_CurvePoint *self , PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->cp->setA( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_setB___doc__[] =
+".. method:: setB(iB)\n"
+"\n"
+" Sets the first SVertex upon which to build the CurvePoint.\n"
+"\n"
+" :arg iB: The second SVertex.\n"
+" :type iB: :class:`SVertex`\n";
+
+static PyObject *CurvePoint_setB( BPy_CurvePoint *self , PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->cp->setB( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_setT2d___doc__[] =
+".. method:: setT2d(t)\n"
+"\n"
+" Sets the 2D interpolation parameter to use.\n"
+"\n"
+" :arg t: The 2D interpolation parameter.\n"
+" :type t: float\n";
+
+static PyObject *CurvePoint_setT2d( BPy_CurvePoint *self , PyObject *args) {
+ float t;
+
+ if(!( PyArg_ParseTuple(args, "f", &t) ))
+ return NULL;
+
+ self->cp->setT2d( t );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_curvatureFredo___doc__[] =
+".. method:: curvatureFredo()\n"
+"\n"
+" Returns the angle in radians.\n"
+"\n"
+" :return: The angle in radians.\n"
+" :rtype: float\n";
+
+static PyObject *CurvePoint_curvatureFredo( BPy_CurvePoint *self , PyObject *args) {
+ return PyFloat_FromDouble( self->cp->curvatureFredo() );
+}
+
+///bool operator== (const CurvePoint &b)
+
+/*----------------------CurvePoint instance definitions ----------------------------*/
+static PyMethodDef BPy_CurvePoint_methods[] = {
+ {"A", ( PyCFunction ) CurvePoint_A, METH_NOARGS, CurvePoint_A___doc__},
+ {"B", ( PyCFunction ) CurvePoint_B, METH_NOARGS, CurvePoint_B___doc__},
+ {"t2d", ( PyCFunction ) CurvePoint_t2d, METH_NOARGS, CurvePoint_t2d___doc__},
+ {"setA", ( PyCFunction ) CurvePoint_setA, METH_VARARGS, CurvePoint_setA___doc__},
+ {"setB", ( PyCFunction ) CurvePoint_setB, METH_VARARGS, CurvePoint_setB___doc__},
+ {"setT2d", ( PyCFunction ) CurvePoint_setT2d, METH_VARARGS, CurvePoint_setT2d___doc__},
+ {"curvatureFredo", ( PyCFunction ) CurvePoint_curvatureFredo, METH_NOARGS, CurvePoint_curvatureFredo___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_CurvePoint type definition ------------------------------*/
+PyTypeObject CurvePoint_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurvePoint", /* tp_name */
+ sizeof(BPy_CurvePoint), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurvePoint___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_CurvePoint_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurvePoint___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
new file mode 100644
index 00000000000..b4c22645503
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CURVEPOINT_H
+#define FREESTYLE_PYTHON_CURVEPOINT_H
+
+#include "../BPy_Interface0D.h"
+#include "../../stroke/Curve.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurvePoint_Type;
+
+#define BPy_CurvePoint_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurvePoint_Type) )
+
+/*---------------------------Python BPy_CurvePoint structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ CurvePoint *cp;
+} BPy_CurvePoint;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVEPOINT_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
new file mode 100644
index 00000000000..cd0131ad570
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -0,0 +1,338 @@
+#include "BPy_SVertex.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+static char SVertex___doc__[] =
+"Class hierarchy: :class:`Interface0D` > :class:`SVertex`\n"
+"\n"
+"Class to define a vertex of the embedding.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A SVertex object.\n"
+" :type iBrother: :class:`SVertex`\n"
+"\n"
+".. method:: __init__(iPoint3D, id)\n"
+"\n"
+" Builds a SVertex from 3D coordinates and an Id.\n"
+"\n"
+" :arg iPoint3D: A three-dimensional vector.\n"
+" :type iPoint3D: :class:`mathutils.Vector`\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`\n";
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static int SVertex___init__(BPy_SVertex *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_point = 0;
+ BPy_Id *py_id = 0;
+
+
+ if (! PyArg_ParseTuple(args, "|OO!", &py_point, &Id_Type, &py_id) )
+ return -1;
+
+ if( !py_point ) {
+ self->sv = new SVertex();
+
+ } else if( !py_id && BPy_SVertex_Check(py_point) ) {
+ self->sv = new SVertex( *(((BPy_SVertex *)py_point)->sv) );
+
+ } else if( py_point && py_id ) {
+ Vec3r *v = Vec3r_ptr_from_PyObject(py_point);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return -1;
+ }
+ self->sv = new SVertex( *v, *(py_id->id) );
+ delete v;
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if0D.if0D = self->sv;
+ self->py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static char SVertex_normals___doc__[] =
+".. method:: normals()\n"
+"\n"
+" Returns the normals for this Vertex as a list. In a smooth surface,\n"
+" a vertex has exactly one normal. In a sharp surface, a vertex can\n"
+" have any number of normals.\n"
+"\n"
+" :return: A list of normals.\n"
+" :rtype: List of :class:`mathutils.Vector` objects\n";
+
+static PyObject * SVertex_normals( BPy_SVertex *self ) {
+ PyObject *py_normals;
+ set< Vec3r > normals;
+
+ py_normals = PyList_New(0);
+ normals = self->sv->normals();
+
+ for( set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++ ) {
+ Vec3r v( *set_iterator );
+ PyList_Append( py_normals, Vector_from_Vec3r(v) );
+ }
+
+ return py_normals;
+}
+
+static char SVertex_normalsSize___doc__[] =
+".. method:: normalsSize()\n"
+"\n"
+" Returns the number of different normals for this vertex.\n"
+"\n"
+" :return: The number of normals.\n"
+" :rtype: int\n";
+
+static PyObject * SVertex_normalsSize( BPy_SVertex *self ) {
+ return PyLong_FromLong( self->sv->normalsSize() );
+}
+
+static char SVertex_viewvertex___doc__[] =
+".. method:: viewvertex()\n"
+"\n"
+" If this SVertex is also a ViewVertex, this method returns the\n"
+" ViewVertex. None is returned otherwise.\n"
+"\n"
+" :return: The ViewVertex object.\n"
+" :rtype: :class:`ViewVertex`\n";
+
+static PyObject * SVertex_viewvertex( BPy_SVertex *self ) {
+ ViewVertex *vv = self->sv->viewvertex();
+ if( vv )
+ return Any_BPy_ViewVertex_from_ViewVertex( *vv );
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_setPoint3D___doc__[] =
+".. method:: setPoint3D(p)\n"
+"\n"
+" Sets the 3D coordinates of the SVertex.\n"
+"\n"
+" :arg p: A three-dimensional vector.\n"
+" :type p: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject *SVertex_setPoint3D( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_point;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_point) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(py_point);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sv->setPoint3D( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_setPoint2D___doc__[] =
+".. method:: setPoint2D(p)\n"
+"\n"
+" Sets the 2D projected coordinates of the SVertex.\n"
+"\n"
+" :arg p: A three-dimensional vector.\n"
+" :type p: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject *SVertex_setPoint2D( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_point;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_point) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(py_point);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sv->setPoint2D( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_AddNormal___doc__[] =
+".. method:: AddNormal(n)\n"
+"\n"
+" Adds a normal to the SVertex's set of normals. If the same normal\n"
+" is already in the set, nothing changes.\n"
+"\n"
+" :arg n: A three-dimensional vector.\n"
+" :type n: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject *SVertex_AddNormal( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_normal;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_normal) ))
+ return NULL;
+ Vec3r *n = Vec3r_ptr_from_PyObject(py_normal);
+ if( !n ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sv->AddNormal( *n );
+ delete n;
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the identifier of the SVertex.\n"
+"\n"
+" :arg id: The identifier.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject *SVertex_setId( BPy_SVertex *self , PyObject *args) {
+ BPy_Id *py_id;
+
+ if( !PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) )
+ return NULL;
+
+ self->sv->setId( *(py_id->id) );
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_AddFEdge___doc__[] =
+".. method:: AddFEdge(fe)\n"
+"\n"
+" Add an FEdge to the list of edges emanating from this SVertex.\n"
+"\n"
+" :arg fe: An FEdge.\n"
+" :type fe: :class:`FEdge`\n";
+
+static PyObject *SVertex_AddFEdge( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->sv->AddFEdge( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_curvatures___doc__[] =
+".. method:: curvatures()\n"
+"\n"
+" Returns curvature information in the form of a seven-element tuple\n"
+" (K1, e1, K2, e2, Kr, er, dKr), where K1 and K2 are scalar values\n"
+" representing the first (maximum) and second (minimum) principal\n"
+" curvatures at this SVertex, respectively; e1 and e2 are\n"
+" three-dimensional vectors representing the first and second principal\n"
+" directions, i.e. the directions of the normal plane where the\n"
+" curvature takes its maximum and minimum values, respectively; and Kr,\n"
+" er and dKr are the radial curvature, radial direction, and the\n"
+" derivative of the radial curvature at this SVertex, repectively.\n"
+" :return: curvature information expressed by a seven-element tuple\n"
+" (K1, e1, K2, e2, Kr, er, dKr).\n"
+" :rtype: tuple\n";
+
+static PyObject *SVertex_curvatures( BPy_SVertex *self , PyObject *args) {
+ const CurvatureInfo *info = self->sv->getCurvatureInfo();
+ if (!info)
+ Py_RETURN_NONE;
+ Vec3r e1(info->e1.x(), info->e1.y(), info->e1.z());
+ Vec3r e2(info->e2.x(), info->e2.y(), info->e2.z());
+ Vec3r er(info->er.x(), info->er.y(), info->er.z());
+ PyObject *retval = PyTuple_New(7);
+ PyTuple_SetItem( retval, 0, PyFloat_FromDouble(info->K1));
+ PyTuple_SetItem( retval, 2, Vector_from_Vec3r(e1));
+ PyTuple_SetItem( retval, 1, PyFloat_FromDouble(info->K2));
+ PyTuple_SetItem( retval, 3, Vector_from_Vec3r(e2));
+ PyTuple_SetItem( retval, 4, PyFloat_FromDouble(info->Kr));
+ PyTuple_SetItem( retval, 5, Vector_from_Vec3r(er));
+ PyTuple_SetItem( retval, 6, PyFloat_FromDouble(info->dKr));
+ return retval;
+}
+
+// virtual bool operator== (const SVertex &iBrother)
+// ViewVertex * viewvertex ()
+
+/*----------------------SVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_SVertex_methods[] = {
+ {"normals", ( PyCFunction ) SVertex_normals, METH_NOARGS, SVertex_normals___doc__},
+ {"normalsSize", ( PyCFunction ) SVertex_normalsSize, METH_NOARGS, SVertex_normalsSize___doc__},
+ {"viewvertex", ( PyCFunction ) SVertex_viewvertex, METH_NOARGS, SVertex_viewvertex___doc__},
+ {"setPoint3D", ( PyCFunction ) SVertex_setPoint3D, METH_VARARGS, SVertex_setPoint3D___doc__},
+ {"setPoint2D", ( PyCFunction ) SVertex_setPoint2D, METH_VARARGS, SVertex_setPoint2D___doc__},
+ {"AddNormal", ( PyCFunction ) SVertex_AddNormal, METH_VARARGS, SVertex_AddNormal___doc__},
+ {"setId", ( PyCFunction ) SVertex_setId, METH_VARARGS, SVertex_setId___doc__},
+ {"AddFEdge", ( PyCFunction ) SVertex_AddFEdge, METH_VARARGS, SVertex_AddFEdge___doc__},
+ {"curvatures", ( PyCFunction ) SVertex_curvatures, METH_NOARGS, SVertex_curvatures___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_SVertex type definition ------------------------------*/
+PyTypeObject SVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SVertex", /* tp_name */
+ sizeof(BPy_SVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h
new file mode 100644
index 00000000000..7d310f2b7dc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h
@@ -0,0 +1,32 @@
+#ifndef FREESTYLE_PYTHON_SVERTEX_H
+#define FREESTYLE_PYTHON_SVERTEX_H
+
+#include "../../view_map/Silhouette.h"
+#include "../BPy_Interface0D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SVertex_Type;
+
+#define BPy_SVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SVertex_Type) )
+
+/*---------------------------Python BPy_SVertex structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ SVertex *sv;
+} BPy_SVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
new file mode 100644
index 00000000000..c1fe6875ea7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
@@ -0,0 +1,195 @@
+#include "BPy_ViewVertex.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewVertex___doc__[] =
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex`\n"
+"\n"
+"Class to define a view vertex. A view vertex is a feature vertex\n"
+"corresponding to a point of the image graph, where the characteristics\n"
+"of an edge (e.g., nature and visibility) might change. A\n"
+":class:`ViewVertex` can be of two kinds: A :class:`TVertex` when it\n"
+"corresponds to the intersection between two ViewEdges or a\n"
+":class:`NonTVertex` when it corresponds to a vertex of the initial\n"
+"input mesh (it is the case for vertices such as corners for example).\n"
+"Thus, this class can be specialized into two classes, the\n"
+":class:`TVertex` class and the :class:`NonTVertex` class.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A ViewVertex object.\n"
+" :type iBrother: :class:`ViewVertex`\n";
+
+static int ViewVertex___init__( BPy_ViewVertex *self, PyObject *args, PyObject *kwds )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->vv = 0; // ViewVertex is abstract
+ self->py_if0D.if0D = self->vv;
+ self->py_if0D.borrowed = 0;
+ return 0;
+}
+
+static char ViewVertex_setNature___doc__[] =
+".. method:: setNature(iNature)\n"
+"\n"
+" Sets the nature of the vertex.\n"
+"\n"
+" :arg iNature: A Nature object.\n"
+" :type iNature: :class:`Nature`\n";
+
+static PyObject * ViewVertex_setNature( BPy_ViewVertex *self, PyObject *args ) {
+ PyObject *py_n;
+
+ if( !self->vv )
+ Py_RETURN_NONE;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) ))
+ return NULL;
+
+ PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i );
+ ((ViewVertex *) self->py_if0D.if0D)->setNature( PyLong_AsLong(i) );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewVertex_edgesBegin___doc__[] =
+".. method:: edgesBegin()\n"
+"\n"
+" Returns an iterator over the ViewEdges that goes to or comes from\n"
+" this ViewVertex pointing to the first ViewEdge of the list. The\n"
+" orientedViewEdgeIterator allows to iterate in CCW order over these\n"
+" ViewEdges and to get the orientation for each ViewEdge\n"
+" (incoming/outgoing).\n"
+"\n"
+" :return: An orientedViewEdgeIterator pointing to the first ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`\n";
+
+static PyObject * ViewVertex_edgesBegin( BPy_ViewVertex *self ) {
+ if( !self->vv )
+ Py_RETURN_NONE;
+
+ ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesBegin() );
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 0 );
+}
+
+static char ViewVertex_edgesEnd___doc__[] =
+".. method:: edgesEnd()\n"
+"\n"
+" Returns an orientedViewEdgeIterator over the ViewEdges around this\n"
+" ViewVertex, pointing after the last ViewEdge.\n"
+"\n"
+" :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`\n";
+
+static PyObject * ViewVertex_edgesEnd( BPy_ViewVertex *self ) {
+#if 0
+ if( !self->vv )
+ Py_RETURN_NONE;
+
+ ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesEnd() );
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 1 );
+#else
+ PyErr_SetString(PyExc_NotImplementedError, "edgesEnd method currently disabled");
+ return NULL;
+#endif
+}
+
+static char ViewVertex_edgesIterator___doc__[] =
+".. method:: edgesIterator(iEdge)\n"
+"\n"
+" Returns an orientedViewEdgeIterator pointing to the ViewEdge given\n"
+" as argument.\n"
+"\n"
+" :arg iEdge: A ViewEdge object.\n"
+" :type iEdge: :class:`ViewEdge`\n"
+" :return: An orientedViewEdgeIterator pointing to the given ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`\n";
+
+static PyObject * ViewVertex_edgesIterator( BPy_ViewVertex *self, PyObject *args ) {
+ PyObject *py_ve;
+
+ if( !self->vv )
+ Py_RETURN_NONE;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ ViewEdge *ve = ((BPy_ViewEdge *) py_ve)->ve;
+ ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesIterator( ve ) );
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 0 );
+}
+
+/*----------------------ViewVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewVertex_methods[] = {
+ {"setNature", ( PyCFunction ) ViewVertex_setNature, METH_VARARGS, ViewVertex_setNature___doc__},
+ {"edgesBegin", ( PyCFunction ) ViewVertex_edgesBegin, METH_NOARGS, ViewVertex_edgesBegin___doc__},
+ {"edgesEnd", ( PyCFunction ) ViewVertex_edgesEnd, METH_NOARGS, ViewVertex_edgesEnd___doc__},
+ {"edgesIterator", ( PyCFunction ) ViewVertex_edgesIterator, METH_VARARGS, ViewVertex_edgesIterator___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewVertex type definition ------------------------------*/
+PyTypeObject ViewVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewVertex", /* tp_name */
+ sizeof(BPy_ViewVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
new file mode 100644
index 00000000000..26c06b50d71
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_VIEWVERTEX_H
+#define FREESTYLE_PYTHON_VIEWVERTEX_H
+
+#include "../../view_map/ViewMap.h"
+#include "../BPy_Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewVertex_Type;
+
+#define BPy_ViewVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewVertex_Type) )
+
+/*---------------------------Python BPy_ViewVertex structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ ViewVertex *vv;
+} BPy_ViewVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
new file mode 100644
index 00000000000..80b9defd95e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
@@ -0,0 +1,400 @@
+#include "BPy_StrokeVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../../BPy_StrokeAttribute.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeVertex___doc__[] =
+"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint` > :class:`StrokeVertex`\n"
+"\n"
+"Class to define a stroke vertex.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A StrokeVertex object.\n"
+" :type iBrother: :class:`StrokeVertex`\n"
+"\n"
+".. method:: __init__(iA, iB, t3)\n"
+"\n"
+" Builds a stroke vertex from 2 stroke vertices and an interpolation\n"
+" parameter.\n"
+"\n"
+" :arg iA: The first StrokeVertex.\n"
+" :type iA: :class:`StrokeVertex`\n"
+" :arg iB: The second StrokeVertex.\n"
+" :type iB: :class:`StrokeVertex`\n"
+" :arg t3: An interpolation parameter.\n"
+" :type t3: float\n"
+"\n"
+".. method:: __init__(iPoint)\n"
+"\n"
+" Builds a stroke vertex from a CurvePoint\n"
+"\n"
+" :arg iPoint: A CurvePoint object.\n"
+" :type iPoint: :class:`CurvePoint`\n"
+"\n"
+".. method:: __init__(iSVertex)\n"
+"\n"
+" Builds a stroke vertex from a SVertex\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`\n"
+"\n"
+".. method:: __init__(iSVertex, iAttribute)\n"
+"\n"
+" Builds a stroke vertex from an SVertex and a StrokeAttribute object.\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`\n"
+" :arg iAttribute: A StrokeAttribute object.\n"
+" :type iAttribute: :class:`StrokeAttribute`\n";
+
+static int StrokeVertex___init__(BPy_StrokeVertex *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3) )
+ return -1;
+
+ if( !obj1 ){
+ self->sv = new StrokeVertex();
+
+ } else if( !obj2 && BPy_StrokeVertex_Check(obj1) && ((BPy_StrokeVertex *) obj1)->sv ) {
+ self->sv = new StrokeVertex( *(((BPy_StrokeVertex *) obj1)->sv) );
+
+ } else if( !obj2 && BPy_CurvePoint_Check(obj1) && ((BPy_CurvePoint *) obj1)->cp ) {
+ self->sv = new StrokeVertex( ((BPy_CurvePoint *) obj1)->cp );
+
+ } else if( !obj2 && BPy_SVertex_Check(obj1) && ((BPy_SVertex *) obj1)->sv ) {
+ self->sv = new StrokeVertex( ((BPy_SVertex *) obj1)->sv );
+
+ } else if( obj3 && BPy_StrokeVertex_Check(obj1) && BPy_StrokeVertex_Check(obj2) ) {
+ StrokeVertex *sv1 = ((BPy_StrokeVertex *) obj1)->sv;
+ StrokeVertex *sv2 = ((BPy_StrokeVertex *) obj2)->sv;
+ if( !sv1 || ( sv1->A() == 0 && sv1->B() == 0 ) ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object");
+ return -1;
+ }
+ if( !sv2 || ( sv2->A() == 0 && sv2->B() == 0 ) ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid StrokeVertex object");
+ return -1;
+ }
+ self->sv = new StrokeVertex( sv1, sv2, PyFloat_AsDouble( obj3 ) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_cp.cp = self->sv;
+ self->py_cp.py_if0D.if0D = self->sv;
+ self->py_cp.py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static char StrokeVertex_x___doc__[] =
+".. method:: x()\n"
+"\n"
+" Returns the 2D point X coordinate.\n"
+"\n"
+" :return: The X coordinate.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_x( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->x() );
+}
+
+static char StrokeVertex_y___doc__[] =
+".. method:: y()\n"
+"\n"
+" Returns the 2D point Y coordinate.\n"
+"\n"
+" :return: The Y coordinate.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_y( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->y() );
+}
+
+static char StrokeVertex_getPoint___doc__[] =
+".. method:: getPoint()\n"
+"\n"
+" Returns the 2D point coordinates as a two-dimensional vector.\n"
+"\n"
+" :return: The 2D coordinates.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject * StrokeVertex_getPoint( BPy_StrokeVertex *self ) {
+ Vec2f v( self->sv->getPoint() );
+ return Vector_from_Vec2f( v );
+}
+
+static char StrokeVertex_attribute___doc__[] =
+".. method:: attribute()\n"
+"\n"
+" Returns the StrokeAttribute for this StrokeVertex.\n"
+"\n"
+" :return: The StrokeAttribute object.\n"
+" :rtype: :class:`StrokeAttribute`\n";
+
+static PyObject * StrokeVertex_attribute( BPy_StrokeVertex *self ) {
+ return BPy_StrokeAttribute_from_StrokeAttribute( self->sv->attribute() );
+}
+
+static char StrokeVertex_curvilinearAbscissa___doc__[] =
+".. method:: curvilinearAbscissa()\n"
+"\n"
+" Returns the curvilinear abscissa.\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_curvilinearAbscissa( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->curvilinearAbscissa() );
+}
+
+static char StrokeVertex_strokeLength___doc__[] =
+".. method:: strokeLength()\n"
+"\n"
+" Returns the length of the Stroke to which this StrokeVertex belongs\n"
+"\n"
+" :return: The stroke length.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_strokeLength( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->strokeLength() );
+}
+
+static char StrokeVertex_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the curvilinear abscissa of this StrokeVertex in the Stroke\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_u( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->u() );
+}
+
+static char StrokeVertex_setX___doc__[] =
+".. method:: setX(x)\n"
+"\n"
+" Sets the 2D point X coordinate.\n"
+"\n"
+" :arg x: The X coordinate.\n"
+" :type x: float\n";
+
+static PyObject *StrokeVertex_setX( BPy_StrokeVertex *self , PyObject *args) {
+ double r;
+
+ if(!( PyArg_ParseTuple(args, "d", &r) ))
+ return NULL;
+
+ self->sv->setX( r );
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setY___doc__[] =
+".. method:: setY(y)\n"
+"\n"
+" Sets the 2D point Y coordinate.\n"
+"\n"
+" :arg y: The Y coordinate.\n"
+" :type y: float\n";
+
+static PyObject *StrokeVertex_setY( BPy_StrokeVertex *self , PyObject *args) {
+ double r;
+
+ if(!( PyArg_ParseTuple(args, "d", &r) ))
+ return NULL;
+
+ self->sv->setY( r );
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setPoint___doc__[] =
+".. method:: setPoint(x, y)\n"
+"\n"
+" Sets the 2D point X and Y coordinates.\n"
+"\n"
+" :arg x: The X coordinate.\n"
+" :type x: float\n"
+" :arg y: The Y coordinate.\n"
+" :type y: float\n"
+"\n"
+".. method:: setPoint(p)\n"
+"\n"
+" Sets the 2D point X and Y coordinates.\n"
+"\n"
+" :arg p: A two-dimensional vector.\n"
+" :type p: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n";
+
+static PyObject *StrokeVertex_setPoint( BPy_StrokeVertex *self , PyObject *args) {
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if(!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) ))
+ return NULL;
+
+ if( obj1 && !obj2 ){
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ self->sv->setPoint( *v );
+ delete v;
+ } else if( PyFloat_Check(obj1) && obj2 && PyFloat_Check(obj2) ){
+ self->sv->setPoint( PyFloat_AsDouble(obj1), PyFloat_AsDouble(obj2) );
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid arguments");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setAttribute___doc__[] =
+".. method:: setAttribute(iAttribute)\n"
+"\n"
+" Sets the attribute.\n"
+"\n"
+" :arg iAttribute: A StrokeAttribute object.\n"
+" :type iAttribute: :class:`StrokeAttribute`\n";
+
+static PyObject *StrokeVertex_setAttribute( BPy_StrokeVertex *self , PyObject *args) {
+ PyObject *py_sa;
+
+ if(!( PyArg_ParseTuple(args, "O!", &StrokeAttribute_Type, &py_sa) ))
+ return NULL;
+
+ self->sv->setAttribute(*( ((BPy_StrokeAttribute *) py_sa)->sa ));
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setCurvilinearAbscissa___doc__[] =
+".. method:: setCurvilinearAbscissa(iAbscissa)\n"
+"\n"
+" Sets the curvilinear abscissa of this StrokeVertex in the Stroke\n"
+"\n"
+" :arg iAbscissa: The curvilinear abscissa.\n"
+" :type iAbscissa: float\n";
+
+static PyObject *StrokeVertex_setCurvilinearAbscissa( BPy_StrokeVertex *self , PyObject *args) {
+ double r;
+
+ if(!( PyArg_ParseTuple(args, "d", &r) ))
+ return NULL;
+
+ self->sv->setCurvilinearAbscissa( r );
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setStrokeLength___doc__[] =
+".. method:: setStrokeLength(iLength)\n"
+"\n"
+" Sets the stroke length (it is only a value retained by the\n"
+" StrokeVertex, and it won't change the real stroke length).\n"
+"\n"
+" :arg iLength: The stroke length.\n"
+" :type iLength: float\n";
+
+static PyObject *StrokeVertex_setStrokeLength( BPy_StrokeVertex *self , PyObject *args) {
+ double r;
+
+ if(!( PyArg_ParseTuple(args, "d", &r) ))
+ return NULL;
+
+ self->sv->setStrokeLength( r );
+
+ Py_RETURN_NONE;
+}
+
+// real operator[] (const int i) const
+// real & operator[] (const int i)
+
+/*----------------------StrokeVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeVertex_methods[] = {
+ {"x", ( PyCFunction ) StrokeVertex_x, METH_NOARGS, StrokeVertex_x___doc__},
+ {"y", ( PyCFunction ) StrokeVertex_y, METH_NOARGS, StrokeVertex_y___doc__},
+ {"getPoint", ( PyCFunction ) StrokeVertex_getPoint, METH_NOARGS, StrokeVertex_getPoint___doc__},
+ {"attribute", ( PyCFunction ) StrokeVertex_attribute, METH_NOARGS, StrokeVertex_attribute___doc__},
+ {"curvilinearAbscissa", ( PyCFunction ) StrokeVertex_curvilinearAbscissa, METH_NOARGS, StrokeVertex_curvilinearAbscissa___doc__},
+ {"strokeLength", ( PyCFunction ) StrokeVertex_strokeLength, METH_NOARGS, StrokeVertex_strokeLength___doc__},
+ {"u", ( PyCFunction ) StrokeVertex_u, METH_NOARGS, StrokeVertex_u___doc__},
+ {"setX", ( PyCFunction ) StrokeVertex_setX, METH_VARARGS, StrokeVertex_setX___doc__},
+ {"setY", ( PyCFunction ) StrokeVertex_setY, METH_VARARGS, StrokeVertex_setY___doc__},
+ {"setPoint", ( PyCFunction ) StrokeVertex_setPoint, METH_VARARGS, StrokeVertex_setPoint___doc__},
+ {"setAttribute", ( PyCFunction ) StrokeVertex_setAttribute, METH_VARARGS, StrokeVertex_setAttribute___doc__},
+ {"setCurvilinearAbscissa", ( PyCFunction ) StrokeVertex_setCurvilinearAbscissa, METH_VARARGS, StrokeVertex_setCurvilinearAbscissa___doc__},
+ {"setStrokeLength", ( PyCFunction ) StrokeVertex_setStrokeLength, METH_VARARGS, StrokeVertex_setStrokeLength___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_StrokeVertex type definition ------------------------------*/
+PyTypeObject StrokeVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeVertex", /* tp_name */
+ sizeof(BPy_StrokeVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &CurvePoint_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h
new file mode 100644
index 00000000000..2a84e2480f0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_STROKEVERTEX_H
+#define FREESTYLE_PYTHON_STROKEVERTEX_H
+
+#include "../BPy_CurvePoint.h"
+#include "../../../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeVertex_Type;
+
+#define BPy_StrokeVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeVertex_Type) )
+
+/*---------------------------Python BPy_StrokeVertex structure definition----------*/
+typedef struct {
+ BPy_CurvePoint py_cp;
+ StrokeVertex *sv;
+} BPy_StrokeVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKEVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
new file mode 100644
index 00000000000..ebb2920353d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
@@ -0,0 +1,153 @@
+#include "BPy_NonTVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char NonTVertex___doc__[] =
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n"
+"\n"
+"View vertex for corners, cusps, etc. associated to a single SVertex.\n"
+"Can be associated to 2 or more view edges.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A NonTVertex object.\n"
+" :type iBrother: :class:`NonTVertex`\n"
+"\n"
+".. method:: __init__(iSVertex)\n"
+"\n"
+" Builds a NonTVertex from a SVertex.\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`\n";
+
+static int NonTVertex___init__(BPy_NonTVertex *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O!", &SVertex_Type, &obj) )
+ return -1;
+
+ if( !obj ){
+ self->ntv = new NonTVertex();
+
+ } else if( ((BPy_SVertex *) obj)->sv ) {
+ self->ntv = new NonTVertex( ((BPy_SVertex *) obj)->sv );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_vv.vv = self->ntv;
+ self->py_vv.py_if0D.if0D = self->ntv;
+ self->py_vv.py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static char NonTVertex_svertex___doc__[] =
+".. method:: svertex()\n"
+"\n"
+" Returns the SVertex on top of which this NonTVertex is built.\n"
+"\n"
+" :return: The SVertex on top of which this NonTVertex is built.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * NonTVertex_svertex( BPy_NonTVertex *self ) {
+ SVertex *v = self->ntv->svertex();
+ if( v ){
+ return BPy_SVertex_from_SVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char NonTVertex_setSVertex___doc__[] =
+".. method:: setSVertex(iSVertex)\n"
+"\n"
+" Sets the SVertex on top of which this NonTVertex is built.\n"
+"\n"
+" :arg iSVertex: The SVertex on top of which this NonTVertex is built.\n"
+" :type iSVertex: :class:`SVertex`\n";
+
+static PyObject * NonTVertex_setSVertex( BPy_NonTVertex *self, PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->ntv->setSVertex( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------NonTVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_NonTVertex_methods[] = {
+ {"svertex", ( PyCFunction ) NonTVertex_svertex, METH_NOARGS, NonTVertex_svertex___doc__},
+ {"setSVertex", ( PyCFunction ) NonTVertex_setSVertex, METH_VARARGS, NonTVertex_setSVertex___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_NonTVertex type definition ------------------------------*/
+PyTypeObject NonTVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "NonTVertex", /* tp_name */
+ sizeof(BPy_NonTVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ NonTVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_NonTVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ViewVertex_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)NonTVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
new file mode 100644
index 00000000000..071194d2d42
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_NONTVERTEX_H
+#define FREESTYLE_PYTHON_NONTVERTEX_H
+
+#include "../BPy_ViewVertex.h"
+#include "../../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject NonTVertex_Type;
+
+#define BPy_NonTVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &NonTVertex_Type) )
+
+/*---------------------------Python BPy_NonTVertex structure definition----------*/
+typedef struct {
+ BPy_ViewVertex py_vv;
+ NonTVertex *ntv;
+} BPy_NonTVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NONTVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
new file mode 100644
index 00000000000..14add743a37
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
@@ -0,0 +1,249 @@
+#include "BPy_TVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../BPy_SVertex.h"
+#include "../../BPy_Id.h"
+#include "../../Interface1D/BPy_FEdge.h"
+#include "../../Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TVertex___doc__[] =
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`TVertex`\n"
+"\n"
+"Class to define a T vertex, i.e. an intersection between two edges.\n"
+"It points towards two SVertex and four ViewEdges. Among the\n"
+"ViewEdges, two are front and the other two are back. Basically a\n"
+"front edge hides part of a back edge. So, among the back edges, one\n"
+"is of invisibility N and the other of invisibility N+1.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A TVertex object.\n"
+" :type iBrother: :class:`TVertex`\n";
+
+static int TVertex___init__(BPy_TVertex *self, PyObject *args, PyObject *kwds)
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->tv = new TVertex();
+ self->py_vv.vv = self->tv;
+ self->py_vv.py_if0D.if0D = self->tv;
+ self->py_vv.py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static char TVertex_frontSVertex___doc__[] =
+".. method:: frontSVertex()\n"
+"\n"
+" Returns the SVertex that is closer to the viewpoint.\n"
+"\n"
+" :return: The SVertex that is closer to the viewpoint.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * TVertex_frontSVertex( BPy_TVertex *self ) {
+ SVertex *v = self->tv->frontSVertex();
+ if( v ){
+ return BPy_SVertex_from_SVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_backSVertex___doc__[] =
+".. method:: backSVertex()\n"
+"\n"
+" Returns the SVertex that is further away from the viewpoint.\n"
+"\n"
+" :return: The SVertex that is further away from the viewpoint.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * TVertex_backSVertex( BPy_TVertex *self ) {
+ SVertex *v = self->tv->backSVertex();
+ if( v ){
+ return BPy_SVertex_from_SVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_setFrontSVertex___doc__[] =
+".. method:: setFrontSVertex(iFrontSVertex)\n"
+"\n"
+" Sets the SVertex that is closer to the viewpoint.\n"
+"\n"
+" :arg iFrontSVertex: An SVertex object.\n"
+" :type iFrontSVertex: :class:`SVertex`\n";
+
+static PyObject * TVertex_setFrontSVertex( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->tv->setFrontSVertex( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_setBackSVertex___doc__[] =
+".. method:: setBackSVertex(iBackSVertex)\n"
+"\n"
+" Sets the SVertex that is further away from the viewpoint.\n"
+"\n"
+" :arg iBackSVertex: An SVertex object.\n"
+" :type iBackSVertex: :class:`SVertex`\n";
+
+static PyObject * TVertex_setBackSVertex( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->tv->setBackSVertex( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_setId___doc__[] =
+".. method:: setId(iId)\n"
+"\n"
+" Sets the Id.\n"
+"\n"
+" :arg iId: An Id object.\n"
+" :type iId: :class:`Id`\n";
+
+static PyObject * TVertex_setId( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ if( ((BPy_Id *) py_id)->id )
+ self->tv->setId(*( ((BPy_Id *) py_id)->id ));
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_getSVertex___doc__[] =
+".. method:: getSVertex(iFEdge)\n"
+"\n"
+" Returns the SVertex (among the 2) belonging to the given FEdge.\n"
+"\n"
+" :arg iFEdge: An FEdge object.\n"
+" :type iFEdge: :class:`FEdge`\n"
+" :return: The SVertex belonging to the given FEdge.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * TVertex_getSVertex( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ SVertex *sv = self->tv->getSVertex( ((BPy_FEdge *) py_fe)->fe );
+ if( sv ){
+ return BPy_SVertex_from_SVertex( *sv );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_mate___doc__[] =
+".. method:: mate(iEdgeA)\n"
+"\n"
+" Returns the mate edge of the ViewEdge given as argument. If the\n"
+" ViewEdge is frontEdgeA, frontEdgeB is returned. If the ViewEdge is\n"
+" frontEdgeB, frontEdgeA is returned. Same for back edges.\n"
+"\n"
+" :arg iEdgeA: A ViewEdge object.\n"
+" :type iEdgeA: :class:`ViewEdge`\n"
+" :return: The mate edge of the given ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * TVertex_mate( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_ve;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ ViewEdge *ve = self->tv->mate( ((BPy_ViewEdge *) py_ve)->ve );
+ if( ve ){
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+ }
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------TVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_TVertex_methods[] = {
+ {"frontSVertex", ( PyCFunction ) TVertex_frontSVertex, METH_NOARGS, TVertex_frontSVertex___doc__},
+ {"backSVertex", ( PyCFunction ) TVertex_backSVertex, METH_NOARGS, TVertex_backSVertex___doc__},
+ {"setFrontSVertex", ( PyCFunction ) TVertex_setFrontSVertex, METH_VARARGS, TVertex_setFrontSVertex___doc__},
+ {"setBackSVertex", ( PyCFunction ) TVertex_setBackSVertex, METH_VARARGS, TVertex_setBackSVertex___doc__},
+ {"setId", ( PyCFunction ) TVertex_setId, METH_VARARGS, TVertex_setId___doc__},
+ {"getSVertex", ( PyCFunction ) TVertex_getSVertex, METH_VARARGS, TVertex_getSVertex___doc__},
+ {"mate", ( PyCFunction ) TVertex_mate, METH_VARARGS, TVertex_mate___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_TVertex type definition ------------------------------*/
+PyTypeObject TVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TVertex", /* tp_name */
+ sizeof(BPy_TVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_TVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ViewVertex_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
new file mode 100644
index 00000000000..12fe5c0cb43
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_TVERTEX_H
+#define FREESTYLE_PYTHON_TVERTEX_H
+
+#include "../BPy_ViewVertex.h"
+#include "../../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TVertex_Type;
+
+#define BPy_TVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TVertex_Type) )
+
+/*---------------------------Python BPy_TVertex structure definition----------*/
+typedef struct {
+ BPy_ViewVertex py_vv;
+ TVertex *tv;
+} BPy_TVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
new file mode 100644
index 00000000000..a7b710f796b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
@@ -0,0 +1,416 @@
+#include "BPy_FEdge.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FEdge___doc__[] =
+"Class hierarchy: :class:`Interface1D` > :class:`FEdge`\n"
+"\n"
+"Base Class for feature edges. This FEdge can represent a silhouette,\n"
+"a crease, a ridge/valley, a border or a suggestive contour. For\n"
+"silhouettes, the FEdge is oriented so that the visible face lies on\n"
+"the left of the edge. For borders, the FEdge is oriented so that the\n"
+"face lies on the left of the edge. An FEdge can represent an initial\n"
+"edge of the mesh or runs accross a face of the initial mesh depending\n"
+"on the smoothness or sharpness of the mesh. This class is specialized\n"
+"into a smooth and a sharp version since their properties slightly vary\n"
+"from one to the other.\n"
+"\n"
+".. method:: FEdge()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: FEdge(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An FEdge object.\n"
+" :type iBrother: :class:`FEdge`\n"
+"\n"
+".. method:: FEdge(vA, vB)\n"
+"\n"
+" Builds an FEdge going from vA to vB.\n"
+"\n"
+" :arg vA: The first SVertex.\n"
+" :type vA: :class:`SVertex`\n"
+" :arg vB: The second SVertex.\n"
+" :type vB: :class:`SVertex`\n";
+
+static int FEdge___init__(BPy_FEdge *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) )
+ return -1;
+
+ if( !obj1 ){
+ self->fe = new FEdge();
+
+ } else if( !obj2 && BPy_FEdge_Check(obj1) ) {
+ self->fe = new FEdge(*( ((BPy_FEdge *) obj1)->fe ));
+
+ } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->fe = new FEdge( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if1D.if1D = self->fe;
+ self->py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char FEdge_vertexA___doc__[] =
+".. method:: vertexA()\n"
+"\n"
+" Returns the first SVertex.\n"
+"\n"
+" :return: The first SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * FEdge_vertexA( BPy_FEdge *self ) {
+ SVertex *A = self->fe->vertexA();
+ if( A ){
+ return BPy_SVertex_from_SVertex( *A );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_vertexB___doc__[] =
+".. method:: vertexB()\n"
+"\n"
+" Returns the second SVertex.\n"
+"\n"
+" :return: The second SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * FEdge_vertexB( BPy_FEdge *self ) {
+ SVertex *B = self->fe->vertexB();
+ if( B ){
+ return BPy_SVertex_from_SVertex( *B );
+ }
+
+ Py_RETURN_NONE;
+}
+
+
+static PyObject * FEdge___getitem__( BPy_FEdge *self, PyObject *args ) {
+ int i;
+
+ if(!( PyArg_ParseTuple(args, "i", &i) ))
+ return NULL;
+ if(!(i == 0 || i == 1)) {
+ PyErr_SetString(PyExc_IndexError, "index must be either 0 or 1");
+ return NULL;
+ }
+
+ SVertex *v = self->fe->operator[](i);
+ if( v )
+ return BPy_SVertex_from_SVertex( *v );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_nextEdge___doc__[] =
+".. method:: nextEdge()\n"
+"\n"
+" Returns the FEdge following this one in the ViewEdge. If this FEdge\n"
+" is the last of the ViewEdge, None is returned.\n"
+"\n"
+" :return: The edge following this one in the ViewEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * FEdge_nextEdge( BPy_FEdge *self ) {
+ FEdge *fe = self->fe->nextEdge();
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge( *fe );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_previousEdge___doc__[] =
+".. method:: previousEdge()\n"
+"\n"
+" Returns the FEdge preceding this one in the ViewEdge. If this FEdge\n"
+" is the first one of the ViewEdge, None is returned.\n"
+"\n"
+" :return: The edge preceding this one in the ViewEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * FEdge_previousEdge( BPy_FEdge *self ) {
+ FEdge *fe = self->fe->previousEdge();
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge( *fe );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_viewedge___doc__[] =
+".. method:: viewedge()\n"
+"\n"
+" Returns the ViewEdge to which this FEdge belongs to.\n"
+"\n"
+" :return: The ViewEdge to which this FEdge belongs to.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * FEdge_viewedge( BPy_FEdge *self ) {
+ ViewEdge *ve = self->fe->viewedge();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_isSmooth___doc__[] =
+".. method:: isSmooth()\n"
+"\n"
+" Returns true if this FEdge is a smooth FEdge.\n"
+"\n"
+" :return: True if this FEdge is a smooth FEdge.\n"
+" :rtype: bool\n";
+
+static PyObject * FEdge_isSmooth( BPy_FEdge *self ) {
+ return PyBool_from_bool( self->fe->isSmooth() );
+}
+
+static char FEdge_setVertexA___doc__[] =
+".. method:: setVertexA(vA)\n"
+"\n"
+" Sets the first SVertex.\n"
+"\n"
+" :arg vA: An SVertex object.\n"
+" :type vA: :class:`SVertex`\n";
+
+static PyObject *FEdge_setVertexA( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->fe->setVertexA( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setVertexB___doc__[] =
+".. method:: setVertexB(vB)\n"
+"\n"
+" Sets the second SVertex.\n"
+"\n"
+" :arg vB: An SVertex object.\n"
+" :type vB: :class:`SVertex`\n";
+
+static PyObject *FEdge_setVertexB( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_sv) && BPy_SVertex_Check(py_sv) )) {
+ cout << "ERROR: FEdge_setVertexB" << endl;
+ Py_RETURN_NONE;
+ }
+
+ self->fe->setVertexB( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the Id of this FEdge.\n"
+"\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject *FEdge_setId( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ self->fe->setId(*( ((BPy_Id *) py_id)->id ));
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setNextEdge___doc__[] =
+".. method:: setNextEdge(iEdge)\n"
+"\n"
+" Sets the pointer to the next FEdge.\n"
+"\n"
+" :arg iEdge: An FEdge object.\n"
+" :type iEdge: :class:`FEdge`\n";
+
+static PyObject *FEdge_setNextEdge( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->fe->setNextEdge( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setPreviousEdge___doc__[] =
+".. method:: setPreviousEdge(iEdge)\n"
+"\n"
+" Sets the pointer to the previous FEdge.\n"
+"\n"
+" :arg iEdge: An FEdge object.\n"
+" :type iEdge: :class:`FEdge`\n";
+
+static PyObject *FEdge_setPreviousEdge( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->fe->setPreviousEdge( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setNature___doc__[] =
+".. method:: setNature(iNature)\n"
+"\n"
+" Sets the nature of this FEdge.\n"
+"\n"
+" :arg iNature: A Nature object.\n"
+" :type iNature: :class:`Nature`\n";
+
+static PyObject * FEdge_setNature( BPy_FEdge *self, PyObject *args ) {
+ PyObject *py_n;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) ))
+ return NULL;
+
+ PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i );
+ self->fe->setNature( PyLong_AsLong(i) );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setViewEdge___doc__[] =
+".. method:: setViewEdge(iViewEdge)\n"
+"\n"
+" Sets the ViewEdge to which this FEdge belongs to.\n"
+"\n"
+" :arg iViewEdge: A ViewEdge object.\n"
+" :type iViewEdge: :class:`ViewEdge`\n";
+
+static PyObject * FEdge_setViewEdge( BPy_FEdge *self, PyObject *args ) {
+ PyObject *py_ve;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ ViewEdge *ve = ((BPy_ViewEdge *) py_ve)->ve;
+ self->fe->setViewEdge( ve );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setSmooth___doc__[] =
+".. method:: setSmooth(iFlag)\n"
+"\n"
+" Sets the flag telling whether this FEdge is smooth or sharp. True\n"
+" for Smooth, false for Sharp.\n"
+"\n"
+" :arg iFlag: True for Smooth, false for Sharp.\n"
+" :type iFlag: bool\n";
+
+static PyObject *FEdge_setSmooth( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_b;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_b) ))
+ return NULL;
+
+ self->fe->setSmooth( bool_from_PyBool(py_b) );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------FEdge instance definitions ----------------------------*/
+
+static PyMethodDef BPy_FEdge_methods[] = {
+ {"vertexA", ( PyCFunction ) FEdge_vertexA, METH_NOARGS, FEdge_vertexA___doc__},
+ {"vertexB", ( PyCFunction ) FEdge_vertexB, METH_NOARGS, FEdge_vertexB___doc__},
+ {"__getitem__", ( PyCFunction ) FEdge___getitem__, METH_VARARGS, "(int i) Returns the first SVertex if i=0, the seccond SVertex if i=1."},
+ {"nextEdge", ( PyCFunction ) FEdge_nextEdge, METH_NOARGS, FEdge_nextEdge___doc__},
+ {"previousEdge", ( PyCFunction ) FEdge_previousEdge, METH_NOARGS, FEdge_previousEdge___doc__},
+ {"viewedge", ( PyCFunction ) FEdge_viewedge, METH_NOARGS, FEdge_viewedge___doc__},
+ {"isSmooth", ( PyCFunction ) FEdge_isSmooth, METH_NOARGS, FEdge_isSmooth___doc__},
+ {"setVertexA", ( PyCFunction ) FEdge_setVertexA, METH_VARARGS, FEdge_setVertexA___doc__},
+ {"setVertexB", ( PyCFunction ) FEdge_setVertexB, METH_VARARGS, FEdge_setVertexB___doc__},
+ {"setId", ( PyCFunction ) FEdge_setId, METH_VARARGS, FEdge_setId___doc__},
+ {"setNextEdge", ( PyCFunction ) FEdge_setNextEdge, METH_VARARGS, FEdge_setNextEdge___doc__},
+ {"setPreviousEdge", ( PyCFunction ) FEdge_setPreviousEdge, METH_VARARGS, FEdge_setPreviousEdge___doc__},
+ {"setSmooth", ( PyCFunction ) FEdge_setSmooth, METH_VARARGS, FEdge_setSmooth___doc__},
+ {"setViewEdge", ( PyCFunction ) FEdge_setViewEdge, METH_VARARGS, FEdge_setViewEdge___doc__},
+ {"setNature", ( PyCFunction ) FEdge_setNature, METH_VARARGS, FEdge_setNature___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FEdge type definition ------------------------------*/
+
+PyTypeObject FEdge_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdge", /* tp_name */
+ sizeof(BPy_FEdge), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FEdge___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FEdge_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdge___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h
new file mode 100644
index 00000000000..9d13145aaf2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FEDGE_H
+#define FREESTYLE_PYTHON_FEDGE_H
+
+#include "../BPy_Interface1D.h"
+#include "../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdge_Type;
+
+#define BPy_FEdge_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdge_Type) )
+
+/*---------------------------Python BPy_FEdge structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ FEdge *fe;
+} BPy_FEdge;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FEDGE_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
new file mode 100644
index 00000000000..5b20db3a267
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
@@ -0,0 +1,202 @@
+#include "BPy_FrsCurve.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_CurvePoint.h"
+#include "../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FrsCurve___doc__[] =
+"Class hierarchy: :class:`Interface1D` > :class:`Curve`\n"
+"\n"
+"Base class for curves made of CurvePoints. :class:`SVertex` is the\n"
+"type of the initial curve vertices. A :class:`Chain` is a\n"
+"specialization of a Curve.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default Constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy Constructor.\n"
+"\n"
+" :arg iBrother: A Curve object.\n"
+" :type iBrother: :class:`Curve`\n"
+"\n"
+".. method:: __init__(iId)\n"
+"\n"
+" Builds a Curve from its Id.\n"
+"\n"
+" :arg iId: An Id object.\n"
+" :type iId: :class:`Id`\n";
+
+static int FrsCurve___init__(BPy_FrsCurve *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ){
+ self->c = new Curve();
+
+ } else if( BPy_FrsCurve_Check(obj) ) {
+ self->c = new Curve(*( ((BPy_FrsCurve *) obj)->c ));
+
+ } else if( BPy_Id_Check(obj) ) {
+ self->c = new Curve(*( ((BPy_Id *) obj)->id ));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_if1D.if1D = self->c;
+ self->py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char FrsCurve_push_vertex_back___doc__[] =
+".. method:: push_vertex_back(iVertex)\n"
+"\n"
+" Adds a single vertex at the end of the Curve.\n"
+"\n"
+" :arg iVertex: A vertex object.\n"
+" :type iVertex: :class:`SVertex` or :class:`CurvePoint`\n";
+
+static PyObject * FrsCurve_push_vertex_back( BPy_FrsCurve *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ if( BPy_CurvePoint_Check(obj) ) {
+ self->c->push_vertex_back( ((BPy_CurvePoint *) obj)->cp );
+ } else if( BPy_SVertex_Check(obj) ) {
+ self->c->push_vertex_back( ((BPy_SVertex *) obj)->sv );
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char FrsCurve_push_vertex_front___doc__[] =
+".. method:: push_vertex_front(iVertex)\n"
+"\n"
+" Adds a single vertex at the front of the Curve.\n"
+"\n"
+" :arg iVertex: A vertex object.\n"
+" :type iVertex: :class:`SVertex` or :class:`CurvePoint`\n";
+
+static PyObject * FrsCurve_push_vertex_front( BPy_FrsCurve *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ if( BPy_CurvePoint_Check(obj) ) {
+ self->c->push_vertex_front( ((BPy_CurvePoint *) obj)->cp );
+ } else if( BPy_SVertex_Check(obj) ) {
+ self->c->push_vertex_front( ((BPy_SVertex *) obj)->sv );
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char FrsCurve_empty___doc__[] =
+".. method:: empty()\n"
+"\n"
+" Returns true if the Curve doesn't have any Vertex yet.\n"
+"\n"
+" :return: True if the Curve has no vertices.\n"
+" :rtype: bool\n";
+
+static PyObject * FrsCurve_empty( BPy_FrsCurve *self ) {
+ return PyBool_from_bool( self->c->empty() );
+}
+
+static char FrsCurve_nSegments___doc__[] =
+".. method:: nSegments()\n"
+"\n"
+" Returns the number of segments in the polyline constituing the\n"
+" Curve.\n"
+"\n"
+" :return: The number of segments.\n"
+" :rtype: int\n";
+
+static PyObject * FrsCurve_nSegments( BPy_FrsCurve *self ) {
+ return PyLong_FromLong( self->c->nSegments() );
+}
+
+/*----------------------FrsCurve instance definitions ----------------------------*/
+static PyMethodDef BPy_FrsCurve_methods[] = {
+ {"push_vertex_back", ( PyCFunction ) FrsCurve_push_vertex_back, METH_VARARGS, FrsCurve_push_vertex_back___doc__},
+ {"push_vertex_front", ( PyCFunction ) FrsCurve_push_vertex_front, METH_VARARGS, FrsCurve_push_vertex_front___doc__},
+ {"empty", ( PyCFunction ) FrsCurve_empty, METH_NOARGS, FrsCurve_empty___doc__},
+ {"nSegments", ( PyCFunction ) FrsCurve_nSegments, METH_NOARGS, FrsCurve_nSegments___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FrsCurve type definition ------------------------------*/
+
+PyTypeObject FrsCurve_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Curve", /* tp_name */
+ sizeof(BPy_FrsCurve), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FrsCurve___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FrsCurve_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsCurve___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h
new file mode 100644
index 00000000000..0829cf0ebf5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FRSCURVE_H
+#define FREESTYLE_PYTHON_FRSCURVE_H
+
+#include "../BPy_Interface1D.h"
+#include "../../stroke/Curve.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FrsCurve_Type;
+
+#define BPy_FrsCurve_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsCurve_Type) )
+
+/*---------------------------Python BPy_FrsCurve structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ Curve *c;
+} BPy_FrsCurve;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FRSCURVE_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
new file mode 100644
index 00000000000..fe215588275
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -0,0 +1,517 @@
+#include "BPy_Stroke.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "../Iterator/BPy_StrokeVertexIterator.h"
+#include "../BPy_MediumType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+// Stroke ()
+// template<class InputVertexIterator> Stroke (InputVertexIterator iBegin, InputVertexIterator iEnd)
+//
+// pb: - need to be able to switch representation: InputVertexIterator <=> position
+// - is it even used ? not even in SWIG version
+
+static char Stroke___doc__[] =
+"Class hierarchy: :class:`Interface1D` > :class:`Stroke`\n"
+"\n"
+"Class to define a stroke. A stroke is made of a set of 2D vertices\n"
+"(:class:`StrokeVertex`), regularly spaced out. This set of vertices\n"
+"defines the stroke's backbone geometry. Each of these stroke vertices\n"
+"defines the stroke's shape and appearance at this vertex position.\n"
+"\n"
+".. method:: Stroke()\n"
+"\n"
+" Default constructor\n"
+"\n"
+".. method:: Stroke(iBrother)\n"
+"\n"
+" Copy constructor\n"
+"\n"
+" :arg iBrother: \n"
+" :type iBrother: :class:`Stroke`\n"
+"\n"
+".. method:: Stroke(iBegin, iEnd)\n"
+"\n"
+" Builds a stroke from a set of StrokeVertex. This constructor is\n"
+" templated by an iterator type. This iterator type must allow the\n"
+" vertices parsing using the ++ operator.\n"
+"\n"
+" :arg iBegin: The iterator pointing to the first vertex.\n"
+" :type iBegin: InputVertexIterator\n"
+" :arg iEnd: The iterator pointing to the end of the vertex list.\n"
+" :type iEnd: InputVertexIterator\n";
+
+static int Stroke___init__(BPy_Stroke *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = NULL, *obj2 = NULL;
+
+ if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) )
+ return -1;
+
+ if( !obj1 ){
+ self->s = new Stroke();
+
+ } else if ( !obj2 && BPy_Stroke_Check(obj1) ) {
+ self->s = new Stroke(*( ((BPy_Stroke *)obj1)->s ));
+
+ } else if ( obj2 ) {
+ PyErr_SetString(PyExc_TypeError,
+ "Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd) not implemented");
+ return -1;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if1D.if1D = self->s;
+ self->py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static PyObject * Stroke___iter__( PyObject *self ) {
+ StrokeInternal::StrokeVertexIterator sv_it( ((BPy_Stroke *)self)->s->strokeVerticesBegin() );
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 0 );
+}
+
+static Py_ssize_t Stroke_length( BPy_Stroke *self ) {
+ return self->s->strokeVerticesSize();
+}
+
+static PyObject * Stroke_item( BPy_Stroke *self, Py_ssize_t i ) {
+ if (i < 0 || i >= (Py_ssize_t)self->s->strokeVerticesSize()) {
+ PyErr_SetString(PyExc_IndexError, "subscript index out of range");
+ return NULL;
+ }
+ return BPy_StrokeVertex_from_StrokeVertex( self->s->strokeVerticeAt(i) );
+}
+
+static PyObject * Stroke___getitem__( BPy_Stroke *self, PyObject *item ) {
+ long i;
+
+ if (!PyLong_Check(item)) {
+ PyErr_SetString(PyExc_TypeError, "subscript indices must be integers");
+ return NULL;
+ }
+ i = PyLong_AsLong(item);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ if (i < 0) {
+ i += self->s->strokeVerticesSize();
+ }
+ return Stroke_item(self, i);
+}
+
+static char Stroke_ComputeSampling___doc__[] =
+".. method:: ComputeSampling(iNVertices)\n"
+"\n"
+" Compute the sampling needed to get iNVertices vertices. If the\n"
+" specified number of vertices is less than the actual number of\n"
+" vertices, the actual sampling value is returned. (To remove Vertices,\n"
+" use the RemoveVertex() method of this class.)\n"
+"\n"
+" :arg iNVertices: The number of stroke vertices we eventually want\n"
+" in our Stroke.\n"
+" :type iNVertices: int\n"
+" :return: The sampling that must be used in the Resample(float)\n"
+" method.\n"
+" :rtype: float\n";
+
+static PyObject * Stroke_ComputeSampling( BPy_Stroke *self, PyObject *args ) {
+ int i;
+
+ if(!( PyArg_ParseTuple(args, "i", &i) ))
+ return NULL;
+
+ return PyFloat_FromDouble( self->s->ComputeSampling( i ) );
+}
+
+static char Stroke_Resample___doc__[] =
+".. method:: Resample(iNPoints)\n"
+"\n"
+" Resamples the stroke so that it eventually has iNPoints. That means\n"
+" it is going to add iNPoints-vertices_size, if vertices_size is the\n"
+" number of points we already have. If vertices_size >= iNPoints, no\n"
+" resampling is done.\n"
+"\n"
+" :arg iNPoints: The number of vertices we eventually want in our stroke.\n"
+" :type iNPoints: int\n"
+"\n"
+".. method:: Resample(iSampling)\n"
+"\n"
+" Resamples the stroke with a given sampling. If the sampling is\n"
+" smaller than the actual sampling value, no resampling is done.\n"
+"\n"
+" :arg iSampling: The new sampling value.\n"
+" :type iSampling: float\n";
+
+static PyObject * Stroke_Resample( BPy_Stroke *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ if( PyLong_Check(obj) )
+ self->s->Resample( (int) PyLong_AsLong(obj) );
+ else if( PyFloat_Check(obj) )
+ self->s->Resample( (float) PyFloat_AsDouble(obj) );
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_InsertVertex___doc__[] =
+".. method:: InsertVertex(iVertex, next)\n"
+"\n"
+" Inserts the stroke vertex iVertex in the stroke before next. The\n"
+" length, curvilinear abscissa are updated consequently.\n"
+"\n"
+" :arg iVertex: The StrokeVertex to insert in the Stroke.\n"
+" :type iVertex: :class:`StrokeVertex`\n"
+" :arg next: A StrokeVertexIterator pointing to the StrokeVertex\n"
+" before which iVertex must be inserted.\n"
+" :type next: :class:`StrokeVertexIterator`\n";
+
+static PyObject * Stroke_InsertVertex( BPy_Stroke *self, PyObject *args ) {
+ PyObject *py_sv = 0, *py_sv_it = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!O!", &StrokeVertex_Type, &py_sv, &StrokeVertexIterator_Type, &py_sv_it) ))
+ return NULL;
+
+ StrokeVertex *sv = ((BPy_StrokeVertex *) py_sv)->sv;
+ StrokeInternal::StrokeVertexIterator sv_it(*( ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it ));
+ self->s->InsertVertex( sv, sv_it );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_RemoveVertex___doc__[] =
+".. method:: RemoveVertex(iVertex)\n"
+"\n"
+" Removes the stroke vertex iVertex from the stroke. The length and\n"
+" curvilinear abscissa are updated consequently.\n"
+"\n"
+" :arg iVertex: \n"
+" :type iVertex: :class:`StrokeVertex`\n";
+
+static PyObject * Stroke_RemoveVertex( BPy_Stroke *self, PyObject *args ) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &StrokeVertex_Type, &py_sv) ))
+ return NULL;
+
+ if( ((BPy_StrokeVertex *) py_sv)->sv )
+ self->s->RemoveVertex( ((BPy_StrokeVertex *) py_sv)->sv );
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_UpdateLength___doc__[] =
+".. method:: UpdateLength()\n"
+"\n"
+" Updates the 2D length of the Stroke.\n";
+
+static PyObject * Stroke_UpdateLength( BPy_Stroke *self ) {
+ self->s->UpdateLength();
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_getLength2D___doc__[] =
+".. method:: getLength2D()\n"
+"\n"
+" Returns the 2D length of the Stroke.\n"
+"\n"
+" :return: the 2D length of the Stroke.\n"
+" :rtype: float\n";
+
+static PyObject * Stroke_getLength2D( BPy_Stroke *self ) {
+ return PyFloat_FromDouble( self->s->getLength2D() );
+}
+
+static char Stroke_getMediumType___doc__[] =
+".. method:: getMediumType()\n"
+"\n"
+" Returns the MediumType used for this Stroke.\n"
+"\n"
+" :return: the MediumType used for this Stroke.\n"
+" :rtype: :class:`MediumType`\n";
+
+static PyObject * Stroke_getMediumType( BPy_Stroke *self ) {
+ return BPy_MediumType_from_MediumType( self->s->getMediumType() );
+}
+
+static char Stroke_getTextureId___doc__[] =
+".. method:: getTextureId()\n"
+"\n"
+" Returns the ID of the texture used to simulate th marks system for\n"
+" this Stroke\n"
+"\n"
+" :return: The texture ID.\n"
+" :rtype: int\n";
+
+static PyObject * Stroke_getTextureId( BPy_Stroke *self ) {
+ return PyLong_FromLong( self->s->getTextureId() );
+}
+
+static char Stroke_hasTips___doc__[] =
+".. method:: hasTips()\n"
+"\n"
+" Returns true if this Stroke uses a texture with tips, false\n"
+" otherwise.\n"
+"\n"
+" :return: True if this Stroke uses a texture with tips.\n"
+" :rtype: bool\n";
+
+static PyObject * Stroke_hasTips( BPy_Stroke *self ) {
+ return PyBool_from_bool( self->s->hasTips() );
+}
+
+static char Stroke_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the Id of the Stroke.\n"
+"\n"
+" :arg id: the Id of the Stroke.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject *Stroke_setId( BPy_Stroke *self , PyObject *args) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ self->s->setId(*( ((BPy_Id *) py_id)->id ));
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_setLength___doc__[] =
+".. method:: setLength(iLength)\n"
+"\n"
+" Sets the 2D length of the Stroke.\n"
+"\n"
+" :arg iLength: The 2D length of the Stroke.\n"
+" :type iLength: float\n";
+
+static PyObject *Stroke_setLength( BPy_Stroke *self , PyObject *args) {
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return NULL;
+
+ self->s->setLength( f );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_setMediumType___doc__[] =
+".. method:: setMediumType(iType)\n"
+"\n"
+" Sets the medium type that must be used for this Stroke.\n"
+"\n"
+" :arg iType: A MediumType object.\n"
+" :type iType: :class:`MediumType`\n";
+
+static PyObject *Stroke_setMediumType( BPy_Stroke *self , PyObject *args) {
+ PyObject *py_mt;
+
+ if(!( PyArg_ParseTuple(args, "O!", &MediumType_Type, &py_mt) ))
+ return NULL;
+
+ self->s->setMediumType( MediumType_from_BPy_MediumType(py_mt) );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_setTextureId___doc__[] =
+".. method:: setTextureId(iId)\n"
+"\n"
+" Sets the texture ID to be used to simulate the marks system for this\n"
+" Stroke.\n"
+"\n"
+" :arg iId: A texture ID.\n"
+" :type iId: int\n";
+
+static PyObject *Stroke_setTextureId( BPy_Stroke *self , PyObject *args) {
+ unsigned int i;
+
+ if(!( PyArg_ParseTuple(args, "I", &i) ))
+ return NULL;
+
+ self->s->setTextureId( i );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_setTips___doc__[] =
+".. method:: setTips(iTips)\n"
+"\n"
+" Sets the flag telling whether this stroke is using a texture with\n"
+" tips or not.\n"
+"\n"
+" :arg iTips: True if this stroke uses a texture with tips.\n"
+" :type iTips: bool\n";
+
+static PyObject *Stroke_setTips( BPy_Stroke *self , PyObject *args) {
+ PyObject *py_b;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_b) ))
+ return NULL;
+
+ self->s->setTips( bool_from_PyBool(py_b) );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_strokeVerticesBegin___doc__[] =
+".. method:: strokeVerticesBegin(t=0.0)\n"
+"\n"
+" Returns a StrokeVertexIterator pointing on the first StrokeVertex of\n"
+" the Stroke. O ne can specify a sampling value to resample the Stroke\n"
+" on the fly if needed.\n"
+"\n"
+" :arg t: The resampling value with which we want our Stroke to be\n"
+" resampled. If 0 is specified, no resampling is done.\n"
+" :type t: float\n"
+" :return: A StrokeVertexIterator pointing on the first StrokeVertex.\n"
+" :rtype: :class:`StrokeVertexIterator`\n";
+
+static PyObject * Stroke_strokeVerticesBegin( BPy_Stroke *self , PyObject *args) {
+ float f = 0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return NULL;
+
+ StrokeInternal::StrokeVertexIterator sv_it( self->s->strokeVerticesBegin(f) );
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 0 );
+}
+
+static char Stroke_strokeVerticesEnd___doc__[] =
+".. method:: strokeVerticesEnd()\n"
+"\n"
+" Returns a StrokeVertexIterator pointing after the last StrokeVertex\n"
+" of the Stroke.\n"
+"\n"
+" :return: A StrokeVertexIterator pointing after the last StrokeVertex.\n"
+" :rtype: :class:`StrokeVertexIterator`\n";
+
+static PyObject * Stroke_strokeVerticesEnd( BPy_Stroke *self ) {
+ StrokeInternal::StrokeVertexIterator sv_it( self->s->strokeVerticesEnd() );
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 1 );
+}
+
+static char Stroke_strokeVerticesSize___doc__[] =
+".. method:: strokeVerticesSize()\n"
+"\n"
+" Returns the number of StrokeVertex constituing the Stroke.\n"
+"\n"
+" :return: The number of stroke vertices.\n"
+" :rtype: int\n";
+
+static PyObject * Stroke_strokeVerticesSize( BPy_Stroke *self ) {
+ return PyLong_FromLong( self->s->strokeVerticesSize() );
+}
+
+/*----------------------Stroke instance definitions ----------------------------*/
+
+static PyMethodDef BPy_Stroke_methods[] = {
+ {"__getitem__", ( PyCFunction ) Stroke___getitem__, METH_O, "(int i) Returns the i-th StrokeVertex constituting the Stroke."},
+ {"ComputeSampling", ( PyCFunction ) Stroke_ComputeSampling, METH_VARARGS, Stroke_ComputeSampling___doc__},
+ {"Resample", ( PyCFunction ) Stroke_Resample, METH_VARARGS, Stroke_Resample___doc__},
+ {"RemoveVertex", ( PyCFunction ) Stroke_RemoveVertex, METH_VARARGS, Stroke_RemoveVertex___doc__},
+ {"InsertVertex", ( PyCFunction ) Stroke_InsertVertex, METH_VARARGS, Stroke_InsertVertex___doc__},
+ {"UpdateLength", ( PyCFunction ) Stroke_UpdateLength, METH_NOARGS, Stroke_UpdateLength___doc__},
+ {"getLength2D", ( PyCFunction ) Stroke_getLength2D, METH_NOARGS, Stroke_getLength2D___doc__},
+ {"getMediumType", ( PyCFunction ) Stroke_getMediumType, METH_NOARGS, Stroke_getMediumType___doc__},
+ {"getTextureId", ( PyCFunction ) Stroke_getTextureId, METH_NOARGS, Stroke_getTextureId___doc__},
+ {"hasTips", ( PyCFunction ) Stroke_hasTips, METH_NOARGS, Stroke_hasTips___doc__},
+ {"setId", ( PyCFunction ) Stroke_setId, METH_VARARGS, Stroke_setId___doc__},
+ {"setLength", ( PyCFunction ) Stroke_setLength, METH_VARARGS, Stroke_setLength___doc__},
+ {"setMediumType", ( PyCFunction ) Stroke_setMediumType, METH_VARARGS, Stroke_setMediumType___doc__},
+ {"setTextureId", ( PyCFunction ) Stroke_setTextureId, METH_VARARGS, Stroke_setTextureId___doc__},
+ {"setTips", ( PyCFunction ) Stroke_setTips, METH_VARARGS, Stroke_setTips___doc__},
+ {"strokeVerticesBegin", ( PyCFunction ) Stroke_strokeVerticesBegin, METH_VARARGS, Stroke_strokeVerticesBegin___doc__},
+ {"strokeVerticesEnd", ( PyCFunction ) Stroke_strokeVerticesEnd, METH_NOARGS, Stroke_strokeVerticesEnd___doc__},
+ {"strokeVerticesSize", ( PyCFunction ) Stroke_strokeVerticesSize, METH_NOARGS, Stroke_strokeVerticesSize___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Stroke type definition ------------------------------*/
+
+static PySequenceMethods Stroke_as_sequence = {
+ (lenfunc)Stroke_length, /* sq_length */
+ NULL, /* sq_concat */
+ NULL, /* sq_repeat */
+ (ssizeargfunc)Stroke_item, /* sq_item */
+ NULL, /* sq_slice */
+ NULL, /* sq_ass_item */
+ NULL, /* sq_ass_slice */
+ NULL, /* sq_contains */
+ NULL, /* sq_inplace_concat */
+ NULL, /* sq_inplace_repeat */
+};
+
+PyTypeObject Stroke_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Stroke", /* tp_name */
+ sizeof(BPy_Stroke), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ &Stroke_as_sequence, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Stroke___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ (getiterfunc)Stroke___iter__, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Stroke_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Stroke___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h
new file mode 100644
index 00000000000..52c6d214b85
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_STROKE_H
+#define FREESTYLE_PYTHON_STROKE_H
+
+#include "../BPy_Interface1D.h"
+#include "../../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Stroke_Type;
+
+#define BPy_Stroke_Check(v) (( (PyObject *) v)->ob_type == &Stroke_Type)
+
+/*---------------------------Python BPy_Stroke structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ Stroke *s;
+} BPy_Stroke;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKE_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
new file mode 100644
index 00000000000..e35ea82ace2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
@@ -0,0 +1,463 @@
+#include "BPy_ViewEdge.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+#include "../Interface1D/BPy_FEdge.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+#include "../BPy_ViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewEdge___doc__[] =
+"Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n"
+"\n"
+"Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n"
+"it connnects two :class:`ViewVertex` objects. It is made by connecting\n"
+"a set of FEdges.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A ViewEdge object.\n"
+" :type iBrother: :class:`ViewEdge`\n";
+
+static int ViewEdge___init__(BPy_ViewEdge *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->ve = new ViewEdge();
+ self->py_if1D.if1D = self->ve;
+ self->py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char ViewEdge_A___doc__[] =
+".. method:: A()\n"
+"\n"
+" Returns the first ViewVertex.\n"
+"\n"
+" :return: The first ViewVertex.\n"
+" :rtype: :class:`ViewVertex`\n";
+
+static PyObject * ViewEdge_A( BPy_ViewEdge *self ) {
+ ViewVertex *v = self->ve->A();
+ if( v ){
+ return Any_BPy_ViewVertex_from_ViewVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_B___doc__[] =
+".. method:: B()\n"
+"\n"
+" Returns the second ViewVertex.\n"
+"\n"
+" :return: The second ViewVertex.\n"
+" :rtype: :class:`ViewVertex`\n";
+
+static PyObject * ViewEdge_B( BPy_ViewEdge *self ) {
+ ViewVertex *v = self->ve->B();
+ if( v ){
+ return Any_BPy_ViewVertex_from_ViewVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_fedgeA___doc__[] =
+".. method:: fedgeA()\n"
+"\n"
+" Returns the first FEdge that constitutes this ViewEdge.\n"
+"\n"
+" :return: The first FEdge constituting this ViewEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * ViewEdge_fedgeA( BPy_ViewEdge *self ) {
+ FEdge *A = self->ve->fedgeA();
+ if( A ){
+ return Any_BPy_FEdge_from_FEdge( *A );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_fedgeB___doc__[] =
+".. method:: fedgeB()\n"
+"\n"
+" Returns the last FEdge that constitutes this ViewEdge.\n"
+"\n"
+" :return: The last FEdge constituting this ViewEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * ViewEdge_fedgeB( BPy_ViewEdge *self ) {
+ FEdge *B = self->ve->fedgeB();
+ if( B ){
+ return Any_BPy_FEdge_from_FEdge( *B );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_viewShape___doc__[] =
+".. method:: viewShape()\n"
+"\n"
+" Returns the ViewShape to which this ViewEdge belongs to.\n"
+"\n"
+" :return: The ViewShape to which this ViewEdge belongs to.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static PyObject * ViewEdge_viewShape( BPy_ViewEdge *self ) {
+ ViewShape *vs = self->ve->viewShape();
+ if( vs ){
+ return BPy_ViewShape_from_ViewShape( *vs );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_aShape___doc__[] =
+".. method:: aShape()\n"
+"\n"
+" Returns the shape that is occluded by the ViewShape to which this\n"
+" ViewEdge belongs to. If no object is occluded, None is returned.\n"
+"\n"
+" :return: The occluded ViewShape.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static PyObject * ViewEdge_aShape( BPy_ViewEdge *self ) {
+ ViewShape *vs = self->ve->aShape();
+ if( vs ){
+ return BPy_ViewShape_from_ViewShape( *vs );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_isClosed___doc__[] =
+".. method:: isClosed()\n"
+"\n"
+" Tells whether this ViewEdge forms a closed loop or not.\n"
+"\n"
+" :return: True if this ViewEdge forms a closed loop.\n"
+" :rtype: bool\n";
+
+static PyObject * ViewEdge_isClosed( BPy_ViewEdge *self ) {
+ return PyBool_from_bool( self->ve->isClosed() );
+}
+
+static char ViewEdge_getChainingTimeStamp___doc__[] =
+".. method:: getChainingTimeStamp()\n"
+"\n"
+" Returns the time stamp of this ViewEdge.\n"
+"\n"
+" :return: The time stamp.\n"
+" :rtype: int\n";
+
+static PyObject * ViewEdge_getChainingTimeStamp( BPy_ViewEdge *self ) {
+ return PyLong_FromLong( self->ve->getChainingTimeStamp() );
+}
+
+static char ViewEdge_setChainingTimeStamp___doc__[] =
+".. method:: setChainingTimeStamp(ts)\n"
+"\n"
+" Sets the time stamp value.\n"
+"\n"
+" :arg ts: The time stamp.\n"
+" :type ts: int\n";
+
+static PyObject * ViewEdge_setChainingTimeStamp( BPy_ViewEdge *self, PyObject *args) {
+ int timestamp = 0 ;
+
+ if( !PyArg_ParseTuple(args, "i", &timestamp) )
+ return NULL;
+
+ self->ve->setChainingTimeStamp( timestamp );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setA___doc__[] =
+".. method:: setA(iA)\n"
+"\n"
+" Sets the first ViewVertex of the ViewEdge.\n"
+"\n"
+" :arg iA: The first ViewVertex of the ViewEdge.\n"
+" :type iA: :class:`ViewVertex`\n";
+
+static PyObject *ViewEdge_setA( BPy_ViewEdge *self , PyObject *args) {
+ PyObject *py_vv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) ))
+ return NULL;
+
+ self->ve->setA( ((BPy_ViewVertex *) py_vv)->vv );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setB___doc__[] =
+".. method:: setB(iB)\n"
+"\n"
+" Sets the last ViewVertex of the ViewEdge.\n"
+"\n"
+" :arg iB: The last ViewVertex of the ViewEdge.\n"
+" :type iB: :class:`ViewVertex`\n";
+
+static PyObject *ViewEdge_setB( BPy_ViewEdge *self , PyObject *args) {
+ PyObject *py_vv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) ))
+ return NULL;
+
+ self->ve->setB( ((BPy_ViewVertex *) py_vv)->vv );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setNature___doc__[] =
+".. method:: setNature(iNature)\n"
+"\n"
+" Sets the nature of the ViewEdge.\n"
+"\n"
+" :arg iNature: The nature of the ViewEdge.\n"
+" :type iNature: :class:`Nature`\n";
+
+static PyObject * ViewEdge_setNature( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_n;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) ))
+ return NULL;
+
+ PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i );
+ self->ve->setNature( PyLong_AsLong(i) );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setFEdgeA___doc__[] =
+".. method:: setFEdgeA(iFEdge)\n"
+"\n"
+" Sets the first FEdge of the ViewEdge.\n"
+"\n"
+" :arg iFEdge: The first FEdge of the ViewEdge.\n"
+" :type iFEdge: :class:`FEdge`\n";
+
+static PyObject * ViewEdge_setFEdgeA( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->ve->setFEdgeA( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setFEdgeB___doc__[] =
+".. method:: setFEdgeB(iFEdge)\n"
+"\n"
+" Sets the last FEdge of the ViewEdge.\n"
+"\n"
+" :arg iFEdge: The last FEdge of the ViewEdge.\n"
+" :type iFEdge: :class:`FEdge`\n";
+
+static PyObject * ViewEdge_setFEdgeB( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->ve->setFEdgeB( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setShape___doc__[] =
+".. method:: setShape(iVShape)\n"
+"\n"
+" Sets the ViewShape to which this ViewEdge belongs to.\n"
+"\n"
+" :arg iVShape: The ViewShape to which this ViewEdge belongs to.\n"
+" :type iVShape: :class:`ViewShape`\n";
+
+static PyObject * ViewEdge_setShape( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_vs;
+
+ if(!( PyArg_ParseTuple(args, "O", &ViewShape_Type, &py_vs) ))
+ return NULL;
+
+ self->ve->setShape( ((BPy_ViewShape *) py_vs)->vs );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the ViewEdge id.\n"
+"\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject * ViewEdge_setId( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ Id id(*( ((BPy_Id *) py_id)->id ));
+ self->ve->setId( id );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_UpdateFEdges___doc__[] =
+".. method:: UpdateFEdges()\n"
+"\n"
+" Sets Viewedge to this for all embedded fedges.\n";
+
+static PyObject * ViewEdge_UpdateFEdges( BPy_ViewEdge *self ) {
+ self->ve->UpdateFEdges();
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setaShape___doc__[] =
+".. method:: setaShape(iShape)\n"
+"\n"
+" Sets the occluded ViewShape.\n"
+"\n"
+" :arg iShape: A ViewShape object.\n"
+" :type iShape: :class:`ViewShape`\n";
+
+static PyObject * ViewEdge_setaShape( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_vs;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewShape_Type, &py_vs) ))
+ return NULL;
+
+ ViewShape *vs = ((BPy_ViewShape *) py_vs)->vs;
+ self->ve->setaShape( vs );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setQI___doc__[] =
+".. method:: setQI(qi)\n"
+"\n"
+" Sets the quantitative invisibility value of the ViewEdge.\n"
+"\n"
+" :arg qi: The quantitative invisibility.\n"
+" :type qi: int\n";
+
+static PyObject * ViewEdge_setQI( BPy_ViewEdge *self, PyObject *args ) {
+ int qi;
+
+ if(!( PyArg_ParseTuple(args, "i", &qi) ))
+ return NULL;
+
+ self->ve->setQI( qi );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_qi___doc__[] =
+".. method:: getChainingTimeStamp()\n"
+"\n"
+" Returns the quantitative invisibility value of the ViewEdge.\n"
+"\n"
+" :return: The quantitative invisibility.\n"
+" :rtype: int\n";
+
+static PyObject * ViewEdge_qi( BPy_ViewEdge *self ) {
+ return PyLong_FromLong( self->ve->qi() );
+}
+
+/*----------------------ViewEdge instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewEdge_methods[] = {
+ {"A", ( PyCFunction ) ViewEdge_A, METH_NOARGS, ViewEdge_A___doc__},
+ {"B", ( PyCFunction ) ViewEdge_B, METH_NOARGS, ViewEdge_B___doc__},
+ {"fedgeA", ( PyCFunction ) ViewEdge_fedgeA, METH_NOARGS, ViewEdge_fedgeA___doc__},
+ {"fedgeB", ( PyCFunction ) ViewEdge_fedgeB, METH_NOARGS, ViewEdge_fedgeB___doc__},
+ {"viewShape", ( PyCFunction ) ViewEdge_viewShape, METH_NOARGS, ViewEdge_viewShape___doc__},
+ {"aShape", ( PyCFunction ) ViewEdge_aShape, METH_NOARGS, ViewEdge_aShape___doc__},
+ {"isClosed", ( PyCFunction ) ViewEdge_isClosed, METH_NOARGS, ViewEdge_isClosed___doc__},
+ {"getChainingTimeStamp", ( PyCFunction ) ViewEdge_getChainingTimeStamp, METH_NOARGS, ViewEdge_getChainingTimeStamp___doc__},
+ {"setChainingTimeStamp", ( PyCFunction ) ViewEdge_setChainingTimeStamp, METH_VARARGS, ViewEdge_setChainingTimeStamp___doc__},
+ {"setA", ( PyCFunction ) ViewEdge_setA, METH_VARARGS, ViewEdge_setA___doc__},
+ {"setB", ( PyCFunction ) ViewEdge_setB, METH_VARARGS, ViewEdge_setB___doc__},
+ {"setNature", ( PyCFunction ) ViewEdge_setNature, METH_VARARGS, ViewEdge_setNature___doc__},
+ {"setFEdgeA", ( PyCFunction ) ViewEdge_setFEdgeA, METH_VARARGS, ViewEdge_setFEdgeA___doc__},
+ {"setFEdgeB", ( PyCFunction ) ViewEdge_setFEdgeB, METH_VARARGS, ViewEdge_setFEdgeB___doc__},
+ {"setShape", ( PyCFunction ) ViewEdge_setShape, METH_VARARGS, ViewEdge_setShape___doc__},
+ {"setId", ( PyCFunction ) ViewEdge_setId, METH_VARARGS, ViewEdge_setId___doc__},
+ {"UpdateFEdges", ( PyCFunction ) ViewEdge_UpdateFEdges, METH_NOARGS, ViewEdge_UpdateFEdges___doc__},
+ {"setaShape", ( PyCFunction ) ViewEdge_setaShape, METH_VARARGS, ViewEdge_setaShape___doc__},
+ {"setQI", ( PyCFunction ) ViewEdge_setQI, METH_VARARGS, ViewEdge_setQI___doc__},
+ {"qi", ( PyCFunction ) ViewEdge_qi, METH_NOARGS, ViewEdge_qi___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewEdge type definition ------------------------------*/
+
+PyTypeObject ViewEdge_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewEdge", /* tp_name */
+ sizeof(BPy_ViewEdge), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewEdge___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewEdge_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewEdge___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h
new file mode 100644
index 00000000000..ead377377e8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h
@@ -0,0 +1,32 @@
+#ifndef FREESTYLE_PYTHON_VIEWEDGE_H
+#define FREESTYLE_PYTHON_VIEWEDGE_H
+
+#include "../../view_map/ViewMap.h"
+
+#include "../BPy_Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewEdge_Type;
+
+#define BPy_ViewEdge_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewEdge_Type) )
+
+/*---------------------------Python BPy_ViewEdge structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ ViewEdge *ve;
+} BPy_ViewEdge;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWEDGE_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
new file mode 100644
index 00000000000..c85134f71d5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
@@ -0,0 +1,171 @@
+#include "BPy_Chain.h"
+
+#include "../../BPy_Convert.h"
+#include "../../BPy_Id.h"
+#include "../BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Chain___doc__[] =
+"Class hierarchy: :class:`Interface1D` > :class:`Curve` > :class:`Chain`\n"
+"\n"
+"Class to represent a 1D elements issued from the chaining process. A\n"
+"Chain is the last step before the :class:`Stroke` and is used in the\n"
+"Splitting and Creation processes.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Defult constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A Chain object.\n"
+" :type iBrother: :class:`Chain`\n"
+"\n"
+".. method:: __init__(id)\n"
+"\n"
+" Builds a chain from its Id.\n"
+"\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`\n";
+
+int Chain___init__(BPy_Chain *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ){
+ self->c = new Chain();
+
+ } else if( BPy_Chain_Check(obj) ) {
+ self->c = new Chain(*( ((BPy_Chain *) obj)->c ));
+
+ } else if( BPy_Id_Check(obj) ) {
+ self->c = new Chain(*( ((BPy_Id *) obj)->id ));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_c.c = self->c;
+ self->py_c.py_if1D.if1D = self->c;
+ self->py_c.py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char Chain_push_viewedge_back___doc__[] =
+".. method:: push_viewedge_back(iViewEdge, orientation)\n"
+"\n"
+" Adds a ViewEdge at the end of the Chain.\n"
+"\n"
+" :arg iViewEdge: The ViewEdge that must be added.\n"
+" :type iViewEdge: :class:`ViewEdge`\n"
+" :arg orientation: The orientation with which the ViewEdge must be\n"
+" processed.\n"
+" :type orientation: bool\n";
+
+PyObject * Chain_push_viewedge_back( BPy_Chain *self, PyObject *args ) {
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!O", &ViewEdge_Type, &obj1, &obj2) ))
+ return NULL;
+
+ ViewEdge *ve = ((BPy_ViewEdge *) obj1)->ve;
+ bool orientation = bool_from_PyBool( obj2 );
+ self->c->push_viewedge_back( ve, orientation);
+
+ Py_RETURN_NONE;
+}
+
+static char Chain_push_viewedge_front___doc__[] =
+".. method:: push_viewedge_front(iViewEdge, orientation)\n"
+"\n"
+" Adds a ViewEdge at the beginning of the Chain.\n"
+"\n"
+" :arg iViewEdge: The ViewEdge that must be added.\n"
+" :type iViewEdge: :class:`ViewEdge`\n"
+" :arg orientation: The orientation with which the ViewEdge must be\n"
+" processed.\n"
+" :type orientation: bool\n";
+
+PyObject * Chain_push_viewedge_front( BPy_Chain *self, PyObject *args ) {
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!O", &ViewEdge_Type, &obj1, &obj2) ))
+ return NULL;
+
+ ViewEdge *ve = ((BPy_ViewEdge *) obj1)->ve;
+ bool orientation = bool_from_PyBool( obj2 );
+ self->c->push_viewedge_front(ve, orientation);
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------Chain instance definitions ----------------------------*/
+static PyMethodDef BPy_Chain_methods[] = {
+ {"push_viewedge_back", ( PyCFunction ) Chain_push_viewedge_back, METH_VARARGS, Chain_push_viewedge_back___doc__},
+ {"push_viewedge_front", ( PyCFunction ) Chain_push_viewedge_front, METH_VARARGS, Chain_push_viewedge_front___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Chain type definition ------------------------------*/
+
+PyTypeObject Chain_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Chain", /* tp_name */
+ sizeof(BPy_Chain), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Chain___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Chain_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &FrsCurve_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Chain___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h
new file mode 100644
index 00000000000..19f325ef513
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CHAIN_H
+#define FREESTYLE_PYTHON_CHAIN_H
+
+#include "../BPy_FrsCurve.h"
+#include "../../../stroke/Chain.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Chain_Type;
+
+#define BPy_Chain_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Chain_Type) )
+
+/*---------------------------Python BPy_Chain structure definition----------*/
+typedef struct {
+ BPy_FrsCurve py_c;
+ Chain *c;
+} BPy_Chain;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAIN_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
new file mode 100644
index 00000000000..39d644b7714
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
@@ -0,0 +1,373 @@
+#include "BPy_FEdgeSharp.h"
+
+#include "../../BPy_Convert.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FEdgeSharp___doc__[] =
+"Class hierarchy: :class:`Interface1D` > :class:`FEdge` > :class:`FEdgeSharp`\n"
+"\n"
+"Class defining a sharp FEdge. A Sharp FEdge corresponds to an initial\n"
+"edge of the input mesh. It can be a silhouette, a crease or a border.\n"
+"If it is a crease edge, then it is borded by two faces of the mesh.\n"
+"Face a lies on its right whereas Face b lies on its left. If it is a\n"
+"border edge, then it doesn't have any face on its right, and thus Face\n"
+"a is None.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An FEdgeSharp object.\n"
+" :type iBrother: :class:`FEdgeSharp`\n"
+"\n"
+".. method:: __init__(vA, vB)\n"
+"\n"
+" Builds an FEdgeSharp going from vA to vB.\n"
+"\n"
+" :arg vA: The first SVertex object.\n"
+" :type vA: :class:`SVertex`\n"
+" :arg vB: The second SVertex object.\n"
+" :type vB: :class:`SVertex`\n";
+
+static int FEdgeSharp___init__(BPy_FEdgeSharp *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) )
+ return -1;
+
+ if( !obj1 ){
+ self->fes = new FEdgeSharp();
+
+ } else if( !obj2 && BPy_FEdgeSharp_Check(obj1) ) {
+ self->fes = new FEdgeSharp(*( ((BPy_FEdgeSharp *) obj1)->fes ));
+
+ } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->fes = new FEdgeSharp( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_fe.fe = self->fes;
+ self->py_fe.py_if1D.if1D = self->fes;
+ self->py_fe.py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char FEdgeSharp_normalA___doc__[] =
+".. method:: normalA()\n"
+"\n"
+" Returns the normal to the face lying on the right of the FEdge. If\n"
+" this FEdge is a border, it has no Face on its right and therefore, no\n"
+" normal.\n"
+"\n"
+" :return: The normal to the face lying on the right of the FEdge.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject * FEdgeSharp_normalA( BPy_FEdgeSharp *self ) {
+ Vec3r v( self->fes->normalA() );
+ return Vector_from_Vec3r( v );
+}
+
+static char FEdgeSharp_normalB___doc__[] =
+".. method:: normalB()\n"
+"\n"
+" Returns the normal to the face lying on the left of the FEdge.\n"
+"\n"
+" :return: The normal to the face lying on the left of the FEdge.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject * FEdgeSharp_normalB( BPy_FEdgeSharp *self ) {
+ Vec3r v( self->fes->normalB() );
+ return Vector_from_Vec3r( v );
+}
+
+static char FEdgeSharp_aMaterialIndex___doc__[] =
+".. method:: aMaterialIndex()\n"
+"\n"
+" Returns the index of the material of the face lying on the right of\n"
+" the FEdge. If this FEdge is a border, it has no Face on its right and\n"
+" therefore, no material.\n"
+"\n"
+" :return: The index of the material of the face lying on the right of\n"
+" the FEdge.\n"
+" :rtype: int\n";
+
+static PyObject * FEdgeSharp_aMaterialIndex( BPy_FEdgeSharp *self ) {
+ return PyLong_FromLong( self->fes->aFrsMaterialIndex() );
+}
+
+static char FEdgeSharp_bMaterialIndex___doc__[] =
+".. method:: bMaterialIndex()\n"
+"\n"
+" Returns the index of the material of the face lying on the left of\n"
+" the FEdge.\n"
+"\n"
+" :return: The index of the material of the face lying on the left of\n"
+" the FEdge.\n"
+" :rtype: int\n";
+
+static PyObject * FEdgeSharp_bMaterialIndex( BPy_FEdgeSharp *self ) {
+ return PyLong_FromLong( self->fes->bFrsMaterialIndex() );
+}
+
+static char FEdgeSharp_aMaterial___doc__[] =
+".. method:: aMaterial()\n"
+"\n"
+" Returns the material of the face lying on the right of the FEdge. If\n"
+" this FEdge is a border, it has no Face on its right and therefore, no\n"
+" material.\n"
+"\n"
+" :return: The material of the face lying on the right of the FEdge.\n"
+" :rtype: :class:`Material`\n";
+
+static PyObject * FEdgeSharp_aMaterial( BPy_FEdgeSharp *self ) {
+ FrsMaterial m( self->fes->aFrsMaterial() );
+ return BPy_FrsMaterial_from_FrsMaterial(m);
+}
+
+static char FEdgeSharp_bMaterial___doc__[] =
+".. method:: bMaterial()\n"
+"\n"
+" Returns the material of the face lying on the left of the FEdge.\n"
+"\n"
+" :return: The material of the face lying on the left of the FEdge.\n"
+" :rtype: :class:`Material`\n";
+
+static PyObject * FEdgeSharp_bMaterial( BPy_FEdgeSharp *self ) {
+ FrsMaterial m( self->fes->aFrsMaterial() );
+ return BPy_FrsMaterial_from_FrsMaterial(m);
+}
+
+static char FEdgeSharp_aFaceMark___doc__[] =
+".. method:: aFaceMark()\n"
+"\n"
+" Returns the face mark of the face lying on the right of the FEdge.\n"
+" If this FEdge is a border, it has no face on the right, and thus\n"
+" false is returned.\n"
+"\n"
+" :return: The face mark of the face lying on the right of the FEdge.\n"
+" :rtype: bool\n";
+
+static PyObject * FEdgeSharp_aFaceMark( BPy_FEdgeSharp *self ) {
+ return PyBool_from_bool( self->fes->aFaceMark() );
+}
+
+static char FEdgeSharp_bFaceMark___doc__[] =
+".. method:: bFaceMark()\n"
+"\n"
+" Returns the face mark of the face lying on the left of the FEdge.\n"
+"\n"
+" :return: The face mark of the face lying on the left of the FEdge.\n"
+" :rtype: bool\n";
+
+static PyObject * FEdgeSharp_bFaceMark( BPy_FEdgeSharp *self ) {
+ return PyBool_from_bool( self->fes->bFaceMark() );
+}
+
+static char FEdgeSharp_setNormalA___doc__[] =
+".. method:: setNormalA(iNormal)\n"
+"\n"
+" Sets the normal to the face lying on the right of the FEdge.\n"
+"\n"
+" :arg iNormal: A three-dimensional vector.\n"
+" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * FEdgeSharp_setNormalA( BPy_FEdgeSharp *self, PyObject *args ) {
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->fes->setNormalA( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSharp_setNormalB___doc__[] =
+".. method:: setNormalB(iNormal)\n"
+"\n"
+" Sets the normal to the face lying on the left of the FEdge.\n"
+"\n"
+" :arg iNormal: A three-dimensional vector.\n"
+" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * FEdgeSharp_setNormalB( BPy_FEdgeSharp *self, PyObject *args ) {
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->fes->setNormalB( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSharp_setaMaterialIndex___doc__[] =
+".. method:: setaMaterialIndex(i)\n"
+"\n"
+" Sets the index of the material lying on the right of the FEdge.\n"
+"\n"
+" :arg i: A material index.\n"
+" :type i: int\n";
+
+static PyObject * FEdgeSharp_setaMaterialIndex( BPy_FEdgeSharp *self, PyObject *args ) {
+ unsigned int i;
+
+ if(!( PyArg_ParseTuple(args, "I", &i) ))
+ return NULL;
+
+ self->fes->setaFrsMaterialIndex( i );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSharp_setbMaterialIndex___doc__[] =
+".. method:: setbMaterialIndex(i)\n"
+"\n"
+" Sets the index of the material lying on the left of the FEdge.\n"
+"\n"
+" :arg i: A material index.\n"
+" :type i: int\n";
+
+static PyObject * FEdgeSharp_setbMaterialIndex( BPy_FEdgeSharp *self, PyObject *args ) {
+ unsigned int i;
+
+ if(!( PyArg_ParseTuple(args, "I", &i) ))
+ return NULL;
+
+ self->fes->setbFrsMaterialIndex( i );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSharp_setaFaceMark___doc__[] =
+".. method:: setaFaceMark(i)\n"
+"\n"
+" Sets the face mark of the face lying on the right of the FEdge.\n"
+"\n"
+" :arg i: A face mark.\n"
+" :type i: bool\n";
+
+static PyObject * FEdgeSharp_setaFaceMark( BPy_FEdgeSharp *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ self->fes->setaFaceMark( bool_from_PyBool(obj) );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSharp_setbFaceMark___doc__[] =
+".. method:: setbFaceMark(i)\n"
+"\n"
+" Sets the face mark of the face lying on the left of the FEdge.\n"
+"\n"
+" :arg i: A face mark.\n"
+" :type i: bool\n";
+
+static PyObject * FEdgeSharp_setbFaceMark( BPy_FEdgeSharp *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ self->fes->setbFaceMark( bool_from_PyBool(obj) );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------FEdgeSharp instance definitions ----------------------------*/
+static PyMethodDef BPy_FEdgeSharp_methods[] = {
+ {"normalA", ( PyCFunction ) FEdgeSharp_normalA, METH_NOARGS, FEdgeSharp_normalA___doc__},
+ {"normalB", ( PyCFunction ) FEdgeSharp_normalB, METH_NOARGS, FEdgeSharp_normalB___doc__},
+ {"aMaterialIndex", ( PyCFunction ) FEdgeSharp_aMaterialIndex, METH_NOARGS, FEdgeSharp_aMaterialIndex___doc__},
+ {"bMaterialIndex", ( PyCFunction ) FEdgeSharp_bMaterialIndex, METH_NOARGS, FEdgeSharp_bMaterialIndex___doc__},
+ {"aMaterial", ( PyCFunction ) FEdgeSharp_aMaterial, METH_NOARGS, FEdgeSharp_aMaterial___doc__},
+ {"bMaterial", ( PyCFunction ) FEdgeSharp_bMaterial, METH_NOARGS, FEdgeSharp_bMaterial___doc__},
+ {"aFaceMark", ( PyCFunction ) FEdgeSharp_aFaceMark, METH_NOARGS, FEdgeSharp_aFaceMark___doc__},
+ {"bFaceMark", ( PyCFunction ) FEdgeSharp_bFaceMark, METH_NOARGS, FEdgeSharp_bFaceMark___doc__},
+ {"setNormalA", ( PyCFunction ) FEdgeSharp_setNormalA, METH_VARARGS, FEdgeSharp_setNormalA___doc__},
+ {"setNormalB", ( PyCFunction ) FEdgeSharp_setNormalB, METH_VARARGS, FEdgeSharp_setNormalB___doc__},
+ {"setaMaterialIndex", ( PyCFunction ) FEdgeSharp_setaMaterialIndex, METH_VARARGS, FEdgeSharp_setaMaterialIndex___doc__},
+ {"setbMaterialIndex", ( PyCFunction ) FEdgeSharp_setbMaterialIndex, METH_VARARGS, FEdgeSharp_setbMaterialIndex___doc__},
+ {"setaFaceMark", ( PyCFunction ) FEdgeSharp_setaFaceMark, METH_NOARGS, FEdgeSharp_setaFaceMark___doc__},
+ {"setbFaceMark", ( PyCFunction ) FEdgeSharp_setbFaceMark, METH_NOARGS, FEdgeSharp_setbFaceMark___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FEdgeSharp type definition ------------------------------*/
+
+PyTypeObject FEdgeSharp_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdgeSharp", /* tp_name */
+ sizeof(BPy_FEdgeSharp), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FEdgeSharp___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FEdgeSharp_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &FEdge_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdgeSharp___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h
new file mode 100644
index 00000000000..84b01e27c21
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FEDGESHARP_H
+#define FREESTYLE_PYTHON_FEDGESHARP_H
+
+#include "../BPy_FEdge.h"
+#include "../../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdgeSharp_Type;
+
+#define BPy_FEdgeSharp_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdgeSharp_Type) )
+
+/*---------------------------Python BPy_FEdgeSharp structure definition----------*/
+typedef struct {
+ BPy_FEdge py_fe;
+ FEdgeSharp *fes;
+} BPy_FEdgeSharp;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FEDGESHARP_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
new file mode 100644
index 00000000000..3ddb4d060de
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
@@ -0,0 +1,240 @@
+#include "BPy_FEdgeSmooth.h"
+
+#include "../../BPy_Convert.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FEdgeSmooth___doc__[] =
+"Class hierarchy: :class:`Interface1D` > :class:`FEdge` > :class:`FEdgeSmooth`\n"
+"\n"
+"Class defining a smooth edge. This kind of edge typically runs across\n"
+"a face of the input mesh. It can be a silhouette, a ridge or valley,\n"
+"a suggestive contour.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An FEdgeSmooth object.\n"
+" :type iBrother: :class:`FEdgeSmooth`\n"
+"\n"
+".. method:: __init__(vA, vB)\n"
+"\n"
+" Builds an FEdgeSmooth going from vA to vB.\n"
+"\n"
+" :arg vA: The first SVertex object.\n"
+" :type vA: :class:`SVertex`\n"
+" :arg vB: The second SVertex object.\n"
+" :type vB: :class:`SVertex`\n";
+
+static int FEdgeSmooth___init__(BPy_FEdgeSmooth *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) )
+ return -1;
+
+ if( !obj1 ){
+ self->fes = new FEdgeSmooth();
+
+ } else if( !obj2 && BPy_FEdgeSmooth_Check(obj1) ) {
+ self->fes = new FEdgeSmooth(*( ((BPy_FEdgeSmooth *) obj1)->fes ));
+
+ } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->fes = new FEdgeSmooth( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_fe.fe = self->fes;
+ self->py_fe.py_if1D.if1D = self->fes;
+ self->py_fe.py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char FEdgeSmooth_normal___doc__[] =
+".. method:: normal()\n"
+"\n"
+" Returns the normal to the Face it is running accross.\n"
+"\n"
+" :return: The normal to the Face it is running accross.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject * FEdgeSmooth_normal( BPy_FEdgeSmooth *self ) {
+ Vec3r v( self->fes->normal() );
+ return Vector_from_Vec3r( v );
+}
+
+static char FEdgeSmooth_materialIndex___doc__[] =
+".. method:: materialIndex()\n"
+"\n"
+" Returns the index of the material of the face it is running accross.\n"
+"\n"
+" :return: The index of the material of the face it is running accross.\n"
+" :rtype: int\n";
+
+static PyObject * FEdgeSmooth_materialIndex( BPy_FEdgeSmooth *self ) {
+ return PyLong_FromLong( self->fes->frs_materialIndex() );
+}
+
+static char FEdgeSmooth_material___doc__[] =
+".. method:: material()\n"
+"\n"
+" Returns the material of the face it is running accross.\n"
+"\n"
+" :return: The material of the face it is running accross.\n"
+" :rtype: :class:`Material`\n";
+
+static PyObject * FEdgeSmooth_material( BPy_FEdgeSmooth *self ) {
+ FrsMaterial m( self->fes->frs_material() );
+ return BPy_FrsMaterial_from_FrsMaterial(m);
+}
+
+static char FEdgeSmooth_faceMark___doc__[] =
+".. method:: faceMark()\n"
+"\n"
+" Returns the face mark of the face it is running across.\n"
+"\n"
+" :return: The face mark of the face it is running across.\n"
+" :rtype: bool\n";
+
+static PyObject * FEdgeSmooth_faceMark( BPy_FEdgeSmooth *self ) {
+ return PyBool_from_bool( self->fes->faceMark() );
+}
+
+static char FEdgeSmooth_setNormal___doc__[] =
+".. method:: setNormal(iNormal)\n"
+"\n"
+" Sets the normal to the Face it is running accross.\n"
+"\n"
+" :arg iNormal: A three-dimensional vector.\n"
+" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * FEdgeSmooth_setNormal( BPy_FEdgeSmooth *self, PyObject *args ) {
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->fes->setNormal( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSmooth_setMaterialIndex___doc__[] =
+".. method:: setMaterialIndex(i)\n"
+"\n"
+" Sets the index of the material of the face it is running accross.\n"
+"\n"
+" :arg i: The index of the material of the face it is running accross.\n"
+" :type i: int\n";
+
+static PyObject * FEdgeSmooth_setMaterialIndex( BPy_FEdgeSmooth *self, PyObject *args ) {
+ unsigned int i;
+
+ if(!( PyArg_ParseTuple(args, "I", &i) ))
+ return NULL;
+
+ self->fes->setFrsMaterialIndex( i );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSmooth_setFaceMark___doc__[] =
+".. method:: setFaceMark(i)\n"
+"\n"
+" Sets the face mark of the face it is running across.\n"
+"\n"
+" :arg i: A face mark.\n"
+" :type i: bool\n";
+
+static PyObject * FEdgeSmooth_setFaceMark( BPy_FEdgeSmooth *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ self->fes->setFaceMark( bool_from_PyBool(obj) );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------FEdgeSmooth instance definitions ----------------------------*/
+static PyMethodDef BPy_FEdgeSmooth_methods[] = {
+ {"normal", ( PyCFunction ) FEdgeSmooth_normal, METH_NOARGS, FEdgeSmooth_normal___doc__},
+ {"materialIndex", ( PyCFunction ) FEdgeSmooth_materialIndex, METH_NOARGS, FEdgeSmooth_materialIndex___doc__},
+ {"material", ( PyCFunction ) FEdgeSmooth_material, METH_NOARGS, FEdgeSmooth_material___doc__},
+ {"faceMark", ( PyCFunction ) FEdgeSmooth_faceMark, METH_NOARGS, FEdgeSmooth_faceMark___doc__},
+ {"setNormal", ( PyCFunction ) FEdgeSmooth_setNormal, METH_VARARGS, FEdgeSmooth_setNormal___doc__},
+ {"setMaterialIndex", ( PyCFunction ) FEdgeSmooth_setMaterialIndex, METH_VARARGS, FEdgeSmooth_setMaterialIndex___doc__},
+ {"setFaceMark", ( PyCFunction ) FEdgeSmooth_setFaceMark, METH_VARARGS, FEdgeSmooth_setFaceMark___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FEdgeSmooth type definition ------------------------------*/
+
+PyTypeObject FEdgeSmooth_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdgeSmooth", /* tp_name */
+ sizeof(BPy_FEdgeSmooth), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FEdgeSmooth___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FEdgeSmooth_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &FEdge_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdgeSmooth___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h
new file mode 100644
index 00000000000..d7b44bb1da7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FEDGESMOOTH_H
+#define FREESTYLE_PYTHON_FEDGESMOOTH_H
+
+#include "../BPy_FEdge.h"
+#include "../../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdgeSmooth_Type;
+
+#define BPy_FEdgeSmooth_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdgeSmooth_Type) )
+
+/*---------------------------Python BPy_FEdgeSmooth structure definition----------*/
+typedef struct {
+ BPy_FEdge py_fe;
+ FEdgeSmooth *fes;
+} BPy_FEdgeSmooth;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FEDGESMOOTH_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
new file mode 100644
index 00000000000..1f4b041cce8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
@@ -0,0 +1,167 @@
+#include "BPy_AdjacencyIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char AdjacencyIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`AdjacencyIterator`\n"
+"\n"
+"Class for representing adjacency iterators used in the chaining\n"
+"process. An AdjacencyIterator is created in the increment() and\n"
+"decrement() methods of a :class:`ChainingIterator` and passed to the\n"
+"traverse() method of the ChainingIterator.\n"
+"\n"
+".. method:: __init__(iVertex, iRestrictToSelection=True, iRestrictToUnvisited=True)\n"
+"\n"
+" Builds a AdjacencyIterator object.\n"
+"\n"
+" :arg iVertex: The vertex which is the next crossing.\n"
+" :type iVertex: :class:`ViewVertex`\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type iRestrictToUnvisited: bool\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: An AdjacencyIterator object.\n"
+" :type it: :class:`AdjacencyIterator`\n";
+
+static int AdjacencyIterator___init__(BPy_AdjacencyIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOO", &obj1, &obj2, &obj3) )
+ return -1;
+
+ if( !obj1 && !obj2 && !obj3 ){
+ self->a_it = new AdjacencyIterator();
+
+ } else if( BPy_AdjacencyIterator_Check(obj1) ) {
+ self->a_it = new AdjacencyIterator(*( ((BPy_AdjacencyIterator *) obj1)->a_it ));
+
+ } else if( BPy_ViewVertex_Check(obj1) ) {
+ bool restrictToSelection = ( obj2 ) ? bool_from_PyBool(obj2) : true;
+ bool restrictToUnvisited = ( obj3 ) ? bool_from_PyBool(obj3) : true;
+
+ self->a_it = new AdjacencyIterator( ((BPy_ViewVertex *) obj1)->vv, restrictToSelection, restrictToUnvisited );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_it.it = self->a_it;
+
+ return 0;
+
+}
+
+static PyObject * AdjacencyIterator_iternext(BPy_AdjacencyIterator *self) {
+ if (self->a_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ ViewEdge *ve = self->a_it->operator*();
+ self->a_it->increment();
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+}
+
+static char AdjacencyIterator_isIncoming___doc__[] =
+".. method:: isIncoming()\n"
+"\n"
+" Returns true if the current ViewEdge is coming towards the\n"
+" iteration vertex. False otherwise.\n"
+"\n"
+" :return: True if the current ViewEdge is coming towards the\n"
+" iteration vertex\n"
+" :rtype: bool\n";
+
+static PyObject * AdjacencyIterator_isIncoming(BPy_AdjacencyIterator *self) {
+ return PyBool_from_bool(self->a_it->isIncoming());
+}
+
+static char AdjacencyIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed ViewEdge.\n"
+"\n"
+" :return: The pointed ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * AdjacencyIterator_getObject(BPy_AdjacencyIterator *self) {
+
+ ViewEdge *ve = self->a_it->operator*();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------AdjacencyIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_AdjacencyIterator_methods[] = {
+ {"isIncoming", ( PyCFunction ) AdjacencyIterator_isIncoming, METH_NOARGS, AdjacencyIterator_isIncoming___doc__},
+ {"getObject", ( PyCFunction ) AdjacencyIterator_getObject, METH_NOARGS, AdjacencyIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_AdjacencyIterator type definition ------------------------------*/
+
+PyTypeObject AdjacencyIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "AdjacencyIterator", /* tp_name */
+ sizeof(BPy_AdjacencyIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ AdjacencyIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)AdjacencyIterator_iternext, /* tp_iternext */
+ BPy_AdjacencyIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)AdjacencyIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h
new file mode 100644
index 00000000000..733a9f2fcab
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h
@@ -0,0 +1,32 @@
+#ifndef FREESTYLE_PYTHON_ADJACENCYITERATOR_H
+#define FREESTYLE_PYTHON_ADJACENCYITERATOR_H
+
+#include "../../stroke/ChainingIterators.h"
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject AdjacencyIterator_Type;
+
+#define BPy_AdjacencyIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &AdjacencyIterator_Type) )
+
+/*---------------------------Python BPy_AdjacencyIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ AdjacencyIterator *a_it;
+} BPy_AdjacencyIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ADJACENCYITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
new file mode 100644
index 00000000000..aa6d10ddb5f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
@@ -0,0 +1,205 @@
+#include "BPy_ChainPredicateIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_BinaryPredicate1D.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ChainPredicateIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator` > :class:`ChainPredicateIterator`\n"
+"\n"
+"A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n"
+"particular built from a unary predicate and a binary predicate.\n"
+"First, the unary predicate is evaluated for all potential next\n"
+"ViewEdges in order to only keep the ones respecting a certain\n"
+"constraint. Then, the binary predicate is evaluated on the current\n"
+"ViewEdge together with each ViewEdge of the previous selection. The\n"
+"first ViewEdge respecting both the unary predicate and the binary\n"
+"predicate is kept as the next one. If none of the potential next\n"
+"ViewEdge respects these two predicates, None is returned.\n"
+"\n"
+".. method:: __init__(iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a ChainPredicateIterator from a starting ViewEdge and its\n"
+" orientation.\n"
+"\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type iRestrictToUnvisited: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin. \n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(upred, bpred, iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a ChainPredicateIterator from a unary predicate, a binary\n"
+" predicate, a starting ViewEdge and its orientation.\n"
+"\n"
+" :arg upred: The unary predicate that the next ViewEdge must satisfy.\n"
+" :type upred: :class:`UnaryPredicate1D`\n"
+" :arg bpred: The binary predicate that the next ViewEdge must\n"
+" satisfy together with the actual pointed ViewEdge.\n"
+" :type bpred: :class:`BinaryPredicate1D`\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type iRestrictToUnvisited: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ChainPredicateIterator object.\n"
+" :type brother: :class:`ChainPredicateIterator`\n";
+
+static int ChainPredicateIterator___init__(BPy_ChainPredicateIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0, *obj5 = 0, *obj6 = 0;
+
+ if (!( PyArg_ParseTuple(args, "|OOOOOO", &obj1, &obj2, &obj3, &obj4, &obj5, &obj6) ))
+ return -1;
+
+ if( obj1 && BPy_ChainPredicateIterator_Check(obj1) ) {
+ self->cp_it = new ChainPredicateIterator(*( ((BPy_ChainPredicateIterator *) obj1)->cp_it ));
+ self->upred = NULL;
+ self->bpred = NULL;
+
+ } else if( obj1 && BPy_UnaryPredicate1D_Check(obj1) &&
+ obj2 && BPy_BinaryPredicate1D_Check(obj2) ) {
+
+ if (!((BPy_UnaryPredicate1D *) obj1)->up1D) {
+ PyErr_SetString(PyExc_TypeError, "1st argument: invalid UnaryPredicate1D object");
+ return -1;
+ }
+ if (!((BPy_BinaryPredicate1D *) obj2)->bp1D) {
+ PyErr_SetString(PyExc_TypeError, "2nd argument: invalid BinaryPredicate1D object");
+ return -1;
+ }
+ UnaryPredicate1D *up1D = ((BPy_UnaryPredicate1D *) obj1)->up1D;
+ BinaryPredicate1D *bp1D = ((BPy_BinaryPredicate1D *) obj2)->bp1D;
+ bool restrictToSelection = ( obj3 ) ? bool_from_PyBool(obj3) : true;
+ bool restrictToUnvisited = ( obj4 ) ? bool_from_PyBool(obj4) : true;
+ ViewEdge *begin;
+ if ( !obj5 || obj5 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj5) )
+ begin = ((BPy_ViewEdge *) obj5)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "5th argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj6 ) ? bool_from_PyBool(obj6) : true;
+
+ self->cp_it = new ChainPredicateIterator( *up1D, *bp1D, restrictToSelection, restrictToUnvisited, begin, orientation);
+ self->upred = obj1;
+ self->bpred = obj2;
+ Py_INCREF( self->upred );
+ Py_INCREF( self->bpred );
+
+ } else {
+ bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true;
+ bool restrictToUnvisited = ( obj2 ) ? bool_from_PyBool(obj2) : true;
+ ViewEdge *begin;
+ if ( !obj3 || obj3 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj3) )
+ begin = ((BPy_ViewEdge *) obj3)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "3rd argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj4 ) ? bool_from_PyBool(obj4) : true;
+
+ self->cp_it = new ChainPredicateIterator( restrictToSelection, restrictToUnvisited, begin, orientation);
+ self->upred = NULL;
+ self->bpred = NULL;
+ }
+
+ self->py_c_it.c_it = self->cp_it;
+ self->py_c_it.py_ve_it.ve_it = self->cp_it;
+ self->py_c_it.py_ve_it.py_it.it = self->cp_it;
+
+
+ return 0;
+
+}
+
+static void ChainPredicateIterator___dealloc__(BPy_ChainPredicateIterator *self)
+{
+ Py_XDECREF( self->upred );
+ Py_XDECREF( self->bpred );
+ ChainingIterator_Type.tp_dealloc((PyObject *)self);
+}
+
+/*-----------------------BPy_ChainPredicateIterator type definition ------------------------------*/
+
+PyTypeObject ChainPredicateIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainPredicateIterator", /* tp_name */
+ sizeof(BPy_ChainPredicateIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ChainPredicateIterator___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ChainPredicateIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ChainingIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainPredicateIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h
new file mode 100644
index 00000000000..5a31ac407d5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H
+#define FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ChainingIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainPredicateIterator_Type;
+
+#define BPy_ChainPredicateIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainPredicateIterator_Type) )
+
+/*---------------------------Python BPy_ChainPredicateIterator structure definition----------*/
+typedef struct {
+ BPy_ChainingIterator py_c_it;
+ ChainPredicateIterator *cp_it;
+ PyObject *upred;
+ PyObject *bpred;
+} BPy_ChainPredicateIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
new file mode 100644
index 00000000000..caf43a800c5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
@@ -0,0 +1,131 @@
+#include "BPy_ChainSilhouetteIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+// ChainSilhouetteIterator (bool iRestrictToSelection=true, ViewEdge *begin=NULL, bool orientation=true)
+// ChainSilhouetteIterator (const ChainSilhouetteIterator &brother)
+
+static char ChainSilhouetteIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator` > :class:`ChainSilhouetteIterator`\n"
+"\n"
+"A ViewEdge Iterator used to follow ViewEdges the most naturally. For\n"
+"example, it will follow visible ViewEdges of same nature. As soon, as\n"
+"the nature or the visibility changes, the iteration stops (by setting\n"
+"the pointed ViewEdge to 0). In the case of an iteration over a set of\n"
+"ViewEdge that are both Silhouette and Crease, there will be a\n"
+"precedence of the silhouette over the crease criterion.\n"
+"\n"
+".. method:: __init__(iRestrictToSelection=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a ChainSilhouetteIterator from the first ViewEdge used for\n"
+" iteration and its orientation.\n"
+"\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ChainSilhouetteIterator object.\n"
+" :type brother: :class:`ChainSilhouetteIterator`\n";
+
+static int ChainSilhouetteIterator___init__(BPy_ChainSilhouetteIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+
+ if (!( PyArg_ParseTuple(args, "|OOO", &obj1, &obj2, &obj3) ))
+ return -1;
+
+ if( obj1 && BPy_ChainSilhouetteIterator_Check(obj1) ) {
+ self->cs_it = new ChainSilhouetteIterator(*( ((BPy_ChainSilhouetteIterator *) obj1)->cs_it ));
+
+ } else {
+ bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true;
+ ViewEdge *begin;
+ if ( !obj2 || obj2 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj2) )
+ begin = ((BPy_ViewEdge *) obj2)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "2nd argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj3 ) ? bool_from_PyBool(obj3) : true;
+
+ self->cs_it = new ChainSilhouetteIterator( restrictToSelection, begin, orientation);
+ }
+
+ self->py_c_it.c_it = self->cs_it;
+ self->py_c_it.py_ve_it.ve_it = self->cs_it;
+ self->py_c_it.py_ve_it.py_it.it = self->cs_it;
+
+ return 0;
+
+}
+
+/*-----------------------BPy_ChainSilhouetteIterator type definition ------------------------------*/
+
+PyTypeObject ChainSilhouetteIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainSilhouetteIterator", /* tp_name */
+ sizeof(BPy_ChainSilhouetteIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ChainSilhouetteIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ChainingIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainSilhouetteIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h
new file mode 100644
index 00000000000..912d397d279
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H
+#define FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ChainingIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainSilhouetteIterator_Type;
+
+#define BPy_ChainSilhouetteIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainSilhouetteIterator_Type) )
+
+/*---------------------------Python BPy_ChainSilhouetteIterator structure definition----------*/
+typedef struct {
+ BPy_ChainingIterator py_c_it;
+ ChainSilhouetteIterator *cs_it;
+} BPy_ChainSilhouetteIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
new file mode 100644
index 00000000000..ddb957c900e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
@@ -0,0 +1,236 @@
+#include "BPy_ChainingIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "BPy_AdjacencyIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ChainingIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator`\n"
+"\n"
+"Base class for chaining iterators. This class is designed to be\n"
+"overloaded in order to describe chaining rules. It makes the\n"
+"description of chaining rules easier. The two main methods that need\n"
+"to overloaded are traverse() and init(). traverse() tells which\n"
+":class:`ViewEdge` to follow, among the adjacent ones. If you specify\n"
+"restriction rules (such as \"Chain only ViewEdges of the selection\"),\n"
+"they will be included in the adjacency iterator (i.e, the adjacent\n"
+"iterator will only stop on \"valid\" edges).\n"
+"\n"
+".. method:: __init__(iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a Chaining Iterator from the first ViewEdge used for\n"
+" iteration and its orientation.\n"
+"\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type iRestrictToUnvisited: bool\n"
+" :arg begin: The ViewEdge from which to start the chain.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: The direction to follow to explore the graph. If\n"
+" true, the direction indicated by the first ViewEdge is used.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: \n"
+" :type brother: ChainingIterator\n";
+
+static int ChainingIterator___init__(BPy_ChainingIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0;
+
+ if (!( PyArg_ParseTuple(args, "|OOOO", &obj1, &obj2, &obj3, &obj4) ))
+ return -1;
+
+ if( obj1 && BPy_ChainingIterator_Check(obj1) ) {
+ self->c_it = new ChainingIterator(*( ((BPy_ChainingIterator *) obj1)->c_it ));
+
+ } else {
+ bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true;
+ bool restrictToUnvisited = ( obj2 ) ? bool_from_PyBool(obj2) : true;
+ ViewEdge *begin;
+ if ( !obj3 || obj3 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj3) )
+ begin = ((BPy_ViewEdge *) obj3)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "3rd argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj4 ) ? bool_from_PyBool(obj4) : true;
+
+ self->c_it = new ChainingIterator( restrictToSelection, restrictToUnvisited, begin, orientation);
+ }
+
+ self->py_ve_it.ve_it = self->c_it;
+ self->py_ve_it.py_it.it = self->c_it;
+
+ self->c_it->py_c_it = (PyObject *) self;
+
+ return 0;
+}
+
+static char ChainingIterator_init___doc__[] =
+".. method:: init()\n"
+"\n"
+" Initializes the iterator context. This method is called each\n"
+" time a new chain is started. It can be used to reset some\n"
+" history information that you might want to keep.\n";
+
+static PyObject *ChainingIterator_init( BPy_ChainingIterator *self ) {
+ if( typeid(*(self->c_it)) == typeid(ChainingIterator) ) {
+ PyErr_SetString(PyExc_TypeError, "init() method not properly overridden");
+ return NULL;
+ }
+ self->c_it->init();
+
+ Py_RETURN_NONE;
+}
+
+static char ChainingIterator_traverse___doc__[] =
+".. method:: traverse(it)\n"
+"\n"
+" This method iterates over the potential next ViewEdges and returns\n"
+" the one that will be followed next. Returns the next ViewEdge to\n"
+" follow or None when the end of the chain is reached.\n"
+"\n"
+" :arg it: The iterator over the ViewEdges adjacent to the end vertex\n"
+" of the current ViewEdge. The adjacency iterator reflects the\n"
+" restriction rules by only iterating over the valid ViewEdges.\n"
+" :type it: :class:`AdjacencyIterator`\n"
+" :return: Returns the next ViewEdge to follow, or None if chaining ends.\n"
+" :rtype: :class:`ViewEdge` or None\n";
+
+static PyObject *ChainingIterator_traverse( BPy_ChainingIterator *self, PyObject *args ) {
+ PyObject *py_a_it;
+
+ if(!( PyArg_ParseTuple(args, "O!", &AdjacencyIterator_Type, &py_a_it) ))
+ return NULL;
+
+ if( typeid(*(self->c_it)) == typeid(ChainingIterator) ) {
+ PyErr_SetString(PyExc_TypeError, "traverse() method not properly overridden");
+ return NULL;
+ }
+ if( ((BPy_AdjacencyIterator *) py_a_it)->a_it )
+ self->c_it->traverse(*( ((BPy_AdjacencyIterator *) py_a_it)->a_it ));
+
+ Py_RETURN_NONE;
+}
+
+static char ChainingIterator_getVertex___doc__[] =
+".. method:: getVertex()\n"
+"\n"
+" Returns the vertex which is the next crossing.\n"
+"\n"
+" :return: The vertex which is the next crossing.\n"
+" :rtype: :class:`ViewVertex`\n";
+
+static PyObject *ChainingIterator_getVertex( BPy_ChainingIterator *self ) {
+ ViewVertex *v = self->c_it->getVertex();
+ if( v )
+ return Any_BPy_ViewVertex_from_ViewVertex( *v );
+
+ Py_RETURN_NONE;
+}
+
+static char ChainingIterator_isIncrementing___doc__[] =
+".. method:: isIncrementing()\n"
+"\n"
+" Returns true if the current iteration is an incrementation.\n"
+"\n"
+" :return: True if the current iteration is an incrementation.\n"
+" :rtype: bool\n";
+
+static PyObject *ChainingIterator_isIncrementing( BPy_ChainingIterator *self ) {
+ return PyBool_from_bool( self->c_it->isIncrementing() );
+}
+
+static char ChainingIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed ViewEdge.\n"
+"\n"
+" :return: The pointed ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * ChainingIterator_getObject( BPy_ChainingIterator *self) {
+
+ ViewEdge *ve = self->c_it->operator*();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------ChainingIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_ChainingIterator_methods[] = {
+ {"init", ( PyCFunction ) ChainingIterator_init, METH_NOARGS, ChainingIterator_init___doc__},
+ {"traverse", ( PyCFunction ) ChainingIterator_traverse, METH_VARARGS, ChainingIterator_traverse___doc__},
+ {"getVertex", ( PyCFunction ) ChainingIterator_getVertex, METH_NOARGS, ChainingIterator_getVertex___doc__},
+ {"isIncrementing", ( PyCFunction ) ChainingIterator_isIncrementing, METH_NOARGS, ChainingIterator_isIncrementing___doc__},
+ {"getObject", ( PyCFunction ) ChainingIterator_getObject, METH_NOARGS, ChainingIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ChainingIterator type definition ------------------------------*/
+
+PyTypeObject ChainingIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainingIterator", /* tp_name */
+ sizeof(BPy_ChainingIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ChainingIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ChainingIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ViewEdgeIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainingIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h
new file mode 100644
index 00000000000..2a00aa8072f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_CHAININGITERATOR_H
+#define FREESTYLE_PYTHON_CHAININGITERATOR_H
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ViewEdgeIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainingIterator_Type;
+
+#define BPy_ChainingIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainingIterator_Type) )
+
+/*---------------------------Python BPy_ChainingIterator structure definition----------*/
+typedef struct {
+ BPy_ViewEdgeIterator py_ve_it;
+ ChainingIterator *c_it;
+} BPy_ChainingIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAININGITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
new file mode 100644
index 00000000000..d1a8fbef6b9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
@@ -0,0 +1,171 @@
+#include "BPy_CurvePointIterator.h"
+
+#include "../BPy_Convert.h"
+#include "BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurvePointIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`CurvePointIterator`\n"
+"\n"
+"Class representing an iterator on a curve. Allows an iterating\n"
+"outside initial vertices. A CurvePoint is instanciated and returned\n"
+"by getObject().\n"
+"\n"
+".. method:: __init__(step=0.0)\n"
+"\n"
+" Builds a CurvePointIterator object.\n"
+"\n"
+" :arg step: A resampling resolution with which the curve is resampled.\n"
+" If zero, no resampling is done (i.e., the iterator iterates over\n"
+" initial vertices).\n"
+" :type step: float\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A CurvePointIterator object.\n"
+" :type brother: :class:`CurvePointIterator`\n";
+
+static int CurvePointIterator___init__(BPy_CurvePointIterator *self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ){
+ self->cp_it = new CurveInternal::CurvePointIterator();
+
+ } else if( BPy_CurvePointIterator_Check(obj) ) {
+ self->cp_it = new CurveInternal::CurvePointIterator(*( ((BPy_CurvePointIterator *) obj)->cp_it ));
+
+ } else if( PyFloat_Check(obj) ) {
+ self->cp_it = new CurveInternal::CurvePointIterator( PyFloat_AsDouble(obj) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_it.it = self->cp_it;
+
+ return 0;
+}
+
+static char CurvePointIterator_t___doc__[] =
+".. method:: t()\n"
+"\n"
+" Returns the curvilinear abscissa.\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+PyObject * CurvePointIterator_t( BPy_CurvePointIterator *self ) {
+ return PyFloat_FromDouble( self->cp_it->t() );
+}
+
+static char CurvePointIterator_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the point parameter in the curve (0<=u<=1).\n"
+"\n"
+" :return: The point parameter.\n"
+" :rtype: float\n";
+
+static PyObject * CurvePointIterator_u( BPy_CurvePointIterator *self ) {
+ return PyFloat_FromDouble( self->cp_it->u() );
+}
+
+static char CurvePointIterator_castToInterface0DIterator___doc__[] =
+".. method:: castToInterface0DIterator()\n"
+"\n"
+" Returns an Interface0DIterator converted from this\n"
+" CurvePointIterator. Useful for any call to a function of the\n"
+" UnaryFunction0D type.\n"
+"\n"
+" :return: An Interface0DIterator object converted from the\n"
+" iterator.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * CurvePointIterator_castToInterface0DIterator( BPy_CurvePointIterator *self ) {
+ Interface0DIterator it( self->cp_it->castToInterface0DIterator() );
+ return BPy_Interface0DIterator_from_Interface0DIterator( it, 0 );
+}
+
+static char CurvePointIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns a CurvePoint pointed by the iterator.\n"
+"\n"
+" :return: \n"
+" :rtype: :class:`CurvePoint`\n";
+
+static PyObject * CurvePointIterator_getObject(BPy_CurvePointIterator *self) {
+ return BPy_CurvePoint_from_CurvePoint( self->cp_it->operator*() );
+}
+
+/*----------------------CurvePointIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_CurvePointIterator_methods[] = {
+ {"t", ( PyCFunction ) CurvePointIterator_t, METH_NOARGS, CurvePointIterator_t___doc__},
+ {"u", ( PyCFunction ) CurvePointIterator_u, METH_NOARGS, CurvePointIterator_u___doc__},
+ {"castToInterface0DIterator", ( PyCFunction ) CurvePointIterator_castToInterface0DIterator, METH_NOARGS, CurvePointIterator_castToInterface0DIterator___doc__},
+ {"getObject", ( PyCFunction ) CurvePointIterator_getObject, METH_NOARGS, CurvePointIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_CurvePointIterator type definition ------------------------------*/
+
+PyTypeObject CurvePointIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurvePointIterator", /* tp_name */
+ sizeof(BPy_CurvePointIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurvePointIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_CurvePointIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurvePointIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h
new file mode 100644
index 00000000000..ad04c7208bb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h
@@ -0,0 +1,32 @@
+#ifndef FREESTYLE_PYTHON_CURVEPOINTITERATOR_H
+#define FREESTYLE_PYTHON_CURVEPOINTITERATOR_H
+
+#include "../../stroke/CurveIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurvePointIterator_Type;
+
+#define BPy_CurvePointIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurvePointIterator_Type) )
+
+/*---------------------------Python BPy_CurvePointIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ CurveInternal::CurvePointIterator *cp_it;
+} BPy_CurvePointIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVEPOINTITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
new file mode 100644
index 00000000000..6643913c32a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
@@ -0,0 +1,151 @@
+#include "BPy_Interface0DIterator.h"
+
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Interface0DIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`Interface0DIterator`\n"
+"\n"
+"Class defining an iterator over Interface0D elements. An instance of\n"
+"this iterator is always obtained from a 1D element.\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n";
+
+static int Interface0DIterator___init__(BPy_Interface0DIterator *self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if (!( PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj) ))
+ return -1;
+
+ self->if0D_it = new Interface0DIterator(*( ((BPy_Interface0DIterator *) obj)->if0D_it ));
+ self->py_it.it = self->if0D_it;
+ self->reversed = 0;
+
+ return 0;
+}
+
+static PyObject * Interface0DIterator_iternext( BPy_Interface0DIterator *self ) {
+ Interface0D *if0D;
+ if (self->reversed) {
+ if (self->if0D_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->if0D_it->decrement();
+ if0D = self->if0D_it->operator->();
+ } else {
+ if (self->if0D_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ if0D = self->if0D_it->operator->();
+ self->if0D_it->increment();
+ }
+ return Any_BPy_Interface0D_from_Interface0D( *if0D );
+}
+
+static char Interface0DIterator_t___doc__[] =
+".. method:: t()\n"
+"\n"
+" Returns the curvilinear abscissa.\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+static PyObject * Interface0DIterator_t( BPy_Interface0DIterator *self ) {
+ return PyFloat_FromDouble( self->if0D_it->t() );
+}
+
+static char Interface0DIterator_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the point parameter in the curve 0<=u<=1.\n"
+"\n"
+" :return: The point parameter.\n"
+" :rtype: float\n";
+
+static PyObject * Interface0DIterator_u( BPy_Interface0DIterator *self ) {
+ return PyFloat_FromDouble( self->if0D_it->u() );
+}
+
+static char Interface0DIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed Interface0D.\n"
+"\n"
+" :return: The pointed Interface0D.\n"
+" :rtype: :class:`Interface0D`\n";
+
+static PyObject * Interface0DIterator_getObject(BPy_Interface0DIterator *self) {
+ return Any_BPy_Interface0D_from_Interface0D( self->if0D_it->operator*() );
+}
+
+/*----------------------Interface0DIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_Interface0DIterator_methods[] = {
+ {"t", ( PyCFunction ) Interface0DIterator_t, METH_NOARGS, Interface0DIterator_t___doc__},
+ {"u", ( PyCFunction ) Interface0DIterator_u, METH_NOARGS, Interface0DIterator_u___doc__},
+ {"getObject", ( PyCFunction ) Interface0DIterator_getObject, METH_NOARGS, Interface0DIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Interface0DIterator type definition ------------------------------*/
+
+PyTypeObject Interface0DIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface0DIterator", /* tp_name */
+ sizeof(BPy_Interface0DIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Interface0DIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)Interface0DIterator_iternext, /* tp_iternext */
+ BPy_Interface0DIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface0DIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h
new file mode 100644
index 00000000000..1972763b2eb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_INTERFACE0DITERATOR_H
+#define FREESTYLE_PYTHON_INTERFACE0DITERATOR_H
+
+#include "../../view_map/Interface0D.h"
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Interface0DIterator_Type;
+
+#define BPy_Interface0DIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface0DIterator_Type) )
+
+/*---------------------------Python BPy_Interface0DIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ Interface0DIterator *if0D_it;
+ int reversed;
+} BPy_Interface0DIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INTERFACE0DITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
new file mode 100644
index 00000000000..ef40d994e27
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
@@ -0,0 +1,181 @@
+#include "BPy_SVertexIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SVertexIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`SVertexIterator`\n"
+"\n"
+"Class representing an iterator over :class:`SVertex` of a\n"
+":class:`ViewEdge`. An instance of an SVertexIterator can be obtained\n"
+"from a ViewEdge by calling verticesBegin() or verticesEnd().\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: An SVertexIterator object.\n"
+" :type it: :class:`SVertexIterator`\n"
+"\n"
+".. method:: __init__(v, begin, prev, next, t)\n"
+"\n"
+" Builds an SVertexIterator that starts iteration from an SVertex\n"
+" object v.\n"
+"\n"
+" :arg v: The SVertex from which the iterator starts iteration.\n"
+" :type v: :class:`SVertex`\n"
+" :arg begin: The first vertex of a view edge.\n"
+" :type begin: :class:`SVertex`\n"
+" :arg prev: The previous FEdge coming to v.\n"
+" :type prev: :class:`FEdge`\n"
+" :arg next: The next FEdge going out from v.\n"
+" :type next: :class:`FEdge`\n"
+" :arg t: The curvilinear abscissa at v.\n"
+" :type t: float\n";
+
+static int SVertexIterator___init__(BPy_SVertexIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0;
+ float f = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOOOf", &obj1, &obj2, &obj3, &obj4, f) )
+ return -1;
+
+ if( !obj1 ){
+ self->sv_it = new ViewEdgeInternal::SVertexIterator();
+
+ } else if( BPy_SVertexIterator_Check(obj1) ) {
+ self->sv_it = new ViewEdgeInternal::SVertexIterator(*( ((BPy_SVertexIterator *) obj1)->sv_it ));
+
+ } else if( obj1 && BPy_SVertex_Check(obj1) &&
+ obj2 && BPy_SVertex_Check(obj2) &&
+ obj3 && BPy_FEdge_Check(obj3) &&
+ obj4 && BPy_FEdge_Check(obj4) ) {
+
+ self->sv_it = new ViewEdgeInternal::SVertexIterator(
+ ((BPy_SVertex *) obj1)->sv,
+ ((BPy_SVertex *) obj2)->sv,
+ ((BPy_FEdge *) obj3)->fe,
+ ((BPy_FEdge *) obj4)->fe,
+ f );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_it.it = self->sv_it;
+
+ return 0;
+}
+
+static char SVertexIterator_t___doc__[] =
+".. method:: t()\n"
+"\n"
+" Returns the curvilinear abscissa.\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+static PyObject * SVertexIterator_t( BPy_SVertexIterator *self ) {
+ return PyFloat_FromDouble( self->sv_it->t() );
+}
+
+static char SVertexIterator_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the point parameter (0<=u<=1).\n"
+"\n"
+" :return: The point parameter.\n"
+" :rtype: float\n";
+
+static PyObject * SVertexIterator_u( BPy_SVertexIterator *self ) {
+ return PyFloat_FromDouble( self->sv_it->u() );
+}
+
+static char SVertexIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed SVertex.\n"
+"\n"
+" :return: the pointed SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * SVertexIterator_getObject( BPy_SVertexIterator *self) {
+ SVertex *sv = self->sv_it->operator->();
+
+ if( sv )
+ return BPy_SVertex_from_SVertex( *sv );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------SVertexIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_SVertexIterator_methods[] = {
+ {"t", ( PyCFunction ) SVertexIterator_t, METH_NOARGS, SVertexIterator_t___doc__},
+ {"u", ( PyCFunction ) SVertexIterator_u, METH_NOARGS, SVertexIterator_u___doc__},
+ {"getObject", ( PyCFunction ) SVertexIterator_getObject, METH_NOARGS, SVertexIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_SVertexIterator type definition ------------------------------*/
+
+PyTypeObject SVertexIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SVertexIterator", /* tp_name */
+ sizeof(BPy_SVertexIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SVertexIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SVertexIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SVertexIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h
new file mode 100644
index 00000000000..b40f4d36420
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_SVERTEXITERATOR_H
+#define FREESTYLE_PYTHON_SVERTEXITERATOR_H
+
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SVertexIterator_Type;
+
+#define BPy_SVertexIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SVertexIterator_Type) )
+
+/*---------------------------Python BPy_SVertexIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewEdgeInternal::SVertexIterator *sv_it;
+} BPy_SVertexIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SVERTEXITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
new file mode 100644
index 00000000000..a9b2c4d774a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
@@ -0,0 +1,197 @@
+#include "BPy_StrokeVertexIterator.h"
+
+#include "../BPy_Convert.h"
+#include "BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeVertexIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`StrokeVertexIterator`\n"
+"\n"
+"Class defining an iterator designed to iterate over the\n"
+":class:`StrokeVertex` of a :class:`Stroke`. An instance of a\n"
+"StrokeVertexIterator can only be obtained from a Stroke by calling\n"
+"strokeVerticesBegin() or strokeVerticesEnd(). It is iterating over\n"
+"the same vertices as an :class:`Interface0DIterator`. The difference\n"
+"resides in the object access. Indeed, an Interface0DIterator allows\n"
+"only an access to an Interface0D whereas we could need to access the\n"
+"specialized StrokeVertex type. In this case, one should use a\n"
+"StrokeVertexIterator. The castToInterface0DIterator() method is\n"
+"useful to get an Interface0DIterator from a StrokeVertexIterator in\n"
+"order to call any functions of the UnaryFunction0D type.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: A StrokeVertexIterator object.\n"
+" :type it: :class:`StrokeVertexIterator`\n";
+
+static int StrokeVertexIterator___init__(BPy_StrokeVertexIterator *self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ){
+ self->sv_it = new StrokeInternal::StrokeVertexIterator();
+
+ } else if( BPy_StrokeVertexIterator_Check(obj) ) {
+ self->sv_it = new StrokeInternal::StrokeVertexIterator(*( ((BPy_StrokeVertexIterator *) obj)->sv_it ));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_it.it = self->sv_it;
+ self->reversed = 0;
+
+ return 0;
+}
+
+static PyObject * StrokeVertexIterator_iternext( BPy_StrokeVertexIterator *self ) {
+ StrokeVertex *sv;
+ if (self->reversed) {
+ if (self->sv_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->sv_it->decrement();
+ sv = self->sv_it->operator->();
+ } else {
+ if (self->sv_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ sv = self->sv_it->operator->();
+ self->sv_it->increment();
+ }
+ return BPy_StrokeVertex_from_StrokeVertex( *sv );
+}
+
+static char StrokeVertexIterator_t___doc__[] =
+".. method:: t()\n"
+"\n"
+" Returns the curvilinear abscissa of the current point.\n"
+"\n"
+" :return: The curvilinear abscissa of the current point.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertexIterator_t( BPy_StrokeVertexIterator *self ) {
+ return PyFloat_FromDouble( self->sv_it->t() );
+}
+
+static char StrokeVertexIterator_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the point parameter in the stroke (0<=u<=1).\n"
+"\n"
+" :return: The point parameter in the stroke\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertexIterator_u( BPy_StrokeVertexIterator *self ) {
+ return PyFloat_FromDouble( self->sv_it->u() );
+}
+
+static char StrokeVertexIterator_castToInterface0DIterator___doc__[] =
+".. method:: castToInterface0DIterator()\n"
+"\n"
+" Returns an Interface0DIterator converted from this\n"
+" StrokeVertexIterator. Useful for any call to a function of the\n"
+" UnaryFunction0D type.\n"
+"\n"
+" :return: An Interface0DIterator converted from the StrokeVertexIterator.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * StrokeVertexIterator_castToInterface0DIterator( BPy_StrokeVertexIterator *self ) {
+ Interface0DIterator it( self->sv_it->castToInterface0DIterator() );
+ return BPy_Interface0DIterator_from_Interface0DIterator( it, 0 );
+}
+
+static char StrokeVertexIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed StrokeVertex.\n"
+"\n"
+" :return: The pointed StrokeVertex.\n"
+" :rtype: :class:`StrokeVertex`\n";
+
+static PyObject * StrokeVertexIterator_getObject( BPy_StrokeVertexIterator *self) {
+ if (!self->reversed && self->sv_it->isEnd())
+ Py_RETURN_NONE;
+ StrokeVertex *sv = self->sv_it->operator->();
+ if( sv )
+ return BPy_StrokeVertex_from_StrokeVertex( *sv );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------StrokeVertexIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeVertexIterator_methods[] = {
+ {"t", ( PyCFunction ) StrokeVertexIterator_t, METH_NOARGS, StrokeVertexIterator_t___doc__},
+ {"u", ( PyCFunction ) StrokeVertexIterator_u, METH_NOARGS, StrokeVertexIterator_u___doc__},
+ {"castToInterface0DIterator", ( PyCFunction ) StrokeVertexIterator_castToInterface0DIterator, METH_NOARGS, StrokeVertexIterator_castToInterface0DIterator___doc__},
+ {"getObject", ( PyCFunction ) StrokeVertexIterator_getObject, METH_NOARGS, StrokeVertexIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_StrokeVertexIterator type definition ------------------------------*/
+
+PyTypeObject StrokeVertexIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeVertexIterator", /* tp_name */
+ sizeof(BPy_StrokeVertexIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeVertexIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)StrokeVertexIterator_iternext, /* tp_iternext */
+ BPy_StrokeVertexIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeVertexIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h
new file mode 100644
index 00000000000..0c4b6e4bb6c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H
+#define FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H
+
+#include "../../stroke/StrokeIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeVertexIterator_Type;
+
+#define BPy_StrokeVertexIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeVertexIterator_Type) )
+
+/*---------------------------Python BPy_StrokeVertexIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ StrokeInternal::StrokeVertexIterator *sv_it;
+ int reversed;
+} BPy_StrokeVertexIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
new file mode 100644
index 00000000000..660e00b7089
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
@@ -0,0 +1,266 @@
+#include "BPy_ViewEdgeIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewEdgeIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator`\n"
+"\n"
+"Base class for iterators over ViewEdges of the :class:`ViewMap` Graph.\n"
+"Basically the increment() operator of this class should be able to\n"
+"take the decision of \"where\" (on which ViewEdge) to go when pointing\n"
+"on a given ViewEdge.\n"
+"\n"
+".. method:: __init__(begin=None, orientation=True)\n"
+"\n"
+" Builds a ViewEdgeIterator from a starting ViewEdge and its\n"
+" orientation.\n"
+"\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: A ViewEdgeIterator object.\n"
+" :type it: :class:`ViewEdgeIterator`\n";
+
+static int ViewEdgeIterator___init__(BPy_ViewEdgeIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) ))
+ return -1;
+
+ if( obj1 && BPy_ViewEdgeIterator_Check(obj1) ) {
+ self->ve_it = new ViewEdgeInternal::ViewEdgeIterator(*( ((BPy_ViewEdgeIterator *) obj1)->ve_it ));
+
+ } else {
+ ViewEdge *begin;
+ if ( !obj1 || obj1 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj1) )
+ begin = ((BPy_ViewEdge *) obj1)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "1st argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj2 ) ? bool_from_PyBool(obj2) : true;
+
+ self->ve_it = new ViewEdgeInternal::ViewEdgeIterator( begin, orientation);
+
+ }
+
+ self->py_it.it = self->ve_it;
+
+ return 0;
+}
+
+static char ViewEdgeIterator_getCurrentEdge___doc__[] =
+".. method:: getCurrentEdge()\n"
+"\n"
+" Returns the current pointed ViewEdge.\n"
+"\n"
+" :return: The current pointed ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject *ViewEdgeIterator_getCurrentEdge( BPy_ViewEdgeIterator *self ) {
+ ViewEdge *ve = self->ve_it->getCurrentEdge();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_setCurrentEdge___doc__[] =
+".. method:: setCurrentEdge(edge)\n"
+"\n"
+" Sets the current pointed ViewEdge.\n"
+"\n"
+" :arg edge: The current pointed ViewEdge.\n"
+" :type edge: :class:`ViewEdge`\n";
+
+static PyObject *ViewEdgeIterator_setCurrentEdge( BPy_ViewEdgeIterator *self, PyObject *args ) {
+ PyObject *py_ve;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ self->ve_it->setCurrentEdge( ((BPy_ViewEdge *) py_ve)->ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_getBegin___doc__[] =
+".. method:: getBegin()\n"
+"\n"
+" Returns the first ViewEdge used for the iteration.\n"
+"\n"
+" :return: The first ViewEdge used for the iteration.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject *ViewEdgeIterator_getBegin( BPy_ViewEdgeIterator *self ) {
+ ViewEdge *ve = self->ve_it->getBegin();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_setBegin___doc__[] =
+".. method:: setBegin(begin)\n"
+"\n"
+" Sets the first ViewEdge used for the iteration.\n"
+"\n"
+" :arg begin: The first ViewEdge used for the iteration.\n"
+" :type begin: :class:`ViewEdge`\n";
+
+static PyObject *ViewEdgeIterator_setBegin( BPy_ViewEdgeIterator *self, PyObject *args ) {
+ PyObject *py_ve;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ self->ve_it->setBegin( ((BPy_ViewEdge *) py_ve)->ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_getOrientation___doc__[] =
+".. method:: getOrientation()\n"
+"\n"
+" Returns the orientation of the pointed ViewEdge in the iteration.\n"
+"\n"
+" :return: The orientation of the pointed ViewEdge in the iteration.\n"
+" :rtype: bool\n";
+
+static PyObject *ViewEdgeIterator_getOrientation( BPy_ViewEdgeIterator *self ) {
+ return PyBool_from_bool( self->ve_it->getOrientation() );
+}
+
+static char ViewEdgeIterator_setOrientation___doc__[] =
+".. method:: setOrientation(orientation)\n"
+"\n"
+" Sets the orientation of the pointed ViewEdge in the iteration.\n"
+"\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n";
+
+static PyObject *ViewEdgeIterator_setOrientation( BPy_ViewEdgeIterator *self, PyObject *args ) {
+ PyObject *py_b;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_b) ))
+ return NULL;
+
+ self->ve_it->setOrientation( bool_from_PyBool(py_b) );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_changeOrientation___doc__[] =
+".. method:: changeOrientation()\n"
+"\n"
+" Changes the current orientation.\n";
+
+static PyObject *ViewEdgeIterator_changeOrientation( BPy_ViewEdgeIterator *self ) {
+ self->ve_it->changeOrientation();
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed ViewEdge.\n"
+"\n"
+" :return: The pointed ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * ViewEdgeIterator_getObject( BPy_ViewEdgeIterator *self) {
+
+ ViewEdge *ve = self->ve_it->operator*();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------ViewEdgeIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewEdgeIterator_methods[] = {
+ {"getCurrentEdge", ( PyCFunction ) ViewEdgeIterator_getCurrentEdge, METH_NOARGS, ViewEdgeIterator_getCurrentEdge___doc__},
+ {"setCurrentEdge", ( PyCFunction ) ViewEdgeIterator_setCurrentEdge, METH_VARARGS, ViewEdgeIterator_setCurrentEdge___doc__},
+ {"getBegin", ( PyCFunction ) ViewEdgeIterator_getBegin, METH_NOARGS, ViewEdgeIterator_getBegin___doc__},
+ {"setBegin", ( PyCFunction ) ViewEdgeIterator_setBegin, METH_VARARGS, ViewEdgeIterator_setBegin___doc__},
+ {"getOrientation", ( PyCFunction ) ViewEdgeIterator_getOrientation, METH_NOARGS, ViewEdgeIterator_getOrientation___doc__},
+ {"setOrientation", ( PyCFunction ) ViewEdgeIterator_setOrientation, METH_VARARGS, ViewEdgeIterator_setOrientation___doc__},
+ {"changeOrientation", ( PyCFunction ) ViewEdgeIterator_changeOrientation, METH_NOARGS, ViewEdgeIterator_changeOrientation___doc__},
+ {"getObject", ( PyCFunction ) ViewEdgeIterator_getObject, METH_NOARGS, ViewEdgeIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewEdgeIterator type definition ------------------------------*/
+
+PyTypeObject ViewEdgeIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewEdgeIterator", /* tp_name */
+ sizeof(BPy_ViewEdgeIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewEdgeIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewEdgeIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewEdgeIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h
new file mode 100644
index 00000000000..dce90efc8cf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_VIEWEDGEITERATOR_H
+#define FREESTYLE_PYTHON_VIEWEDGEITERATOR_H
+
+
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewEdgeIterator_Type;
+
+#define BPy_ViewEdgeIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewEdgeIterator_Type) )
+
+/*---------------------------Python BPy_ViewEdgeIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewEdgeInternal::ViewEdgeIterator *ve_it;
+} BPy_ViewEdgeIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWEDGEITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
new file mode 100644
index 00000000000..46eb7055217
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
@@ -0,0 +1,140 @@
+#include "BPy_orientedViewEdgeIterator.h"
+
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char orientedViewEdgeIterator___doc__[] =
+"Class hierarchy: :class:`Iterator` > :class:`orientedViewEdgeIterator`\n"
+"\n"
+"Class representing an iterator over oriented ViewEdges around a\n"
+":class:`ViewVertex`. This iterator allows a CCW iteration (in the image\n"
+"plane). An instance of an orientedViewEdgeIterator can only be\n"
+"obtained from a ViewVertex by calling edgesBegin() or edgesEnd().\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An orientedViewEdgeIterator object.\n"
+" :type iBrother: :class:`orientedViewEdgeIterator`\n";
+
+static int orientedViewEdgeIterator___init__(BPy_orientedViewEdgeIterator *self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if (!( PyArg_ParseTuple(args, "|O", &obj) ))
+ return -1;
+
+ if( !obj )
+ self->ove_it = new ViewVertexInternal::orientedViewEdgeIterator();
+ else if( BPy_orientedViewEdgeIterator_Check(obj) )
+ self->ove_it = new ViewVertexInternal::orientedViewEdgeIterator(*( ((BPy_orientedViewEdgeIterator *) obj)->ove_it ));
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_it.it = self->ove_it;
+ self->reversed = 0;
+
+ return 0;
+}
+
+static PyObject * orientedViewEdgeIterator_iternext( BPy_orientedViewEdgeIterator *self ) {
+ ViewVertex::directedViewEdge *dve;
+ if (self->reversed) {
+ if (self->ove_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->ove_it->decrement();
+ dve = self->ove_it->operator->();
+ } else {
+ if (self->ove_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ dve = self->ove_it->operator->();
+ self->ove_it->increment();
+ }
+ return BPy_directedViewEdge_from_directedViewEdge( *dve );
+}
+
+static char orientedViewEdgeIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed oriented ViewEdge.\n"
+"\n"
+" :return: A tuple of the pointed ViewEdge and a boolean value. If\n"
+" the boolean value is true, the ViewEdge is incoming.\n"
+" :rtype: (:class:`directedViewEdge`, bool)\n";
+
+static PyObject * orientedViewEdgeIterator_getObject( BPy_orientedViewEdgeIterator *self) {
+ return BPy_directedViewEdge_from_directedViewEdge( self->ove_it->operator*() );
+}
+
+/*----------------------orientedViewEdgeIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_orientedViewEdgeIterator_methods[] = {
+ {"getObject", ( PyCFunction ) orientedViewEdgeIterator_getObject, METH_NOARGS, orientedViewEdgeIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_orientedViewEdgeIterator type definition ------------------------------*/
+
+PyTypeObject orientedViewEdgeIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "orientedViewEdgeIterator", /* tp_name */
+ sizeof(BPy_orientedViewEdgeIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ orientedViewEdgeIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)orientedViewEdgeIterator_iternext, /* tp_iternext */
+ BPy_orientedViewEdgeIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)orientedViewEdgeIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h
new file mode 100644
index 00000000000..cd9edf1e224
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H
+#define FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H
+
+#include "../../stroke/Stroke.h"
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject orientedViewEdgeIterator_Type;
+
+#define BPy_orientedViewEdgeIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &orientedViewEdgeIterator_Type) )
+
+/*---------------------------Python BPy_orientedViewEdgeIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewVertexInternal::orientedViewEdgeIterator *ove_it;
+ int reversed;
+} BPy_orientedViewEdgeIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp
new file mode 100644
index 00000000000..cdab4b38b95
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp
@@ -0,0 +1,91 @@
+#include "BPy_BackboneStretcherShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BackboneStretcherShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`BackboneStretcherShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iAmount=2.0)\n"
+"\n"
+" Builds a BackboneStretcherShader object.\n"
+"\n"
+" :arg iAmount: The stretching amount value.\n"
+" :type iAmount: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Stretches the stroke at its two extremities and following the\n"
+" respective directions: v(1)v(0) and v(n-1)v(n).\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int BackboneStretcherShader___init__( BPy_BackboneStretcherShader* self, PyObject *args)
+{
+ float f = 2.0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::BackboneStretcherShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_BackboneStretcherShader type definition ------------------------------*/
+
+PyTypeObject BackboneStretcherShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BackboneStretcherShader", /* tp_name */
+ sizeof(BPy_BackboneStretcherShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BackboneStretcherShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BackboneStretcherShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h
new file mode 100644
index 00000000000..35a74c0bda2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H
+#define FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject BackboneStretcherShader_Type;
+
+#define BPy_BackboneStretcherShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BackboneStretcherShader_Type) )
+
+/*---------------------------Python BPy_BackboneStretcherShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_BackboneStretcherShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp
new file mode 100644
index 00000000000..f3d3bfafd08
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp
@@ -0,0 +1,93 @@
+#include "BPy_BezierCurveShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BezierCurveShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`BezierCurveShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(error=4.0)\n"
+"\n"
+" Builds a BezierCurveShader object.\n"
+"\n"
+" :arg error: The error we're allowing for the approximation. This\n"
+" error is the max distance allowed between the new curve and the\n"
+" original geometry.\n"
+" :type error: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Transforms the stroke backbone geometry so that it corresponds to a\n"
+" Bezier Curve approximation of the original backbone geometry.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int BezierCurveShader___init__( BPy_BezierCurveShader* self, PyObject *args)
+{
+ float f = 4.0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::BezierCurveShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_BezierCurveShader type definition ------------------------------*/
+
+PyTypeObject BezierCurveShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BezierCurveShader", /* tp_name */
+ sizeof(BPy_BezierCurveShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BezierCurveShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BezierCurveShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h
new file mode 100644
index 00000000000..b94ef88acea
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_BEZIERCURVESHADER_H
+#define FREESTYLE_PYTHON_BEZIERCURVESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject BezierCurveShader_Type;
+
+#define BPy_BezierCurveShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BezierCurveShader_Type) )
+
+/*---------------------------Python BPy_BezierCurveShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_BezierCurveShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BEZIERCURVESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp
new file mode 100644
index 00000000000..bb77d0ba5be
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp
@@ -0,0 +1,113 @@
+#include "BPy_CalligraphicShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CalligraphicShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`CalligraphicShader`\n"
+"\n"
+"[Thickness Shader]\n"
+"\n"
+".. method:: __init__(iMinThickness, iMaxThickness, iOrientation, iClamp)\n"
+"\n"
+" Builds a CalligraphicShader object.\n"
+"\n"
+" :arg iMinThickness: The minimum thickness in the direction\n"
+" perpendicular to the main direction.\n"
+" :type iMinThickness: float\n"
+" :arg iMaxThickness: The maximum thickness in the main direction.\n"
+" :type iMaxThickness: float\n"
+" :arg iOrientation: The 2D vector giving the main direction.\n"
+" :type iOrientation: :class:`mathutils.Vector`\n"
+" :arg iClamp: If true, the strokes are drawn in black when the stroke\n"
+" direction is between -90 and 90 degrees with respect to the main\n"
+" direction and drawn in white otherwise. If false, the strokes\n"
+" are always drawn in black.\n"
+" :type iClamp: bool\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns thicknesses to the stroke vertices so that the stroke looks\n"
+" like made with a calligraphic tool, i.e. the stroke will be the\n"
+" thickest in a main direction, and the thinest in the direction\n"
+" perpendicular to this one, and an interpolation inbetween.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int CalligraphicShader___init__( BPy_CalligraphicShader* self, PyObject *args)
+{
+ double d1, d2;
+ PyObject *obj3 = 0, *obj4 = 0;
+
+
+ if(!( PyArg_ParseTuple(args, "ddOO", &d1, &d2, &obj3, &obj4) ))
+ return -1;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj3);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 3 must be a 2D vector (either a list of 2 elements or Vector)");
+ return -1;
+ }
+ self->py_ss.ss = new CalligraphicShader(d1, d2, *v, bool_from_PyBool(obj4) );
+ delete v;
+
+ return 0;
+
+}
+
+/*-----------------------BPy_CalligraphicShader type definition ------------------------------*/
+
+PyTypeObject CalligraphicShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CalligraphicShader", /* tp_name */
+ sizeof(BPy_CalligraphicShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CalligraphicShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CalligraphicShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h
new file mode 100644
index 00000000000..c573b0184ad
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H
+#define FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CalligraphicShader_Type;
+
+#define BPy_CalligraphicShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CalligraphicShader_Type)
+
+/*---------------------------Python BPy_CalligraphicShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_CalligraphicShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
new file mode 100644
index 00000000000..d005e8ccfe8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
@@ -0,0 +1,92 @@
+#include "BPy_ColorNoiseShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ColorNoiseShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ColorNoiseShader`\n"
+"\n"
+"[Color shader]\n"
+"\n"
+".. method:: __init__(iAmplitude, iPeriod)\n"
+"\n"
+" Builds a ColorNoiseShader object.\n"
+"\n"
+" :arg iAmplitude: The amplitude of the noise signal.\n"
+" :type iAmplitude: float\n"
+" :arg iPeriod: The period of the noise signal.\n"
+" :type iPeriod: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Shader to add noise to the stroke colors.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ColorNoiseShader___init__( BPy_ColorNoiseShader* self, PyObject *args)
+{
+ float f1, f2;
+
+ if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ColorNoiseShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_ColorNoiseShader type definition ------------------------------*/
+
+PyTypeObject ColorNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ColorNoiseShader", /* tp_name */
+ sizeof(BPy_ColorNoiseShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ColorNoiseShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ColorNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h
new file mode 100644
index 00000000000..694b847565e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_COLORNOISESHADER_H
+#define FREESTYLE_PYTHON_COLORNOISESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ColorNoiseShader_Type;
+
+#define BPy_ColorNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ColorNoiseShader_Type) )
+
+/*---------------------------Python BPy_ColorNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ColorNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_COLORNOISESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
new file mode 100644
index 00000000000..2d48df78da1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
@@ -0,0 +1,98 @@
+#include "BPy_ColorVariationPatternShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ColorVariationPatternShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ColorVariationPatternShader`\n"
+"\n"
+"[Color shader]\n"
+"\n"
+".. method:: __init__(pattern_name, stretch=True)\n"
+"\n"
+" Builds a ColorVariationPatternShader object.\n"
+"\n"
+" :arg pattern_name: The file name of the texture file to use as\n"
+" pattern.\n"
+" :type pattern_name: str\n"
+" :arg stretch: Tells whether the texture must be strecthed or\n"
+" repeted to fit the stroke.\n"
+" :type stretch: bool\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Applies a pattern to vary the original color. The new color is the\n"
+" result of the multiplication of the pattern and the original color.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ColorVariationPatternShader___init__( BPy_ColorVariationPatternShader* self, PyObject *args)
+{
+ const char *s;
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "s|O", &s, &obj) ))
+ return -1;
+
+ bool b = (obj) ? bool_from_PyBool(obj) : true;
+ self->py_ss.ss = new StrokeShaders::ColorVariationPatternShader(s,b);
+ return 0;
+}
+
+/*-----------------------BPy_ColorVariationPatternShader type definition ------------------------------*/
+
+PyTypeObject ColorVariationPatternShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ColorVariationPatternShader", /* tp_name */
+ sizeof(BPy_ColorVariationPatternShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ColorVariationPatternShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ColorVariationPatternShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
new file mode 100644
index 00000000000..b1898ebfecf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H
+#define FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ColorVariationPatternShader_Type;
+
+#define BPy_ColorVariationPatternShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ColorVariationPatternShader_Type) )
+
+/*---------------------------Python BPy_ColorVariationPatternShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ColorVariationPatternShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp
new file mode 100644
index 00000000000..d0f4c365a80
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp
@@ -0,0 +1,96 @@
+#include "BPy_ConstantColorShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstantColorShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ConstantColorShader`\n"
+"\n"
+"[Color shader]\n"
+"\n"
+".. method:: __init__(iR, iG, iB, iAlpha=1.0)\n"
+"\n"
+" Builds a ConstantColorShader object.\n"
+"\n"
+" :arg iR: The red component.\n"
+" :type iR: float\n"
+" :arg iG: The green component.\n"
+" :type iG: float\n"
+" :arg iB: The blue component.\n"
+" :type iB: float\n"
+" :arg iAlpha: The alpha value.\n"
+" :type iAlpha: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns a constant color to every vertex of the Stroke.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ConstantColorShader___init__( BPy_ConstantColorShader* self, PyObject *args)
+{
+ float f1, f2, f3, f4 = 1.0;
+
+ if(!( PyArg_ParseTuple(args, "fff|f", &f1, &f2, &f3, &f4) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ConstantColorShader(f1, f2, f3, f4);
+ return 0;
+}
+
+/*-----------------------BPy_ConstantColorShader type definition ------------------------------*/
+
+PyTypeObject ConstantColorShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstantColorShader", /* tp_name */
+ sizeof(BPy_ConstantColorShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ConstantColorShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ConstantColorShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h
new file mode 100644
index 00000000000..30a09d852fd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H
+#define FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstantColorShader_Type;
+
+#define BPy_ConstantColorShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstantColorShader_Type) )
+
+/*---------------------------Python BPy_ConstantColorShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstantColorShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp
new file mode 100644
index 00000000000..60d3e696675
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp
@@ -0,0 +1,90 @@
+#include "BPy_ConstantThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstantThicknessShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ConstantThicknessShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(thickness)\n"
+"\n"
+" Builds a ConstantThicknessShader object.\n"
+"\n"
+" :arg thickness: The thickness that must be assigned to the stroke.\n"
+" :type thickness: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns an absolute constant thickness to every vertex of the Stroke.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ConstantThicknessShader___init__( BPy_ConstantThicknessShader* self, PyObject *args)
+{
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ConstantThicknessShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_ConstantThicknessShader type definition ------------------------------*/
+
+PyTypeObject ConstantThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstantThicknessShader", /* tp_name */
+ sizeof(BPy_ConstantThicknessShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ConstantThicknessShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ConstantThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h
new file mode 100644
index 00000000000..bb7f3c0f622
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H
+#define FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstantThicknessShader_Type;
+
+#define BPy_ConstantThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstantThicknessShader_Type) )
+
+/*---------------------------Python BPy_ConstantThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstantThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp
new file mode 100644
index 00000000000..3892ccca37b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp
@@ -0,0 +1,96 @@
+#include "BPy_ConstrainedIncreasingThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstrainedIncreasingThicknessShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ConstrainedIncreasingThicknessShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(iThicknessMin, iThicknessMax, iRatio)\n"
+"\n"
+" Builds a ConstrainedIncreasingThicknessShader object.\n"
+"\n"
+" :arg iThicknessMin: The minimum thickness.\n"
+" :type iThicknessMin: float\n"
+" :arg iThicknessMax: The maximum thickness.\n"
+" :type iThicknessMax: float\n"
+" :arg iRatio: The thickness/length ratio that we don't want to exceed. \n"
+" :type iRatio: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Same as the :class:`IncreasingThicknessShader`, but here we allow\n"
+" the user to control the thickness/length ratio so that we don't get\n"
+" fat short lines.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ConstrainedIncreasingThicknessShader___init__( BPy_ConstrainedIncreasingThicknessShader* self, PyObject *args)
+{
+ float f1, f2, f3;
+
+ if(!( PyArg_ParseTuple(args, "fff", &f1, &f2, &f3) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ConstrainedIncreasingThicknessShader(f1, f2, f3);
+ return 0;
+}
+
+/*-----------------------BPy_ConstrainedIncreasingThicknessShader type definition ------------------------------*/
+
+PyTypeObject ConstrainedIncreasingThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstrainedIncreasingThicknessShader", /* tp_name */
+ sizeof(BPy_ConstrainedIncreasingThicknessShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ConstrainedIncreasingThicknessShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ConstrainedIncreasingThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h
new file mode 100644
index 00000000000..38a8aa2bfe0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H
+#define FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstrainedIncreasingThicknessShader_Type;
+
+#define BPy_ConstrainedIncreasingThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstrainedIncreasingThicknessShader_Type) )
+
+/*---------------------------Python BPy_ConstrainedIncreasingThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstrainedIncreasingThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp
new file mode 100644
index 00000000000..79af155b728
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp
@@ -0,0 +1,98 @@
+#include "BPy_GuidingLinesShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GuidingLinesShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`GuidingLinesShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iOffset)\n"
+"\n"
+" Builds a GuidingLinesShader object.\n"
+"\n"
+" :arg iOffset: The line that replaces the stroke is initially in the\n"
+" middle of the initial stroke bounding box. iOffset is the value\n"
+" of the displacement which is applied to this line along its\n"
+" normal.\n"
+" :type iOffset: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Shader to modify the Stroke geometry so that it corresponds to its\n"
+" main direction line. This shader must be used together with the\n"
+" splitting operator using the curvature criterion. Indeed, the\n"
+" precision of the approximation will depend on the size of the\n"
+" stroke's pieces. The bigger the pieces are, the rougher the\n"
+" approximation is.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int GuidingLinesShader___init__( BPy_GuidingLinesShader* self, PyObject *args)
+{
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::GuidingLinesShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_GuidingLinesShader type definition ------------------------------*/
+
+PyTypeObject GuidingLinesShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GuidingLinesShader", /* tp_name */
+ sizeof(BPy_GuidingLinesShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GuidingLinesShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GuidingLinesShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h
new file mode 100644
index 00000000000..e25704c33ba
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_GUIDINGLINESSHADER_H
+#define FREESTYLE_PYTHON_GUIDINGLINESSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GuidingLinesShader_Type;
+
+#define BPy_GuidingLinesShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GuidingLinesShader_Type) )
+
+/*---------------------------Python BPy_GuidingLinesShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_GuidingLinesShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_GUIDINGLINESSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp
new file mode 100644
index 00000000000..063e5cd587d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp
@@ -0,0 +1,106 @@
+#include "BPy_IncreasingColorShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncreasingColorShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`IncreasingColorShader`\n"
+"\n"
+"[Color shader]\n"
+"\n"
+".. method:: __init__(iRm, iGm, iBm, iAlpham, iRM, iGM, iBM, iAlphaM)\n"
+"\n"
+" Builds an IncreasingColorShader object.\n"
+"\n"
+" :arg iRm: The first color red component.\n"
+" :type iRm: float\n"
+" :arg iGm: The first color green component.\n"
+" :type iGm: float\n"
+" :arg iBm: The first color blue component.\n"
+" :type iBm: float\n"
+" :arg iAlpham: The first color alpha value.\n"
+" :type iAlpham: float\n"
+" :arg iRM: The second color red component.\n"
+" :type iRM: float\n"
+" :arg iGM: The second color green component.\n"
+" :type iGM: float\n"
+" :arg iBM: The second color blue component.\n"
+" :type iBM: float\n"
+" :arg iAlphaM: The second color alpha value.\n"
+" :type iAlphaM: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns a varying color to the stroke. The user specifies two\n"
+" colors A and B. The stroke color will change linearly from A to B\n"
+" between the first and the last vertex.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int IncreasingColorShader___init__( BPy_IncreasingColorShader* self, PyObject *args)
+{
+ float f1, f2, f3, f4, f5, f6, f7, f8;
+
+ if(!( PyArg_ParseTuple(args, "ffffffff", &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::IncreasingColorShader(f1, f2, f3, f4, f5, f6, f7, f8);
+ return 0;
+}
+
+/*-----------------------BPy_IncreasingColorShader type definition ------------------------------*/
+
+PyTypeObject IncreasingColorShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncreasingColorShader", /* tp_name */
+ sizeof(BPy_IncreasingColorShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ IncreasingColorShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)IncreasingColorShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h
new file mode 100644
index 00000000000..9bc82e98098
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H
+#define FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncreasingColorShader_Type;
+
+#define BPy_IncreasingColorShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncreasingColorShader_Type) )
+
+/*---------------------------Python BPy_IncreasingColorShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_IncreasingColorShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp
new file mode 100644
index 00000000000..398587df23e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp
@@ -0,0 +1,96 @@
+#include "BPy_IncreasingThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncreasingThicknessShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`IncreasingThicknessShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(iThicknessA, iThicknessB)\n"
+"\n"
+" Builds an IncreasingThicknessShader object.\n"
+"\n"
+" :arg iThicknessA: The first thickness value.\n"
+" :type iThicknessA: float\n"
+" :arg iThicknessB: The second thickness value.\n"
+" :type iThicknessB: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns thicknesses values such as the thickness increases from a\n"
+" thickness value A to a thickness value B between the first vertex\n"
+" to the midpoint vertex and then decreases from B to a A between\n"
+" this midpoint vertex and the last vertex. The thickness is\n"
+" linearly interpolated from A to B.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int IncreasingThicknessShader___init__( BPy_IncreasingThicknessShader* self, PyObject *args)
+{
+ float f1, f2;
+
+ if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::IncreasingThicknessShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_IncreasingThicknessShader type definition ------------------------------*/
+
+PyTypeObject IncreasingThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncreasingThicknessShader", /* tp_name */
+ sizeof(BPy_IncreasingThicknessShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ IncreasingThicknessShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)IncreasingThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h
new file mode 100644
index 00000000000..33d883b1860
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H
+#define FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncreasingThicknessShader_Type;
+
+#define BPy_IncreasingThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncreasingThicknessShader_Type) )
+
+/*---------------------------Python BPy_IncreasingThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_IncreasingThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp
new file mode 100644
index 00000000000..2ea4bf14941
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp
@@ -0,0 +1,97 @@
+#include "BPy_PolygonalizationShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char PolygonalizationShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`PolygonalizationShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iError)\n"
+"\n"
+" Builds a PolygonalizationShader object.\n"
+"\n"
+" :arg iError: The error we want our polygonal approximation to have\n"
+" with respect to the original geometry. The smaller, the closer\n"
+" the new stroke is to the orinal one. This error corresponds to\n"
+" the maximum distance between the new stroke and the old one.\n"
+" :type iError: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Modifies the Stroke geometry so that it looks more \"polygonal\".\n"
+" The basic idea is to start from the minimal stroke approximation\n"
+" consisting in a line joining the first vertex to the last one and\n"
+" to subdivide using the original stroke vertices until a certain\n"
+" error is reached.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int PolygonalizationShader___init__( BPy_PolygonalizationShader* self, PyObject *args)
+{
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::PolygonalizationShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_PolygonalizationShader type definition ------------------------------*/
+
+PyTypeObject PolygonalizationShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "PolygonalizationShader", /* tp_name */
+ sizeof(BPy_PolygonalizationShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ PolygonalizationShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)PolygonalizationShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h
new file mode 100644
index 00000000000..85bcc00e869
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H
+#define FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject PolygonalizationShader_Type;
+
+#define BPy_PolygonalizationShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &PolygonalizationShader_Type) )
+
+/*---------------------------Python BPy_PolygonalizationShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_PolygonalizationShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp
new file mode 100644
index 00000000000..08b1e64f7a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp
@@ -0,0 +1,90 @@
+#include "BPy_SamplingShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SamplingShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`SamplingShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(sampling)\n"
+"\n"
+" Builds a SamplingShader object.\n"
+"\n"
+" :arg sampling: The sampling to use for the stroke resampling.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Resamples the stroke.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int SamplingShader___init__( BPy_SamplingShader* self, PyObject *args)
+{
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::SamplingShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_SamplingShader type definition ------------------------------*/
+
+PyTypeObject SamplingShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SamplingShader", /* tp_name */
+ sizeof(BPy_SamplingShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SamplingShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SamplingShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h
new file mode 100644
index 00000000000..dfc6efb3319
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_SAMPLINGSHADER_H
+#define FREESTYLE_PYTHON_SAMPLINGSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SamplingShader_Type;
+
+#define BPy_SamplingShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SamplingShader_Type) )
+
+/*---------------------------Python BPy_SamplingShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SamplingShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_SAMPLINGSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp
new file mode 100644
index 00000000000..6f62865f99a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp
@@ -0,0 +1,108 @@
+#include "BPy_SmoothingShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SmoothingShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`SmoothingShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iNbIteration, iFactorPoint, ifactorCurvature, iFactorCurvatureDifference, iAnisoPoint, iAnisNormal, iAnisoCurvature, icarricatureFactor)\n"
+"\n"
+" Builds a SmoothingShader object.\n"
+"\n"
+" :arg iNbIteration: The number of iterations (400).\n"
+" :type iNbIteration: int\n"
+" :arg iFactorPoint: 0.0\n"
+" :type iFactorPoint: float\n"
+" :arg ifactorCurvature: 0.0\n"
+" :type ifactorCurvature: float\n"
+" :arg iFactorCurvatureDifference: 0.2\n"
+" :type iFactorCurvatureDifference: float\n"
+" :arg iAnisoPoint: \n"
+" :type iAnisoPoint: float\n"
+" :arg iAnisNormal: 0.0\n"
+" :type iAnisNormal: float\n"
+" :arg iAnisoCurvature: 0.0\n"
+" :type iAnisoCurvature: float\n"
+" :arg icarricatureFactor: 1.0\n"
+" :type icarricatureFactor: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Smoothes the stroke by moving the vertices to make the stroke\n"
+" smoother. Uses curvature flow to converge towards a curve of\n"
+" constant curvature. The diffusion method we use is anisotropic to\n"
+" prevent the diffusion accross corners.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int SmoothingShader___init__( BPy_SmoothingShader* self, PyObject *args)
+{
+ int i1;
+ double d2, d3, d4, d5, d6, d7, d8;
+
+ if(!( PyArg_ParseTuple(args, "iddddddd", &i1, &d2, &d3, &d4, &d5, &d6, &d7, &d8) ))
+ return -1;
+
+ self->py_ss.ss = new SmoothingShader(i1, d2, d3, d4, d5, d6, d7, d8);
+ return 0;
+}
+
+/*-----------------------BPy_SmoothingShader type definition ------------------------------*/
+
+PyTypeObject SmoothingShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SmoothingShader", /* tp_name */
+ sizeof(BPy_SmoothingShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SmoothingShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SmoothingShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h
new file mode 100644
index 00000000000..18d6ca3cc30
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHONSMOOTHINGSHADER_H
+#define FREESTYLE_PYTHONSMOOTHINGSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SmoothingShader_Type;
+
+#define BPy_SmoothingShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SmoothingShader_Type) )
+
+/*---------------------------Python BPy_SmoothingShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SmoothingShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHONSMOOTHINGSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp
new file mode 100644
index 00000000000..245212c3950
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp
@@ -0,0 +1,102 @@
+#include "BPy_SpatialNoiseShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SpatialNoiseShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`SpatialNoiseShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iAmount, ixScale, nbOctave, smooth, pureRandom)\n"
+"\n"
+" Builds a SpatialNoiseShader object.\n"
+"\n"
+" :arg iAmount: The amplitude of the noise.\n"
+" :type iAmount: float\n"
+" :arg ixScale: The noise frequency.\n"
+" :type ixScale: float\n"
+" :arg nbOctave: The number of octaves\n"
+" :type nbOctave: int\n"
+" :arg smooth: True if you want the noise to be smooth.\n"
+" :type smooth: bool\n"
+" :arg pureRandom: True if you don't want any coherence.\n"
+" :type pureRandom: bool\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Spatial Noise stroke shader. Moves the vertices to make the stroke\n"
+" more noisy.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int SpatialNoiseShader___init__( BPy_SpatialNoiseShader* self, PyObject *args)
+{
+ float f1, f2;
+ int i3;
+ PyObject *obj4 = 0, *obj5 = 0;
+
+ if(!( PyArg_ParseTuple(args, "ffiOO", &f1, &f2, &i3, &obj4, &obj5) ))
+ return -1;
+
+ self->py_ss.ss = new SpatialNoiseShader(f1, f2, i3, bool_from_PyBool(obj4), bool_from_PyBool(obj5) );
+ return 0;
+}
+
+/*-----------------------BPy_SpatialNoiseShader type definition ------------------------------*/
+
+PyTypeObject SpatialNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SpatialNoiseShader", /* tp_name */
+ sizeof(BPy_SpatialNoiseShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SpatialNoiseShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SpatialNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h
new file mode 100644
index 00000000000..46e1c12385d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_SPATIALNOISESHADER_H
+#define FREESTYLE_PYTHON_SPATIALNOISESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SpatialNoiseShader_Type;
+
+#define BPy_SpatialNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SpatialNoiseShader_Type) )
+
+/*---------------------------Python BPy_SpatialNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SpatialNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_SPATIALNOISESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
new file mode 100644
index 00000000000..a6e2d9f71e0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
@@ -0,0 +1,117 @@
+#include "BPy_StrokeTextureShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+#include "../BPy_Convert.h"
+#include "../BPy_MediumType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeTextureShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`StrokeTextureShader`\n"
+"\n"
+"[Texture shader]\n"
+"\n"
+".. method:: __init__(textureFile, mediumType=MediumType.OPAQUE_MEDIUM, iTips=False)\n"
+"\n"
+" Builds a StrokeTextureShader object.\n"
+"\n"
+" :arg textureFile: \n"
+" :type textureFile: str\n"
+" :arg mediumType: The medium type and therefore, the blending mode\n"
+" that must be used for the rendering of this stroke.\n"
+" :type mediumType: :class:`MediumType`\n"
+" :arg iTips: Tells whether the texture includes tips or not. If it\n"
+" is the case, the texture image must respect the following format.\n"
+" :type iTips: bool\n"
+"\n"
+" The format of a texture image including tips::\n"
+"\n"
+" ___________\n"
+" | |\n"
+" | A |\n"
+" |___________|\n"
+" | | |\n"
+" | B | C |\n"
+" |_____|_____|\n"
+"\n"
+" * A : The stroke's corpus texture.\n"
+" * B : The stroke's left extremity texture.\n"
+" * C : The stroke's right extremity texture.\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns a texture and a blending mode to the stroke in order to\n"
+" simulate its marks system.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int StrokeTextureShader___init__( BPy_StrokeTextureShader* self, PyObject *args)
+{
+ const char *s1;
+ PyObject *obj2 = 0, *obj3 = 0;
+
+ if(!( PyArg_ParseTuple(args, "s|O!O", &s1, &MediumType_Type, &obj2, &obj3) ))
+ return -1;
+
+ Stroke::MediumType mt = (obj2) ? MediumType_from_BPy_MediumType(obj2) : Stroke::OPAQUE_MEDIUM;
+ bool b = (obj3) ? bool_from_PyBool(obj3) : true;
+
+ self->py_ss.ss = new StrokeShaders::StrokeTextureShader(s1,mt,b);
+ return 0;
+}
+
+/*-----------------------BPy_StrokeTextureShader type definition ------------------------------*/
+
+PyTypeObject StrokeTextureShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeTextureShader", /* tp_name */
+ sizeof(BPy_StrokeTextureShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeTextureShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeTextureShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h
new file mode 100644
index 00000000000..c65506f2f14
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_STROKETEXTURESHADER_H
+#define FREESTYLE_PYTHON_STROKETEXTURESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeTextureShader_Type;
+
+#define BPy_StrokeTextureShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeTextureShader_Type) )
+
+/*---------------------------Python BPy_StrokeTextureShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_StrokeTextureShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_STROKETEXTURESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
new file mode 100644
index 00000000000..7fbb3462fb4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
@@ -0,0 +1,106 @@
+#include "BPy_TextureAssignerShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TextureAssignerShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`TextureAssignerShader`\n"
+"\n"
+"[Texture shader]\n"
+"\n"
+".. method:: __init__(id)\n"
+"\n"
+" Builds a TextureAssignerShader object.\n"
+"\n"
+" :arg id: The preset number to use.\n"
+" :type id: int\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns a texture to the stroke in order to simulate its marks\n"
+" system. This shader takes as input an integer value telling which\n"
+" texture and blending mode to use among a set of predefined\n"
+" textures. Here are the different presets:\n"
+"\n"
+" * 0: `/brushes/charcoalAlpha.bmp`, `MediumType.HUMID_MEDIUM`\n"
+" * 1: `/brushes/washbrushAlpha.bmp`, `MediumType.HUMID_MEDIUM`\n"
+" * 2: `/brushes/oil.bmp`, `MediumType.HUMID_MEDIUM`\n"
+" * 3: `/brushes/oilnoblend.bmp`, `MediumType.HUMID_MEDIUM`\n"
+" * 4: `/brushes/charcoalAlpha.bmp`, `MediumType.DRY_MEDIUM`\n"
+" * 5: `/brushes/washbrushAlpha.bmp`, `MediumType.DRY_MEDIUM`\n"
+" * 6: `/brushes/opaqueDryBrushAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n"
+" * 7: `/brushes/opaqueBrushAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n"
+"\n"
+" Any other value will lead to the following preset:\n"
+"\n"
+" * Default: `/brushes/smoothAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int TextureAssignerShader___init__( BPy_TextureAssignerShader* self, PyObject *args)
+{
+ int i;
+
+ if(!( PyArg_ParseTuple(args, "i", &i) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::TextureAssignerShader(i);
+ return 0;
+}
+
+/*-----------------------BPy_TextureAssignerShader type definition ------------------------------*/
+
+PyTypeObject TextureAssignerShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TextureAssignerShader", /* tp_name */
+ sizeof(BPy_TextureAssignerShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TextureAssignerShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TextureAssignerShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h
new file mode 100644
index 00000000000..9cffc1c1662
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H
+#define FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TextureAssignerShader_Type;
+
+#define BPy_TextureAssignerShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TextureAssignerShader_Type) )
+
+/*---------------------------Python BPy_TextureAssignerShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_TextureAssignerShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp
new file mode 100644
index 00000000000..c0cf2176b52
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp
@@ -0,0 +1,92 @@
+#include "BPy_ThicknessNoiseShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ThicknessNoiseShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ThicknessNoiseShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(iAmplitude, iPeriod)\n"
+"\n"
+" Builds a ThicknessNoiseShader object.\n"
+"\n"
+" :arg iAmplitude: The amplitude of the noise signal.\n"
+" :type iAmplitude: float\n"
+" :arg iPeriod: The period of the noise signal.\n"
+" :type iPeriod: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Adds some noise to the stroke thickness.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ThicknessNoiseShader___init__( BPy_ThicknessNoiseShader* self, PyObject *args)
+{
+ float f1, f2;
+
+ if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ThicknessNoiseShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_ThicknessNoiseShader type definition ------------------------------*/
+
+PyTypeObject ThicknessNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ThicknessNoiseShader", /* tp_name */
+ sizeof(BPy_ThicknessNoiseShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ThicknessNoiseShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ThicknessNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h
new file mode 100644
index 00000000000..c3ef101683e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_THICKNESSNOISESHADER_H
+#define FREESTYLE_PYTHON_THICKNESSNOISESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ThicknessNoiseShader_Type;
+
+#define BPy_ThicknessNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ThicknessNoiseShader_Type) )
+
+/*---------------------------Python BPy_ThicknessNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ThicknessNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_THICKNESSNOISESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
new file mode 100644
index 00000000000..afcfd68fcec
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
@@ -0,0 +1,103 @@
+#include "BPy_ThicknessVariationPatternShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ThicknessVariationPatternShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ThicknessVariationPatternShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(pattern_name, iMinThickness, iMaxThickness, stretch)\n"
+"\n"
+" Builds a ThicknessVariationPatternShader object.\n"
+"\n"
+" :arg pattern_name: The texture file name.\n"
+" :type pattern_name: str\n"
+" :arg iMinThickness: The minimum thickness we don't want to exceed.\n"
+" :type iMinThickness: float\n"
+" :arg iMaxThickness: The maximum thickness we don't want to exceed.\n"
+" :type iMaxThickness: float\n"
+" :arg stretch: Tells whether the pattern texture must be stretched\n"
+" or repeted to fit the stroke.\n"
+" :type stretch: bool\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Applies a pattern (texture) to vary thickness. The new thicknesses\n"
+" are the result of the multiplication of the pattern and the\n"
+" original thickness.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ThicknessVariationPatternShader___init__( BPy_ThicknessVariationPatternShader* self, PyObject *args)
+{
+ const char *s1;
+ float f2 = 1.0, f3 = 5.0;
+ PyObject *obj4 = 0;
+
+ if(!( PyArg_ParseTuple(args, "s|ffO", &s1, &f2, &f3, &obj4) ))
+ return -1;
+
+ bool b = (obj4) ? bool_from_PyBool(obj4) : true;
+ self->py_ss.ss = new StrokeShaders::ThicknessVariationPatternShader(s1, f2, f3, b);
+ return 0;
+}
+
+/*-----------------------BPy_ThicknessVariationPatternShader type definition ------------------------------*/
+
+PyTypeObject ThicknessVariationPatternShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ThicknessVariationPatternShader", /* tp_name */
+ sizeof(BPy_ThicknessVariationPatternShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ThicknessVariationPatternShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ThicknessVariationPatternShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
new file mode 100644
index 00000000000..302c9e005ae
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H
+#define FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ThicknessVariationPatternShader_Type;
+
+#define BPy_ThicknessVariationPatternShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ThicknessVariationPatternShader_Type) )
+
+/*---------------------------Python BPy_ThicknessVariationPatternShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ThicknessVariationPatternShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp
new file mode 100644
index 00000000000..8241a03892c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp
@@ -0,0 +1,91 @@
+#include "BPy_TipRemoverShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TipRemoverShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`TipRemoverShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(tipLength)\n"
+"\n"
+" Builds a TipRemoverShader object.\n"
+"\n"
+" :arg tipLength: The length of the piece of stroke we want to remove\n"
+" at each extremity.\n"
+" :type tipLength: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Removes the stroke's extremities.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int TipRemoverShader___init__( BPy_TipRemoverShader* self, PyObject *args)
+{
+ double d;
+
+ if(!( PyArg_ParseTuple(args, "d", &d) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::TipRemoverShader(d);
+ return 0;
+}
+
+/*-----------------------BPy_TipRemoverShader type definition ------------------------------*/
+
+PyTypeObject TipRemoverShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TipRemoverShader", /* tp_name */
+ sizeof(BPy_TipRemoverShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TipRemoverShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TipRemoverShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h
new file mode 100644
index 00000000000..a1b2e3988bc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_TIPREMOVERSHADER_H
+#define FREESTYLE_PYTHON_TIPREMOVERSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TipRemoverShader_Type;
+
+#define BPy_TipRemoverShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TipRemoverShader_Type) )
+
+/*---------------------------Python BPy_TipRemoverShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_TipRemoverShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_TIPREMOVERSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
new file mode 100644
index 00000000000..2d9828c232c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
@@ -0,0 +1,90 @@
+#include "BPy_fstreamShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char fstreamShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`fstreamShader`\n"
+"\n"
+"[Output shader]\n"
+"\n"
+".. method:: __init__(iFileName)\n"
+"\n"
+" Builds a fstreamShader object.\n"
+"\n"
+" :arg iFileName: The output file name.\n"
+" :type iFileName: str\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Streams the Stroke in a file.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int fstreamShader___init__( BPy_fstreamShader* self, PyObject *args)
+{
+ const char *s;
+
+ if(!( PyArg_ParseTuple(args, "s", &s) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::fstreamShader(s);
+ return 0;
+}
+
+/*-----------------------BPy_fstreamShader type definition ------------------------------*/
+
+PyTypeObject fstreamShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "fstreamShader", /* tp_name */
+ sizeof(BPy_fstreamShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ fstreamShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)fstreamShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h
new file mode 100644
index 00000000000..843d50505db
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FSTREAMSHADER_H
+#define FREESTYLE_PYTHON_FSTREAMSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject fstreamShader_Type;
+
+#define BPy_fstreamShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &fstreamShader_Type) )
+
+/*---------------------------Python BPy_fstreamShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_fstreamShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_FSTREAMSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp
new file mode 100644
index 00000000000..722c51c440e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp
@@ -0,0 +1,84 @@
+#include "BPy_streamShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char streamShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`streamShader`\n"
+"\n"
+"[Output shader]\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a streamShader object.\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Streams the Stroke into stdout.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int streamShader___init__( BPy_streamShader* self, PyObject *args)
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::streamShader();
+ return 0;
+}
+
+/*-----------------------BPy_streamShader type definition ------------------------------*/
+
+PyTypeObject streamShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "streamShader", /* tp_name */
+ sizeof(BPy_streamShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ streamShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)streamShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h
new file mode 100644
index 00000000000..38056d5fa59
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_STREAMSHADER_H
+#define FREESTYLE_PYTHON_STREAMSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject streamShader_Type;
+
+#define BPy_streamShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &streamShader_Type) )
+
+/*---------------------------Python BPy_streamShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_streamShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_STREAMSHADER_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp
new file mode 100644
index 00000000000..b61b9baf033
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp
@@ -0,0 +1,215 @@
+#include "BPy_UnaryFunction0DDouble.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h"
+#include "UnaryFunction0D_double/BPy_DensityF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedXF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedYF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedZF0D.h"
+#include "UnaryFunction0D_double/BPy_GetXF0D.h"
+#include "UnaryFunction0D_double/BPy_GetYF0D.h"
+#include "UnaryFunction0D_double/BPy_GetZF0D.h"
+#include "UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h"
+#include "UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h"
+
+#include "../Director.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DDouble_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DDouble_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DDouble_Type );
+ PyModule_AddObject(module, "UnaryFunction0DDouble", (PyObject *)&UnaryFunction0DDouble_Type);
+
+ if( PyType_Ready( &DensityF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &DensityF0D_Type );
+ PyModule_AddObject(module, "DensityF0D", (PyObject *)&DensityF0D_Type);
+
+ if( PyType_Ready( &LocalAverageDepthF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &LocalAverageDepthF0D_Type );
+ PyModule_AddObject(module, "LocalAverageDepthF0D", (PyObject *)&LocalAverageDepthF0D_Type);
+
+ if( PyType_Ready( &Curvature2DAngleF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Curvature2DAngleF0D_Type );
+ PyModule_AddObject(module, "Curvature2DAngleF0D", (PyObject *)&Curvature2DAngleF0D_Type);
+
+ if( PyType_Ready( &GetProjectedXF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedXF0D_Type );
+ PyModule_AddObject(module, "GetProjectedXF0D", (PyObject *)&GetProjectedXF0D_Type);
+
+ if( PyType_Ready( &GetProjectedYF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedYF0D_Type );
+ PyModule_AddObject(module, "GetProjectedYF0D", (PyObject *)&GetProjectedYF0D_Type);
+
+ if( PyType_Ready( &GetProjectedZF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedZF0D_Type );
+ PyModule_AddObject(module, "GetProjectedZF0D", (PyObject *)&GetProjectedZF0D_Type);
+
+ if( PyType_Ready( &GetXF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetXF0D_Type );
+ PyModule_AddObject(module, "GetXF0D", (PyObject *)&GetXF0D_Type);
+
+ if( PyType_Ready( &GetYF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetYF0D_Type );
+ PyModule_AddObject(module, "GetYF0D", (PyObject *)&GetYF0D_Type);
+
+ if( PyType_Ready( &GetZF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetZF0D_Type );
+ PyModule_AddObject(module, "GetZF0D", (PyObject *)&GetZF0D_Type);
+
+ if( PyType_Ready( &ZDiscontinuityF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ZDiscontinuityF0D_Type );
+ PyModule_AddObject(module, "ZDiscontinuityF0D", (PyObject *)&ZDiscontinuityF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DDouble___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DDouble___init__(BPy_UnaryFunction0DDouble* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_double = new UnaryFunction0D<double>();
+ self->uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DDouble___dealloc__(BPy_UnaryFunction0DDouble* self)
+{
+ if (self->uf0D_double)
+ delete self->uf0D_double;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DDouble___repr__(BPy_UnaryFunction0DDouble* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_double->getName().c_str(), self->uf0D_double );
+}
+
+static char UnaryFunction0DDouble_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DDouble_getName( BPy_UnaryFunction0DDouble *self )
+{
+ return PyUnicode_FromString( self->uf0D_double->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DDouble___call__( BPy_UnaryFunction0DDouble *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_double)) == typeid(UnaryFunction0D<double>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_double->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_double->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble( self->uf0D_double->result );
+
+}
+
+/*----------------------UnaryFunction0DDouble instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DDouble_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DDouble_getName, METH_NOARGS, UnaryFunction0DDouble_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DDouble type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DDouble_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DDouble", /* tp_name */
+ sizeof(BPy_UnaryFunction0DDouble), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DDouble___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DDouble___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DDouble___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DDouble___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DDouble_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DDouble___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h
new file mode 100644
index 00000000000..dbeb70cc082
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DDouble_Type;
+
+#define BPy_UnaryFunction0DDouble_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DDouble_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DDouble structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<double> *uf0D_double;
+} BPy_UnaryFunction0DDouble;
+
+/*---------------------------Python BPy_UnaryFunction0DDouble visible prototypes-----------*/
+int UnaryFunction0DDouble_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp
new file mode 100644
index 00000000000..a5ecd46b3bd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp
@@ -0,0 +1,159 @@
+#include "BPy_UnaryFunction0DEdgeNature.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DEdgeNature_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DEdgeNature_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DEdgeNature_Type );
+ PyModule_AddObject(module, "UnaryFunction0DEdgeNature", (PyObject *)&UnaryFunction0DEdgeNature_Type);
+
+ if( PyType_Ready( &CurveNatureF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CurveNatureF0D_Type );
+ PyModule_AddObject(module, "CurveNatureF0D", (PyObject *)&CurveNatureF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DEdgeNature___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DEdgeNature`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`Nature` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DEdgeNature___init__(BPy_UnaryFunction0DEdgeNature* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_edgenature = new UnaryFunction0D<Nature::EdgeNature>();
+ self->uf0D_edgenature->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DEdgeNature___dealloc__(BPy_UnaryFunction0DEdgeNature* self)
+{
+ if (self->uf0D_edgenature)
+ delete self->uf0D_edgenature;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DEdgeNature___repr__(BPy_UnaryFunction0DEdgeNature* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_edgenature->getName().c_str(), self->uf0D_edgenature );
+}
+
+static char UnaryFunction0DEdgeNature_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DEdgeNature_getName( BPy_UnaryFunction0DEdgeNature *self )
+{
+ return PyUnicode_FromString( self->uf0D_edgenature->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DEdgeNature___call__( BPy_UnaryFunction0DEdgeNature *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_edgenature)) == typeid(UnaryFunction0D<Nature::EdgeNature>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_edgenature->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_edgenature->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_Nature_from_Nature( self->uf0D_edgenature->result );
+
+}
+
+/*----------------------UnaryFunction0DEdgeNature instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DEdgeNature_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DEdgeNature_getName, METH_NOARGS, UnaryFunction0DEdgeNature_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DEdgeNature type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DEdgeNature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DEdgeNature", /* tp_name */
+ sizeof(BPy_UnaryFunction0DEdgeNature), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DEdgeNature___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DEdgeNature___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DEdgeNature___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DEdgeNature___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DEdgeNature_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DEdgeNature___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h
new file mode 100644
index 00000000000..d6959cae57f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DEdgeNature_Type;
+
+#define BPy_UnaryFunction0DEdgeNature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DEdgeNature_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DEdgeNature structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Nature::EdgeNature> *uf0D_edgenature;
+} BPy_UnaryFunction0DEdgeNature;
+
+/*---------------------------Python BPy_UnaryFunction0DEdgeNature visible prototypes-----------*/
+int UnaryFunction0DEdgeNature_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp
new file mode 100644
index 00000000000..72ca2acf3b7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp
@@ -0,0 +1,189 @@
+#include "BPy_UnaryFunction0DFloat.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h"
+#include "UnaryFunction0D_float/BPy_GetParameterF0D.h"
+#include "UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadMapPixelF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DFloat_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DFloat_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DFloat_Type );
+ PyModule_AddObject(module, "UnaryFunction0DFloat", (PyObject *)&UnaryFunction0DFloat_Type);
+
+ if( PyType_Ready( &GetCurvilinearAbscissaF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetCurvilinearAbscissaF0D_Type );
+ PyModule_AddObject(module, "GetCurvilinearAbscissaF0D", (PyObject *)&GetCurvilinearAbscissaF0D_Type);
+
+ if( PyType_Ready( &GetParameterF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetParameterF0D_Type );
+ PyModule_AddObject(module, "GetParameterF0D", (PyObject *)&GetParameterF0D_Type);
+
+ if( PyType_Ready( &GetViewMapGradientNormF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetViewMapGradientNormF0D_Type );
+ PyModule_AddObject(module, "GetViewMapGradientNormF0D", (PyObject *)&GetViewMapGradientNormF0D_Type);
+
+ if( PyType_Ready( &ReadCompleteViewMapPixelF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ReadCompleteViewMapPixelF0D_Type );
+ PyModule_AddObject(module, "ReadCompleteViewMapPixelF0D", (PyObject *)&ReadCompleteViewMapPixelF0D_Type);
+
+ if( PyType_Ready( &ReadMapPixelF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ReadMapPixelF0D_Type );
+ PyModule_AddObject(module, "ReadMapPixelF0D", (PyObject *)&ReadMapPixelF0D_Type);
+
+ if( PyType_Ready( &ReadSteerableViewMapPixelF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ReadSteerableViewMapPixelF0D_Type );
+ PyModule_AddObject(module, "ReadSteerableViewMapPixelF0D", (PyObject *)&ReadSteerableViewMapPixelF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DFloat___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DFloat___init__(BPy_UnaryFunction0DFloat* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_float = new UnaryFunction0D<float>();
+ self->uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DFloat___dealloc__(BPy_UnaryFunction0DFloat* self)
+{
+ if (self->uf0D_float)
+ delete self->uf0D_float;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DFloat___repr__(BPy_UnaryFunction0DFloat* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_float->getName().c_str(), self->uf0D_float );
+}
+
+static char UnaryFunction0DFloat_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DFloat_getName( BPy_UnaryFunction0DFloat *self )
+{
+ return PyUnicode_FromString( self->uf0D_float->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DFloat___call__( BPy_UnaryFunction0DFloat *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_float)) == typeid(UnaryFunction0D<float>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_float->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_float->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble( self->uf0D_float->result );
+
+}
+
+/*----------------------UnaryFunction0DFloat instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DFloat_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DFloat_getName, METH_NOARGS, UnaryFunction0DFloat_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DFloat type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DFloat_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DFloat", /* tp_name */
+ sizeof(BPy_UnaryFunction0DFloat), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DFloat___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DFloat___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DFloat___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DFloat___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DFloat_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DFloat___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h
new file mode 100644
index 00000000000..fbf207d48c7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DFloat_Type;
+
+#define BPy_UnaryFunction0DFloat_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DFloat_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DFloat structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<float> *uf0D_float;
+} BPy_UnaryFunction0DFloat;
+
+/*---------------------------Python BPy_UnaryFunction0DFloat visible prototypes-----------*/
+int UnaryFunction0DFloat_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp
new file mode 100644
index 00000000000..3c4ccdbcbf1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp
@@ -0,0 +1,158 @@
+#include "BPy_UnaryFunction0DId.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Id/BPy_ShapeIdF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DId_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DId_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DId_Type );
+ PyModule_AddObject(module, "UnaryFunction0DId", (PyObject *)&UnaryFunction0DId_Type);
+
+ if( PyType_Ready( &ShapeIdF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ShapeIdF0D_Type );
+ PyModule_AddObject(module, "ShapeIdF0D", (PyObject *)&ShapeIdF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DId___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DId`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return an :class:`Id` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DId___init__(BPy_UnaryFunction0DId* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_id = new UnaryFunction0D<Id>();
+ self->uf0D_id->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DId___dealloc__(BPy_UnaryFunction0DId* self)
+{
+ if (self->uf0D_id)
+ delete self->uf0D_id;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DId___repr__(BPy_UnaryFunction0DId* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_id->getName().c_str(), self->uf0D_id );
+}
+
+static char UnaryFunction0DId_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DId_getName( BPy_UnaryFunction0DId *self )
+{
+ return PyUnicode_FromString( self->uf0D_id->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DId___call__( BPy_UnaryFunction0DId *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_id)) == typeid(UnaryFunction0D<Id>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_id->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_id->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_Id_from_Id( self->uf0D_id->result );
+}
+
+/*----------------------UnaryFunction0DId instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DId_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DId_getName, METH_NOARGS, UnaryFunction0DId_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DId type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DId_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DId", /* tp_name */
+ sizeof(BPy_UnaryFunction0DId), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DId___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DId___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DId___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DId___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DId_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DId___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h
new file mode 100644
index 00000000000..159e24e2674
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DID_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DID_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../system/Id.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DId_Type;
+
+#define BPy_UnaryFunction0DId_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DId_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DId structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Id> *uf0D_id;
+} BPy_UnaryFunction0DId;
+
+/*---------------------------Python BPy_UnaryFunction0DId visible prototypes-----------*/
+int UnaryFunction0DId_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DID_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp
new file mode 100644
index 00000000000..d61453172b9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp
@@ -0,0 +1,160 @@
+#include "BPy_UnaryFunction0DMaterial.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Material/BPy_MaterialF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DMaterial_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DMaterial_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DMaterial_Type );
+ PyModule_AddObject(module, "UnaryFunction0DMaterial", (PyObject *)&UnaryFunction0DMaterial_Type);
+
+ if( PyType_Ready( &MaterialF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &MaterialF0D_Type );
+ PyModule_AddObject(module, "MaterialF0D", (PyObject *)&MaterialF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DMaterial___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DMaterial`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`Material` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DMaterial___init__(BPy_UnaryFunction0DMaterial* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_material = new UnaryFunction0D<FrsMaterial>();
+ self->uf0D_material->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DMaterial___dealloc__(BPy_UnaryFunction0DMaterial* self)
+{
+ if (self->uf0D_material)
+ delete self->uf0D_material;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+
+static PyObject * UnaryFunction0DMaterial___repr__(BPy_UnaryFunction0DMaterial* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_material->getName().c_str(), self->uf0D_material );
+}
+
+static char UnaryFunction0DMaterial_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DMaterial_getName( BPy_UnaryFunction0DMaterial *self )
+{
+ return PyUnicode_FromString( self->uf0D_material->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DMaterial___call__( BPy_UnaryFunction0DMaterial *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_material)) == typeid(UnaryFunction0D<FrsMaterial>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_material->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_material->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_FrsMaterial_from_FrsMaterial( self->uf0D_material->result );
+
+}
+
+/*----------------------UnaryFunction0DMaterial instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DMaterial_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DMaterial_getName, METH_NOARGS, UnaryFunction0DMaterial_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DMaterial type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DMaterial_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DMaterial", /* tp_name */
+ sizeof(BPy_UnaryFunction0DMaterial), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DMaterial___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DMaterial___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DMaterial___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DMaterial___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DMaterial_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DMaterial___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h
new file mode 100644
index 00000000000..02fb2b99ccd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../scene_graph/FrsMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DMaterial_Type;
+
+#define BPy_UnaryFunction0DMaterial_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DMaterial_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DMaterial structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<FrsMaterial> *uf0D_material;
+} BPy_UnaryFunction0DMaterial;
+
+/*---------------------------Python BPy_UnaryFunction0DMaterial visible prototypes-----------*/
+int UnaryFunction0DMaterial_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
new file mode 100644
index 00000000000..37f6a2ab342
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
@@ -0,0 +1,159 @@
+#include "BPy_UnaryFunction0DUnsigned.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DUnsigned_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DUnsigned_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DUnsigned_Type );
+ PyModule_AddObject(module, "UnaryFunction0DUnsigned", (PyObject *)&UnaryFunction0DUnsigned_Type);
+
+ if( PyType_Ready( &QuantitativeInvisibilityF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &QuantitativeInvisibilityF0D_Type );
+ PyModule_AddObject(module, "QuantitativeInvisibilityF0D", (PyObject *)&QuantitativeInvisibilityF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DUnsigned___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DUnsigned`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return an int value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+ " Default constructor.\n";
+
+static int UnaryFunction0DUnsigned___init__(BPy_UnaryFunction0DUnsigned* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_unsigned = new UnaryFunction0D<unsigned int>();
+ self->uf0D_unsigned->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DUnsigned___dealloc__(BPy_UnaryFunction0DUnsigned* self)
+{
+ if (self->uf0D_unsigned)
+ delete self->uf0D_unsigned;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DUnsigned___repr__(BPy_UnaryFunction0DUnsigned* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_unsigned->getName().c_str(), self->uf0D_unsigned );
+}
+
+static char UnaryFunction0DUnsigned_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DUnsigned_getName( BPy_UnaryFunction0DUnsigned *self )
+{
+ return PyUnicode_FromString( self->uf0D_unsigned->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DUnsigned___call__( BPy_UnaryFunction0DUnsigned *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_unsigned)) == typeid(UnaryFunction0D<unsigned int>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_unsigned->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_unsigned->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyLong_FromLong( self->uf0D_unsigned->result );
+
+}
+
+/*----------------------UnaryFunction0DUnsigned instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DUnsigned_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DUnsigned_getName, METH_NOARGS, UnaryFunction0DUnsigned_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DUnsigned type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DUnsigned_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DUnsigned", /* tp_name */
+ sizeof(BPy_UnaryFunction0DUnsigned), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DUnsigned___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DUnsigned___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DUnsigned___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DUnsigned___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DUnsigned_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DUnsigned___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h
new file mode 100644
index 00000000000..4776ce30918
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DUnsigned_Type;
+
+#define BPy_UnaryFunction0DUnsigned_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DUnsigned_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DUnsigned structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<unsigned int> *uf0D_unsigned;
+} BPy_UnaryFunction0DUnsigned;
+
+/*---------------------------Python BPy_UnaryFunction0DUnsigned visible prototypes-----------*/
+int UnaryFunction0DUnsigned_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp
new file mode 100644
index 00000000000..9c9e2e85568
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp
@@ -0,0 +1,165 @@
+#include "BPy_UnaryFunction0DVec2f.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h"
+#include "UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVec2f_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DVec2f_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DVec2f_Type );
+ PyModule_AddObject(module, "UnaryFunction0DVec2f", (PyObject *)&UnaryFunction0DVec2f_Type);
+
+ if( PyType_Ready( &Normal2DF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Normal2DF0D_Type );
+ PyModule_AddObject(module, "Normal2DF0D", (PyObject *)&Normal2DF0D_Type);
+
+ if( PyType_Ready( &VertexOrientation2DF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &VertexOrientation2DF0D_Type );
+ PyModule_AddObject(module, "VertexOrientation2DF0D", (PyObject *)&VertexOrientation2DF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVec2f___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec2f`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a 2D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVec2f___init__(BPy_UnaryFunction0DVec2f* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_vec2f = new UnaryFunction0D<Vec2f>();
+ self->uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVec2f___dealloc__(BPy_UnaryFunction0DVec2f* self)
+{
+ if (self->uf0D_vec2f)
+ delete self->uf0D_vec2f;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DVec2f___repr__(BPy_UnaryFunction0DVec2f* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vec2f->getName().c_str(), self->uf0D_vec2f );
+}
+
+static char UnaryFunction0DVec2f_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DVec2f_getName( BPy_UnaryFunction0DVec2f *self )
+{
+ return PyUnicode_FromString( self->uf0D_vec2f->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DVec2f___call__( BPy_UnaryFunction0DVec2f *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_vec2f)) == typeid(UnaryFunction0D<Vec2f>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vec2f->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_vec2f->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec2f( self->uf0D_vec2f->result );
+
+}
+
+/*----------------------UnaryFunction0DVec2f instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DVec2f_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DVec2f_getName, METH_NOARGS, UnaryFunction0DVec2f_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DVec2f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVec2f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVec2f", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVec2f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVec2f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVec2f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVec2f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVec2f___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DVec2f_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVec2f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h
new file mode 100644
index 00000000000..6628d629a41
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVec2f_Type;
+
+#define BPy_UnaryFunction0DVec2f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVec2f_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DVec2f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Vec2f> *uf0D_vec2f;
+} BPy_UnaryFunction0DVec2f;
+
+/*---------------------------Python BPy_UnaryFunction0DVec2f visible prototypes-----------*/
+int UnaryFunction0DVec2f_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp
new file mode 100644
index 00000000000..13f8dd69fa1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp
@@ -0,0 +1,159 @@
+#include "BPy_UnaryFunction0DVec3f.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVec3f_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DVec3f_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DVec3f_Type );
+ PyModule_AddObject(module, "UnaryFunction0DVec3f", (PyObject *)&UnaryFunction0DVec3f_Type);
+
+ if( PyType_Ready( &VertexOrientation3DF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &VertexOrientation3DF0D_Type );
+ PyModule_AddObject(module, "VertexOrientation3DF0D", (PyObject *)&VertexOrientation3DF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVec3f___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec3f`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a 3D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVec3f___init__(BPy_UnaryFunction0DVec3f* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_vec3f = new UnaryFunction0D<Vec3f>();
+ self->uf0D_vec3f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVec3f___dealloc__(BPy_UnaryFunction0DVec3f* self)
+{
+ if (self->uf0D_vec3f)
+ delete self->uf0D_vec3f;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DVec3f___repr__(BPy_UnaryFunction0DVec3f* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vec3f->getName().c_str(), self->uf0D_vec3f );
+}
+
+static char UnaryFunction0DVec3f_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DVec3f_getName( BPy_UnaryFunction0DVec3f *self )
+{
+ return PyUnicode_FromString( self->uf0D_vec3f->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DVec3f___call__( BPy_UnaryFunction0DVec3f *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_vec3f)) == typeid(UnaryFunction0D<Vec3f>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vec3f->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_vec3f->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec3f( self->uf0D_vec3f->result );
+
+}
+
+/*----------------------UnaryFunction0DVec3f instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DVec3f_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DVec3f_getName, METH_NOARGS, UnaryFunction0DVec3f_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DVec3f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVec3f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVec3f", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVec3f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVec3f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVec3f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVec3f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVec3f___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DVec3f_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVec3f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h
new file mode 100644
index 00000000000..47ec89fb179
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVec3f_Type;
+
+#define BPy_UnaryFunction0DVec3f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVec3f_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DVec3f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Vec3f> *uf0D_vec3f;
+} BPy_UnaryFunction0DVec3f;
+
+/*---------------------------Python BPy_UnaryFunction0DVec3f visible prototypes-----------*/
+int UnaryFunction0DVec3f_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
new file mode 100644
index 00000000000..40564b018d6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
@@ -0,0 +1,172 @@
+#include "BPy_UnaryFunction0DVectorViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVectorViewShape_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DVectorViewShape_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DVectorViewShape_Type );
+ PyModule_AddObject(module, "UnaryFunction0DVectorViewShape", (PyObject *)&UnaryFunction0DVectorViewShape_Type);
+
+ if( PyType_Ready( &GetOccludersF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetOccludersF0D_Type );
+ PyModule_AddObject(module, "GetOccludersF0D", (PyObject *)&GetOccludersF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVectorViewShape___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVectorViewShape`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a list of :class:`ViewShape`\n"
+"objects.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVectorViewShape___init__(BPy_UnaryFunction0DVectorViewShape* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_vectorviewshape = new UnaryFunction0D< std::vector<ViewShape*> >();
+ self->uf0D_vectorviewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVectorViewShape___dealloc__(BPy_UnaryFunction0DVectorViewShape* self)
+{
+ if (self->uf0D_vectorviewshape)
+ delete self->uf0D_vectorviewshape;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DVectorViewShape___repr__(BPy_UnaryFunction0DVectorViewShape* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vectorviewshape->getName().c_str(), self->uf0D_vectorviewshape );
+}
+
+static char UnaryFunction0DVectorViewShape_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DVectorViewShape_getName( BPy_UnaryFunction0DVectorViewShape *self )
+{
+ return PyUnicode_FromString( self->uf0D_vectorviewshape->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DVectorViewShape___call__( BPy_UnaryFunction0DVectorViewShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_vectorviewshape)) == typeid(UnaryFunction0D< std::vector<ViewShape*> >) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vectorviewshape->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_vectorviewshape->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ PyObject *list = PyList_New(0);
+ PyObject *item;
+ for( unsigned int i = 0; i < self->uf0D_vectorviewshape->result.size(); i++) {
+ ViewShape *v = self->uf0D_vectorviewshape->result[i];
+ if (v) {
+ item = BPy_ViewShape_from_ViewShape(*v);
+ } else {
+ item = Py_None;
+ Py_INCREF(item);
+ }
+ PyList_Append(list, item);
+ }
+
+ return list;
+}
+
+/*----------------------UnaryFunction0DVectorViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DVectorViewShape_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DVectorViewShape_getName, METH_NOARGS, UnaryFunction0DVectorViewShape_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DVectorViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVectorViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVectorViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVectorViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVectorViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVectorViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVectorViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVectorViewShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DVectorViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVectorViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h
new file mode 100644
index 00000000000..77f96e96f20
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include <vector>
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVectorViewShape_Type;
+
+#define BPy_UnaryFunction0DVectorViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVectorViewShape_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DVectorViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D< std::vector<ViewShape*> > *uf0D_vectorviewshape;
+} BPy_UnaryFunction0DVectorViewShape;
+
+/*---------------------------Python BPy_UnaryFunction0DVectorViewShape visible prototypes-----------*/
+int UnaryFunction0DVectorViewShape_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp
new file mode 100644
index 00000000000..5f3f18453ba
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp
@@ -0,0 +1,165 @@
+#include "BPy_UnaryFunction0DViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h"
+#include "UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DViewShape_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DViewShape_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DViewShape_Type );
+ PyModule_AddObject(module, "UnaryFunction0DViewShape", (PyObject *)&UnaryFunction0DViewShape_Type);
+
+ if( PyType_Ready( &GetOccludeeF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetOccludeeF0D_Type );
+ PyModule_AddObject(module, "GetOccludeeF0D", (PyObject *)&GetOccludeeF0D_Type);
+
+ if( PyType_Ready( &GetShapeF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetShapeF0D_Type );
+ PyModule_AddObject(module, "GetShapeF0D", (PyObject *)&GetShapeF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DViewShape___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DViewShape`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`ViewShape` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DViewShape___init__(BPy_UnaryFunction0DViewShape* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_viewshape = new UnaryFunction0D<ViewShape*>();
+ self->uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DViewShape___dealloc__(BPy_UnaryFunction0DViewShape* self)
+{
+ if (self->uf0D_viewshape)
+ delete self->uf0D_viewshape;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DViewShape___repr__(BPy_UnaryFunction0DViewShape* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_viewshape->getName().c_str(), self->uf0D_viewshape );
+}
+
+static char UnaryFunction0DViewShape_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction0DViewShape_getName( BPy_UnaryFunction0DViewShape *self )
+{
+ return PyUnicode_FromString( self->uf0D_viewshape->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DViewShape___call__( BPy_UnaryFunction0DViewShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_viewshape)) == typeid(UnaryFunction0D<ViewShape*>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_viewshape->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_viewshape->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_ViewShape_from_ViewShape( *(self->uf0D_viewshape->result) );
+
+}
+
+/*----------------------UnaryFunction0DViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DViewShape_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DViewShape_getName, METH_NOARGS, UnaryFunction0DViewShape_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction0DViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DViewShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h
new file mode 100644
index 00000000000..68c888eb36b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DViewShape_Type;
+
+#define BPy_UnaryFunction0DViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DViewShape_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<ViewShape*> *uf0D_viewshape;
+} BPy_UnaryFunction0DViewShape;
+
+/*---------------------------Python BPy_UnaryFunction0DViewShape visible prototypes-----------*/
+int UnaryFunction0DViewShape_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp
new file mode 100644
index 00000000000..49e8310380a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_ShapeIdF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ShapeIdF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DId` > :class:`ShapeIdF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a ShapeIdF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`Id` of the Shape the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator belongs to. This evaluation can\n"
+" be ambiguous (in the case of a :class:`TVertex` for example). This\n"
+" functor tries to remove this ambiguity using the context offered by\n"
+" the 1D element to which the Interface0DIterator belongs to.\n"
+" However, there still can be problematic cases, and the user willing\n"
+" to deal with this cases in a specific way should implement its own\n"
+" getShapeIdF0D functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Id of the Shape the pointed Interface0D belongs to.\n"
+" :rtype: :class:`Id`\n";
+
+static int ShapeIdF0D___init__( BPy_ShapeIdF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_id.uf0D_id = new Functions0D::ShapeIdF0D();
+ self->py_uf0D_id.uf0D_id->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ShapeIdF0D type definition ------------------------------*/
+
+PyTypeObject ShapeIdF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ShapeIdF0D", /* tp_name */
+ sizeof(BPy_ShapeIdF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ShapeIdF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DId_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ShapeIdF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h
new file mode 100644
index 00000000000..11995bb4e88
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_SHAPEIDF0D_H
+#define FREESTYLE_PYTHON_SHAPEIDF0D_H
+
+#include "../BPy_UnaryFunction0DId.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ShapeIdF0D_Type;
+
+#define BPy_ShapeIdF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ShapeIdF0D_Type) )
+
+/*---------------------------Python BPy_ShapeIdF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DId py_uf0D_id;
+} BPy_ShapeIdF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SHAPEIDF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
new file mode 100644
index 00000000000..85ea137134a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
@@ -0,0 +1,96 @@
+#include "BPy_MaterialF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char MaterialF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DMaterial` > :class:`MaterialF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a MaterialF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the material of the object evaluated at the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator. This\n"
+" evaluation can be ambiguous (in the case of a :class:`TVertex` for\n"
+" example. This functor tries to remove this ambiguity using the\n"
+" context offered by the 1D element to which the Interface0DIterator\n"
+" belongs to and by arbitrary chosing the material of the face that\n"
+" lies on its left when following the 1D element if there are two\n"
+" different materials on each side of the point. However, there\n"
+" still can be problematic cases, and the user willing to deal with\n"
+" this cases in a specific way should implement its own getMaterial\n"
+" functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The material of the object evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: :class:`Material`\n";
+
+static int MaterialF0D___init__( BPy_MaterialF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_material.uf0D_material = new Functions0D::MaterialF0D();
+ self->py_uf0D_material.uf0D_material->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_MaterialF0D type definition ------------------------------*/
+
+PyTypeObject MaterialF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "MaterialF0D", /* tp_name */
+ sizeof(BPy_MaterialF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ MaterialF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DMaterial_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)MaterialF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h
new file mode 100644
index 00000000000..1ae30484ba5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_MATERIALF0D_H
+#define FREESTYLE_PYTHON_MATERIALF0D_H
+
+#include "../BPy_UnaryFunction0DMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject MaterialF0D_Type;
+
+#define BPy_MaterialF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &MaterialF0D_Type) )
+
+/*---------------------------Python BPy_MaterialF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DMaterial py_uf0D_material;
+} BPy_MaterialF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_MATERIALF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp
new file mode 100644
index 00000000000..0d2023313ca
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_CurveNatureF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurveNatureF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DEdgeNature` > :class:`CurveNatureF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a CurveNatureF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`Nature` of the 1D element the Interface0D pointed\n"
+" by the Interface0DIterator belongs to.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The nature of the 1D element to which the pointed Interface0D\n"
+" belongs.\n"
+" :rtype: :class:`Nature`\n";
+
+static int CurveNatureF0D___init__( BPy_CurveNatureF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_edgenature.uf0D_edgenature = new Functions0D::CurveNatureF0D();
+ self->py_uf0D_edgenature.uf0D_edgenature->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_CurveNatureF0D type definition ------------------------------*/
+
+PyTypeObject CurveNatureF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurveNatureF0D", /* tp_name */
+ sizeof(BPy_CurveNatureF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurveNatureF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DEdgeNature_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurveNatureF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h
new file mode 100644
index 00000000000..63b3050c474
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CURVENATUREF0D_H
+#define FREESTYLE_PYTHON_CURVENATUREF0D_H
+
+#include "../BPy_UnaryFunction0DEdgeNature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurveNatureF0D_Type;
+
+#define BPy_CurveNatureF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurveNatureF0D_Type) )
+
+/*---------------------------Python BPy_CurveNatureF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DEdgeNature py_uf0D_edgenature;
+} BPy_CurveNatureF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVENATUREF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp
new file mode 100644
index 00000000000..fdec2c324c6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp
@@ -0,0 +1,89 @@
+#include "BPy_Normal2DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Normal2DF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec2f` > :class:`Normal2DF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a Normal2DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a two-dimensional vector giving the normalized 2D normal to\n"
+" the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The normal is evaluated at the pointed\n"
+" Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D normal of the 1D element evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Normal2DF0D___init__( BPy_Normal2DF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_vec2f.uf0D_vec2f = new Functions0D::Normal2DF0D();
+ self->py_uf0D_vec2f.uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_Normal2DF0D type definition ------------------------------*/
+
+PyTypeObject Normal2DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Normal2DF0D", /* tp_name */
+ sizeof(BPy_Normal2DF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Normal2DF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Normal2DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h
new file mode 100644
index 00000000000..0b3be2df428
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_NORMAL2DF0D_H
+#define FREESTYLE_PYTHON_NORMAL2DF0D_H
+
+#include "../BPy_UnaryFunction0DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Normal2DF0D_Type;
+
+#define BPy_Normal2DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Normal2DF0D_Type) )
+
+/*---------------------------Python BPy_Normal2DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec2f py_uf0D_vec2f;
+} BPy_Normal2DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NORMAL2DF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp
new file mode 100644
index 00000000000..f362293e179
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp
@@ -0,0 +1,89 @@
+#include "BPy_VertexOrientation2DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char VertexOrientation2DF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec2f` > :class:`VertexOrientation2DF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a VertexOrientation2DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a two-dimensional vector giving the 2D oriented tangent to\n"
+" the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 2D oriented tangent is evaluated\n"
+" at the pointed Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D oriented tangent to the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int VertexOrientation2DF0D___init__( BPy_VertexOrientation2DF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_vec2f.uf0D_vec2f = new Functions0D::VertexOrientation2DF0D();
+ self->py_uf0D_vec2f.uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_VertexOrientation2DF0D type definition ------------------------------*/
+
+PyTypeObject VertexOrientation2DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "VertexOrientation2DF0D", /* tp_name */
+ sizeof(BPy_VertexOrientation2DF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ VertexOrientation2DF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)VertexOrientation2DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h
new file mode 100644
index 00000000000..1cce9b592ba
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H
+#define FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H
+
+#include "../BPy_UnaryFunction0DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject VertexOrientation2DF0D_Type;
+
+#define BPy_VertexOrientation2DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &VertexOrientation2DF0D_Type) )
+
+/*---------------------------Python BPy_VertexOrientation2DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec2f py_uf0D_vec2f;
+} BPy_VertexOrientation2DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp
new file mode 100644
index 00000000000..8cb3e88efe3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp
@@ -0,0 +1,89 @@
+#include "BPy_VertexOrientation3DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char VertexOrientation3DF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec3f` > :class:`VertexOrientation3DF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a VertexOrientation3DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a three-dimensional vector giving the 3D oriented tangent\n"
+" to the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 3D oriented tangent is evaluated\n"
+" at the pointed Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 3D oriented tangent to the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int VertexOrientation3DF0D___init__( BPy_VertexOrientation3DF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_vec3f.uf0D_vec3f = new Functions0D::VertexOrientation3DF0D();
+ self->py_uf0D_vec3f.uf0D_vec3f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_VertexOrientation3DF0D type definition ------------------------------*/
+
+PyTypeObject VertexOrientation3DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "VertexOrientation3DF0D", /* tp_name */
+ sizeof(BPy_VertexOrientation3DF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ VertexOrientation3DF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DVec3f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)VertexOrientation3DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h
new file mode 100644
index 00000000000..80cac529f0b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H
+#define FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H
+
+#include "../BPy_UnaryFunction0DVec3f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject VertexOrientation3DF0D_Type;
+
+#define BPy_VertexOrientation3DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &VertexOrientation3DF0D_Type) )
+
+/*---------------------------Python BPy_VertexOrientation3DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec3f py_uf0D_vec3f;
+} BPy_VertexOrientation3DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp
new file mode 100644
index 00000000000..8bfd2bb2638
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetOccludeeF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludeeF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DViewShape` > :class:`GetOccludeeF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludeeF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`ViewShape` that the Interface0D pointed by the\n"
+" Interface0DIterator occludes.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The ViewShape occluded by the pointed Interface0D.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static int GetOccludeeF0D___init__( BPy_GetOccludeeF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_viewshape.uf0D_viewshape = new Functions0D::GetOccludeeF0D();
+ self->py_uf0D_viewshape.uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludeeF0D type definition ------------------------------*/
+
+PyTypeObject GetOccludeeF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludeeF0D", /* tp_name */
+ sizeof(BPy_GetOccludeeF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetOccludeeF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludeeF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h
new file mode 100644
index 00000000000..fd4f7d92bbb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETOCCLUDEEF0D_H
+#define FREESTYLE_PYTHON_GETOCCLUDEEF0D_H
+
+#include "../BPy_UnaryFunction0DViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludeeF0D_Type;
+
+#define BPy_GetOccludeeF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludeeF0D_Type) )
+
+/*---------------------------Python BPy_GetOccludeeF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DViewShape py_uf0D_viewshape;
+} BPy_GetOccludeeF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETOCCLUDEEF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp
new file mode 100644
index 00000000000..3cc931edec5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetShapeF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetShapeF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DViewShape` > :class:`GetShapeF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetShapeF0D.cpp object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`ViewShape` containing the Interface0D pointed\n"
+" by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The ViewShape containing the pointed Interface0D.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static int GetShapeF0D___init__( BPy_GetShapeF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_viewshape.uf0D_viewshape = new Functions0D::GetShapeF0D();
+ self->py_uf0D_viewshape.uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetShapeF0D type definition ------------------------------*/
+
+PyTypeObject GetShapeF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetShapeF0D", /* tp_name */
+ sizeof(BPy_GetShapeF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetShapeF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetShapeF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h
new file mode 100644
index 00000000000..040c753968d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETSHAPEF0D_H
+#define FREESTYLE_PYTHON_GETSHAPEF0D_H
+
+#include "../BPy_UnaryFunction0DViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetShapeF0D_Type;
+
+#define BPy_GetShapeF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetShapeF0D_Type) )
+
+/*---------------------------Python BPy_GetShapeF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DViewShape py_uf0D_viewshape;
+} BPy_GetShapeF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETSHAPEF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp
new file mode 100644
index 00000000000..e28b1ca138a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp
@@ -0,0 +1,89 @@
+#include "BPy_Curvature2DAngleF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Curvature2DAngleF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`Curvature2DAngleF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a Curvature2DAngleF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a real value giving the 2D curvature (as an angle) of the\n"
+" 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 2D curvature is evaluated at the\n"
+" Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D curvature of the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int Curvature2DAngleF0D___init__( BPy_Curvature2DAngleF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::Curvature2DAngleF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_Curvature2DAngleF0D type definition ------------------------------*/
+
+PyTypeObject Curvature2DAngleF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Curvature2DAngleF0D", /* tp_name */
+ sizeof(BPy_Curvature2DAngleF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Curvature2DAngleF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Curvature2DAngleF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h
new file mode 100644
index 00000000000..810ba04db8a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H
+#define FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Curvature2DAngleF0D_Type;
+
+#define BPy_Curvature2DAngleF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Curvature2DAngleF0D_Type) )
+
+/*---------------------------Python BPy_Curvature2DAngleF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_Curvature2DAngleF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp
new file mode 100644
index 00000000000..64c2d453552
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp
@@ -0,0 +1,96 @@
+#include "BPy_DensityF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`DensityF0D`\n"
+"\n"
+".. method:: __init__(sigma=2.0)\n"
+"\n"
+" Builds a DensityF0D object.\n"
+"\n"
+" :arg sigma: The gaussian sigma value ndicating the X value for\n"
+" which the gaussian function is 0.5. It leads to the window size\n"
+" value (the larger, the smoother).\n"
+" :type sigma: float\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the density of the (result) image evaluated at the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator. This\n"
+" density is evaluated using a pixels square window around the\n"
+" evaluation point and integrating these values using a gaussian.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The density of the image evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: float\n";
+
+static int DensityF0D___init__( BPy_DensityF0D* self, PyObject *args)
+{
+ double d = 2;
+
+ if( !PyArg_ParseTuple(args, "|d", &d) )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::DensityF0D(d);
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_DensityF0D type definition ------------------------------*/
+
+PyTypeObject DensityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityF0D", /* tp_name */
+ sizeof(BPy_DensityF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DensityF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h
new file mode 100644
index 00000000000..17ea95a771c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_DENSITYF0D_H
+#define FREESTYLE_PYTHON_DENSITYF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityF0D_Type;
+
+#define BPy_DensityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityF0D_Type) )
+
+/*---------------------------Python BPy_DensityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_DensityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_DENSITYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp
new file mode 100644
index 00000000000..e539ca10dc8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetProjectedXF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedXF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedXF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedXF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the X 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The X 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedXF0D___init__( BPy_GetProjectedXF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedXF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedXF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedXF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedXF0D", /* tp_name */
+ sizeof(BPy_GetProjectedXF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedXF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedXF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h
new file mode 100644
index 00000000000..da73623cbf0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDXF0D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDXF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedXF0D_Type;
+
+#define BPy_GetProjectedXF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedXF0D_Type) )
+
+/*---------------------------Python BPy_GetProjectedXF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedXF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDXF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp
new file mode 100644
index 00000000000..4e1fbbd699c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetProjectedYF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedYF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedYF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedYF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Y 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Y 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedYF0D___init__( BPy_GetProjectedYF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedYF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedYF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedYF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedYF0D", /* tp_name */
+ sizeof(BPy_GetProjectedYF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedYF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedYF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h
new file mode 100644
index 00000000000..3a26e093747
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDYF0D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDYF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedYF0D_Type;
+
+#define BPy_GetProjectedYF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedYF0D_Type) )
+
+/*---------------------------Python BPy_GetProjectedYF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedYF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp
new file mode 100644
index 00000000000..73a68b8f6a8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetProjectedZF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedZF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedZF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedZF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Z 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Z 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedZF0D___init__( BPy_GetProjectedZF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedZF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedZF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedZF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedZF0D", /* tp_name */
+ sizeof(BPy_GetProjectedZF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedZF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedZF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h
new file mode 100644
index 00000000000..aa41b70c660
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDZF0D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDZF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedZF0D_Type;
+
+#define BPy_GetProjectedZF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedZF0D_Type) )
+
+/*---------------------------Python BPy_GetProjectedZF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedZF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDZF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp
new file mode 100644
index 00000000000..099977e35eb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetXF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetXF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetXF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetXF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the X 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The X 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetXF0D___init__( BPy_GetXF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetXF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetXF0D type definition ------------------------------*/
+
+PyTypeObject GetXF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetXF0D", /* tp_name */
+ sizeof(BPy_GetXF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetXF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetXF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h
new file mode 100644
index 00000000000..69e9a892f4a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETXF0D_H
+#define FREESTYLE_PYTHON_GETXF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetXF0D_Type;
+
+#define BPy_GetXF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetXF0D_Type) )
+
+/*---------------------------Python BPy_GetXF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetXF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETXF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp
new file mode 100644
index 00000000000..7640dafef6f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetYF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetYF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetYF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetYF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Y 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Y 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetYF0D___init__( BPy_GetYF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetYF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetYF0D type definition ------------------------------*/
+
+PyTypeObject GetYF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetYF0D", /* tp_name */
+ sizeof(BPy_GetYF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetYF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetYF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h
new file mode 100644
index 00000000000..0601f38585f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETYF0D_H
+#define FREESTYLE_PYTHON_GETYF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetYF0D_Type;
+
+#define BPy_GetYF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetYF0D_Type) )
+
+/*---------------------------Python BPy_GetYF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetYF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp
new file mode 100644
index 00000000000..01932c2b4ed
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetZF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetZF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetZF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetZF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Z 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Z 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetZF0D___init__( BPy_GetZF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetZF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetZF0D type definition ------------------------------*/
+
+PyTypeObject GetZF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetZF0D", /* tp_name */
+ sizeof(BPy_GetZF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetZF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetZF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h
new file mode 100644
index 00000000000..eac52426600
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETZF0D_H
+#define FREESTYLE_PYTHON_GETZF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetZF0D_Type;
+
+#define BPy_GetZF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetZF0D_Type) )
+
+/*---------------------------Python BPy_GetZF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetZF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETZF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp
new file mode 100644
index 00000000000..f268fdf7003
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_LocalAverageDepthF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char LocalAverageDepthF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`LocalAverageDepthF0D`\n"
+"\n"
+".. method:: __init__(maskSize=5.0)\n"
+"\n"
+" Builds a LocalAverageDepthF0D object.\n"
+"\n"
+" :arg maskSize: The size of the mask.\n"
+" :type maskSize: float\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the average depth around the :class:`Interface0D` pointed\n"
+" by the Interface0DIterator. The result is obtained by querying the\n"
+" depth buffer on a window around that point.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The average depth around the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int LocalAverageDepthF0D___init__( BPy_LocalAverageDepthF0D* self, PyObject *args)
+{
+ double d = 5.0;
+
+ if( !PyArg_ParseTuple(args, "|d", &d) )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::LocalAverageDepthF0D(d);
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_LocalAverageDepthF0D type definition ------------------------------*/
+
+PyTypeObject LocalAverageDepthF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "LocalAverageDepthF0D", /* tp_name */
+ sizeof(BPy_LocalAverageDepthF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ LocalAverageDepthF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)LocalAverageDepthF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h
new file mode 100644
index 00000000000..7385e1d24c1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H
+#define FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject LocalAverageDepthF0D_Type;
+
+#define BPy_LocalAverageDepthF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &LocalAverageDepthF0D_Type) )
+
+/*---------------------------Python BPy_LocalAverageDepthF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_LocalAverageDepthF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
new file mode 100644
index 00000000000..20e2ab31bda
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
@@ -0,0 +1,91 @@
+#include "BPy_ZDiscontinuityF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ZDiscontinuityF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`ZDiscontinuityF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a ZDiscontinuityF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a real value giving the distance between the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator and the\n"
+" shape that lies behind (occludee). This distance is evaluated in\n"
+" the camera space and normalized between 0 and 1. Therefore, if no\n"
+" oject is occluded by the shape to which the Interface0D belongs to,\n"
+" 1 is returned.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The normalized distance between the pointed Interface0D\n"
+" and the occludee.\n"
+" :rtype: float\n";
+
+static int ZDiscontinuityF0D___init__( BPy_ZDiscontinuityF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::ZDiscontinuityF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ZDiscontinuityF0D type definition ------------------------------*/
+
+PyTypeObject ZDiscontinuityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ZDiscontinuityF0D", /* tp_name */
+ sizeof(BPy_ZDiscontinuityF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ZDiscontinuityF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ZDiscontinuityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h
new file mode 100644
index 00000000000..a26ba4fdbd6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H
+#define FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ZDiscontinuityF0D_Type;
+
+#define BPy_ZDiscontinuityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ZDiscontinuityF0D_Type) )
+
+/*---------------------------Python BPy_ZDiscontinuityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_ZDiscontinuityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp
new file mode 100644
index 00000000000..4aaceb3559a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_GetCurvilinearAbscissaF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetCurvilinearAbscissaF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetCurvilinearAbscissaF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetCurvilinearAbscissaF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the curvilinear abscissa of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator in the context of its 1D\n"
+" element.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The curvilinear abscissa of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetCurvilinearAbscissaF0D___init__( BPy_GetCurvilinearAbscissaF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetCurvilinearAbscissaF0D();
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetCurvilinearAbscissaF0D type definition ------------------------------*/
+
+PyTypeObject GetCurvilinearAbscissaF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetCurvilinearAbscissaF0D", /* tp_name */
+ sizeof(BPy_GetCurvilinearAbscissaF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetCurvilinearAbscissaF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetCurvilinearAbscissaF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h
new file mode 100644
index 00000000000..0cb56fcec70
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H
+#define FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetCurvilinearAbscissaF0D_Type;
+
+#define BPy_GetCurvilinearAbscissaF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetCurvilinearAbscissaF0D_Type) )
+
+/*---------------------------Python BPy_GetCurvilinearAbscissaF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetCurvilinearAbscissaF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp
new file mode 100644
index 00000000000..aeea47deffc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetParameterF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetParameterF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetParameterF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetParameterF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the parameter of the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator in the context of its 1D element.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The parameter of an Interface0D.\n"
+" :rtype: float\n";
+
+static int GetParameterF0D___init__( BPy_GetParameterF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetParameterF0D();
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetParameterF0D type definition ------------------------------*/
+
+PyTypeObject GetParameterF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetParameterF0D", /* tp_name */
+ sizeof(BPy_GetParameterF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetParameterF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetParameterF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h
new file mode 100644
index 00000000000..4817e5cec86
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPARAMETERF0D_H
+#define FREESTYLE_PYTHON_GETPARAMETERF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetParameterF0D_Type;
+
+#define BPy_GetParameterF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetParameterF0D_Type) )
+
+/*---------------------------Python BPy_GetParameterF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetParameterF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPARAMETERF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp
new file mode 100644
index 00000000000..bac65716ba9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp
@@ -0,0 +1,93 @@
+#include "BPy_GetViewMapGradientNormF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetViewMapGradientNormF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetViewMapGradientNormF0D`\n"
+"\n"
+".. method:: __init__(level)\n"
+"\n"
+" Builds a GetViewMapGradientNormF0D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the norm of the gradient of the global viewmap density\n"
+" image.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The norm of the gradient of the global viewmap density\n"
+" image.\n"
+" :rtype: float\n";
+
+static int GetViewMapGradientNormF0D___init__( BPy_GetViewMapGradientNormF0D* self, PyObject *args)
+{
+ int i;
+
+ if( !PyArg_ParseTuple(args, "i", &i) )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetViewMapGradientNormF0D(i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetViewMapGradientNormF0D type definition ------------------------------*/
+
+PyTypeObject GetViewMapGradientNormF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetViewMapGradientNormF0D", /* tp_name */
+ sizeof(BPy_GetViewMapGradientNormF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetViewMapGradientNormF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetViewMapGradientNormF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h
new file mode 100644
index 00000000000..c072ba7f408
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H
+#define FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetViewMapGradientNormF0D_Type;
+
+#define BPy_GetViewMapGradientNormF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetViewMapGradientNormF0D_Type) )
+
+/*---------------------------Python BPy_GetViewMapGradientNormF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetViewMapGradientNormF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp
new file mode 100644
index 00000000000..6a40266cf7b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp
@@ -0,0 +1,91 @@
+#include "BPy_ReadCompleteViewMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadCompleteViewMapPixelF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadCompleteViewMapPixelF0D`\n"
+"\n"
+".. method:: __init__(level)\n"
+"\n"
+" Builds a ReadCompleteViewMapPixelF0D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in one of the level of the complete viewmap.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in one of the level of the complete viewmap.\n"
+" :rtype: float\n";
+
+static int ReadCompleteViewMapPixelF0D___init__( BPy_ReadCompleteViewMapPixelF0D* self, PyObject *args)
+{
+ int i;
+
+ if( !PyArg_ParseTuple(args, "i", &i) )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadCompleteViewMapPixelF0D(i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadCompleteViewMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadCompleteViewMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadCompleteViewMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadCompleteViewMapPixelF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ReadCompleteViewMapPixelF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadCompleteViewMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h
new file mode 100644
index 00000000000..6a10e6c06a4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H
+#define FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadCompleteViewMapPixelF0D_Type;
+
+#define BPy_ReadCompleteViewMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadCompleteViewMapPixelF0D_Type) )
+
+/*---------------------------Python BPy_ReadCompleteViewMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadCompleteViewMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp
new file mode 100644
index 00000000000..74cf688507e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_ReadMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadMapPixelF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadMapPixelF0D`\n"
+"\n"
+".. method:: __init__(iMapName, level)\n"
+"\n"
+" Builds a ReadMapPixelF0D object.\n"
+"\n"
+" :arg iMapName: The name of the map to be read.\n"
+" :type iMapName: str\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in a map.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in a map.\n"
+" :rtype: float\n";
+
+static int ReadMapPixelF0D___init__( BPy_ReadMapPixelF0D* self, PyObject *args)
+{
+ const char *s;
+ int i;
+
+ if( !PyArg_ParseTuple(args, "si", &s, &i) )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadMapPixelF0D(s,i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadMapPixelF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ReadMapPixelF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h
new file mode 100644
index 00000000000..9aed0cd82bf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_READMAPPIXELF0D_H
+#define FREESTYLE_PYTHON_READMAPPIXELF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadMapPixelF0D_Type;
+
+#define BPy_ReadMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadMapPixelF0D_Type) )
+
+/*---------------------------Python BPy_ReadMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_READMAPPIXELF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
new file mode 100644
index 00000000000..db0145e3e2a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
@@ -0,0 +1,95 @@
+#include "BPy_ReadSteerableViewMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadSteerableViewMapPixelF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadSteerableViewMapPixelF0D`\n"
+"\n"
+".. method:: __init__(nOrientation, level)\n"
+"\n"
+" Builds a ReadSteerableViewMapPixelF0D object.\n"
+"\n"
+" :arg nOrientation: The integer belonging to [0, 4] indicating the\n"
+" orientation (E, NE, N, NW) we are interested in.\n"
+" :type nOrientation: int\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in one of the level of one of the steerable viewmaps.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in one of the level of one of the steerable viewmaps.\n"
+" :rtype: float\n";
+
+static int ReadSteerableViewMapPixelF0D___init__( BPy_ReadSteerableViewMapPixelF0D* self, PyObject *args)
+{
+ unsigned int u;
+ int i;
+
+ if( !PyArg_ParseTuple(args, "Ii", &u, &i) )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadSteerableViewMapPixelF0D(u,i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadSteerableViewMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadSteerableViewMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadSteerableViewMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadSteerableViewMapPixelF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ReadSteerableViewMapPixelF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadSteerableViewMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h
new file mode 100644
index 00000000000..a881a10f72d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H
+#define FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadSteerableViewMapPixelF0D_Type;
+
+#define BPy_ReadSteerableViewMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadSteerableViewMapPixelF0D_Type) )
+
+/*---------------------------Python BPy_ReadSteerableViewMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadSteerableViewMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp
new file mode 100644
index 00000000000..e993a99c1d8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_QuantitativeInvisibilityF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DUnsigned` > :class:`QuantitativeInvisibilityF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a QuantitativeInvisibilityF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the quantitative invisibility of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator. This evaluation can be\n"
+" ambiguous (in the case of a :class:`TVertex` for example). This\n"
+" functor tries to remove this ambiguity using the context offered by\n"
+" the 1D element to which the Interface0D belongs to. However, there\n"
+" still can be problematic cases, and the user willing to deal with\n"
+" this cases in a specific way should implement its own getQIF0D\n"
+" functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The quantitative invisibility of the pointed Interface0D.\n"
+" :rtype: int\n";
+
+static int QuantitativeInvisibilityF0D___init__( BPy_QuantitativeInvisibilityF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_unsigned.uf0D_unsigned = new Functions0D::QuantitativeInvisibilityF0D();
+ self->py_uf0D_unsigned.uf0D_unsigned->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityF0D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityF0D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ QuantitativeInvisibilityF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DUnsigned_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h
new file mode 100644
index 00000000000..39b73343608
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H
+#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H
+
+#include "../BPy_UnaryFunction0DUnsigned.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityF0D_Type;
+
+#define BPy_QuantitativeInvisibilityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityF0D_Type) )
+
+/*---------------------------Python BPy_QuantitativeInvisibilityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DUnsigned py_uf0D_unsigned;
+} BPy_QuantitativeInvisibilityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp
new file mode 100644
index 00000000000..50686ce92f9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_GetOccludersF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludersF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVectorViewShape` > :class:`GetOccludersF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludersF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a list of :class:`ViewShape` objects occluding the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A list of ViewShape objects occluding the pointed\n"
+" Interface0D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludersF0D___init__( BPy_GetOccludersF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_vectorviewshape.uf0D_vectorviewshape = new Functions0D::GetOccludersF0D();
+ self->py_uf0D_vectorviewshape.uf0D_vectorviewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludersF0D type definition ------------------------------*/
+
+PyTypeObject GetOccludersF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludersF0D", /* tp_name */
+ sizeof(BPy_GetOccludersF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetOccludersF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludersF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h
new file mode 100644
index 00000000000..0e92158a2e7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETOCCLUDERSF0D_H
+#define FREESTYLE_PYTHON_GETOCCLUDERSF0D_H
+
+#include "../BPy_UnaryFunction0DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludersF0D_Type;
+
+#define BPy_GetOccludersF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludersF0D_Type) )
+
+/*---------------------------Python BPy_GetOccludersF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVectorViewShape py_uf0D_vectorviewshape;
+} BPy_GetOccludersF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETOCCLUDERSF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
new file mode 100644
index 00000000000..07fb48dd9a8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
@@ -0,0 +1,289 @@
+#include "BPy_UnaryFunction1DDouble.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h"
+#include "UnaryFunction1D_double/BPy_DensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedXF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedYF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedZF1D.h"
+#include "UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h"
+#include "UnaryFunction1D_double/BPy_GetXF1D.h"
+#include "UnaryFunction1D_double/BPy_GetYF1D.h"
+#include "UnaryFunction1D_double/BPy_GetZF1D.h"
+#include "UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h"
+#include "UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DDouble_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DDouble_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DDouble_Type );
+ PyModule_AddObject(module, "UnaryFunction1DDouble", (PyObject *)&UnaryFunction1DDouble_Type);
+
+ if( PyType_Ready( &DensityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &DensityF1D_Type );
+ PyModule_AddObject(module, "DensityF1D", (PyObject *)&DensityF1D_Type);
+
+ if( PyType_Ready( &Curvature2DAngleF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Curvature2DAngleF1D_Type );
+ PyModule_AddObject(module, "Curvature2DAngleF1D", (PyObject *)&Curvature2DAngleF1D_Type);
+
+ if( PyType_Ready( &GetCompleteViewMapDensityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetCompleteViewMapDensityF1D_Type );
+ PyModule_AddObject(module, "GetCompleteViewMapDensityF1D", (PyObject *)&GetCompleteViewMapDensityF1D_Type);
+
+ if( PyType_Ready( &GetDirectionalViewMapDensityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetDirectionalViewMapDensityF1D_Type );
+ PyModule_AddObject(module, "GetDirectionalViewMapDensityF1D", (PyObject *)&GetDirectionalViewMapDensityF1D_Type);
+
+ if( PyType_Ready( &GetProjectedXF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedXF1D_Type );
+ PyModule_AddObject(module, "GetProjectedXF1D", (PyObject *)&GetProjectedXF1D_Type);
+
+ if( PyType_Ready( &GetProjectedYF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedYF1D_Type );
+ PyModule_AddObject(module, "GetProjectedYF1D", (PyObject *)&GetProjectedYF1D_Type);
+
+ if( PyType_Ready( &GetProjectedZF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedZF1D_Type );
+ PyModule_AddObject(module, "GetProjectedZF1D", (PyObject *)&GetProjectedZF1D_Type);
+
+ if( PyType_Ready( &GetSteerableViewMapDensityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetSteerableViewMapDensityF1D_Type );
+ PyModule_AddObject(module, "GetSteerableViewMapDensityF1D", (PyObject *)&GetSteerableViewMapDensityF1D_Type);
+
+ if( PyType_Ready( &GetViewMapGradientNormF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetViewMapGradientNormF1D_Type );
+ PyModule_AddObject(module, "GetViewMapGradientNormF1D", (PyObject *)&GetViewMapGradientNormF1D_Type);
+
+ if( PyType_Ready( &GetXF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetXF1D_Type );
+ PyModule_AddObject(module, "GetXF1D", (PyObject *)&GetXF1D_Type);
+
+ if( PyType_Ready( &GetYF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetYF1D_Type );
+ PyModule_AddObject(module, "GetYF1D", (PyObject *)&GetYF1D_Type);
+
+ if( PyType_Ready( &GetZF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetZF1D_Type );
+ PyModule_AddObject(module, "GetZF1D", (PyObject *)&GetZF1D_Type);
+
+ if( PyType_Ready( &LocalAverageDepthF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &LocalAverageDepthF1D_Type );
+ PyModule_AddObject(module, "LocalAverageDepthF1D", (PyObject *)&LocalAverageDepthF1D_Type);
+
+ if( PyType_Ready( &ZDiscontinuityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ZDiscontinuityF1D_Type );
+ PyModule_AddObject(module, "ZDiscontinuityF1D", (PyObject *)&ZDiscontinuityF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DDouble___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DDouble___init__(BPy_UnaryFunction1DDouble* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_double = new UnaryFunction1D<double>();
+ else {
+ self->uf1D_double = new UnaryFunction1D<double>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_double->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DDouble___dealloc__(BPy_UnaryFunction1DDouble* self)
+{
+ if (self->uf1D_double)
+ delete self->uf1D_double;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DDouble___repr__(BPy_UnaryFunction1DDouble* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_double->getName().c_str(), self->uf1D_double );
+}
+
+static char UnaryFunction1DDouble_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction1DDouble_getName( BPy_UnaryFunction1DDouble *self )
+{
+ return PyUnicode_FromString( self->uf1D_double->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DDouble___call__( BPy_UnaryFunction1DDouble *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_double)) == typeid(UnaryFunction1D<double>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_double->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_double->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble( self->uf1D_double->result );
+
+}
+
+static char UnaryFunction1DDouble_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DDouble_setIntegrationType(BPy_UnaryFunction1DDouble* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_double->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DDouble_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DDouble_getIntegrationType(BPy_UnaryFunction1DDouble* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_double->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DDouble instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DDouble_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DDouble_getName, METH_NOARGS, UnaryFunction1DDouble_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DDouble_setIntegrationType, METH_VARARGS, UnaryFunction1DDouble_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DDouble_getIntegrationType, METH_NOARGS, UnaryFunction1DDouble_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DDouble type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DDouble_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DDouble", /* tp_name */
+ sizeof(BPy_UnaryFunction1DDouble), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DDouble___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DDouble___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DDouble___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DDouble___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DDouble_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DDouble___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h
new file mode 100644
index 00000000000..9a9170cfe17
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DDouble_Type;
+
+#define BPy_UnaryFunction1DDouble_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DDouble_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DDouble structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<double> *uf1D_double;
+} BPy_UnaryFunction1DDouble;
+
+/*---------------------------Python BPy_UnaryFunction1DDouble visible prototypes-----------*/
+int UnaryFunction1DDouble_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
new file mode 100644
index 00000000000..4f6a672857a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
@@ -0,0 +1,210 @@
+#include "BPy_UnaryFunction1DEdgeNature.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DEdgeNature_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DEdgeNature_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DEdgeNature_Type );
+ PyModule_AddObject(module, "UnaryFunction1DEdgeNature", (PyObject *)&UnaryFunction1DEdgeNature_Type);
+
+ if( PyType_Ready( &CurveNatureF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CurveNatureF1D_Type );
+ PyModule_AddObject(module, "CurveNatureF1D", (PyObject *)&CurveNatureF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DEdgeNature___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DEdgeNature`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a :class:`Nature` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DEdgeNature___init__(BPy_UnaryFunction1DEdgeNature* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_edgenature = new UnaryFunction1D<Nature::EdgeNature>();
+ else {
+ self->uf1D_edgenature = new UnaryFunction1D<Nature::EdgeNature>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_edgenature->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DEdgeNature___dealloc__(BPy_UnaryFunction1DEdgeNature* self)
+{
+ if (self->uf1D_edgenature)
+ delete self->uf1D_edgenature;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DEdgeNature___repr__(BPy_UnaryFunction1DEdgeNature* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_edgenature->getName().c_str(), self->uf1D_edgenature );
+}
+
+static char UnaryFunction1DEdgeNature_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction1DEdgeNature_getName( BPy_UnaryFunction1DEdgeNature *self )
+{
+ return PyUnicode_FromString( self->uf1D_edgenature->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DEdgeNature___call__( BPy_UnaryFunction1DEdgeNature *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_edgenature)) == typeid(UnaryFunction1D<Nature::EdgeNature>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_edgenature->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_edgenature->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_Nature_from_Nature( self->uf1D_edgenature->result );
+
+}
+
+static char UnaryFunction1DEdgeNature_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DEdgeNature_setIntegrationType(BPy_UnaryFunction1DEdgeNature* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_edgenature->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DEdgeNature_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DEdgeNature_getIntegrationType(BPy_UnaryFunction1DEdgeNature* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_edgenature->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DEdgeNature instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DEdgeNature_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DEdgeNature_getName, METH_NOARGS, UnaryFunction1DEdgeNature_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DEdgeNature_setIntegrationType, METH_VARARGS, UnaryFunction1DEdgeNature_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DEdgeNature_getIntegrationType, METH_NOARGS, UnaryFunction1DEdgeNature_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DEdgeNature type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DEdgeNature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DEdgeNature", /* tp_name */
+ sizeof(BPy_UnaryFunction1DEdgeNature), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DEdgeNature___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DEdgeNature___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DEdgeNature___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DEdgeNature___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DEdgeNature_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DEdgeNature___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h
new file mode 100644
index 00000000000..05e3e522c4b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DEdgeNature_Type;
+
+#define BPy_UnaryFunction1DEdgeNature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DEdgeNature_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DEdgeNature structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Nature::EdgeNature> *uf1D_edgenature;
+} BPy_UnaryFunction1DEdgeNature;
+
+/*---------------------------Python BPy_UnaryFunction1DEdgeNature visible prototypes-----------*/
+int UnaryFunction1DEdgeNature_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
new file mode 100644
index 00000000000..9f16ed9ce36
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
@@ -0,0 +1,203 @@
+#include "BPy_UnaryFunction1DFloat.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DFloat_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DFloat_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DFloat_Type );
+ PyModule_AddObject(module, "UnaryFunction1DFloat", (PyObject *)&UnaryFunction1DFloat_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DFloat___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DFloat`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DFloat___init__(BPy_UnaryFunction1DFloat* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_float = new UnaryFunction1D<float>();
+ else {
+ self->uf1D_float = new UnaryFunction1D<float>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_float->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DFloat___dealloc__(BPy_UnaryFunction1DFloat* self)
+{
+ if (self->uf1D_float)
+ delete self->uf1D_float;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DFloat___repr__(BPy_UnaryFunction1DFloat* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_float->getName().c_str(), self->uf1D_float );
+}
+
+static char UnaryFunction1DFloat_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction1DFloat_getName( BPy_UnaryFunction1DFloat *self )
+{
+ return PyUnicode_FromString( self->uf1D_float->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DFloat___call__( BPy_UnaryFunction1DFloat *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_float)) == typeid(UnaryFunction1D<float>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_float->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_float->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble( self->uf1D_float->result );
+
+}
+
+static char UnaryFunction1DFloat_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DFloat_setIntegrationType(BPy_UnaryFunction1DFloat* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_float->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DFloat_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DFloat_getIntegrationType(BPy_UnaryFunction1DFloat* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_float->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DFloat instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DFloat_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DFloat_getName, METH_NOARGS, UnaryFunction1DFloat_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DFloat_setIntegrationType, METH_VARARGS, UnaryFunction1DFloat_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DFloat_getIntegrationType, METH_NOARGS, UnaryFunction1DFloat_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DFloat type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DFloat_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DFloat", /* tp_name */
+ sizeof(BPy_UnaryFunction1DFloat), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DFloat___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DFloat___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DFloat___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DFloat___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DFloat_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DFloat___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h
new file mode 100644
index 00000000000..529b382372e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DFloat_Type;
+
+#define BPy_UnaryFunction1DFloat_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DFloat_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DFloat structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<float> *uf1D_float;
+} BPy_UnaryFunction1DFloat;
+
+/*---------------------------Python BPy_UnaryFunction1DFloat visible prototypes-----------*/
+int UnaryFunction1DFloat_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
new file mode 100644
index 00000000000..98615728c63
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
@@ -0,0 +1,210 @@
+#include "BPy_UnaryFunction1DUnsigned.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DUnsigned_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DUnsigned_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DUnsigned_Type );
+ PyModule_AddObject(module, "UnaryFunction1DUnsigned", (PyObject *)&UnaryFunction1DUnsigned_Type);
+
+ if( PyType_Ready( &QuantitativeInvisibilityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &QuantitativeInvisibilityF1D_Type );
+ PyModule_AddObject(module, "QuantitativeInvisibilityF1D", (PyObject *)&QuantitativeInvisibilityF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DUnsigned___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DUnsigned`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return an int value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DUnsigned___init__(BPy_UnaryFunction1DUnsigned* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_unsigned = new UnaryFunction1D<unsigned int>();
+ else {
+ self->uf1D_unsigned = new UnaryFunction1D<unsigned int>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_unsigned->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DUnsigned___dealloc__(BPy_UnaryFunction1DUnsigned* self)
+{
+ if (self->uf1D_unsigned)
+ delete self->uf1D_unsigned;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DUnsigned___repr__(BPy_UnaryFunction1DUnsigned* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_unsigned->getName().c_str(), self->uf1D_unsigned );
+}
+
+static char UnaryFunction1DUnsigned_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction1DUnsigned_getName( BPy_UnaryFunction1DUnsigned *self )
+{
+ return PyUnicode_FromString( self->uf1D_unsigned->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DUnsigned___call__( BPy_UnaryFunction1DUnsigned *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_unsigned)) == typeid(UnaryFunction1D<unsigned int>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_unsigned->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_unsigned->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyLong_FromLong( self->uf1D_unsigned->result );
+
+}
+
+static char UnaryFunction1DUnsigned_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DUnsigned_setIntegrationType(BPy_UnaryFunction1DUnsigned* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_unsigned->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DUnsigned_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DUnsigned_getIntegrationType(BPy_UnaryFunction1DUnsigned* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_unsigned->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DUnsigned instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DUnsigned_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DUnsigned_getName, METH_NOARGS, UnaryFunction1DUnsigned_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DUnsigned_setIntegrationType, METH_VARARGS, UnaryFunction1DUnsigned_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DUnsigned_getIntegrationType, METH_NOARGS, UnaryFunction1DUnsigned_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DUnsigned type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DUnsigned_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DUnsigned", /* tp_name */
+ sizeof(BPy_UnaryFunction1DUnsigned), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DUnsigned___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DUnsigned___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DUnsigned___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DUnsigned___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DUnsigned_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DUnsigned___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h
new file mode 100644
index 00000000000..c70cc6257a7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DUnsigned_Type;
+
+#define BPy_UnaryFunction1DUnsigned_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DUnsigned_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DUnsigned structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<unsigned int> *uf1D_unsigned;
+} BPy_UnaryFunction1DUnsigned;
+
+/*---------------------------Python BPy_UnaryFunction1DUnsigned visible prototypes-----------*/
+int UnaryFunction1DUnsigned_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
new file mode 100644
index 00000000000..9f2c52c6f44
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
@@ -0,0 +1,216 @@
+#include "BPy_UnaryFunction1DVec2f.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h"
+#include "UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVec2f_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DVec2f_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DVec2f_Type );
+ PyModule_AddObject(module, "UnaryFunction1DVec2f", (PyObject *)&UnaryFunction1DVec2f_Type);
+
+ if( PyType_Ready( &Normal2DF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Normal2DF1D_Type );
+ PyModule_AddObject(module, "Normal2DF1D", (PyObject *)&Normal2DF1D_Type);
+
+ if( PyType_Ready( &Orientation2DF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Orientation2DF1D_Type );
+ PyModule_AddObject(module, "Orientation2DF1D", (PyObject *)&Orientation2DF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVec2f___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec2f`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a 2D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVec2f___init__(BPy_UnaryFunction1DVec2f* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_vec2f = new UnaryFunction1D<Vec2f>();
+ else {
+ self->uf1D_vec2f = new UnaryFunction1D<Vec2f>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_vec2f->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVec2f___dealloc__(BPy_UnaryFunction1DVec2f* self)
+{
+ if (self->uf1D_vec2f)
+ delete self->uf1D_vec2f;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DVec2f___repr__(BPy_UnaryFunction1DVec2f* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vec2f->getName().c_str(), self->uf1D_vec2f );
+}
+
+static char UnaryFunction1DVec2f_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction1DVec2f_getName( BPy_UnaryFunction1DVec2f *self )
+{
+ return PyUnicode_FromString( self->uf1D_vec2f->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DVec2f___call__( BPy_UnaryFunction1DVec2f *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_vec2f)) == typeid(UnaryFunction1D<Vec2f>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vec2f->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_vec2f->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec2f( self->uf1D_vec2f->result );
+
+}
+
+static char UnaryFunction1DVec2f_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVec2f_setIntegrationType(BPy_UnaryFunction1DVec2f* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_vec2f->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVec2f_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVec2f_getIntegrationType(BPy_UnaryFunction1DVec2f* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_vec2f->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DVec2f instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DVec2f_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DVec2f_getName, METH_NOARGS, UnaryFunction1DVec2f_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVec2f_setIntegrationType, METH_VARARGS, UnaryFunction1DVec2f_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVec2f_getIntegrationType, METH_NOARGS, UnaryFunction1DVec2f_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DVec2f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVec2f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVec2f", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVec2f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVec2f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVec2f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVec2f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVec2f___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DVec2f_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVec2f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h
new file mode 100644
index 00000000000..64a616e211a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVec2f_Type;
+
+#define BPy_UnaryFunction1DVec2f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVec2f_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DVec2f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Vec2f> *uf1D_vec2f;
+} BPy_UnaryFunction1DVec2f;
+
+/*---------------------------Python BPy_UnaryFunction1DVec2f visible prototypes-----------*/
+int UnaryFunction1DVec2f_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
new file mode 100644
index 00000000000..67a7955f0d5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
@@ -0,0 +1,210 @@
+#include "BPy_UnaryFunction1DVec3f.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVec3f_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DVec3f_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DVec3f_Type );
+ PyModule_AddObject(module, "UnaryFunction1DVec3f", (PyObject *)&UnaryFunction1DVec3f_Type);
+
+ if( PyType_Ready( &Orientation3DF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Orientation3DF1D_Type );
+ PyModule_AddObject(module, "Orientation3DF1D", (PyObject *)&Orientation3DF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVec3f___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec3f`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a 3D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+int UnaryFunction1DVec3f___init__(BPy_UnaryFunction1DVec3f* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_vec3f = new UnaryFunction1D<Vec3f>();
+ else {
+ self->uf1D_vec3f = new UnaryFunction1D<Vec3f>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_vec3f->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+void UnaryFunction1DVec3f___dealloc__(BPy_UnaryFunction1DVec3f* self)
+{
+ if (self->uf1D_vec3f)
+ delete self->uf1D_vec3f;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+
+PyObject * UnaryFunction1DVec3f___repr__(BPy_UnaryFunction1DVec3f* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vec3f->getName().c_str(), self->uf1D_vec3f );
+}
+
+static char UnaryFunction1DVec3f_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: str\n";
+
+PyObject * UnaryFunction1DVec3f_getName( BPy_UnaryFunction1DVec3f *self )
+{
+ return PyUnicode_FromString( self->uf1D_vec3f->getName().c_str() );
+}
+
+PyObject * UnaryFunction1DVec3f___call__( BPy_UnaryFunction1DVec3f *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_vec3f)) == typeid(UnaryFunction1D<Vec3f>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vec3f->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_vec3f->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec3f( self->uf1D_vec3f->result );
+
+}
+
+static char UnaryFunction1DVec3f_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+PyObject * UnaryFunction1DVec3f_setIntegrationType(BPy_UnaryFunction1DVec3f* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_vec3f->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVec3f_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+PyObject * UnaryFunction1DVec3f_getIntegrationType(BPy_UnaryFunction1DVec3f* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_vec3f->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DVec3f instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DVec3f_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DVec3f_getName, METH_NOARGS, UnaryFunction1DVec3f_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVec3f_setIntegrationType, METH_VARARGS, UnaryFunction1DVec3f_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVec3f_getIntegrationType, METH_NOARGS, UnaryFunction1DVec3f_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DVec3f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVec3f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVec3f", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVec3f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVec3f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVec3f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVec3f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVec3f___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DVec3f_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVec3f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h
new file mode 100644
index 00000000000..7730271fc09
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVec3f_Type;
+
+#define BPy_UnaryFunction1DVec3f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVec3f_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DVec3f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Vec3f> *uf1D_vec3f;
+} BPy_UnaryFunction1DVec3f;
+
+/*---------------------------Python BPy_UnaryFunction1DVec3f visible prototypes-----------*/
+int UnaryFunction1DVec3f_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
new file mode 100644
index 00000000000..5555f401cbf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
@@ -0,0 +1,235 @@
+#include "BPy_UnaryFunction1DVectorViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h"
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h"
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVectorViewShape_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DVectorViewShape_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DVectorViewShape_Type );
+ PyModule_AddObject(module, "UnaryFunction1DVectorViewShape", (PyObject *)&UnaryFunction1DVectorViewShape_Type);
+
+ if( PyType_Ready( &GetOccludeeF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetOccludeeF1D_Type );
+ PyModule_AddObject(module, "GetOccludeeF1D", (PyObject *)&GetOccludeeF1D_Type);
+
+ if( PyType_Ready( &GetOccludersF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetOccludersF1D_Type );
+ PyModule_AddObject(module, "GetOccludersF1D", (PyObject *)&GetOccludersF1D_Type);
+
+ if( PyType_Ready( &GetShapeF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetShapeF1D_Type );
+ PyModule_AddObject(module, "GetShapeF1D", (PyObject *)&GetShapeF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVectorViewShape___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a list of :class:`ViewShape`\n"
+"objects.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVectorViewShape___init__(BPy_UnaryFunction1DVectorViewShape* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_vectorviewshape = new UnaryFunction1D< std::vector<ViewShape*> >();
+ else {
+ self->uf1D_vectorviewshape = new UnaryFunction1D< std::vector<ViewShape*> >( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_vectorviewshape->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVectorViewShape___dealloc__(BPy_UnaryFunction1DVectorViewShape* self)
+{
+ if (self->uf1D_vectorviewshape)
+ delete self->uf1D_vectorviewshape;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DVectorViewShape___repr__(BPy_UnaryFunction1DVectorViewShape* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vectorviewshape->getName().c_str(), self->uf1D_vectorviewshape );
+}
+
+static char UnaryFunction1DVectorViewShape_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction1DVectorViewShape_getName( BPy_UnaryFunction1DVectorViewShape *self )
+{
+ return PyUnicode_FromString( self->uf1D_vectorviewshape->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DVectorViewShape___call__( BPy_UnaryFunction1DVectorViewShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_vectorviewshape)) == typeid(UnaryFunction1D< std::vector<ViewShape*> >) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vectorviewshape->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_vectorviewshape->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ PyObject *list = PyList_New(0);
+ PyObject *item;
+ for( unsigned int i = 0; i < self->uf1D_vectorviewshape->result.size(); i++) {
+ ViewShape *v = self->uf1D_vectorviewshape->result[i];
+ if (v) {
+ item = BPy_ViewShape_from_ViewShape(*v);
+ } else {
+ item = Py_None;
+ Py_INCREF(item);
+ }
+ PyList_Append(list, item);
+ }
+
+ return list;
+}
+
+static char UnaryFunction1DVectorViewShape_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVectorViewShape_setIntegrationType(BPy_UnaryFunction1DVectorViewShape* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_vectorviewshape->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVectorViewShape_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVectorViewShape_getIntegrationType(BPy_UnaryFunction1DVectorViewShape* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_vectorviewshape->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DVectorViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DVectorViewShape_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DVectorViewShape_getName, METH_NOARGS, UnaryFunction1DVectorViewShape_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVectorViewShape_setIntegrationType, METH_VARARGS, UnaryFunction1DVectorViewShape_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVectorViewShape_getIntegrationType, METH_NOARGS, UnaryFunction1DVectorViewShape_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DVectorViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVectorViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVectorViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVectorViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVectorViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVectorViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVectorViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVectorViewShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DVectorViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVectorViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h
new file mode 100644
index 00000000000..e2321a6107f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include <vector>
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVectorViewShape_Type;
+
+#define BPy_UnaryFunction1DVectorViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVectorViewShape_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DVectorViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D< std::vector<ViewShape*> > *uf1D_vectorviewshape;
+} BPy_UnaryFunction1DVectorViewShape;
+
+/*---------------------------Python BPy_UnaryFunction1DVectorViewShape visible prototypes-----------*/
+int UnaryFunction1DVectorViewShape_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
new file mode 100644
index 00000000000..f18421d8754
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
@@ -0,0 +1,222 @@
+#include "BPy_UnaryFunction1DVoid.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h"
+#include "UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h"
+#include "UnaryFunction1D_void/BPy_TimeStampF1D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVoid_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DVoid_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DVoid_Type );
+ PyModule_AddObject(module, "UnaryFunction1DVoid", (PyObject *)&UnaryFunction1DVoid_Type);
+
+ if( PyType_Ready( &ChainingTimeStampF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ChainingTimeStampF1D_Type );
+ PyModule_AddObject(module, "ChainingTimeStampF1D", (PyObject *)&ChainingTimeStampF1D_Type);
+
+ if( PyType_Ready( &IncrementChainingTimeStampF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &IncrementChainingTimeStampF1D_Type );
+ PyModule_AddObject(module, "IncrementChainingTimeStampF1D", (PyObject *)&IncrementChainingTimeStampF1D_Type);
+
+ if( PyType_Ready( &TimeStampF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TimeStampF1D_Type );
+ PyModule_AddObject(module, "TimeStampF1D", (PyObject *)&TimeStampF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVoid___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid`\n"
+"\n"
+"Base class for unary functions (functors) working on\n"
+":class:`Interface1D`.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVoid___init__(BPy_UnaryFunction1DVoid* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_void = new UnaryFunction1D_void();
+ else {
+ self->uf1D_void = new UnaryFunction1D_void( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_void->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVoid___dealloc__(BPy_UnaryFunction1DVoid* self)
+{
+ if (self->uf1D_void)
+ delete self->uf1D_void;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DVoid___repr__(BPy_UnaryFunction1DVoid* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_void->getName().c_str(), self->uf1D_void );
+}
+
+static char UnaryFunction1DVoid_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: str\n";
+
+static PyObject * UnaryFunction1DVoid_getName( BPy_UnaryFunction1DVoid *self )
+{
+ return PyUnicode_FromString( self->uf1D_void->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DVoid___call__( BPy_UnaryFunction1DVoid *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_void)) == typeid(UnaryFunction1D_void) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_void->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_void->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVoid_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVoid_setIntegrationType(BPy_UnaryFunction1DVoid* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_void->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVoid_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVoid_getIntegrationType(BPy_UnaryFunction1DVoid* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_void->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DVoid instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DVoid_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DVoid_getName, METH_NOARGS, UnaryFunction1DVoid_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVoid_setIntegrationType, METH_VARARGS, UnaryFunction1DVoid_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVoid_getIntegrationType, METH_NOARGS, UnaryFunction1DVoid_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DVoid type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVoid_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVoid", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVoid), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVoid___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVoid___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVoid___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVoid___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DVoid_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVoid___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h
new file mode 100644
index 00000000000..af907aeec84
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVoid_Type;
+
+#define BPy_UnaryFunction1DVoid_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVoid_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DVoid structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D_void *uf1D_void;
+} BPy_UnaryFunction1DVoid;
+
+/*---------------------------Python BPy_UnaryFunction1DVoid visible prototypes-----------*/
+int UnaryFunction1DVoid_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp
new file mode 100644
index 00000000000..a31d96ad1a4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp
@@ -0,0 +1,99 @@
+#include "BPy_CurveNatureF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurveNatureF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DEdgeNature` > :class:`CurveNatureF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a CurveNatureF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the nature of the Interface1D (silhouette, ridge, crease,\n"
+" and so on). Except if the Interface1D is a :class:`ViewEdge`, this\n"
+" result might be ambiguous. Indeed, the Interface1D might result\n"
+" from the gathering of several 1D elements, each one being of a\n"
+" different nature. An integration method, such as the MEAN, might\n"
+" give, in this case, irrelevant results.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The nature of the Interface1D.\n"
+" :rtype: :class:`Nature`\n";
+
+static int CurveNatureF1D___init__( BPy_CurveNatureF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_edgenature.uf1D_edgenature = new Functions1D::CurveNatureF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_CurveNatureF1D type definition ------------------------------*/
+
+PyTypeObject CurveNatureF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurveNatureF1D", /* tp_name */
+ sizeof(BPy_CurveNatureF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurveNatureF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DEdgeNature_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurveNatureF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h
new file mode 100644
index 00000000000..852f8937954
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CURVENATUREF1D_H
+#define FREESTYLE_PYTHON_CURVENATUREF1D_H
+
+#include "../BPy_UnaryFunction1DEdgeNature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurveNatureF1D_Type;
+
+#define BPy_CurveNatureF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurveNatureF1D_Type) )
+
+/*---------------------------Python BPy_CurveNatureF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DEdgeNature py_uf1D_edgenature;
+} BPy_CurveNatureF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVENATUREF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp
new file mode 100644
index 00000000000..92ba5b05e75
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_Normal2DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Normal2DF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec2f` > :class:`Normal2DF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a Normal2DF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D normal for the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D normal for the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Normal2DF1D___init__( BPy_Normal2DF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec2f.uf1D_vec2f = new Functions1D::Normal2DF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_Normal2DF1D type definition ------------------------------*/
+
+PyTypeObject Normal2DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Normal2DF1D", /* tp_name */
+ sizeof(BPy_Normal2DF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Normal2DF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Normal2DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h
new file mode 100644
index 00000000000..32078558d0c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_NORMAL2DF1D_H
+#define FREESTYLE_PYTHON_NORMAL2DF1D_H
+
+#include "../BPy_UnaryFunction1DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Normal2DF1D_Type;
+
+#define BPy_Normal2DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Normal2DF1D_Type) )
+
+/*---------------------------Python BPy_Normal2DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec2f py_uf1D_vec2f;
+} BPy_Normal2DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NORMAL2DF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp
new file mode 100644
index 00000000000..a1b87b9cf17
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp
@@ -0,0 +1,96 @@
+#include "BPy_Orientation2DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Orientation2DF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec2f` > :class:`Orientation2DF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds an Orientation2DF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D orientation of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D orientation of the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Orientation2DF1D___init__( BPy_Orientation2DF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec2f.uf1D_vec2f = new Functions1D::Orientation2DF1D(t);
+ return 0;
+
+}
+
+
+/*-----------------------BPy_Orientation2DF1D type definition ------------------------------*/
+
+PyTypeObject Orientation2DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Orientation2DF1D", /* tp_name */
+ sizeof(BPy_Orientation2DF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Orientation2DF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Orientation2DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h
new file mode 100644
index 00000000000..189ab04db4f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_ORIENTATION2DF1D_H
+#define FREESTYLE_PYTHON_ORIENTATION2DF1D_H
+
+#include "../BPy_UnaryFunction1DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Orientation2DF1D_Type;
+
+#define BPy_Orientation2DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Orientation2DF1D_Type) )
+
+/*---------------------------Python BPy_Orientation2DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec2f py_uf1D_vec2f;
+} BPy_Orientation2DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ORIENTATION2DF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp
new file mode 100644
index 00000000000..a55c1f7a542
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_Orientation3DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Orientation3DF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec3f` > :class:`Orientation3DF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds an Orientation3DF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 3D orientation of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 3D orientation of the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Orientation3DF1D___init__( BPy_Orientation3DF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec3f.uf1D_vec3f = new Functions1D::Orientation3DF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_Orientation3DF1D type definition ------------------------------*/
+
+PyTypeObject Orientation3DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Orientation3DF1D", /* tp_name */
+ sizeof(BPy_Orientation3DF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Orientation3DF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVec3f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Orientation3DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h
new file mode 100644
index 00000000000..b69baf106f4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_ORIENTATION3DF1D_H
+#define FREESTYLE_PYTHON_ORIENTATION3DF1D_H
+
+#include "../BPy_UnaryFunction1DVec3f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Orientation3DF1D_Type;
+
+#define BPy_Orientation3DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Orientation3DF1D_Type) )
+
+/*---------------------------Python BPy_Orientation3DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec3f py_uf1D_vec3f;
+} BPy_Orientation3DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ORIENTATION3DF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp
new file mode 100644
index 00000000000..aec76c2888c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_Curvature2DAngleF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Curvature2DAngleF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`Curvature2DAngleF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a Curvature2DAngleF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D curvature as an angle for an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D curvature as an angle.\n"
+" :rtype: float\n";
+
+static int Curvature2DAngleF1D___init__( BPy_Curvature2DAngleF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::Curvature2DAngleF1D(t);
+ return 0;
+
+}
+/*-----------------------BPy_Curvature2DAngleF1D type definition ------------------------------*/
+
+PyTypeObject Curvature2DAngleF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Curvature2DAngleF1D", /* tp_name */
+ sizeof(BPy_Curvature2DAngleF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Curvature2DAngleF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Curvature2DAngleF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h
new file mode 100644
index 00000000000..1603a7dc4ea
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H
+#define FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Curvature2DAngleF1D_Type;
+
+#define BPy_Curvature2DAngleF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Curvature2DAngleF1D_Type) )
+
+/*---------------------------Python BPy_Curvature2DAngleF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_Curvature2DAngleF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp
new file mode 100644
index 00000000000..360f98fa361
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp
@@ -0,0 +1,109 @@
+#include "BPy_DensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`DensityF1D`\n"
+"\n"
+".. method:: __init__(sigma=2.0, iType=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a DensityF1D object.\n"
+"\n"
+" :arg sigma: The sigma used in DensityF0D and determining the window size\n"
+" used in each density query.\n"
+" :type sigma: float\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D. The density is\n"
+" evaluated for a set of points along the Interface1D (using the\n"
+" :class:`DensityF0D` functor) with a user-defined sampling and then\n"
+" integrated into a single value using a user-defined integration\n"
+" method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density evaluated for an Interface1D.\n"
+" :rtype: float\n";
+
+static int DensityF1D___init__( BPy_DensityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ double d = 2.0;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "|dO!f", &d, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::DensityF1D(d,t,f);
+ return 0;
+
+}
+
+/*-----------------------BPy_DensityF1D type definition ------------------------------*/
+
+PyTypeObject DensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityF1D", /* tp_name */
+ sizeof(BPy_DensityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DensityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h
new file mode 100644
index 00000000000..36426536b36
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_DENSITYF1D_H
+#define FREESTYLE_PYTHON_DENSITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityF1D_Type;
+
+#define BPy_DensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityF1D_Type) )
+
+/*---------------------------Python BPy_DensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_DensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_DENSITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp
new file mode 100644
index 00000000000..b30d26c8516
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp
@@ -0,0 +1,110 @@
+#include "BPy_GetCompleteViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetCompleteViewMapDensityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetCompleteViewMapDensityF1D`\n"
+"\n"
+".. method:: __init__(level, iType=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetCompleteViewMapDensityF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D in the complete\n"
+" viewmap image. The density is evaluated for a set of points along\n"
+" the Interface1D (using the :class:`ReadCompleteViewMapPixelF0D`\n"
+" functor) and then integrated into a single value using a\n"
+" user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density evaluated for the Interface1D in the complete\n"
+" viewmap image.\n"
+" :rtype: float\n";
+
+static int GetCompleteViewMapDensityF1D___init__( BPy_GetCompleteViewMapDensityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ unsigned i;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetCompleteViewMapDensityF1D(i,t,f);
+ return 0;
+
+}
+
+/*-----------------------BPy_GetCompleteViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetCompleteViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetCompleteViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetCompleteViewMapDensityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetCompleteViewMapDensityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetCompleteViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h
new file mode 100644
index 00000000000..5963b820348
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H
+#define FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetCompleteViewMapDensityF1D_Type;
+
+#define BPy_GetCompleteViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetCompleteViewMapDensityF1D_Type) )
+
+/*---------------------------Python BPy_GetCompleteViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetCompleteViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
new file mode 100644
index 00000000000..494297d3a3b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
@@ -0,0 +1,114 @@
+#include "BPy_GetDirectionalViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetDirectionalViewMapDensityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetDirectionalViewMapDensityF1D`\n"
+"\n"
+".. method:: __init__(iOrientation, level, iType=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetDirectionalViewMapDensityF1D object.\n"
+"\n"
+" :arg iOrientation: The number of the directional map we must work\n"
+" with.\n"
+" :type iOrientation: int\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D in of the\n"
+" steerable viewmaps image. The direction telling which Directional\n"
+" map to choose is explicitely specified by the user. The density is\n"
+" evaluated for a set of points along the Interface1D (using the\n"
+" :class:`ReadSteerableViewMapPixelF0D` functor) and then integrated\n"
+" into a single value using a user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: the density evaluated for an Interface1D in of the\n"
+" steerable viewmaps image.\n"
+" :rtype: float\n";
+
+static int GetDirectionalViewMapDensityF1D___init__( BPy_GetDirectionalViewMapDensityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ unsigned int u1, u2;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "II|O!f", &u1, &u2, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetDirectionalViewMapDensityF1D(u1, u2, t, f);
+ return 0;
+
+}
+
+/*-----------------------BPy_GetDirectionalViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetDirectionalViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetDirectionalViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetDirectionalViewMapDensityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetDirectionalViewMapDensityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetDirectionalViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h
new file mode 100644
index 00000000000..0e2d7ec2718
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H
+#define FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetDirectionalViewMapDensityF1D_Type;
+
+#define BPy_GetDirectionalViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetDirectionalViewMapDensityF1D_Type) )
+
+/*---------------------------Python BPy_GetDirectionalViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetDirectionalViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp
new file mode 100644
index 00000000000..7b1e7193b85
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp
@@ -0,0 +1,95 @@
+#include "BPy_GetProjectedXF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedXF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedXF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedXF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected X 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected X 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedXF1D___init__( BPy_GetProjectedXF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedXF1D(t);
+ return 0;
+}
+
+
+/*-----------------------BPy_GetProjectedXF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedXF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedXF1D", /* tp_name */
+ sizeof(BPy_GetProjectedXF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedXF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedXF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h
new file mode 100644
index 00000000000..d799fb7b334
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDXF1D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDXF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedXF1D_Type;
+
+#define BPy_GetProjectedXF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedXF1D_Type) )
+
+/*---------------------------Python BPy_GetProjectedXF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedXF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDXF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp
new file mode 100644
index 00000000000..df09b32b5b9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_GetProjectedYF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedYF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedYF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedYF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected Y 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected Y 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedYF1D___init__( BPy_GetProjectedYF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedYF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedYF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedYF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedYF1D", /* tp_name */
+ sizeof(BPy_GetProjectedYF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedYF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedYF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h
new file mode 100644
index 00000000000..1b7fe6c6b5f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDYF1D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedYF1D_Type;
+
+#define BPy_GetProjectedYF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedYF1D_Type) )
+
+/*---------------------------Python BPy_GetProjectedYF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedYF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp
new file mode 100644
index 00000000000..acd03856b2c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_GetProjectedZF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedZF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedZF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedZF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected Z 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected Z 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedZF1D___init__( BPy_GetProjectedZF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedZF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedZF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedZF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedZF1D", /* tp_name */
+ sizeof(BPy_GetProjectedZF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedZF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedZF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h
new file mode 100644
index 00000000000..a87ac6f8c5e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDZF1D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDZF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedZF1D_Type;
+
+#define BPy_GetProjectedZF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedZF1D_Type) )
+
+/*---------------------------Python BPy_GetProjectedZF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedZF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDZF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp
new file mode 100644
index 00000000000..cc3813030ac
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp
@@ -0,0 +1,107 @@
+#include "BPy_GetSteerableViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetSteerableViewMapDensityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetSteerableViewMapDensityF1D`\n"
+"\n"
+".. method:: __init__(level, iType=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetSteerableViewMapDensityF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density of the ViewMap for a given Interface1D. The\n"
+" density of each :class:`FEdge` is evaluated in the proper steerable\n"
+" :class:`ViewMap` depending on its orientation.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density of the ViewMap for a given Interface1D.\n"
+" :rtype: float\n";
+
+static int GetSteerableViewMapDensityF1D___init__( BPy_GetSteerableViewMapDensityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ int i;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetSteerableViewMapDensityF1D(i,t,f);
+ return 0;
+
+}
+
+/*-----------------------BPy_GetSteerableViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetSteerableViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetSteerableViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetSteerableViewMapDensityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetSteerableViewMapDensityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetSteerableViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h
new file mode 100644
index 00000000000..29880c7e9a7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H
+#define FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetSteerableViewMapDensityF1D_Type;
+
+#define BPy_GetSteerableViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetSteerableViewMapDensityF1D_Type) )
+/*---------------------------Python BPy_GetSteerableViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetSteerableViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp
new file mode 100644
index 00000000000..c3e12fd7792
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp
@@ -0,0 +1,107 @@
+#include "BPy_GetViewMapGradientNormF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetViewMapGradientNormF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetViewMapGradientNormF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetViewMapGradientNormF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density of the ViewMap for a given Interface1D. The\n"
+" density of each :class:`FEdge` is evaluated in the proper steerable\n"
+" :class:`ViewMap` depending on its orientation.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density of the ViewMap for a given Interface1D.\n"
+" :rtype: float\n";
+
+static int GetViewMapGradientNormF1D___init__( BPy_GetViewMapGradientNormF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ int i;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetViewMapGradientNormF1D(i,t,f);
+ return 0;
+
+}
+
+/*-----------------------BPy_GetViewMapGradientNormF1D type definition ------------------------------*/
+
+PyTypeObject GetViewMapGradientNormF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetViewMapGradientNormF1D", /* tp_name */
+ sizeof(BPy_GetViewMapGradientNormF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetViewMapGradientNormF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetViewMapGradientNormF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h
new file mode 100644
index 00000000000..4f07629870f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H
+#define FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetViewMapGradientNormF1D_Type;
+
+#define BPy_GetViewMapGradientNormF1D_Check(v) ( ((PyObject *) v)->ob_type == PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetViewMapGradientNormF1D_Type) )
+
+/*---------------------------Python BPy_GetViewMapGradientNormF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetViewMapGradientNormF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp
new file mode 100644
index 00000000000..a15c6f59a3b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp
@@ -0,0 +1,95 @@
+#include "BPy_GetXF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetXF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetXF1D`\n"
+"\n"
+".. method:: __init__(iType)\n"
+"\n"
+" Builds a GetXF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the X 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The X 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetXF1D___init__( BPy_GetXF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetXF1D(t);
+ return 0;
+}
+
+
+/*-----------------------BPy_GetXF1D type definition ------------------------------*/
+
+PyTypeObject GetXF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetXF1D", /* tp_name */
+ sizeof(BPy_GetXF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetXF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetXF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h
new file mode 100644
index 00000000000..5eae107daae
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETXF1D_H
+#define FREESTYLE_PYTHON_GETXF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetXF1D_Type;
+
+#define BPy_GetXF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetXF1D_Type) )
+
+/*---------------------------Python BPy_GetXF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetXF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETXF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp
new file mode 100644
index 00000000000..b8ee3d8be27
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp
@@ -0,0 +1,93 @@
+#include "BPy_GetYF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetYF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetYF1D`\n"
+"\n"
+".. method:: __init__(iType)\n"
+"\n"
+" Builds a GetYF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Y 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Y 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetYF1D___init__( BPy_GetYF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetYF1D(t);
+ return 0;
+}
+/*-----------------------BPy_GetYF1D type definition ------------------------------*/
+
+PyTypeObject GetYF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetYF1D", /* tp_name */
+ sizeof(BPy_GetYF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetYF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetYF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h
new file mode 100644
index 00000000000..5864c245776
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETYF1D_H
+#define FREESTYLE_PYTHON_GETYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetYF1D_Type;
+
+#define BPy_GetYF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetYF1D_Type) )
+
+/*---------------------------Python BPy_GetYF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetYF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp
new file mode 100644
index 00000000000..af275c906c4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_GetZF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetZF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetZF1D`\n"
+"\n"
+".. method:: __init__(iType)\n"
+"\n"
+" Builds a GetZF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Z 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Z 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetZF1D___init__( BPy_GetZF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetZF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetZF1D type definition ------------------------------*/
+
+PyTypeObject GetZF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetZF1D", /* tp_name */
+ sizeof(BPy_GetZF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetZF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetZF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h
new file mode 100644
index 00000000000..4b91a567eef
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETZF1D_H
+#define FREESTYLE_PYTHON_GETZF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetZF1D_Type;
+
+#define BPy_GetZF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetZF1D_Type) )
+
+/*---------------------------Python BPy_GetZF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetZF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETZF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp
new file mode 100644
index 00000000000..a3b15e6b5f7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp
@@ -0,0 +1,101 @@
+#include "BPy_LocalAverageDepthF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char LocalAverageDepthF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`LocalAverageDepthF1D`\n"
+"\n"
+".. method:: __init__(sigma, iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a LocalAverageDepthF1D object.\n"
+"\n"
+" :arg sigma: The sigma used in DensityF0D and determining the window\n"
+" size used in each density query.\n"
+" :type sigma: float\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the average depth evaluated for an Interface1D. The\n"
+" average depth is evaluated for a set of points along the\n"
+" Interface1D (using the :class:`LocalAverageDepthF0D` functor) with\n"
+" a user-defined sampling and then integrated into a single value\n"
+" using a user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The average depth evaluated for the Interface1D.\n"
+" :rtype: float\n";
+
+static int LocalAverageDepthF1D___init__( BPy_LocalAverageDepthF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ double d;
+
+ if( !PyArg_ParseTuple(args, "d|O!", &d, &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::LocalAverageDepthF1D(d,t);
+ return 0;
+}
+/*-----------------------BPy_LocalAverageDepthF1D type definition ------------------------------*/
+
+PyTypeObject LocalAverageDepthF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "LocalAverageDepthF1D", /* tp_name */
+ sizeof(BPy_LocalAverageDepthF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ LocalAverageDepthF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)LocalAverageDepthF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h
new file mode 100644
index 00000000000..627d10b6414
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H
+#define FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject LocalAverageDepthF1D_Type;
+
+#define BPy_LocalAverageDepthF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &LocalAverageDepthF1D_Type) )
+
+/*---------------------------Python BPy_LocalAverageDepthF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_LocalAverageDepthF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
new file mode 100644
index 00000000000..32a5106b380
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
@@ -0,0 +1,99 @@
+#include "BPy_ZDiscontinuityF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ZDiscontinuityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`ZDiscontinuityF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a ZDiscontinuityF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a real value giving the distance between an Interface1D\n"
+" and the shape that lies behind (occludee). This distance is\n"
+" evaluated in the camera space and normalized between 0 and 1.\n"
+" Therefore, if no oject is occluded by the shape to which the\n"
+" Interface1D belongs to, 1 is returned.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The normalized distance between the Interface1D and the occludee.\n"
+" :rtype: float\n";
+
+static int ZDiscontinuityF1D___init__( BPy_ZDiscontinuityF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::ZDiscontinuityF1D(t);
+ return 0;
+}
+
+
+/*-----------------------BPy_ZDiscontinuityF1D type definition ------------------------------*/
+
+PyTypeObject ZDiscontinuityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ZDiscontinuityF1D", /* tp_name */
+ sizeof(BPy_ZDiscontinuityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ZDiscontinuityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ZDiscontinuityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h
new file mode 100644
index 00000000000..e6b4be556d7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H
+#define FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ZDiscontinuityF1D_Type;
+
+#define BPy_ZDiscontinuityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ZDiscontinuityF1D_Type) )
+
+/*---------------------------Python BPy_ZDiscontinuityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_ZDiscontinuityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp
new file mode 100644
index 00000000000..a7379c4f769
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp
@@ -0,0 +1,99 @@
+#include "BPy_QuantitativeInvisibilityF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DUnsigned` > :class:`QuantitativeInvisibilityF1D`\n"
+"\n"
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a QuantitativeInvisibilityF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Quantitative Invisibility of an Interface1D element.\n"
+" If the Interface1D is a :class:`ViewEdge`, then there is no\n"
+" ambiguity concerning the result. But, if the Interface1D results\n"
+" of a chaining (chain, stroke), then it might be made of several 1D\n"
+" elements of different Quantitative Invisibilities.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Quantitative Invisibility of the Interface1D.\n"
+" :rtype: int\n";
+
+static int QuantitativeInvisibilityF1D___init__( BPy_QuantitativeInvisibilityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_unsigned.uf1D_unsigned = new Functions1D::QuantitativeInvisibilityF1D(t);
+ return 0;
+
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityF1D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityF1D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ QuantitativeInvisibilityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DUnsigned_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h
new file mode 100644
index 00000000000..5bcf5fcc0a2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H
+#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H
+
+#include "../BPy_UnaryFunction1DUnsigned.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityF1D_Type;
+
+#define BPy_QuantitativeInvisibilityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityF1D_Type) )
+
+/*---------------------------Python BPy_QuantitativeInvisibilityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DUnsigned py_uf1D_unsigned;
+} BPy_QuantitativeInvisibilityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp
new file mode 100644
index 00000000000..4bd03f8fe75
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetOccludeeF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludeeF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetOccludeeF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludeeF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of occluded shapes covered by this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of occluded shapes covered by the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludeeF1D___init__( BPy_GetOccludeeF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetOccludeeF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludeeF1D type definition ------------------------------*/
+
+PyTypeObject GetOccludeeF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludeeF1D", /* tp_name */
+ sizeof(BPy_GetOccludeeF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetOccludeeF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludeeF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h
new file mode 100644
index 00000000000..c8d5e99a6a7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETOCCLUDEEF1D_H
+#define FREESTYLE_PYTHON_GETOCCLUDEEF1D_H
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludeeF1D_Type;
+
+#define BPy_GetOccludeeF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludeeF1D_Type) )
+
+/*---------------------------Python BPy_GetOccludeeF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetOccludeeF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETOCCLUDEEF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp
new file mode 100644
index 00000000000..d37102a8447
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetOccludersF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludersF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetOccludersF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludersF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of occluding shapes that cover this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of occluding shapes that cover the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludersF1D___init__( BPy_GetOccludersF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetOccludersF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludersF1D type definition ------------------------------*/
+
+PyTypeObject GetOccludersF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludersF1D", /* tp_name */
+ sizeof(BPy_GetOccludersF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetOccludersF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludersF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h
new file mode 100644
index 00000000000..ad39ad25c3d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETOCCLUDERSF1D_H
+#define FREESTYLE_PYTHON_GETOCCLUDERSF1D_H
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludersF1D_Type;
+
+#define BPy_GetOccludersF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludersF1D_Type) )
+
+/*---------------------------Python BPy_GetOccludersF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetOccludersF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETOCCLUDERSF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp
new file mode 100644
index 00000000000..9b2007296f9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp
@@ -0,0 +1,86 @@
+#include "BPy_GetShapeF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetShapeF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetShapeF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetShapeF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of shapes covered by this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of shapes covered by the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetShapeF1D___init__( BPy_GetShapeF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetShapeF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetShapeF1D type definition ------------------------------*/
+
+PyTypeObject GetShapeF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetShapeF1D", /* tp_name */
+ sizeof(BPy_GetShapeF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetShapeF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetShapeF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h
new file mode 100644
index 00000000000..39d1268c03f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETSHAPEF1D_H
+#define FREESTYLE_PYTHON_GETSHAPEF1D_H
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetShapeF1D_Type;
+
+#define BPy_GetShapeF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetShapeF1D_Type) )
+
+/*---------------------------Python BPy_GetShapeF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetShapeF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETSHAPEF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp
new file mode 100644
index 00000000000..be774a09d99
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_ChainingTimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ChainingTimeStampF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`ChainingTimeStampF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a ChainingTimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Sets the chaining time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int ChainingTimeStampF1D___init__( BPy_ChainingTimeStampF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::ChainingTimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_ChainingTimeStampF1D type definition ------------------------------*/
+
+PyTypeObject ChainingTimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainingTimeStampF1D", /* tp_name */
+ sizeof(BPy_ChainingTimeStampF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ChainingTimeStampF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainingTimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h
new file mode 100644
index 00000000000..6855ddaf14b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H
+#define FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainingTimeStampF1D_Type;
+
+#define BPy_ChainingTimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainingTimeStampF1D_Type) )
+
+/*---------------------------Python BPy_ChainingTimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_ChainingTimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp
new file mode 100644
index 00000000000..2d1a1344c4b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_IncrementChainingTimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncrementChainingTimeStampF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`IncrementChainingTimeStampF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds an IncrementChainingTimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Increments the chaining time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int IncrementChainingTimeStampF1D___init__( BPy_IncrementChainingTimeStampF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::IncrementChainingTimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_IncrementChainingTimeStampF1D type definition ------------------------------*/
+
+PyTypeObject IncrementChainingTimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncrementChainingTimeStampF1D", /* tp_name */
+ sizeof(BPy_IncrementChainingTimeStampF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ IncrementChainingTimeStampF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)IncrementChainingTimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h
new file mode 100644
index 00000000000..a1d5714ab63
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H
+#define FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncrementChainingTimeStampF1D_Type;
+
+#define BPy_IncrementChainingTimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncrementChainingTimeStampF1D_Type) )
+
+/*---------------------------Python BPy_IncrementChainingTimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_IncrementChainingTimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp
new file mode 100644
index 00000000000..c5311501098
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_TimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TimeStampF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`TimeStampF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a TimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int TimeStampF1D___init__( BPy_TimeStampF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::TimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_TimeStampF1D type definition ------------------------------*/
+
+PyTypeObject TimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TimeStampF1D", /* tp_name */
+ sizeof(BPy_TimeStampF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TimeStampF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h
new file mode 100644
index 00000000000..d9bee247c09
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_TIMESTAMPF1D_H
+#define FREESTYLE_PYTHON_TIMESTAMPF1D_H
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TimeStampF1D_Type;
+
+#define BPy_TimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TimeStampF1D_Type) )
+
+/*---------------------------Python BPy_TimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_TimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp
new file mode 100644
index 00000000000..afefa703d14
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp
@@ -0,0 +1,78 @@
+#include "BPy_FalseUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseUP0D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate0D` > :class:`FalseUP0D`\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseUP0D___init__( BPy_FalseUP0D* self, PyObject *args)
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up0D.up0D = new Predicates0D::FalseUP0D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseUP0D type definition ------------------------------*/
+
+PyTypeObject FalseUP0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseUP0D", /* tp_name */
+ sizeof(BPy_FalseUP0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FalseUP0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseUP0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h
new file mode 100644
index 00000000000..399941d442d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_FALSEUP0D_H
+#define FREESTYLE_PYTHON_FALSEUP0D_H
+
+#include "../BPy_UnaryPredicate0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseUP0D_Type;
+
+#define BPy_FalseUP0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseUP0D_Type) )
+
+/*---------------------------Python BPy_FalseUP0D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate0D py_up0D;
+} BPy_FalseUP0D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FALSEUP0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp
new file mode 100644
index 00000000000..2efc9ed6f74
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp
@@ -0,0 +1,78 @@
+#include "BPy_TrueUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueUP0D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate0D` > :class:`TrueUP0D`\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueUP0D___init__( BPy_TrueUP0D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up0D.up0D = new Predicates0D::TrueUP0D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueUP0D type definition ------------------------------*/
+
+PyTypeObject TrueUP0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueUP0D", /* tp_name */
+ sizeof(BPy_TrueUP0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TrueUP0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueUP0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h
new file mode 100644
index 00000000000..24976aaa5c9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_TRUEUP0D_H
+#define FREESTYLE_PYTHON_TRUEUP0D_H
+
+#include "../BPy_UnaryPredicate0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueUP0D_Type;
+
+#define BPy_TrueUP0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueUP0D_Type) )
+
+/*---------------------------Python BPy_TrueUP0D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate0D py_up0D;
+} BPy_TrueUP0D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TRUEUP0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp
new file mode 100644
index 00000000000..dbbcc4255cf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp
@@ -0,0 +1,79 @@
+#include "BPy_ContourUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ContourUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ContourUP1D`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D is a contour. An Interface1D is a\n"
+" contour if it is borded by a different shape on each of its sides.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the Interface1D is a contour, false otherwise.\n"
+" :rtype: bool\n";
+
+static int ContourUP1D___init__( BPy_ContourUP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::ContourUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_ContourUP1D type definition ------------------------------*/
+
+PyTypeObject ContourUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ContourUP1D", /* tp_name */
+ sizeof(BPy_ContourUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ContourUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ContourUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h
new file mode 100644
index 00000000000..a24261a60de
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_CONTOURUP1D_H
+#define FREESTYLE_PYTHON_CONTOURUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ContourUP1D_Type;
+
+#define BPy_ContourUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ContourUP1D_Type) )
+
+/*---------------------------Python BPy_ContourUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ContourUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CONTOURUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp
new file mode 100644
index 00000000000..c88f077c23b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp
@@ -0,0 +1,95 @@
+#include "BPy_DensityLowerThanUP1D.h"
+
+#include "../../stroke/AdvancedPredicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityLowerThanUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`DensityLowerThanUP1D`\n"
+"\n"
+".. method:: __init__(threshold, sigma=2.0)\n"
+"\n"
+" Builds a DensityLowerThanUP1D object.\n"
+"\n"
+" :arg threshold: The value of the threshold density. Any Interface1D\n"
+" having a density lower than this threshold will match.\n"
+" :type threshold: float\n"
+" :arg sigma: The sigma value defining the density evaluation window\n"
+" size used in the :class:`DensityF0D` functor.\n"
+" :type sigma: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the density evaluated for the Interface1D is less\n"
+" than a user-defined density value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the density is lower than a threshold.\n"
+" :rtype: bool\n";
+
+static int DensityLowerThanUP1D___init__( BPy_DensityLowerThanUP1D* self, PyObject *args )
+{
+ double d1, d2 = 2.0;
+
+ if( !PyArg_ParseTuple(args, "d|d", &d1, &d2) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::DensityLowerThanUP1D(d1,d2);
+ return 0;
+}
+
+/*-----------------------BPy_DensityLowerThanUP1D type definition ------------------------------*/
+
+PyTypeObject DensityLowerThanUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityLowerThanUP1D", /* tp_name */
+ sizeof(BPy_DensityLowerThanUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DensityLowerThanUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityLowerThanUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h
new file mode 100644
index 00000000000..2862b060a0a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H
+#define FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityLowerThanUP1D_Type;
+
+#define BPy_DensityLowerThanUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityLowerThanUP1D_Type) )
+
+/*---------------------------Python BPy_DensityLowerThanUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_DensityLowerThanUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
new file mode 100644
index 00000000000..2310f5792c5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
@@ -0,0 +1,89 @@
+#include "BPy_EqualToChainingTimeStampUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char EqualToChainingTimeStampUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`EqualToChainingTimeStampUP1D`\n"
+"\n"
+".. method:: __init__(ts)\n"
+"\n"
+" Builds a EqualToChainingTimeStampUP1D object.\n"
+"\n"
+" :arg ts: A time stamp value.\n"
+" :type ts: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D's time stamp is equal to a certain\n"
+" user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the time stamp is equal to a user-defined value.\n"
+" :rtype: bool\n";
+
+static int EqualToChainingTimeStampUP1D___init__( BPy_EqualToChainingTimeStampUP1D* self, PyObject *args )
+{
+ unsigned u;
+
+ if( !PyArg_ParseTuple(args, "I", &u) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::EqualToChainingTimeStampUP1D(u);
+ return 0;
+}
+
+/*-----------------------BPy_EqualToChainingTimeStampUP1D type definition ------------------------------*/
+
+PyTypeObject EqualToChainingTimeStampUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "EqualToChainingTimeStampUP1D", /* tp_name */
+ sizeof(BPy_EqualToChainingTimeStampUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ EqualToChainingTimeStampUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)EqualToChainingTimeStampUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h
new file mode 100644
index 00000000000..39423423b8e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H
+#define FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject EqualToChainingTimeStampUP1D_Type;
+
+#define BPy_EqualToChainingTimeStampUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &EqualToChainingTimeStampUP1D_Type) )
+
+/*---------------------------Python BPy_EqualToChainingTimeStampUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_EqualToChainingTimeStampUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
new file mode 100644
index 00000000000..97415b2b28f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
@@ -0,0 +1,89 @@
+#include "BPy_EqualToTimeStampUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char EqualToTimeStampUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`EqualToTimeStampUP1D`\n"
+"\n"
+".. method:: __init__(ts)\n"
+"\n"
+" Builds a EqualToTimeStampUP1D object.\n"
+"\n"
+" :arg ts: A time stamp value.\n"
+" :type ts: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D's time stamp is equal to a certain\n"
+" user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the time stamp is equal to a user-defined value.\n"
+" :rtype: bool\n";
+
+static int EqualToTimeStampUP1D___init__( BPy_EqualToTimeStampUP1D* self, PyObject *args )
+{
+ unsigned u;
+
+ if( !PyArg_ParseTuple(args, "I", &u) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::EqualToTimeStampUP1D(u);
+ return 0;
+}
+
+/*-----------------------BPy_EqualToTimeStampUP1D type definition ------------------------------*/
+
+PyTypeObject EqualToTimeStampUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "EqualToTimeStampUP1D", /* tp_name */
+ sizeof(BPy_EqualToTimeStampUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ EqualToTimeStampUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)EqualToTimeStampUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h
new file mode 100644
index 00000000000..538dc400dc2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H
+#define FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject EqualToTimeStampUP1D_Type;
+
+#define BPy_EqualToTimeStampUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &EqualToTimeStampUP1D_Type) )
+
+/*---------------------------Python BPy_EqualToTimeStampUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_EqualToTimeStampUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp
new file mode 100644
index 00000000000..3c9156f3a89
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp
@@ -0,0 +1,81 @@
+#include "BPy_ExternalContourUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ExternalContourUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ExternalContourUP1D`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D is an external contour. An\n"
+" Interface1D is an external contour if it is borded by no shape on\n"
+" one of its sides.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the Interface1D is an external contour, false\n"
+" otherwise.\n"
+" :rtype: bool\n";
+
+static int ExternalContourUP1D___init__( BPy_ExternalContourUP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::ExternalContourUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_ExternalContourUP1D type definition ------------------------------*/
+
+PyTypeObject ExternalContourUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ExternalContourUP1D", /* tp_name */
+ sizeof(BPy_ExternalContourUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ExternalContourUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ExternalContourUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h
new file mode 100644
index 00000000000..31300f04dfe
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H
+#define FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ExternalContourUP1D_Type;
+
+#define BPy_ExternalContourUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ExternalContourUP1D_Type) )
+
+/*---------------------------Python BPy_ExternalContourUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ExternalContourUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp
new file mode 100644
index 00000000000..ac878a7770b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp
@@ -0,0 +1,78 @@
+#include "BPy_FalseUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`FalseUP1D`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseUP1D___init__( BPy_FalseUP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::FalseUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseUP1D type definition ------------------------------*/
+
+PyTypeObject FalseUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseUP1D", /* tp_name */
+ sizeof(BPy_FalseUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FalseUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h
new file mode 100644
index 00000000000..273e4962db9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_FALSEUP1D_H
+#define FREESTYLE_PYTHON_FALSEUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseUP1D_Type;
+
+#define BPy_FalseUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseUP1D_Type) )
+
+/*---------------------------Python BPy_FalseUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_FalseUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FALSEUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp
new file mode 100644
index 00000000000..cabc4689a03
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_QuantitativeInvisibilityUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`QuantitativeInvisibilityUP1D`\n"
+"\n"
+".. method:: __init__(qi=0)\n"
+"\n"
+" Builds a QuantitativeInvisibilityUP1D object.\n"
+"\n"
+" :arg qi: The Quantitative Invisibility you want the Interface1D to\n"
+" have.\n"
+" :type qi: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Quantitative Invisibility evaluated at an\n"
+" Interface1D, using the :class:`QuantitativeInvisibilityF1D`\n"
+" functor, equals a certain user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if Quantitative Invisibility equals a user-defined\n"
+" value.\n"
+" :rtype: bool\n";
+
+static int QuantitativeInvisibilityUP1D___init__( BPy_QuantitativeInvisibilityUP1D* self, PyObject *args )
+{
+ int i = 0;
+
+ if( !PyArg_ParseTuple(args, "|i", &i) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::QuantitativeInvisibilityUP1D(i);
+ return 0;
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityUP1D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityUP1D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ QuantitativeInvisibilityUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h
new file mode 100644
index 00000000000..f120ecb9778
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H
+#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityUP1D_Type;
+
+#define BPy_QuantitativeInvisibilityUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityUP1D_Type) )
+
+/*---------------------------Python BPy_QuantitativeInvisibilityUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_QuantitativeInvisibilityUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
new file mode 100644
index 00000000000..9e6e57c8d94
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_ShapeUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ShapeUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ShapeUP1D`\n"
+"\n"
+".. method:: __init__(idFirst, idSecond=0)\n"
+"\n"
+" Builds a ShapeUP1D object.\n"
+"\n"
+" :arg idFirst: The first Id component.\n"
+" :type idFirst: int\n"
+" :arg idSecond: The second Id component.\n"
+" :type idSecond: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the shape to which the Interface1D belongs to has\n"
+" the same :class:`Id` as the one specified by the user.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if Interface1D belongs to the shape of the\n"
+" user-specified Id.\n"
+" :rtype: bool\n";
+
+static int ShapeUP1D___init__( BPy_ShapeUP1D* self, PyObject *args )
+{
+ unsigned u1, u2 = 0;
+
+ if( !PyArg_ParseTuple(args, "I|I", &u1, &u2) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::ShapeUP1D(u1,u2);
+ return 0;
+}
+
+/*-----------------------BPy_ShapeUP1D type definition ------------------------------*/
+
+PyTypeObject ShapeUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ShapeUP1D", /* tp_name */
+ sizeof(BPy_ShapeUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ShapeUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ShapeUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h
new file mode 100644
index 00000000000..ce6d0276edd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_SHAPEUP1D_H
+#define FREESTYLE_PYTHON_SHAPEUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ShapeUP1D_Type;
+
+#define BPy_ShapeUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ShapeUP1D_Type) )
+
+/*---------------------------Python BPy_ShapeUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ShapeUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SHAPEUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp
new file mode 100644
index 00000000000..01da1a44453
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp
@@ -0,0 +1,78 @@
+#include "BPy_TrueUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`TrueUP1D`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueUP1D___init__( BPy_TrueUP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::TrueUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueUP1D type definition ------------------------------*/
+
+PyTypeObject TrueUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueUP1D", /* tp_name */
+ sizeof(BPy_TrueUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TrueUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h
new file mode 100644
index 00000000000..5a01ad42d2a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_TRUEUP1D_H
+#define FREESTYLE_PYTHON_TRUEUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueUP1D_Type;
+
+#define BPy_TrueUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueUP1D_Type) )
+
+/*---------------------------Python BPy_TrueUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_TrueUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TRUEUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp
new file mode 100644
index 00000000000..9beae103113
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp
@@ -0,0 +1,88 @@
+#include "BPy_WithinImageBoundaryUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char WithinImageBoundaryUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`WithinImageBoundaryUP1D`\n"
+"\n"
+".. method:: __init__(xmin, ymin, xmax, ymax)\n"
+"\n"
+" Builds an WithinImageBoundaryUP1D object.\n"
+"\n"
+" :arg xmin: X lower bound of the image boundary.\n"
+" :type xmin: float\n"
+" :arg ymin: Y lower bound of the image boundary.\n"
+" :type ymin: float\n"
+" :arg xmax: X upper bound of the image boundary.\n"
+" :type xmax: float\n"
+" :arg ymax: Y upper bound of the image boundary.\n"
+" :type ymax: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D intersects with image boundary.\n";
+
+static int WithinImageBoundaryUP1D___init__( BPy_WithinImageBoundaryUP1D* self, PyObject *args )
+{
+ double xmin, ymin, xmax, ymax;
+
+ if(!( PyArg_ParseTuple(args, "dddd", &xmin, &ymin, &xmax, &ymax) ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::WithinImageBoundaryUP1D(xmin, ymin, xmax, ymax);
+ return 0;
+}
+
+/*-----------------------BPy_TrueUP1D type definition ------------------------------*/
+
+PyTypeObject WithinImageBoundaryUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "WithinImageBoundaryUP1D", /* tp_name */
+ sizeof(BPy_WithinImageBoundaryUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ WithinImageBoundaryUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)WithinImageBoundaryUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h
new file mode 100644
index 00000000000..2bd3e698a21
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H
+#define FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject WithinImageBoundaryUP1D_Type;
+
+#define BPy_WithinImageBoundaryUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &WithinImageBoundaryUP1D_Type) )
+
+/*---------------------------Python BPy_WithinImageBoundaryUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_WithinImageBoundaryUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H */
diff --git a/source/blender/freestyle/intern/scene_graph/DrawingStyle.h b/source/blender/freestyle/intern/scene_graph/DrawingStyle.h
new file mode 100755
index 00000000000..58dcf4fede9
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/DrawingStyle.h
@@ -0,0 +1,82 @@
+//
+// Filename : DrawingStyle.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the drawing style of a node
+// Date of creation : 10/10/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef DRAWINGSTYLE_H
+# define DRAWINGSTYLE_H
+
+class DrawingStyle
+{
+public:
+ enum STYLE
+ {FILLED, LINES, POINTS, INVISIBLE};
+
+ inline DrawingStyle() {Style = FILLED; LineWidth = 2.f; PointSize = 2.f; LightingEnabled = true;}
+ inline explicit DrawingStyle(const DrawingStyle& iBrother);
+
+ virtual ~DrawingStyle() {}
+
+ /*! operators */
+ inline DrawingStyle& operator=(const DrawingStyle& ds);
+
+ inline void setStyle(const STYLE iStyle) {Style = iStyle;}
+ inline void setLineWidth(const float iLineWidth) {LineWidth = iLineWidth;}
+ inline void setPointSize(const float iPointSize) {PointSize = iPointSize;}
+ inline void setLightingEnabled(const bool on) {LightingEnabled = on;}
+
+ inline STYLE style() const {return Style;}
+ inline float lineWidth() const {return LineWidth;}
+ inline float pointSize() const {return PointSize;}
+ inline bool lightingEnabled() const {return LightingEnabled;}
+
+private:
+ STYLE Style;
+ float LineWidth;
+ float PointSize;
+ bool LightingEnabled;
+};
+
+DrawingStyle::DrawingStyle(const DrawingStyle& iBrother)
+{
+ Style = iBrother.Style;
+ LineWidth = iBrother.LineWidth;
+ PointSize = iBrother.PointSize;
+ LightingEnabled = iBrother.LightingEnabled;
+}
+
+DrawingStyle& DrawingStyle::operator=(const DrawingStyle& ds)
+{
+ Style = ds.Style;
+ LineWidth = ds.LineWidth;
+ PointSize = ds.PointSize;
+ LightingEnabled = ds.LightingEnabled;
+
+ return *this;
+}
+
+#endif // DRAWINGSTYLE_H
diff --git a/source/blender/freestyle/intern/scene_graph/FrsMaterial.h b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
new file mode 100755
index 00000000000..1cbadab2bd3
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
@@ -0,0 +1,304 @@
+//
+// Filename : FrsMaterial.h
+// Author(s) : Stephane Grabli
+// Purpose : Class used to handle materials.
+// Date of creation : 10/10/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef FRS_MATERIAL_H
+# define FRS_MATERIAL_H
+
+# include "../system/FreestyleConfig.h"
+
+/*! Class defining a material */
+class FrsMaterial
+{
+public:
+ /*! Default constructor */
+ inline FrsMaterial();
+ /*! Builds a Material from its diffuse, ambiant, specular, emissive
+ * colors and a shininess coefficient.
+ * \param iDiffuse
+ * A 4 element float-array containing the diffuse color.
+ * \param iAmbiant
+ * A 4 element float-array containing the ambiant color.
+ * \param iSpecular
+ * A 4 element float-array containing the specular color.
+ * \param iEmission
+ * A 4 element float-array containing the emissive color.
+ * \param iShininess
+ * The shininess coefficient.
+ */
+ inline FrsMaterial(const float *iDiffuse,
+ const float *iAmbiant,
+ const float *iSpecular,
+ const float *iEmission,
+ const float iShininess);
+
+ /*! Copy constructor */
+ inline FrsMaterial(const FrsMaterial& m);
+ /*! Destructor */
+ virtual ~FrsMaterial() {}
+
+
+ /*! Returns the diffuse color as a 4 float array */
+ inline const float * diffuse() const { return Diffuse; }
+ /*! Returns the red component of the diffuse color */
+ inline const float diffuseR() const { return Diffuse[0]; }
+ /*! Returns the green component of the diffuse color */
+ inline const float diffuseG() const { return Diffuse[1]; }
+ /*! Returns the blue component of the diffuse color */
+ inline const float diffuseB() const { return Diffuse[2]; }
+ /*! Returns the alpha component of the diffuse color */
+ inline const float diffuseA() const { return Diffuse[3]; }
+
+ /*! Returns the specular color as a 4 float array */
+ inline const float * specular() const { return Specular; }
+ /*! Returns the red component of the specular color */
+ inline const float specularR() const { return Specular[0]; }
+ /*! Returns the green component of the specular color */
+ inline const float specularG() const { return Specular[1]; }
+ /*! Returns the blue component of the specular color */
+ inline const float specularB() const { return Specular[2]; }
+ /*! Returns the alpha component of the specular color */
+ inline const float specularA() const { return Specular[3]; }
+
+ /*! Returns the ambiant color as a 4 float array */
+ inline const float * ambient() const { return Ambient; }
+ /*! Returns the red component of the ambiant color */
+ inline const float ambientR() const { return Ambient[0]; }
+ /*! Returns the green component of the ambiant color */
+ inline const float ambientG() const { return Ambient[1]; }
+ /*! Returns the blue component of the ambiant color */
+ inline const float ambientB() const { return Ambient[2]; }
+ /*! Returns the alpha component of the ambiant color */
+ inline const float ambientA() const { return Ambient[3]; }
+
+ /*! Returns the emissive color as a 4 float array */
+ inline const float * emission() const { return Emission; }
+ /*! Returns the red component of the emissive color */
+ inline const float emissionR() const { return Emission[0]; }
+ /*! Returns the green component of the emissive color */
+ inline const float emissionG() const { return Emission[1]; }
+ /*! Returns the blue component of the emissive color */
+ inline const float emissionB() const { return Emission[2]; }
+ /*! Returns the alpha component of the emissive color */
+ inline const float emissionA() const { return Emission[3]; }
+
+ /*! Returns the shininess coefficient */
+ inline const float shininess() const { return Shininess; }
+
+ /*! Sets the diffuse color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setDiffuse(const float r, const float g, const float b, const float a);
+ /*! Sets the specular color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setSpecular(const float r, const float g, const float b, const float a);
+ /*! Sets the ambiant color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setAmbient(const float r, const float g, const float b, const float a);
+
+ /*! Sets the emissive color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setEmission(const float r, const float g, const float b, const float a);
+
+ /*! Sets the shininess.
+ * \param s
+ * Shininess
+ */
+ inline void setShininess(const float s);
+
+ /* operators */
+ inline FrsMaterial& operator=(const FrsMaterial& m);
+ inline bool operator!=(const FrsMaterial& m) const;
+ inline bool operator==(const FrsMaterial& m) const;
+
+private:
+
+ /*! Material properties */
+ float Diffuse[4];
+ float Specular[4];
+ float Ambient[4];
+ float Emission[4];
+ float Shininess;
+
+};
+
+FrsMaterial::FrsMaterial()
+{
+ Ambient[0] = Ambient[1] = Ambient[2] = 0.2f;
+ Ambient[3] = 1.f;
+
+ Diffuse[0] = Diffuse[1] = Diffuse[2] = 0.8f;
+ Diffuse[3] = 1.f;
+
+ Emission[0] = Emission[1] = Emission[2] = 0.f;
+ Emission[3] = 1.f;
+
+ Specular[0] = Specular[1] = Specular[2] = 0.f;
+ Specular[3] = 1.f;
+
+ Shininess = 0.f;
+}
+
+FrsMaterial::FrsMaterial(const float *iDiffuse,
+ const float *iAmbiant,
+ const float *iSpecular,
+ const float *iEmission,
+ const float iShininess)
+{
+ for(int i=0; i<4; i++)
+ {
+ Diffuse[i] = iDiffuse[i];
+ Specular[i] = iSpecular[i];
+ Ambient[i] = iAmbiant[i];
+ Emission[i] = iEmission[i];
+ }
+
+ Shininess = iShininess;
+}
+
+FrsMaterial::FrsMaterial(const FrsMaterial& m)
+{
+ for(int i=0; i<4; i++)
+ {
+ Diffuse[i] = m.diffuse()[i];
+ Specular[i] = m.specular()[i];
+ Ambient[i] = m.ambient()[i];
+ Emission[i] = m.emission()[i];
+ }
+
+ Shininess = m.shininess();
+}
+
+void FrsMaterial::setDiffuse(const float r, const float g, const float b, const float a)
+{
+ Diffuse[0] = r;
+ Diffuse[1] = g;
+ Diffuse[2] = b;
+ Diffuse[3] = a;
+}
+
+void FrsMaterial::setSpecular(const float r, const float g, const float b, const float a)
+{
+ Specular[0] = r;
+ Specular[1] = g;
+ Specular[2] = b;
+ Specular[3] = a;
+}
+
+void FrsMaterial::setAmbient(const float r, const float g, const float b, const float a)
+{
+ Ambient[0] = r;
+ Ambient[1] = g;
+ Ambient[2] = b;
+ Ambient[3] = a;
+}
+
+void FrsMaterial::setEmission(const float r, const float g, const float b, const float a)
+{
+ Emission[0] = r;
+ Emission[1] = g;
+ Emission[2] = b;
+ Emission[3] = a;
+}
+
+void FrsMaterial::setShininess(const float s)
+{
+ Shininess = s;
+}
+
+FrsMaterial& FrsMaterial::operator=(const FrsMaterial& m)
+{
+ for(int i=0; i<4; i++)
+ {
+ Diffuse[i] = m.diffuse()[i];
+ Specular[i] = m.specular()[i];
+ Ambient[i] = m.ambient()[i];
+ Emission[i] = m.emission()[i];
+ }
+
+ Shininess = m.shininess();
+
+ return *this;
+}
+
+bool FrsMaterial::operator!=(const FrsMaterial& m) const
+{
+ if(Shininess != m.shininess())
+ return true;
+ for(int i=0; i<4; i++)
+ {
+ if(Diffuse[i] != m.diffuse()[i])
+ return true;
+ if(Specular[i] != m.specular()[i])
+ return true;
+ if(Ambient[i] != m.ambient()[i])
+ return true;
+ if(Emission[i] != m.emission()[i])
+ return true;
+ }
+
+ return false;
+}
+
+bool FrsMaterial::operator==(const FrsMaterial& m) const
+{
+ return (!((*this)!=m));
+}
+
+#endif // FRS_MATERIAL_H
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
new file mode 100755
index 00000000000..aaeba943ab6
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
@@ -0,0 +1,336 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "IndexedFaceSet.h"
+
+IndexedFaceSet::IndexedFaceSet()
+: Rep()
+{
+ _Vertices = NULL;
+ _Normals = NULL;
+ _FrsMaterials = 0;
+ _TexCoords = 0;
+ _FaceEdgeMarks = 0;
+ _VSize = 0;
+ _NSize = 0;
+ _MSize = 0;
+ _TSize = 0;
+ _NumFaces = 0;
+ _NumVertexPerFace = NULL;
+ _FaceStyle = NULL;
+ _VIndices = NULL;
+ _VISize = 0;
+ _NIndices = NULL;
+ _NISize = 0;
+ _MIndices = NULL;
+ _MISize = 0;
+ _TIndices = NULL;
+ _TISize = 0;
+ _displayList = 0;
+}
+
+IndexedFaceSet::IndexedFaceSet( real *iVertices, unsigned iVSize,
+ real *iNormals, unsigned iNSize,
+ FrsMaterial **iMaterials, unsigned iMSize,
+ real *iTexCoords, unsigned iTSize,
+ unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle,
+ FaceEdgeMark *iFaceEdgeMarks,
+ unsigned *iVIndices, unsigned iVISize,
+ unsigned *iNIndices, unsigned iNISize,
+ unsigned *iMIndices, unsigned iMISize,
+ unsigned *iTIndices, unsigned iTISize,
+ unsigned iCopy)
+ : Rep()
+{
+ if(1 == iCopy)
+ {
+ _VSize = iVSize;
+ _Vertices = new real[_VSize];
+ memcpy(_Vertices, iVertices, iVSize*sizeof(real));
+
+ _NSize = iNSize;
+ _Normals = new real[_NSize];
+ memcpy(_Normals, iNormals, iNSize*sizeof(real));
+
+ _MSize = iMSize;
+ _FrsMaterials = 0;
+ if(iMaterials){
+ _FrsMaterials = new FrsMaterial*[_MSize];
+ for(unsigned i=0; i<_MSize; ++i)
+ _FrsMaterials[i] = new FrsMaterial(*(iMaterials[i]));
+ }
+ _TSize = iTSize;
+ _TexCoords = 0;
+ if(_TSize){
+ _TexCoords = new real[_TSize];
+ memcpy(_TexCoords, iTexCoords, iTSize*sizeof(real));
+ }
+
+ _NumFaces = iNumFaces;
+ _NumVertexPerFace = new unsigned[_NumFaces];
+ memcpy(_NumVertexPerFace, iNumVertexPerFace, _NumFaces*sizeof(unsigned));
+
+ _FaceStyle = new TRIANGLES_STYLE[_NumFaces];
+ memcpy(_FaceStyle, iFaceStyle, _NumFaces*sizeof(TRIANGLES_STYLE));
+
+ _FaceEdgeMarks = new FaceEdgeMark[_NumFaces];
+ memcpy(_FaceEdgeMarks, iFaceEdgeMarks, _NumFaces*sizeof(FaceEdgeMark));
+
+ _VISize = iVISize;
+ _VIndices = new unsigned[_VISize];
+ memcpy(_VIndices, iVIndices, _VISize*sizeof(unsigned));
+
+ _NISize = iNISize;
+ _NIndices = new unsigned[_NISize];
+ memcpy(_NIndices, iNIndices, _NISize*sizeof(unsigned));
+
+ _MISize = iMISize;
+ _MIndices = 0;
+ if(iMIndices){
+ _MIndices = new unsigned[_MISize];
+ memcpy(_MIndices, iMIndices, _MISize*sizeof(unsigned));
+ }
+ _TISize = iTISize;
+ _TIndices = 0;
+ if(_TISize){
+ _TIndices = new unsigned[_TISize];
+ memcpy(_TIndices, iTIndices, _TISize*sizeof(unsigned));
+ }
+ }
+ else
+ {
+ _VSize = iVSize;
+ _Vertices = iVertices;
+
+ _NSize = iNSize;
+ _Normals = iNormals;
+
+ _MSize = iMSize;
+ _FrsMaterials = 0;
+ if(iMaterials)
+ _FrsMaterials = iMaterials;
+
+ _TSize = iTSize;
+ _TexCoords = iTexCoords;
+
+ _NumFaces = iNumFaces;
+ _NumVertexPerFace = iNumVertexPerFace;
+ _FaceStyle = iFaceStyle;
+ _FaceEdgeMarks = iFaceEdgeMarks;
+
+ _VISize = iVISize;
+ _VIndices = iVIndices;
+
+ _NISize = iNISize;
+ _NIndices = iNIndices;
+
+ _MISize = iMISize;
+ _MIndices = 0;
+ if(iMISize)
+ _MIndices = iMIndices;
+
+ _TISize = iTISize;
+ _TIndices = iTIndices;
+ }
+
+ _displayList = 0;
+}
+
+IndexedFaceSet::IndexedFaceSet( const IndexedFaceSet& iBrother)
+:Rep(iBrother)
+{
+ _VSize = iBrother.vsize();
+ _Vertices = new real[_VSize];
+ memcpy(_Vertices, iBrother.vertices(), _VSize*sizeof(real));
+
+ _NSize = iBrother.nsize();
+ _Normals = new real[_NSize];
+ memcpy(_Normals, iBrother.normals(), _NSize*sizeof(real));
+
+ _MSize = iBrother.msize();
+ if(_MSize){
+ _FrsMaterials = new FrsMaterial*[_MSize];
+ for(unsigned i=0; i<_MSize; ++i){
+ _FrsMaterials[i] = new FrsMaterial(*(iBrother._FrsMaterials[i]));
+ }
+ }else{
+ _FrsMaterials = 0;
+ }
+
+ _TSize = iBrother.tsize();
+ _TexCoords = 0;
+ if(_TSize){
+ _TexCoords = new real[_TSize];
+ memcpy(_TexCoords, iBrother.texCoords(), _TSize*sizeof(real));
+ }
+
+ _NumFaces = iBrother.numFaces();
+ _NumVertexPerFace = new unsigned[_NumFaces];
+ memcpy(_NumVertexPerFace, iBrother.numVertexPerFaces(), _NumFaces*sizeof(unsigned));
+
+ _FaceStyle = new TRIANGLES_STYLE[_NumFaces];
+ memcpy(_FaceStyle, iBrother.trianglesStyle(), _NumFaces*sizeof(TRIANGLES_STYLE));
+
+ _FaceEdgeMarks = new FaceEdgeMark[_NumFaces];
+ memcpy(_FaceEdgeMarks, iBrother.faceEdgeMarks(), _NumFaces*sizeof(FaceEdgeMark));
+
+ _VISize = iBrother.visize();
+ _VIndices = new unsigned[_VISize];
+ memcpy(_VIndices, iBrother.vindices(), _VISize*sizeof(unsigned));
+
+ _NISize = iBrother.nisize();
+ _NIndices = new unsigned[_NISize];
+ memcpy(_NIndices, iBrother.nindices(), _NISize*sizeof(unsigned));
+
+ _MISize = iBrother.misize();
+ if(_MISize){
+ _MIndices = new unsigned[_MISize];
+ memcpy(_MIndices, iBrother.mindices(), _MISize*sizeof(unsigned));
+ }else{
+ _MIndices=0;
+ }
+
+ _TISize = iBrother.tisize();
+ _TIndices = 0;
+ if(_TISize){
+ _TIndices = new unsigned[_TISize];
+ memcpy(_TIndices, iBrother.tindices(), _TISize*sizeof(unsigned));
+ }
+
+ _displayList = 0;
+}
+
+IndexedFaceSet::~IndexedFaceSet()
+{
+ if(NULL != _Vertices)
+ {
+ delete [] _Vertices;
+ _Vertices = NULL;
+ }
+
+ if(NULL != _Normals)
+ {
+ delete [] _Normals;
+ _Normals = NULL;
+ }
+
+ if(NULL != _FrsMaterials)
+ {
+ for(unsigned i=0; i<_MSize; ++i)
+ delete _FrsMaterials[i];
+ delete [] _FrsMaterials;
+ _FrsMaterials = NULL;
+ }
+
+ if(NULL != _TexCoords)
+ {
+ delete [] _TexCoords;
+ _TexCoords = NULL;
+ }
+
+ if(NULL != _NumVertexPerFace)
+ {
+ delete [] _NumVertexPerFace;
+ _NumVertexPerFace = NULL;
+ }
+
+ if(NULL != _FaceStyle)
+ {
+ delete [] _FaceStyle;
+ _FaceStyle = NULL;
+ }
+
+ if(NULL != _FaceEdgeMarks)
+ {
+ delete [] _FaceEdgeMarks;
+ _FaceEdgeMarks = NULL;
+ }
+
+ if(NULL != _VIndices)
+ {
+ delete [] _VIndices;
+ _VIndices = NULL;
+ }
+
+ if(NULL != _NIndices)
+ {
+ delete [] _NIndices;
+ _NIndices = NULL;
+ }
+
+ if(NULL != _MIndices)
+ {
+ delete [] _MIndices;
+ _MIndices = NULL;
+ }
+ if(NULL != _TIndices)
+ {
+ delete [] _TIndices;
+ _TIndices = NULL;
+ }
+ // should find a way to deallocates the displayList
+ // glDeleteLists(GLuint list, GLSizei range)
+ _displayList = 0;
+}
+
+void IndexedFaceSet::accept(SceneVisitor& v) {
+ Rep::accept(v);
+ v.visitIndexedFaceSet(*this);
+}
+
+void IndexedFaceSet::ComputeBBox()
+{
+ real XMax = _Vertices[0];
+ real YMax = _Vertices[1];
+ real ZMax = _Vertices[2];
+
+ real XMin = _Vertices[0];
+ real YMin = _Vertices[1];
+ real ZMin = _Vertices[2];
+
+ // parse all the coordinates to find
+ // the Xmax, YMax, ZMax
+ real *v = _Vertices;
+
+ for(unsigned i=0; i<_VSize/3; i++)
+ {
+ // X
+ if(*v > XMax)
+ XMax = *v;
+ if(*v < XMin)
+ XMin = *v;
+ v++;
+
+ if(*v > YMax)
+ YMax = *v;
+ if(*v < YMin)
+ YMin = *v;
+ v++;
+
+ if(*v > ZMax)
+ ZMax = *v;
+ if(*v < ZMin)
+ ZMin = *v;
+ v++;
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
new file mode 100755
index 00000000000..b578dc1257e
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
@@ -0,0 +1,233 @@
+//
+// Filename : IndexedFaceSet.h
+// Author(s) : Stephane Grabli
+// Purpose : A Set of indexed faces to represent a surfacic object
+// Date of creation : 22/01/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef INDEXEDFACESET_H
+# define INDEXEDFACESET_H
+
+# include <stdio.h>
+# include <memory.h>
+
+//! inherits from class Rep
+# include "Rep.h"
+
+# include "../system/FreestyleConfig.h"
+
+class LIB_SCENE_GRAPH_EXPORT IndexedFaceSet : public Rep
+ {
+public:
+
+ /*! Triangles description style:*/
+ enum TRIANGLES_STYLE{TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES};
+
+ /*! User-specified face and edge marks for feature edge detection */
+ typedef unsigned char FaceEdgeMark;
+ static const FaceEdgeMark FACE_MARK = 1;
+ static const FaceEdgeMark EDGE_MARK_V1V2 = 2;
+ static const FaceEdgeMark EDGE_MARK_V2V3 = 4;
+ static const FaceEdgeMark EDGE_MARK_V3V1 = 8;
+
+ /*! Builds an empty indexed face set
+ */
+ IndexedFaceSet();
+ /*! Builds an indexed face set
+ iVertices
+ The array of object vertices 3D coordinates (for all faces).
+ If iCopy != 0, the array is copied; you must desallocate iVertices. Else you must not.
+ iVSize
+ The size of iVertices (must be a multiple of 3)
+ iNormals
+ The array of object normals 3D coordinates.
+ If iCopy != 0, the array is copied; you must desallocate iNormals. Else you must not.
+ iNSize
+ The size of iNormals
+ iMaterials
+ The array of materials
+ iMSize
+ The size of iMaterials
+ iTexCoords
+ The array of texture coordinates.
+ iTSize
+ The size of iTexCoords (must be multiple of 2)
+ iNumFaces
+ The number of faces
+ iNumVertexPerFace
+ Array containing the number of vertices per face.
+ iFaceStyle
+ Array containing the description style of each faces.
+ The style belongs to:
+ - TRIANGLE_STRIP: the face indices describe a triangle strip
+ - TRIANGLE_FAN : the face indices describe a triangle fan
+ - TRIANGLES : the face indices describe single triangles
+ If iCopy != 0, the array is copied; you must desallocate iFaceStyle. Else you must not.
+ iVIndices,
+ Array of vertices indices.
+ The integers contained in this array must be multiple of 3.
+ If iCopy != 0, the array is copied; you must desallocate iVIndices. Else you must not.
+ iVISize
+ The size of iVIndices.
+ iNIndices
+ Array of normals indices.
+ The integers contained in this array must be multiple of 3.
+ If iCopy != 0, the array is copied; you must desallocate iNIndices. Else you must not.
+ iNISize
+ The size of iNIndices
+ iMIndices
+ The Material indices (per vertex)
+ iMISize
+ The size of iMIndices
+ iTIndices
+ The Texture coordinates indices (per vertex). The integers contained in this array must be multiple of 2.
+ iTISize
+ The size of iMIndices
+ iCopy
+ 0 : the arrays are not copied. The pointers passed as arguments are used.
+ IndexedFaceSet takes these arrays desallocation in charge.
+ 1 : the arrays are copied. The caller is in charge of the arrays, passed
+ as arguments desallocation.
+ */
+ IndexedFaceSet( real *iVertices, unsigned iVSize,
+ real *iNormals, unsigned iNSize,
+ FrsMaterial **iMaterials, unsigned iMSize,
+ real *iTexCoords, unsigned iTSize,
+ unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle,
+ FaceEdgeMark *iFaceEdgeMarks,
+ unsigned *iVIndices, unsigned iVISize,
+ unsigned *iNIndices, unsigned iNISize,
+ unsigned *iMIndices, unsigned iMISize,
+ unsigned *iTIndices, unsigned iTISize,
+ unsigned iCopy = 1
+ );
+
+ /*! Builds an indexed face set from an other indexed face set */
+ IndexedFaceSet(const IndexedFaceSet& iBrother);
+
+ void swap(IndexedFaceSet& ioOther){
+ std::swap(_Vertices, ioOther._Vertices);
+ std::swap(_Normals, ioOther._Normals);
+ std::swap(_FrsMaterials, ioOther._FrsMaterials);
+ std::swap(_TexCoords, ioOther._TexCoords);
+ std::swap(_FaceEdgeMarks, ioOther._FaceEdgeMarks);
+
+ std::swap(_VSize, ioOther._VSize);
+ std::swap(_NSize, ioOther._NSize);
+ std::swap(_MSize, ioOther._MSize);
+ std::swap(_TSize, ioOther._TSize);
+
+ std::swap(_NumFaces, ioOther._NumFaces);
+ std::swap(_NumVertexPerFace, ioOther._NumVertexPerFace);
+ std::swap(_FaceStyle, ioOther._FaceStyle);
+
+ std::swap(_VIndices, ioOther._VIndices);
+ std::swap(_NIndices, ioOther._NIndices);
+ std::swap(_MIndices, ioOther._MIndices); // Material Indices
+ std::swap(_TIndices, ioOther._TIndices);
+
+ std::swap(_VISize, ioOther._VISize);
+ std::swap(_NISize, ioOther._NISize);
+ std::swap(_MISize, ioOther._MISize);
+ std::swap(_TISize, ioOther._TISize);
+
+ std::swap(_displayList, ioOther._displayList);
+
+ Rep::swap(ioOther);
+ }
+
+ IndexedFaceSet& operator=(const IndexedFaceSet& iBrother){
+ IndexedFaceSet tmp(iBrother);
+ swap(tmp);
+ return *this;
+ }
+
+ /*! Desctructor
+ desallocates all the ressources */
+ virtual ~IndexedFaceSet();
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Compute the Bounding Box */
+ virtual void ComputeBBox();
+
+ /*! modifiers */
+ inline void setDisplayList(unsigned int index) {_displayList = index;}
+
+ /*! Accessors */
+ virtual const real * vertices() const {return _Vertices;}
+ virtual const real * normals() const {return _Normals;}
+ virtual const FrsMaterial*const* frs_materials() const {return _FrsMaterials;}
+ virtual const real* texCoords() const {return _TexCoords;}
+ virtual const unsigned vsize() const {return _VSize;}
+ virtual const unsigned nsize() const {return _NSize;}
+ virtual const unsigned msize() const {return _MSize;}
+ virtual const unsigned tsize() const {return _TSize;}
+ virtual const unsigned numFaces() const {return _NumFaces;}
+ virtual const unsigned * numVertexPerFaces() const {return _NumVertexPerFace;}
+ virtual const TRIANGLES_STYLE * trianglesStyle() const {return _FaceStyle;}
+ virtual const unsigned char * faceEdgeMarks() const {return _FaceEdgeMarks;}
+ virtual const unsigned* vindices() const {return _VIndices;}
+ virtual const unsigned* nindices() const {return _NIndices;}
+ virtual const unsigned* mindices() const {return _MIndices;}
+ virtual const unsigned* tindices() const {return _TIndices;}
+ virtual const unsigned visize() const {return _VISize;}
+ virtual const unsigned nisize() const {return _NISize;}
+ virtual const unsigned misize() const {return _MISize;}
+ virtual const unsigned tisize() const {return _TISize;}
+ inline unsigned int displayList() const {return _displayList;}
+
+protected:
+ real *_Vertices;
+ real *_Normals;
+ FrsMaterial** _FrsMaterials;
+ real *_TexCoords;
+
+ unsigned _VSize;
+ unsigned _NSize;
+ unsigned _MSize;
+ unsigned _TSize;
+
+ unsigned _NumFaces;
+ unsigned *_NumVertexPerFace;
+ TRIANGLES_STYLE *_FaceStyle;
+ FaceEdgeMark *_FaceEdgeMarks;
+
+ unsigned *_VIndices;
+ unsigned *_NIndices;
+ unsigned *_MIndices; // Material Indices
+ unsigned *_TIndices; // Texture coordinates Indices
+
+ unsigned _VISize;
+ unsigned _NISize;
+ unsigned _MISize;
+ unsigned _TISize;
+
+ unsigned int _displayList;
+
+};
+
+#endif // INDEXEDFACESET_H
diff --git a/source/blender/freestyle/intern/scene_graph/LineRep.cpp b/source/blender/freestyle/intern/scene_graph/LineRep.cpp
new file mode 100755
index 00000000000..504db06acf4
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/LineRep.cpp
@@ -0,0 +1,58 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "LineRep.h"
+
+void LineRep::ComputeBBox()
+{
+ real XMax = _vertices.front()[0];
+ real YMax = _vertices.front()[1];
+ real ZMax = _vertices.front()[2];
+
+ real XMin = _vertices.front()[0];
+ real YMin = _vertices.front()[1];
+ real ZMin = _vertices.front()[2];
+
+ // parse all the coordinates to find
+ // the XMax, YMax, ZMax
+ vector<Vec3r>::iterator v;
+ for(v=_vertices.begin(); v!=_vertices.end(); v++) {
+ // X
+ if((*v)[0] > XMax)
+ XMax = (*v)[0];
+ if((*v)[0] < XMin)
+ XMin = (*v)[0];
+
+ // Y
+ if((*v)[1] > YMax)
+ YMax = (*v)[1];
+ if((*v)[1] < YMin)
+ YMin = (*v)[1];
+
+ // Z
+ if((*v)[2] > ZMax)
+ ZMax = (*v)[2];
+ if((*v)[2] < ZMin)
+ ZMin = (*v)[2];
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/LineRep.h b/source/blender/freestyle/intern/scene_graph/LineRep.h
new file mode 100755
index 00000000000..232557af857
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/LineRep.h
@@ -0,0 +1,130 @@
+//
+// Filename : LineRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the representation of 3D Line.
+// Date of creation : 26/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LINEREP_H
+# define LINEREP_H
+
+# include <vector>
+# include <list>
+# include "Rep.h"
+# include "../system/FreestyleConfig.h"
+
+using namespace std;
+
+/*! Base class for all lines objects */
+class LIB_SCENE_GRAPH_EXPORT LineRep : public Rep
+{
+public:
+
+ /*! Line description style */
+ enum LINES_STYLE{LINES, LINE_STRIP, LINE_LOOP};
+ inline LineRep() : Rep() {_width = 0.f;}
+
+ /*! Builds a single line from 2 vertices
+ * v1
+ * first vertex
+ * v2
+ * second vertex
+ */
+ inline LineRep(const Vec3r& v1, const Vec3r& v2)
+ : Rep()
+ {
+ setStyle(LINES);
+ AddVertex(v1);
+ AddVertex(v2);
+ _width = 0.f;
+ }
+
+ /*! Builds a line rep from a vertex chain */
+ inline LineRep(const vector<Vec3r>& vertices)
+ : Rep()
+ {
+ _vertices = vertices;
+ setStyle(LINE_STRIP);
+ _width = 0.f;
+ }
+
+ /*! Builds a line rep from a vertex chain */
+ inline LineRep(const list<Vec3r>& vertices)
+ : Rep()
+ {
+ for(list<Vec3r>::const_iterator v=vertices.begin(), end=vertices.end();
+ v!=end;
+ v++)
+ {
+ _vertices.push_back(*v);
+ }
+ setStyle(LINE_STRIP);
+ _width = 0.f;
+ }
+
+ virtual ~LineRep()
+ {
+ _vertices.clear();
+ }
+
+ /*! accessors */
+ inline const LINES_STYLE style() const {return _Style;}
+ inline const vector<Vec3r>& vertices() const {return _vertices;}
+ inline float width() const {return _width;}
+
+ /*! modifiers */
+ inline void setStyle(const LINES_STYLE iStyle) {_Style = iStyle;}
+ inline void AddVertex(const Vec3r& iVertex) {_vertices.push_back(iVertex);}
+ inline void setVertices(const vector<Vec3r>& iVertices)
+ {
+ if(0 != _vertices.size())
+ {
+ _vertices.clear();
+ }
+ for(vector<Vec3r>::const_iterator v=iVertices.begin(), end=iVertices.end();
+ v!=end;
+ v++)
+ {
+ _vertices.push_back(*v);
+ }
+ }
+ inline void setWidth(float iWidth) {_width=iWidth;}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v) {
+ Rep::accept(v);
+ v.visitLineRep(*this);
+ }
+
+ /*! Computes the line bounding box.*/
+ virtual void ComputeBBox();
+
+private:
+ LINES_STYLE _Style;
+ vector<Vec3r> _vertices;
+ float _width;
+};
+
+#endif // LINEREP_H
diff --git a/source/blender/freestyle/intern/scene_graph/Node.h b/source/blender/freestyle/intern/scene_graph/Node.h
new file mode 100755
index 00000000000..41afaa353be
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/Node.h
@@ -0,0 +1,97 @@
+//
+// Filename : Node.h
+// Author(s) : Stephane Grabli
+// Purpose : Abstract class for scene graph nodes. Inherits from
+// BaseObject which defines the addRef release mechanism.
+// Date of creation : 24/01/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef NODE_H
+# define NODE_H
+
+# include "../system/FreestyleConfig.h"
+# include "../system/BaseObject.h"
+# include "SceneVisitor.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+# include "../system/Precision.h"
+
+using namespace std;
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT Node : public BaseObject
+{
+public:
+
+ inline Node() : BaseObject() {}
+ inline Node(const Node& iBrother) : BaseObject()
+ {
+ _BBox = iBrother.bbox();
+ }
+ virtual ~Node(){}
+
+ /*! Accept the corresponding visitor
+ * Each inherited node
+ * must overload this method
+ */
+ virtual void accept(SceneVisitor& v) {
+ v.visitNode(*this);
+ }
+
+ /*! bounding box management */
+ /*! Returns the node bounding box
+ * If no bounding box exists, an empty bbox
+ * is returned
+ */
+ virtual const BBox<Vec3r>& bbox() const {return _BBox;}
+
+ /*! Sets the Node bounding box */
+ virtual void setBBox(const BBox<Vec3r>& iBox) {_BBox = iBox;}
+
+ /*! Makes the union of _BBox and iBox */
+ virtual void AddBBox(const BBox<Vec3r>& iBox)
+ {
+ if(iBox.empty())
+ return;
+
+ if(_BBox.empty())
+ _BBox = iBox;
+ else
+ _BBox += iBox;
+ }
+
+ /*! Updates the BBox */
+ virtual const BBox<Vec3r>& UpdateBBox() {return _BBox;}
+
+ /*! Clears the bounding box */
+ virtual void clearBBox() { _BBox.clear(); }
+
+protected:
+
+private:
+ BBox<Vec3r> _BBox;
+};
+
+#endif // NODE_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp
new file mode 100644
index 00000000000..1d095b35a0d
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp
@@ -0,0 +1,120 @@
+#include <string.h> // for memcpy
+#include "NodeCamera.h"
+#include <math.h>
+
+void loadIdentity(double * matrix){
+ int i;
+
+ // Build Identity matrix
+ for(i=0;i<16;++i){
+ double value ;
+ if((i % 5) == 0)
+ value = 1.0;
+ else
+ value = 0;
+ matrix[i] = value;
+ }
+}
+
+NodeCamera::NodeCamera(CameraType camera_type)
+:camera_type_(camera_type){
+ loadIdentity(modelview_matrix_);
+ loadIdentity(projection_matrix_);
+}
+
+NodeCamera::NodeCamera(const NodeCamera& iBrother)
+:camera_type_(iBrother.camera_type_){
+ memcpy(modelview_matrix_, iBrother.modelview_matrix_, 16*sizeof(double));
+ memcpy(projection_matrix_, iBrother.projection_matrix_, 16*sizeof(double));
+}
+
+void NodeCamera::accept(SceneVisitor& v){
+ v.visitNodeCamera(*this) ;
+}
+
+void NodeCamera::setModelViewMatrix(double modelview_matrix[16]){
+ memcpy(modelview_matrix_, modelview_matrix,16*sizeof(double));
+}
+
+void NodeCamera::setProjectionMatrix(double projection_matrix[16]){
+ memcpy(projection_matrix_, projection_matrix,16*sizeof(double));
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera()
+:NodeCamera(NodeCamera::ORTHOGRAPHIC),
+left_(0),right_(0),bottom_(0),top_(0),zNear_(0),zFar_(0){
+ loadIdentity(projection_matrix_);
+ loadIdentity(modelview_matrix_);
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera(double left
+ , double right
+ , double bottom
+ , double top
+ , double zNear
+ , double zFar
+ )
+:NodeCamera(NodeCamera::ORTHOGRAPHIC),
+left_(left),
+right_(right),
+bottom_(bottom),
+top_(top),
+zNear_(zNear),
+zFar_(zFar){
+
+ loadIdentity(projection_matrix_);
+
+ projection_matrix_[0] = 2.0/(right-left);
+ projection_matrix_[3] = -(right + left) / (right - left) ;
+ projection_matrix_[5] = 2.0/(top-bottom);
+ projection_matrix_[7] = -(top + bottom) / (top - bottom) ;
+ projection_matrix_[10] = -2.0/(zFar-zNear);
+ projection_matrix_[11] = -(zFar + zNear) / (zFar - zNear);
+
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera(const NodeOrthographicCamera& iBrother)
+:NodeCamera(iBrother),left_(iBrother.left_),right_(iBrother.right_),bottom_(iBrother.bottom_),top_(iBrother.top_),zNear_(iBrother.zNear_),zFar_(iBrother.zFar_){
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera()
+:NodeCamera(NodeCamera::PERSPECTIVE){
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera(double fovy
+ , double aspect
+ , double zNear
+ , double zFar)
+:NodeCamera(NodeCamera::PERSPECTIVE){
+ loadIdentity(projection_matrix_);
+
+ double f = cos(fovy/2.0)/sin(fovy/2.0); // cotangent
+
+ projection_matrix_[0] = f/aspect;
+ projection_matrix_[5] = f;
+ projection_matrix_[10] = (zNear+zFar)/(zNear-zFar);
+ projection_matrix_[11] = (2.0*zNear*zFar)/(zNear-zFar);
+ projection_matrix_[14] = -1.0;
+ projection_matrix_[15] = 0;
+
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera(double left,
+ double right,
+ double bottom,
+ double top,
+ double zNear,
+ double zFar)
+:NodeCamera(NodeCamera::PERSPECTIVE){
+ loadIdentity(projection_matrix_);
+
+ projection_matrix_[0] = (2.0*zNear)/(right-left);
+ projection_matrix_[2] = (right+left)/(right-left);
+ projection_matrix_[5] = (2.0*zNear)/(top-bottom);
+ projection_matrix_[6] = (top+bottom)/(top-bottom);
+ projection_matrix_[10] = - (zFar+zNear)/(zFar-zNear);
+ projection_matrix_[11] = - (2.0*zFar*zNear)/(zFar-zNear);
+ projection_matrix_[14] = -1.0;
+ projection_matrix_[15] = 0;
+}
+
diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.h b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
new file mode 100644
index 00000000000..cdd6fa83048
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
@@ -0,0 +1,192 @@
+//
+// Filename : NodeCamera.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a light node
+// Date of creation : 25/01/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef NODE_CAMERA_H_
+#define NODE_CAMERA_H_
+
+# include "../geometry/Geom.h"
+# include "../system/FreestyleConfig.h"
+# include "Node.h"
+
+using namespace Geometry;
+
+class NodeOrthographicCamera;
+class NodePerspectiveCamera;
+class LIB_SCENE_GRAPH_EXPORT NodeCamera : public Node
+{
+public:
+ typedef enum {PERSPECTIVE,ORTHOGRAPHIC,GENERIC} CameraType;
+
+ /*! Default matrices: Identity for both projection and modelview. */
+ NodeCamera(CameraType camera_type = GENERIC);
+ NodeCamera(const NodeCamera& iBrother);
+
+ virtual ~NodeCamera() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Matrix is copied */
+ void setModelViewMatrix(double modelview_matrix[16]);
+ /*! Matrix is copied */
+ void setProjectionMatrix(double projection_matrix[16]);
+
+ double * modelViewMatrix() {return modelview_matrix_;}
+ double * projectionMatrix() {return projection_matrix_;}
+
+protected:
+ // row major right handed matrix
+ double modelview_matrix_[16];
+ // row major right handed matrix
+ double projection_matrix_[16];
+
+ CameraType camera_type_;
+};
+
+class LIB_SCENE_GRAPH_EXPORT NodeOrthographicCamera : public NodeCamera{
+public:
+ NodeOrthographicCamera();
+ /*! Builds a parallel projection matrix a la glOrtho.
+ A 0 0 tx
+ 0 B 0 ty
+ 0 0 C tz
+ 0 0 0 1
+
+ where
+
+ A =
+ 2 / (right - left)
+ B =
+ 2 / (top - bottom)
+ C =
+ -2 / (far - near)
+ tx =
+ -(right + left) / (right - left)
+ ty =
+ -(top + bottom) / (top - bottom)
+ tz =
+ -(zFar + zNear) / (zFar - zNear)
+ */
+ NodeOrthographicCamera(double left
+ , double right
+ , double bottom
+ , double top
+ , double zNear
+ , double zFar
+ );
+
+ double left() const {return left_;}
+ double right() const {return right_;}
+ double bottom() const {return bottom_;}
+ double top() const {return top_;}
+ double zNear() const {return zNear_;}
+ double zFar() const {return zFar_;}
+
+ NodeOrthographicCamera(const NodeOrthographicCamera& iBrother);
+
+private:
+ double left_;
+ double right_;
+ double bottom_;
+ double top_;
+ double zNear_;
+ double zFar_;
+};
+
+class LIB_SCENE_GRAPH_EXPORT NodePerspectiveCamera : public NodeCamera {
+public:
+ NodePerspectiveCamera();
+ /*! Builds a perspective projection matrix a la gluPerspective.
+ Given f defined as follows:
+ fovy
+ f = cotangent(____)
+ 2
+ The generated matrix is
+
+
+ ( f )
+ | ______ |
+ | aspect 0 0 0 |
+ | |
+ | 0 f 0 0 |
+ | |
+ | zNear+zFar 2*zNear*zFar |
+ | __________ ____________ |
+ | 0 0 zNear-zFar zNear-zFar |
+ | |
+ ( 0 0 -1 0 )
+ \param fovy
+ Field of View specified in radians.
+ */
+ NodePerspectiveCamera(double fovy
+ , double aspect
+ , double zNear
+ , double zFar);
+
+ /*! Builds a perspective projection matrix a la glFrustum.
+ ( 2*zNear )
+ | __________ |
+ | right-left 0 A 0 |
+ | |
+ | 2*zNear |
+ | 0 __________ B 0 |
+ | top-bottom |
+ | |
+ | 0 0 C D |
+ | |
+ | 0 0 -1 0 |
+ ( )
+
+ right+left
+ A = __________
+ right-left
+
+ top+bottom
+ B = __________
+ top-bottom
+
+ zFar+zNear
+ C = - __________
+ zFar-zNear
+
+ 2*zFar*zNear
+ D = - ____________
+ zFar-zNear
+ */
+ NodePerspectiveCamera(double left,
+ double right,
+ double bottom,
+ double top,
+ double zNear,
+ double zFar);
+};
+
+
+#endif // NODE_CAMERA_H_
diff --git a/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp
new file mode 100755
index 00000000000..acd740ee055
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp
@@ -0,0 +1,34 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "NodeDrawingStyle.h"
+
+void NodeDrawingStyle::accept(SceneVisitor& v) {
+ v.visitNodeDrawingStyle(*this);
+
+ v.visitNodeDrawingStyleBefore(*this);
+ v.visitDrawingStyle(_DrawingStyle);
+ for(vector<Node*>::iterator node=_Children.begin(), end=_Children.end();
+ node!=end;
+ node++)
+ (*node)->accept(v);
+ v.visitNodeDrawingStyleAfter(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h
new file mode 100755
index 00000000000..012f963ea8c
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h
@@ -0,0 +1,70 @@
+//
+// Filename : NodeDrawingStyle.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a Drawing Style to be applied
+// to the underlying children. Inherits from NodeGroup.
+// Date of creation : 06/02/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef NODEDRAWINGSTYLE_H
+# define NODEDRAWINGSTYLE_H
+
+# include "../system/FreestyleConfig.h"
+# include "NodeGroup.h"
+# include "DrawingStyle.h"
+
+class LIB_SCENE_GRAPH_EXPORT NodeDrawingStyle : public NodeGroup
+{
+public:
+
+ inline NodeDrawingStyle() : NodeGroup() {}
+ virtual ~NodeDrawingStyle() {}
+
+ inline const DrawingStyle& drawingStyle() const { return _DrawingStyle; }
+ inline void setDrawingStyle(const DrawingStyle& iDrawingStyle) { _DrawingStyle = iDrawingStyle; }
+
+ /*! Sets the style. Must be one of FILLED, LINES, POINTS, INVISIBLE. */
+ inline void setStyle(const DrawingStyle::STYLE iStyle) { _DrawingStyle.setStyle(iStyle); }
+ /*! Sets the line width in the LINES style case */
+ inline void setLineWidth(const float iLineWidth) { _DrawingStyle.setLineWidth(iLineWidth); }
+ /*! Sets the Point size in the POINTS style case */
+ inline void setPointSize(const float iPointSize) { _DrawingStyle.setPointSize(iPointSize); }
+ /*! Enables or disables the lighting. TRUE = enable */
+ inline void setLightingEnabled(const bool iEnableLighting) { _DrawingStyle.setLightingEnabled(iEnableLighting); }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! accessors */
+ inline DrawingStyle::STYLE style() const {return _DrawingStyle.style();}
+ inline float lineWidth() const {return _DrawingStyle.lineWidth();}
+ inline float pointSize() const {return _DrawingStyle.pointSize();}
+ inline bool lightingEnabled() const {return _DrawingStyle.lightingEnabled();}
+
+private:
+ DrawingStyle _DrawingStyle;
+};
+
+#endif // NODEDRAWINGSTYLE_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp b/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp
new file mode 100755
index 00000000000..3d2aa2c8694
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp
@@ -0,0 +1,122 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "NodeGroup.h"
+
+void NodeGroup::AddChild(Node *iChild)
+{
+ if(NULL == iChild)
+ return;
+
+ _Children.push_back(iChild);
+ iChild->addRef();
+}
+
+int NodeGroup::destroy()
+{
+ /*! Node::destroy makes a release on the object
+ * and then returns the reference counter.
+ * If the reference counter is equal to 0,
+ * that means that nobody else is linking
+ * this node group and that we can destroy the whole
+ * underlying tree.
+ * Else, one or several Node link this node group,
+ * and we only returns the reference counter
+ * decremented by Node::destroy();
+ */
+ int refThis = Node::destroy();
+
+ // if refThis != 0, we can't destroy the tree
+ if(0 != refThis)
+ return refThis;
+
+ // If we are here, that means that nobody else
+ // needs our NodeGroup and we can destroy it.
+ int refCount = 0;
+ vector<Node *>::iterator node;
+
+ for(node=_Children.begin(); node!=_Children.end(); node++)
+ {
+ refCount = (*node)->destroy();
+ if(0 == refCount)
+ delete (*node);
+ }
+
+ _Children.clear();
+
+ return refThis;
+}
+
+void NodeGroup::accept(SceneVisitor& v) {
+ v.visitNodeGroup(*this);
+
+ v.visitNodeGroupBefore(*this);
+ for(vector<Node *>::iterator node=_Children.begin(), end=_Children.end();
+ node!=end;
+ node++)
+ (*node)->accept(v);
+ v.visitNodeGroupAfter(*this);
+}
+
+void NodeGroup::DetachChildren()
+{
+ vector<Node *>::iterator node;
+
+ for(node=_Children.begin(); node!=_Children.end(); node++)
+ {
+ (*node)->release();
+ }
+
+ _Children.clear();
+}
+
+void NodeGroup::DetachChild(Node *iChild)
+{
+ int found = 0;
+ vector<Node*>::iterator node;
+
+ for(node=_Children.begin(); node!=_Children.end(); node++)
+ {
+ if((*node) == iChild)
+ {
+ (*node)->release();
+ _Children.erase(node);
+ found = 1;
+ break;
+ }
+ }
+}
+
+void NodeGroup::RetrieveChildren(vector<Node*>& oNodes){
+ oNodes = _Children;
+}
+
+const BBox<Vec3r>& NodeGroup::UpdateBBox()
+{
+ vector<Node *>::iterator node;
+ clearBBox();
+ for(node=_Children.begin(); node!=_Children.end(); node++)
+ {
+ AddBBox((*node)->UpdateBBox());
+ }
+
+ return Node::UpdateBBox();
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeGroup.h b/source/blender/freestyle/intern/scene_graph/NodeGroup.h
new file mode 100755
index 00000000000..a1bd2b57e56
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeGroup.h
@@ -0,0 +1,84 @@
+//
+// Filename : NodeGroup.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a group node. This node can contains
+// several children. It also contains a transform matrix
+// indicating the transform state of the underlying
+// children.
+// Date of creation : 24/01/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef NODEGROUP_H
+# define NODEGROUP_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "Node.h"
+
+using namespace std;
+
+class LIB_SCENE_GRAPH_EXPORT NodeGroup : public Node
+{
+public:
+
+ inline NodeGroup(): Node() {}
+ virtual ~NodeGroup(){}
+
+ /*! Adds a child. Makes a addRef on the
+ * iChild reference counter */
+ virtual void AddChild(Node *iChild);
+
+ /*! destroys all the underlying nodes
+ * Returns the reference counter
+ * after having done a release() */
+ virtual int destroy();
+
+ /*! Detaches all the children */
+ virtual void DetachChildren();
+
+ /*! Detached the sepcified child */
+ virtual void DetachChild(Node *iChild);
+
+ /*! Retrieve children */
+ virtual void RetrieveChildren(vector<Node*>& oNodes);
+
+
+ /*! Renders every children */
+ // virtual void Render(Renderer *iRenderer);
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Updates the BBox */
+ virtual const BBox<Vec3r>& UpdateBBox();
+
+ /*! Returns the number of children */
+ virtual int numberOfChildren() {return _Children.size();}
+
+protected:
+ vector<Node*> _Children;
+};
+
+#endif // NODEGROUP_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.cpp b/source/blender/freestyle/intern/scene_graph/NodeLight.cpp
new file mode 100755
index 00000000000..61a46155cfa
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeLight.cpp
@@ -0,0 +1,80 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "NodeLight.h"
+
+int NodeLight::numberOfLights = 0;
+
+NodeLight::NodeLight()
+: Node()
+{
+ if(numberOfLights > 7)
+ {
+ _number = 7;
+ }
+ else
+ {
+ _number = numberOfLights;
+ numberOfLights++;
+ }
+
+ Ambient[0] = Ambient[1] = Ambient[2] = 0.f;
+ Ambient[3] = 1.f;
+
+ for(int i=0; i<4; i++)
+ {
+ Diffuse[i] = 1.f;
+ Specular[i] = 1.f;
+ }
+
+ Position[0] = Position[1] = Position[3] = 0.f;
+ Position[2] = 1.f;
+
+ on = true;
+}
+
+NodeLight::NodeLight(NodeLight& iBrother)
+: Node(iBrother)
+{
+ if(numberOfLights > 7)
+ {
+ _number = 7;
+ }
+ else
+ {
+ _number = numberOfLights;
+ numberOfLights++;
+ }
+
+ for(int i=0; i<4; i++)
+ {
+ Ambient[i] = iBrother.ambient()[i];
+ Diffuse[i] = iBrother.diffuse()[i];
+ Specular[i] = iBrother.specular()[i];
+ Position[i] = iBrother.position()[i];
+ }
+
+ on = iBrother.isOn();
+}
+
+void NodeLight::accept(SceneVisitor& v) {
+ v.visitNodeLight(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.h b/source/blender/freestyle/intern/scene_graph/NodeLight.h
new file mode 100755
index 00000000000..0689505fb24
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeLight.h
@@ -0,0 +1,86 @@
+//
+// Filename : NodeLight.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a light node
+// Date of creation : 25/01/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef NODELIGHT_H
+# define NODELIGHT_H
+
+# include "../geometry/Geom.h"
+# include "../system/FreestyleConfig.h"
+# include "Node.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeLight : public Node
+{
+public:
+
+ NodeLight();
+ NodeLight(NodeLight& iBrother);
+
+ virtual ~NodeLight() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Accessors for the light properties */
+ inline const float * ambient() const {return Ambient;}
+ inline const float * diffuse() const {return Diffuse;}
+ inline const float * specular() const {return Specular;}
+ inline const float * position() const {return Position;}
+ inline bool isOn() const {return on;}
+ inline int number() const {return _number;}
+
+private:
+ // Data members
+ // ============
+
+ /*! on=true, the light is on */
+ bool on;
+
+ /*! The color definition */
+ float Ambient[4];
+ float Diffuse[4];
+ float Specular[4];
+
+ /*! Light position. if w = 0, the light is
+ * placed at infinite.
+ */
+ float Position[4];
+
+ /*! used to manage the number of lights */
+ /*! numberOfLights
+ * the number of lights in the scene.
+ * Initially, 0.
+ */
+ static int numberOfLights;
+ /*! The current lignt number */
+ int _number;
+};
+
+#endif // NODELIGHT_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeShape.cpp b/source/blender/freestyle/intern/scene_graph/NodeShape.cpp
new file mode 100755
index 00000000000..9083c852d36
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeShape.cpp
@@ -0,0 +1,51 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "NodeShape.h"
+
+NodeShape::~NodeShape()
+{
+ vector<Rep *>::iterator rep;
+
+ if(0 != _Shapes.size())
+ {
+ for(rep=_Shapes.begin(); rep!=_Shapes.end(); rep++)
+ {
+ int refCount = (*rep)->destroy();
+ if(0 == refCount)
+ delete (*rep);
+ }
+
+ _Shapes.clear();
+ }
+}
+
+void NodeShape::accept(SceneVisitor& v) {
+ v.visitNodeShape(*this);
+
+ v.visitFrsMaterial(_FrsMaterial);
+
+ v.visitNodeShapeBefore(*this);
+ vector<Rep *>::iterator rep;
+ for(rep = _Shapes.begin(); rep != _Shapes.end(); rep++)
+ (*rep)->accept(v);
+ v.visitNodeShapeAfter(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeShape.h b/source/blender/freestyle/intern/scene_graph/NodeShape.h
new file mode 100755
index 00000000000..9849d4661b8
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeShape.h
@@ -0,0 +1,89 @@
+//
+// Filename : NodeShape.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build a shape node. It contains a Rep,
+// which is the shape geometry
+// Date of creation : 25/01/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef NODESHAPE_H
+# define NODESHAPE_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "Node.h"
+# include "Rep.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+# include "FrsMaterial.h"
+
+using namespace std;
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeShape : public Node
+{
+public:
+
+ inline NodeShape() : Node() {}
+
+ virtual ~NodeShape();
+
+ /*! Adds a Rep to the _Shapes list
+ * The delete of the rep is done
+ * when it is not used any more by
+ * the Scene Manager. So, it must not
+ * be deleted by the caller
+ */
+ virtual void AddRep(Rep *iRep)
+ {
+ if(NULL == iRep)
+ return;
+ _Shapes.push_back(iRep);
+ iRep->addRef();
+
+ // updates bbox:
+ AddBBox(iRep->bbox());
+ }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Sets the shape material */
+ inline void setFrsMaterial(const FrsMaterial& iMaterial) { _FrsMaterial = iMaterial; }
+
+ /*! accessors */
+ /*! returns the shape's material */
+ inline FrsMaterial& frs_material() { return _FrsMaterial; }
+ inline const vector<Rep*>& shapes() {return _Shapes;}
+
+private:
+ /*! list of shapes */
+ vector<Rep*> _Shapes;
+
+ /*! Shape Material */
+ FrsMaterial _FrsMaterial;
+};
+
+#endif // NODESHAPE_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
new file mode 100755
index 00000000000..8f706c78259
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
@@ -0,0 +1,166 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "../system/FreestyleConfig.h"
+#include "NodeTransform.h"
+
+void NodeTransform::Translate(real x, real y, real z)
+{
+ _Matrix(0, 3) += x;
+ _Matrix(1, 3) += y;
+ _Matrix(2, 3) += z;
+}
+
+void NodeTransform::Rotate(real iAngle, real x, real y, real z)
+{
+ //Normalize the x,y,z vector;
+ real norm = (real)sqrt(x*x+y*y+z*z);
+ if(0 == norm)
+ return;
+
+ x /= norm;
+ y /= norm;
+ z /= norm;
+
+ // find the corresponding matrix with the Rodrigues formula:
+ // R = I + sin(iAngle)*Ntilda + (1-cos(iAngle))*Ntilda*Ntilda
+ Matrix33r Ntilda;
+ Ntilda(0,0) = Ntilda(1,1) = Ntilda(2,2) = 0.f;
+ Ntilda(0,1) = -z;
+ Ntilda(0,2) = y;
+ Ntilda(1,0) = z;
+ Ntilda(1,2) = -x;
+ Ntilda(2,0) = -y;
+ Ntilda(2,1) = x;
+
+ const Matrix33r Ntilda2(Ntilda * Ntilda);
+
+
+ const real sinAngle = (real)sin((iAngle/180.f)*M_PI);
+ const real cosAngle = (real)cos((iAngle/180.f)*M_PI);
+
+ Matrix33r NS(Ntilda*sinAngle);
+ Matrix33r NC(Ntilda2*(1.f-cosAngle));
+ Matrix33r R;
+ R = Matrix33r::identity();
+ R += NS + NC;
+
+ //R4 is the corresponding 4x4 matrix
+ Matrix44r R4;
+ R4 = Matrix44r::identity();
+
+ for(int i=0; i<3; i++)
+ for(int j=0; j<3; j++)
+ R4(i,j) = R(i,j);
+
+ // Finally, we multiply our current matrix by R4:
+ Matrix44r mat_tmp(_Matrix);
+ _Matrix = mat_tmp * R4;
+}
+
+void NodeTransform::Scale(real x, real y, real z)
+{
+ _Matrix(0,0) *= x;
+ _Matrix(1,1) *= y;
+ _Matrix(2,2) *= z;
+
+ _Scaled = true;
+}
+
+void NodeTransform::MultiplyMatrix(const Matrix44r &iMatrix)
+{
+ Matrix44r mat_tmp(_Matrix);
+ _Matrix = mat_tmp * iMatrix;
+}
+
+void NodeTransform::setMatrix(const Matrix44r &iMatrix)
+{
+ _Matrix = iMatrix;
+ if(isScaled(iMatrix))
+ _Scaled = true;
+}
+
+void NodeTransform::accept(SceneVisitor& v) {
+ v.visitNodeTransform(*this);
+
+ v.visitNodeTransformBefore(*this);
+ for(vector<Node *>::iterator node=_Children.begin(), end=_Children.end();
+ node!=end;
+ node++)
+ (*node)->accept(v);
+ v.visitNodeTransformAfter(*this);
+}
+
+void NodeTransform::AddBBox(const BBox<Vec3r>& iBBox)
+{
+ Vec3r oldMin(iBBox.getMin());
+ Vec3r oldMax(iBBox.getMax());
+
+ // compute the 8 corners of the bbox
+ HVec3r box[8];
+ box[0] = HVec3r(iBBox.getMin());
+ box[1] = HVec3r(oldMax[0], oldMin[1], oldMin[2]);
+ box[2] = HVec3r(oldMax[0], oldMax[1], oldMin[2]);
+ box[3] = HVec3r(oldMin[0], oldMax[1], oldMin[2]);
+ box[4] = HVec3r(oldMin[0], oldMin[1], oldMax[2]);
+ box[5] = HVec3r(oldMax[0], oldMin[1], oldMax[2]);
+ box[6] = HVec3r(oldMax[0], oldMax[1], oldMax[2]);
+ box[7] = HVec3r(oldMin[0], oldMax[1], oldMax[2]);
+
+ // Computes the transform iBBox
+ HVec3r tbox[8];
+ unsigned i;
+ for(i = 0; i < 8; i++)
+ tbox[i] = _Matrix * box[i];
+
+ Vec3r newMin(tbox[0]);
+ Vec3r newMax(tbox[0]);
+ for (i=0; i<8; i++)
+ {
+ for (unsigned int j=0; j<3; j++)
+ {
+ if (newMin[j] > tbox[i][j])
+ newMin[j] = tbox[i][j];
+ if (newMax[j] < tbox[i][j])
+ newMax[j] = tbox[i][j];
+ }
+ }
+
+ BBox<Vec3r> transformBox(newMin, newMax);
+
+ Node::AddBBox(transformBox);
+}
+
+bool NodeTransform::isScaled(const Matrix44r &M)
+{
+ for(unsigned int j=0; j<3; j++)
+ {
+ real norm = 0;
+ for(unsigned int i=0; i<3; i++)
+ {
+ norm += M(i,j)*M(i,j);
+ }
+ if((norm > 1.01) || (norm < 0.99))
+ return true;
+ }
+
+ return false;
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.h b/source/blender/freestyle/intern/scene_graph/NodeTransform.h
new file mode 100755
index 00000000000..e75132466f0
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.h
@@ -0,0 +1,107 @@
+//
+// Filename : NodeTransform.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a transform node. A Transform node
+// contains one or several children, all affected by the
+// transformation.
+// Date of creation : 06/02/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef NODETRANSFORM_H
+# define NODETRANSFORM_H
+
+# include "../geometry/Geom.h"
+# include "../system/FreestyleConfig.h"
+# include "NodeGroup.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeTransform : public NodeGroup
+{
+public:
+
+ inline NodeTransform() : NodeGroup() {
+ _Matrix = Matrix44r::identity();
+ _Scaled=false;
+ }
+
+ virtual ~NodeTransform() {}
+
+ /*! multiplys the current matrix by the
+ * x, y, z translation matrix.
+ */
+ void Translate(real x, real y, real z);
+
+ /*! multiplys the current matrix by a
+ * rotation matrix
+ * iAngle
+ * The rotation angle
+ * x, y, z
+ * The rotation axis
+ */
+ void Rotate(real iAngle, real x, real y, real z);
+
+ /*! multiplys the current matrix by a
+ * scaling matrix.
+ * x, y, z
+ * The scaling coefficients
+ * with respect to the x,y,z axis
+ */
+ void Scale(real x, real y, real z);
+
+ /*! Multiplys the current matrix
+ * by iMatrix
+ */
+ void MultiplyMatrix(const Matrix44r &iMatrix);
+
+ /*! Sets the current matrix to iMatrix */
+ void setMatrix(const Matrix44r &iMatrix);
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Overloads the Node::AddBBox in order to take care
+ * about the transformation
+ */
+ virtual void AddBBox(const BBox<Vec3r>& iBBox);
+
+ /*! Checks whether a matrix contains a scale factor
+ * or not.
+ * Returns true if yes.
+ * iMatrix
+ * The matrix to check
+ */
+ bool isScaled(const Matrix44r &M);
+
+ /*! accessors */
+ inline const Matrix44r& matrix() const { return _Matrix; }
+ inline bool scaled() const {return _Scaled;}
+
+private:
+ Matrix44r _Matrix;
+ bool _Scaled;
+};
+
+#endif // NODETRANSFORM_H
diff --git a/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp
new file mode 100755
index 00000000000..94068983596
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp
@@ -0,0 +1,31 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "OrientedLineRep.h"
+#include "../system/BaseObject.h"
+
+void OrientedLineRep::accept(SceneVisitor& v) {
+ Rep::accept(v);
+ if(!frs_material())
+ v.visitOrientedLineRep(*this);
+ else
+ v.visitLineRep(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h
new file mode 100755
index 00000000000..4274581e39a
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h
@@ -0,0 +1,67 @@
+//
+// Filename : OrientedLineRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to display an oriented line representation.
+// Date of creation : 24/10/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWEDGEREP_H
+# define VIEWEDGEREP_H
+
+# include "../system/FreestyleConfig.h"
+# include "LineRep.h"
+
+class LIB_SCENE_GRAPH_EXPORT OrientedLineRep : public LineRep
+{
+public:
+
+ OrientedLineRep() : LineRep() {}
+ /*! Builds a single line from 2 vertices
+ * v1
+ * first vertex
+ * v2
+ * second vertex
+ */
+ inline OrientedLineRep(const Vec3r& v1, const Vec3r& v2)
+ : LineRep(v1,v2)
+ {}
+
+ /*! Builds a line rep from a vertex chain */
+ inline OrientedLineRep(const vector<Vec3r>& vertices)
+ : LineRep(vertices)
+ {}
+
+ /*! Builds a line rep from a vertex chain */
+ inline OrientedLineRep(const list<Vec3r>& vertices)
+ : LineRep(vertices)
+ {}
+
+ virtual ~OrientedLineRep() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+};
+
+#endif // VIEWEDGEREP_H
diff --git a/source/blender/freestyle/intern/scene_graph/Rep.cpp b/source/blender/freestyle/intern/scene_graph/Rep.cpp
new file mode 100755
index 00000000000..84ad2c2a966
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/Rep.cpp
@@ -0,0 +1 @@
+#include "Rep.h"
diff --git a/source/blender/freestyle/intern/scene_graph/Rep.h b/source/blender/freestyle/intern/scene_graph/Rep.h
new file mode 100755
index 00000000000..58be0374ae4
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/Rep.h
@@ -0,0 +1,133 @@
+//
+// Filename : Rep.h
+// Author(s) : Stephane Grabli
+// Purpose : Base class for all shapes. Inherits from BasicObjects
+// for references counter management (addRef, release).
+// Date of creation : 25/01/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef REP_H
+# define REP_H
+
+# include "../system/BaseObject.h"
+# include "SceneVisitor.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+# include "../system/Precision.h"
+# include "FrsMaterial.h"
+# include "../system/Id.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT Rep : public BaseObject
+{
+public:
+
+ inline Rep() : BaseObject() {_Id = 0; _FrsMaterial=0;}
+ inline Rep(const Rep& iBrother)
+ : BaseObject()
+ {
+ _Id = iBrother._Id;
+ _Name = iBrother._Name;
+ if(0 == iBrother._FrsMaterial)
+ _FrsMaterial = 0;
+ else
+ _FrsMaterial = new FrsMaterial(*(iBrother._FrsMaterial));
+
+ _BBox = iBrother.bbox();
+ }
+ inline void swap(Rep& ioOther){
+ std::swap(_BBox,ioOther._BBox);
+ std::swap(_Id, ioOther._Id);
+ std::swap(_Name, ioOther._Name);
+ std::swap(_FrsMaterial,ioOther._FrsMaterial);
+ }
+ Rep& operator=(const Rep& iBrother){
+ if(&iBrother != this){
+ _Id = iBrother._Id;
+ _Name = iBrother._Name;
+ if(0 == iBrother._FrsMaterial)
+ _FrsMaterial = 0;
+ else{
+ if(_FrsMaterial == 0){
+ _FrsMaterial = new FrsMaterial(*iBrother._FrsMaterial);
+ }else{
+ (*_FrsMaterial)=(*(iBrother._FrsMaterial));
+ }
+ _BBox = iBrother.bbox();
+ }
+ }
+ return *this;
+ }
+ virtual ~Rep()
+ {
+ if(0 != _FrsMaterial)
+ {
+ delete _FrsMaterial;
+ _FrsMaterial = 0;
+ }
+ }
+
+ /*! Accept the corresponding visitor
+ * Must be overload by
+ * inherited classes
+ */
+ virtual void accept(SceneVisitor& v) {
+ if(_FrsMaterial)
+ v.visitFrsMaterial(*_FrsMaterial);
+ v.visitRep(*this);
+ }
+
+ /*! Computes the rep bounding box.
+ * Each Inherited rep must compute
+ * its bbox depending on the way the data
+ * are stored. So, each inherited class
+ * must overload this method
+ */
+ virtual void ComputeBBox() = 0;
+
+ /*! Returns the rep bounding box */
+ virtual const BBox<Vec3r>& bbox() const {return _BBox;}
+ inline Id getId() const {return _Id;}
+ inline const string& getName() const {return _Name;}
+ inline const FrsMaterial * frs_material() const {return _FrsMaterial;}
+
+ /*! Sets the Rep bounding box */
+ virtual void setBBox(const BBox<Vec3r>& iBox) {_BBox = iBox;}
+ inline void setId(const Id& id) {_Id = id;}
+ inline void setName(const string& name) {_Name = name;}
+ inline void setFrsMaterial(const FrsMaterial& iMaterial)
+ {
+ _FrsMaterial = new FrsMaterial(iMaterial);
+ }
+
+private:
+ BBox<Vec3r> _BBox;
+ Id _Id;
+ string _Name;
+ FrsMaterial *_FrsMaterial;
+};
+
+#endif // REP_H
diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
new file mode 100755
index 00000000000..aeee87f8222
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
@@ -0,0 +1,86 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+#include "ScenePrettyPrinter.h"
+#include "IndexedFaceSet.h"
+
+#define VISIT(CLASS) \
+ void ScenePrettyPrinter::visit##CLASS(CLASS&) { \
+ _ofs << _space << #CLASS << endl; \
+ }
+
+VISIT(Node)
+VISIT(NodeShape)
+VISIT(NodeGroup)
+VISIT(NodeLight)
+VISIT(NodeDrawingStyle)
+VISIT(NodeTransform)
+
+void ScenePrettyPrinter::visitNodeShapeBefore(NodeShape&) {
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeShapeAfter(NodeShape&) {
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeGroupBefore(NodeGroup&) {
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeGroupAfter(NodeGroup&) {
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeDrawingStyleBefore(NodeDrawingStyle&) {
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeDrawingStyleAfter(NodeDrawingStyle&) {
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeTransformBefore(NodeTransform&) {
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeTransformAfter(NodeTransform&) {
+ decreaseSpace();
+}
+
+VISIT(LineRep)
+VISIT(OrientedLineRep)
+VISIT(TriangleRep)
+VISIT(VertexRep)
+
+void ScenePrettyPrinter::visitIndexedFaceSet(IndexedFaceSet& ifs) {
+ const real* vertices = ifs.vertices();
+ unsigned vsize = ifs.vsize();
+
+ _ofs << _space << "IndexedFaceSet" << endl;
+ const real *p = vertices;
+ for (unsigned i = 0; i < vsize / 3; i++) {
+ _ofs << _space << " " << setw(3) << setfill('0') << i << ": "
+ << p[0] << ", " << p[1] << ", " << p[2] << endl;
+ p += 3;
+ }
+}
diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h
new file mode 100755
index 00000000000..4e83825ff55
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h
@@ -0,0 +1,105 @@
+//
+// Filename : ScenePrettyPrinter.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class to display textual information
+// about a scene graph.
+// Date of creation : 26/04/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SCENE_PRETTY_PRINTER_H
+# define SCENE_PRETTY_PRINTER_H
+
+# include <iostream>
+# include <fstream>
+# include <string>
+# include "SceneVisitor.h"
+
+using namespace std;
+
+class ScenePrettyPrinter : public SceneVisitor
+{
+public:
+
+ ScenePrettyPrinter(const string filename = "SceneLog.txt")
+ : SceneVisitor() {
+ if (!filename.empty())
+ _ofs.open(filename.c_str());
+ if (!_ofs.is_open())
+ cerr << "Warning, unable to open file \"" << filename << "\"" << endl;
+ _space = "";
+ }
+
+ virtual ~ScenePrettyPrinter() {
+ if (_ofs.is_open())
+ _ofs.close();
+ }
+
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_DECL(Node)
+ VISIT_DECL(NodeShape)
+ VISIT_DECL(NodeGroup)
+ VISIT_DECL(NodeLight)
+ VISIT_DECL(NodeDrawingStyle)
+ VISIT_DECL(NodeTransform)
+
+ VISIT_DECL(LineRep)
+ VISIT_DECL(OrientedLineRep)
+ VISIT_DECL(TriangleRep)
+ VISIT_DECL(VertexRep)
+ VISIT_DECL(IndexedFaceSet)
+
+ virtual void visitNodeShapeBefore(NodeShape&);
+ virtual void visitNodeShapeAfter(NodeShape&);
+ virtual void visitNodeGroupBefore(NodeGroup&);
+ virtual void visitNodeGroupAfter(NodeGroup&);
+ virtual void visitNodeDrawingStyleBefore(NodeDrawingStyle&);
+ virtual void visitNodeDrawingStyleAfter(NodeDrawingStyle&);
+ virtual void visitNodeTransformBefore(NodeTransform&);
+ virtual void visitNodeTransformAfter(NodeTransform&);
+
+ protected:
+
+ void increaseSpace()
+ {
+ _space += " ";
+ }
+
+ void decreaseSpace()
+ {
+ _space.erase(0, 2);
+ }
+
+ private:
+
+ ofstream _ofs;
+ string _space;
+};
+
+#endif // SCENE_PRETTY_PRINTER_H
diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp b/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp
new file mode 100755
index 00000000000..da9c94930bd
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp
@@ -0,0 +1 @@
+#include "SceneVisitor.h"
diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
new file mode 100755
index 00000000000..5f67b4b44aa
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
@@ -0,0 +1,98 @@
+//
+// Filename : SceneVisitor.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Class to visit (without doing anything)
+// a scene graph structure
+// Date of creation : 26/04/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SCENE_VISITOR_H
+# define SCENE_VISITOR_H
+
+# define VISIT_COMPLETE_DEF(type) \
+virtual void visit##type(type&) {} \
+virtual void visit##type##Before(type&) {} \
+virtual void visit##type##After(type&) {}
+
+# define VISIT_DECL(type) virtual void visit##type(type&);
+
+# define VISIT_COMPLETE_DECL(type) \
+ virtual void visit##type##Before(type&); \
+ virtual void visit##type(type&); \
+ virtual void visit##type##After(type&);
+
+#include "../system/FreestyleConfig.h"
+
+class Node;
+class NodeShape;
+class NodeGroup;
+class NodeLight;
+class NodeCamera;
+class NodeDrawingStyle;
+class NodeTransform;
+
+class Rep;
+class LineRep;
+class OrientedLineRep;
+class TriangleRep;
+class VertexRep;
+class IndexedFaceSet;
+class DrawingStyle;
+class FrsMaterial;
+
+class LIB_SCENE_GRAPH_EXPORT SceneVisitor
+{
+public:
+
+ SceneVisitor() {}
+ virtual ~SceneVisitor() {}
+
+ virtual void beginScene() {}
+ virtual void endScene() {}
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_COMPLETE_DEF(Node)
+ VISIT_COMPLETE_DEF(NodeShape)
+ VISIT_COMPLETE_DEF(NodeGroup)
+ VISIT_COMPLETE_DEF(NodeLight)
+ VISIT_COMPLETE_DEF(NodeCamera)
+ VISIT_COMPLETE_DEF(NodeDrawingStyle)
+ VISIT_COMPLETE_DEF(NodeTransform)
+
+ VISIT_COMPLETE_DEF(Rep)
+ VISIT_COMPLETE_DEF(LineRep)
+ VISIT_COMPLETE_DEF(OrientedLineRep)
+ VISIT_COMPLETE_DEF(TriangleRep)
+ VISIT_COMPLETE_DEF(VertexRep)
+ VISIT_COMPLETE_DEF(IndexedFaceSet)
+ VISIT_COMPLETE_DEF(DrawingStyle)
+ VISIT_COMPLETE_DEF(FrsMaterial)
+};
+
+#endif // SCENEVISITOR_H
diff --git a/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp b/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp
new file mode 100755
index 00000000000..f73a8498714
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp
@@ -0,0 +1,59 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "TriangleRep.h"
+
+void TriangleRep::ComputeBBox()
+{
+ real XMax = _vertices[0][0];
+ real YMax = _vertices[0][1];
+ real ZMax = _vertices[0][2];
+
+ real XMin = _vertices[0][0];
+ real YMin = _vertices[0][1];
+ real ZMin = _vertices[0][2];
+
+ // parse all the coordinates to find
+ // the XMax, YMax, ZMax
+ for(int i=0; i<3; ++i)
+ {
+ // X
+ if(_vertices[i][0] > XMax)
+ XMax = _vertices[i][0];
+ if(_vertices[i][0] < XMin)
+ XMin = _vertices[i][0];
+
+ // Y
+ if(_vertices[i][1] > YMax)
+ YMax = _vertices[i][1];
+ if(_vertices[i][1] < YMin)
+ YMin = _vertices[i][1];
+
+ // Z
+ if(_vertices[i][2] > ZMax)
+ ZMax = _vertices[i][2];
+ if(_vertices[i][2] < ZMin)
+ ZMin = _vertices[i][2];
+
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/TriangleRep.h b/source/blender/freestyle/intern/scene_graph/TriangleRep.h
new file mode 100755
index 00000000000..9d986857060
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/TriangleRep.h
@@ -0,0 +1,106 @@
+//
+// Filename : TriangleRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the represenation of a triangle
+// Date of creation : 16/12/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TRIANGLEREP_H
+# define TRIANGLEREP_H
+
+//! inherits from class Rep
+#include "Rep.h"
+
+/*! Base class for all lines objects */
+class LIB_SCENE_GRAPH_EXPORT TriangleRep : public Rep
+{
+public:
+
+ /*! Line description style */
+ enum TRIANGLE_STYLE{FILL, LINES};
+private:
+ TRIANGLE_STYLE _Style;
+ Vec3r _vertices[3];
+ Vec3r _colors[3];
+public:
+ inline TriangleRep() : Rep() {_Style = FILL;}
+
+ /*! Builds a triangle from 3 vertices
+ * v0
+ * first vertex
+ * v1
+ * second vertex
+ * v2
+ * third vertex
+ */
+ inline TriangleRep(const Vec3r& v0, const Vec3r& v1, const Vec3r& v2)
+ : Rep()
+ {
+ _vertices[0] = v0;
+ _vertices[1] = v1;
+ _vertices[2] = v2;
+ _Style = FILL;
+ }
+ inline TriangleRep( const Vec3r& v0, const Vec3r& c0,
+ const Vec3r& v1, const Vec3r& c1,
+ const Vec3r& v2, const Vec3r& c2)
+ : Rep()
+ {
+ _vertices[0] = v0;
+ _vertices[1] = v1;
+ _vertices[2] = v2;
+ _colors[0] = c0;
+ _colors[1] = c1;
+ _colors[2] = c2;
+ _Style = FILL;
+ }
+
+ virtual ~TriangleRep()
+ {}
+
+ /*! accessors */
+ inline const TRIANGLE_STYLE style() const {return _Style;}
+ inline const Vec3r& vertex(int index) const {return _vertices[index];}
+ inline const Vec3r& color(int index) const {return _colors[index];}
+ /*! modifiers */
+ inline void setStyle(const TRIANGLE_STYLE iStyle) {_Style = iStyle;}
+ inline void setVertex(int index, const Vec3r& iVertex) {_vertices[index] = iVertex;}
+ inline void setColor(int index, const Vec3r& iColor) {_colors[index] = iColor;}
+ inline void setVertices(const Vec3r& v0, const Vec3r& v1, const Vec3r& v2) {_vertices[0] = v0; _vertices[1] = v1; _vertices[2] = v2;}
+ inline void setColors(const Vec3r& c0, const Vec3r& c1, const Vec3r& c2) {_colors[0] = c0; _colors[1] = c1; _colors[2] = c2;}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v) {
+ Rep::accept(v);
+ v.visitTriangleRep(*this);
+ }
+
+ /*! Computes the triangle bounding box.*/
+ virtual void ComputeBBox();
+
+
+};
+
+#endif
diff --git a/source/blender/freestyle/intern/scene_graph/VertexRep.cpp b/source/blender/freestyle/intern/scene_graph/VertexRep.cpp
new file mode 100755
index 00000000000..e4f774bfb84
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/VertexRep.cpp
@@ -0,0 +1,29 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "VertexRep.h"
+
+void VertexRep::ComputeBBox()
+{
+
+ setBBox(BBox<Vec3r>(Vec3r(_coordinates[0], _coordinates[1], _coordinates[2]),
+ Vec3r(_coordinates[0], _coordinates[1], _coordinates[2])));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/VertexRep.h b/source/blender/freestyle/intern/scene_graph/VertexRep.h
new file mode 100755
index 00000000000..9e31b4b8ef9
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/VertexRep.h
@@ -0,0 +1,87 @@
+//
+// Filename : VertexRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the representation of a vertex for
+// displaying purpose.
+// Date of creation : 03/04/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VERTEXREP_H
+# define VERTEXREP_H
+
+#include "Rep.h"
+
+class LIB_SCENE_GRAPH_EXPORT VertexRep : public Rep
+{
+public:
+
+ inline VertexRep() : Rep() {_vid = 0;_PointSize = 0.f;}
+ inline VertexRep(real x, real y, real z, int id = 0)
+ : Rep()
+ {
+ _coordinates[0] = x;
+ _coordinates[1] = y;
+ _coordinates[2] = z;
+
+ _vid = id;
+ _PointSize = 0.f;
+ }
+
+ inline ~VertexRep() {}
+
+ /*! Accept the corresponding visitor */
+
+ virtual void accept(SceneVisitor& v) {
+ Rep::accept(v);
+ v.visitVertexRep(*this);
+ }
+
+ /*! Computes the rep bounding box.
+ */
+ virtual void ComputeBBox();
+
+ /*! accessors */
+ inline const int vid() const {return _vid;}
+ inline const real * coordinates() const {return _coordinates;}
+ inline real x() const {return _coordinates[0];}
+ inline real y() const {return _coordinates[1];}
+ inline real z() const {return _coordinates[2];}
+ inline float pointSize() const {return _PointSize;}
+
+ /*! modifiers */
+ inline void setVid(int id) {_vid = id;}
+ inline void setX(real x) {_coordinates[0] = x;}
+ inline void setY(real y) {_coordinates[1] = y;}
+ inline void setZ(real z) {_coordinates[2] = z;}
+ inline void setCoordinates(real x, real y, real z) {_coordinates[0] = x;_coordinates[1] = y; _coordinates[2] = z;}
+ inline void setPointSize(float iPointSize) {_PointSize = iPointSize;}
+
+private:
+ int _vid; // vertex id
+ real _coordinates[3];
+ float _PointSize;
+};
+
+#endif // VERTEXREP_H
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp
new file mode 100755
index 00000000000..7a51a1a78df
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp
@@ -0,0 +1,92 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "../view_map/Functions0D.h"
+# include "AdvancedFunctions0D.h"
+# include "../view_map/SteerableViewMap.h"
+# include "Canvas.h"
+
+namespace Functions0D {
+
+ int DensityF0D::operator()(Interface0DIterator& iter) {
+ Canvas* canvas = Canvas::getInstance();
+ int bound = _filter.getBound();
+ if( (iter->getProjectedX()-bound < 0) || (iter->getProjectedX()+bound>canvas->width())
+ || (iter->getProjectedY()-bound < 0) || (iter->getProjectedY()+bound>canvas->height())) {
+ result = 0.0;
+ return 0;
+ }
+ RGBImage image;
+ canvas->readColorPixels((int)iter->getProjectedX() - bound,
+ (int)iter->getProjectedY() - bound,
+ _filter.maskSize(),
+ _filter.maskSize(),
+ image);
+ result = _filter.getSmoothedPixel<RGBImage>(&image, (int)iter->getProjectedX(),
+ (int)iter->getProjectedY());
+ return 0;
+ }
+
+
+ int LocalAverageDepthF0D::operator()(Interface0DIterator& iter) {
+ Canvas * iViewer = Canvas::getInstance();
+ int bound = _filter.getBound();
+
+ if( (iter->getProjectedX()-bound < 0) || (iter->getProjectedX()+bound>iViewer->width())
+ || (iter->getProjectedY()-bound < 0) || (iter->getProjectedY()+bound>iViewer->height())) {
+ result = 0.0;
+ return 0;
+ }
+ GrayImage image ;
+ iViewer->readDepthPixels((int)iter->getProjectedX()-bound,(int)iter->getProjectedY()-bound,_filter.maskSize(),_filter.maskSize(),image);
+ result = _filter.getSmoothedPixel(&image, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+ }
+
+ int ReadMapPixelF0D::operator()(Interface0DIterator& iter) {
+ Canvas * canvas = Canvas::getInstance();
+ result = canvas->readMapPixel(_mapName, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+ }
+
+ int ReadSteerableViewMapPixelF0D::operator()(Interface0DIterator& iter) {
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ result = svm->readSteerableViewMapPixel(_orientation, _level,(int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+ }
+
+ int ReadCompleteViewMapPixelF0D::operator()(Interface0DIterator& iter) {
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ result = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+ }
+
+ int GetViewMapGradientNormF0D::operator()(Interface0DIterator& iter){
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ float pxy = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY());
+ float gx = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX()+_step, (int)iter->getProjectedY())
+ - pxy;
+ float gy = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY()+_step)
+ - pxy;
+ result = Vec2f(gx,gy).norm();
+ return 0;
+ }
+} // end of namespace Functions0D
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h
new file mode 100755
index 00000000000..5d62ea8d9eb
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h
@@ -0,0 +1,209 @@
+//
+// Filename : AdvancedFunctions0D.h
+// Author(s) : Stephane Grabli
+// Emmanuel Turquin
+// Purpose : Functions taking 0D input
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ADVANCED_FUNCTIONS0D_HPP
+# define ADVANCED_FUNCTIONS0D_HPP
+
+
+# include "../image/Image.h"
+# include "../image/GaussianFilter.h"
+# include "../view_map/Functions0D.h"
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions0D {
+
+ // DensityF0D
+ /*! Returns the density of the (result) image evaluated at an Interface0D.
+ * This density is evaluated using a pixels square window around the
+ * evaluation point and integrating these values using
+ * a gaussian.
+ */
+ class LIB_STROKE_EXPORT DensityF0D : public UnaryFunction0D<double>
+ {
+ public:
+ /*! Builds the functor from the gaussian sigma value.
+ * \param sigma
+ * sigma indicates the x value for which the gaussian
+ * function is 0.5. It leads to the window size
+ * value. (the larger, the smoother)
+ */
+ DensityF0D(double sigma = 2) : UnaryFunction0D<double>() {
+ _filter.setSigma((float)sigma);
+ }
+ /*! Returns the string "DensityF0D"*/
+ string getName() const {
+ return "DensityF0D";
+ }
+ /*! The () operator. */
+ int operator()(Interface0DIterator& iter);
+
+ private:
+
+ GaussianFilter _filter;
+ };
+
+ // LocalAverageDepthF0D
+ /*! Returns the average depth around a point.
+ * The result is obtained by querying the
+ * depth buffer on a window around that point.
+ */
+ class LIB_STROKE_EXPORT LocalAverageDepthF0D : public UnaryFunction0D<double>
+ {
+ private:
+ GaussianFilter _filter;
+ public:
+ /*! Builds the functor from the size of the mask that
+ * will be used.
+ */
+ LocalAverageDepthF0D(real maskSize=5.f) : UnaryFunction0D<double>() {
+ _filter.setSigma((float)maskSize/2.f);
+ }
+ /*! Returns the string "LocalAverageDepthF0D"*/
+ string getName() const {
+ return "LocalAverageDepthF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // ReadMapPixel
+ /*! Reads a pixel in a map.
+ */
+ class LIB_STROKE_EXPORT ReadMapPixelF0D : public UnaryFunction0D<float>
+ {
+ private:
+ const char * _mapName;
+ int _level;
+ public:
+ /*! Builds the functor from name of the
+ * Map that must be read.
+ * \param iMapName
+ * The name of the map.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ */
+ ReadMapPixelF0D(const char *iMapName, int level) : UnaryFunction0D<float>() {
+ _mapName = iMapName;
+ _level = level;
+ }
+ /*! Returns the string "ReadMapPixelF0D"*/
+ string getName() const {
+ return "ReadMapPixelF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // ReadSteerableViewMapPixel
+ /*! Reads a pixel in one of the level of one of the steerable viewmaps.
+ */
+ class LIB_STROKE_EXPORT ReadSteerableViewMapPixelF0D : public UnaryFunction0D<float>
+ {
+ private:
+ unsigned _orientation;
+ int _level;
+ public:
+ /*! Builds the functor
+ * \param nOrientation
+ * The integer belonging to [0,4] indicating the orientation (E,NE,N,NW)
+ * we are interested in.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ */
+ ReadSteerableViewMapPixelF0D(unsigned nOrientation, int level) : UnaryFunction0D<float>() {
+ _orientation = nOrientation;
+ _level = level;
+ }
+ /*! Returns the string "ReadSteerableViewMapPixelF0D"*/
+ string getName() const {
+ return "ReadSteerableViewMapPixelF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // ReadCompleteViewMapPixel
+ /*! Reads a pixel in one of the level of the complete viewmap.
+ */
+ class LIB_STROKE_EXPORT ReadCompleteViewMapPixelF0D : public UnaryFunction0D<float>
+ {
+ private:
+ int _level;
+ public:
+ /*! Builds the functor
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ */
+ ReadCompleteViewMapPixelF0D(int level) : UnaryFunction0D<float>() {
+ _level = level;
+ }
+ /*! Returns the string "ReadCompleteViewMapPixelF0D"*/
+ string getName() const {
+ return "ReadCompleteViewMapPixelF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // GetViewMapGradientNormF0D
+ /*! Returns the norm of the gradient of the global viewmap density image.
+ */
+ class LIB_STROKE_EXPORT GetViewMapGradientNormF0D: public UnaryFunction0D< float>
+ {
+ private:
+ int _level;
+ float _step;
+ public:
+ /*! Builds the functor
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ */
+ GetViewMapGradientNormF0D(int level) : UnaryFunction0D<float>() {
+ _level = level;
+ _step = (float)pow(2.0,_level);
+ }
+ /*! Returns the string "GetOccludeeF0D"*/
+ string getName() const {
+ return "GetViewMapGradientNormF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+} // end of namespace Functions0D
+
+#endif // ADVANCED_FUNCTIONS0D_HPP
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
new file mode 100755
index 00000000000..2548ce38659
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
@@ -0,0 +1,110 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "AdvancedFunctions1D.h"
+# include "../view_map/SteerableViewMap.h"
+# include "Canvas.h"
+
+// FIXME
+namespace Functions1D {
+
+ int GetSteerableViewMapDensityF1D::operator()(Interface1D& inter) {
+ SteerableViewMap * svm = Canvas::getInstance()->getSteerableViewMap();
+ Interface0DIterator it = inter.pointsBegin(_sampling);
+ Interface0DIterator itnext = it;++itnext;
+ FEdge *fe;
+ unsigned nSVM;
+ vector<float> values;
+ while(!itnext.isEnd()){
+ Interface0D& i0D = (*it);
+ Interface0D& i0Dnext = (*itnext);
+ fe = i0D.getFEdge(i0Dnext);
+ if(fe == 0){
+ cerr << "GetSteerableViewMapDensityF1D warning: no FEdge between " << i0D.getId() << " and " << i0Dnext.getId() << endl;
+ // compute the direction between these two ???
+ Vec2f dir = i0Dnext.getPoint2D()-i0D.getPoint2D();
+ nSVM = svm->getSVMNumber(dir);
+ }else{
+ nSVM = svm->getSVMNumber(fe->getId().getFirst());
+ }
+ Vec2r m((i0D.getProjectedX()+i0Dnext.getProjectedX())/2.0,
+ (i0D.getProjectedY()+i0Dnext.getProjectedY())/2.0);
+ values.push_back(svm->readSteerableViewMapPixel(nSVM,_level,(int)m[0],(int)m[1]));
+ ++it;++itnext;
+ }
+ float res, res_tmp;
+ vector<float>::iterator v = values.begin(), vend=values.end();
+ unsigned size = 1;
+ switch(_integration) {
+ case MIN:
+ res = *v;++v;
+ for (; v!=vend; ++v) {
+ res_tmp = *v;
+ if (res_tmp < res)
+ res = res_tmp;
+ }
+ break;
+ case MAX:
+ res = *v;++v;
+ for (; v!=vend; ++v) {
+ res_tmp = *v;
+ if (res_tmp > res)
+ res = res_tmp;
+ }
+ break;
+ case FIRST:
+ res = *v;
+ break;
+ case LAST:
+ --vend;
+ res = *vend;
+ break;
+ case MEAN:
+ default:
+ res = *v;++v;
+ for (; v!=vend; ++v, ++size)
+ res += *v;
+ res /= (size ? size : 1);
+ break;
+ }
+ result = res;
+ return 0;
+ }
+
+ int GetDirectionalViewMapDensityF1D::operator()(Interface1D& inter) {
+ //soc unsigned size;
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+
+ int GetCompleteViewMapDensityF1D::operator()(Interface1D& inter) {
+ //soc unsigned size;
+ Id id = inter.getId();
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+
+ int GetViewMapGradientNormF1D::operator()(Interface1D& inter){
+ result = integrate(_func, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+}
+
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
new file mode 100755
index 00000000000..ab963c68034
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
@@ -0,0 +1,288 @@
+//
+// Filename : AdvancedFunctions1D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Functions taking 1D input
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ADVANCED_FUNCTIONS1D_HPP
+# define ADVANCED_FUNCTIONS1D_HPP
+
+
+# include "../view_map/Functions1D.h"
+# include "AdvancedFunctions0D.h"
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions1D {
+
+ // DensityF1D
+ /*! Returns the density evaluated for an Interface1D.
+ * The density is evaluated for a set of points along
+ * the Interface1D (using the DensityF0D functor)
+ * with a user-defined sampling and
+ * then integrated into a single value using
+ * a user-defined integration method.
+ */
+ class DensityF1D : public UnaryFunction1D<double>
+ {
+ private:
+ float _sampling;
+ public:
+ /*! Builds the functor.
+ * \param sigma
+ * Thesigma used in DensityF0D and determining
+ * the window size used in each density query.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ DensityF1D(double sigma = 2, IntegrationType iType = MEAN, float sampling=2.f) : UnaryFunction1D<double>(iType), _fun(sigma) {
+ _sampling = sampling;
+ }
+ /*! Destructor */
+ virtual ~DensityF1D(){}
+
+ /*! Returns the string "DensityF1D"*/
+ string getName() const {
+ return "DensityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) {
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+ private:
+ Functions0D::DensityF0D _fun;
+ };
+
+ // LocalAverageDepthF1D
+ /*! Returns the average depth evaluated for an Interface1D.
+ * The average depth is evaluated for a set of points along
+ * the Interface1D (using the LocalAverageDepthF0D functor)
+ * with a user-defined sampling and
+ * then integrated into a single value using
+ * a user-defined integration method.
+ */
+ class LocalAverageDepthF1D : public UnaryFunction1D<double>
+ {
+ public:
+ /*! Builds the functor.
+ * \param sigma
+ * The sigma used in DensityF0D and determining
+ * the window size used in each density query.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ LocalAverageDepthF1D(real sigma, IntegrationType iType = MEAN)
+ : UnaryFunction1D<double>(iType), _fun(sigma){
+ }
+ /*! Returns the string "LocalAverageDepthF1D"*/
+ string getName() const {
+ return "LocalAverageDepthF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+ private:
+ Functions0D::LocalAverageDepthF0D _fun;
+ };
+
+ // GetCompleteViewMapDensity
+ /*! Returns the density evaluated for an Interface1D in the
+ * complete viewmap image.
+ * The density is evaluated for a set of points along
+ * the Interface1D (using the ReadCompleteViewMapPixelF0D functor)
+ * and then integrated into a single value using
+ * a user-defined integration method.
+ */
+ class LIB_STROKE_EXPORT GetCompleteViewMapDensityF1D : public UnaryFunction1D<double>
+ {
+ public:
+ /*! Builds the functor.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetCompleteViewMapDensityF1D(unsigned level, IntegrationType iType = MEAN, float sampling=2.f)
+ : UnaryFunction1D<double>(iType), _fun(level){_sampling = sampling;}
+ /*! Returns the string "GetCompleteViewMapDensityF1D"*/
+ string getName() const {
+ return "GetCompleteViewMapDensityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+
+ private:
+ Functions0D::ReadCompleteViewMapPixelF0D _fun;
+ float _sampling;
+ };
+
+ // GetDirectionalViewMapDensity
+ /*! Returns the density evaluated for an Interface1D in of the
+ * steerable viewmaps image.
+ * The direction telling which Directional map to choose
+ * is explicitely specified by the user.
+ * The density is evaluated for a set of points along
+ * the Interface1D (using the ReadSteerableViewMapPixelF0D functor)
+ * and then integrated into a single value using
+ * a user-defined integration method.
+ */
+ class LIB_STROKE_EXPORT GetDirectionalViewMapDensityF1D : public UnaryFunction1D<double>
+ {
+ public:
+ /*! Builds the functor.
+ * \param iOrientation
+ * The number of the directional map
+ * we must work with.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetDirectionalViewMapDensityF1D(unsigned iOrientation, unsigned level, IntegrationType iType = MEAN, float sampling=2.f)
+ : UnaryFunction1D<double>(iType), _fun(iOrientation,level){_sampling = sampling;}
+ /*! Returns the string "GetDirectionalViewMapDensityF1D"*/
+ string getName() const {
+ return "GetDirectionalViewMapDensityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+
+ private:
+ Functions0D::ReadSteerableViewMapPixelF0D _fun;
+ float _sampling;
+ };
+
+ // GetSteerableViewMapDensityF1D
+ /*! Returns the density of the viewmap
+ * for a given Interface1D. The density of each
+ * FEdge is evaluated in the proper steerable
+ * ViewMap depending on its oorientation.
+ */
+ class LIB_STROKE_EXPORT GetSteerableViewMapDensityF1D : public UnaryFunction1D<real>
+ {
+ private:
+ int _level;
+ float _sampling;
+ public:
+ /*! Builds the functor from the level
+ * of the pyramid from which the pixel must be read.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetSteerableViewMapDensityF1D(int level,IntegrationType iType = MEAN, float sampling=2.f) : UnaryFunction1D<real>(iType) {
+ _level = level;
+ _sampling = sampling;
+ }
+ /*! Destructor */
+ virtual ~GetSteerableViewMapDensityF1D(){}
+
+ /*! Returns the string "GetSteerableViewMapDensityF1D"*/
+ string getName() const {
+ return "GetSteerableViewMapDensityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // GetViewMapGradientNormF1D
+ /*! Returns the density of the viewmap
+ * for a given Interface1D. The density of each
+ * FEdge is evaluated in the proper steerable
+ * ViewMap depending on its oorientation.
+ */
+ class LIB_STROKE_EXPORT GetViewMapGradientNormF1D : public UnaryFunction1D<real>
+ {
+ private:
+ int _level;
+ float _sampling;
+ Functions0D::GetViewMapGradientNormF0D _func;
+ public:
+ /*! Builds the functor from the level
+ * of the pyramid from which the pixel must be read.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetViewMapGradientNormF1D(int level,IntegrationType iType = MEAN, float sampling=2.f)
+ : UnaryFunction1D<real>(iType), _func(level) {
+ _level = level;
+ _sampling = sampling;
+ }
+
+ /*! Returns the string "GetSteerableViewMapDensityF1D"*/
+ string getName() const {
+ return "GetViewMapGradientNormF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+} // end of namespace Functions1D
+
+#endif // ADVANCED_FUNCTIONS1D_HPP
diff --git a/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h
new file mode 100755
index 00000000000..91b63168aa9
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h
@@ -0,0 +1,84 @@
+//
+// Filename : AdvancedPredicates1D.h
+// Author(s) : Stephane Grabli
+// Purpose : Class gathering stroke creation algorithms
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ADVANCED_PREDICATES1D_H
+# define ADVANCED_PREDICATES1D_H
+
+# include <string>
+# include "../view_map/Interface1D.h"
+# include "AdvancedFunctions1D.h"
+# include "Predicates1D.h"
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates1D {
+
+ // DensityLowerThanUP1D
+ /*! Returns true if the density evaluated for the
+ * Interface1D is less than a user-defined density value.
+ */
+ class DensityLowerThanUP1D : public UnaryPredicate1D
+ {
+ public:
+ /*! Builds the functor.
+ * \param threshold
+ * The value of the threshold density.
+ * Any Interface1D having a density lower than
+ * this threshold will match.
+ * \param sigma
+ * The sigma value defining the density evaluation window size
+ * used in the DensityF0D functor.
+ */
+ DensityLowerThanUP1D(double threshold, double sigma = 2) {
+ _threshold = threshold;
+ _sigma = sigma;
+ }
+ /*! Returns the string "DensityLowerThanUP1D"*/
+ string getName() const {
+ return "DensityLowerThanUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ Functions1D::DensityF1D fun(_sigma);
+ if (fun(inter) < 0)
+ return -1;
+ result = (fun.result < _threshold);
+ return 0;
+ }
+ private:
+ double _sigma;
+ double _threshold;
+ };
+
+} // end of namespace Predicates1D
+
+#endif // ADVANCED_PREDICATES1D_H
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
new file mode 100755
index 00000000000..697531b383f
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
@@ -0,0 +1,435 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "AdvancedStrokeShaders.h"
+#include "../system/PseudoNoise.h"
+#include "../system/RandGen.h"
+#include "StrokeIterators.h"
+
+/////////////////////////////////////////
+//
+// CALLIGRAPHICS SHADER
+//
+/////////////////////////////////////////
+
+
+CalligraphicShader::CalligraphicShader (real iMinThickness, real iMaxThickness,
+ const Vec2f &iOrientation, bool clamp)
+ : StrokeShader()
+{
+ _minThickness=iMinThickness;
+ _maxThickness=iMaxThickness;
+ _orientation = iOrientation;
+ _orientation.normalize();
+ _clamp = clamp;
+}
+
+float ksinToto=0;
+
+int
+CalligraphicShader::shade(Stroke &ioStroke) const
+{
+ Interface0DIterator v;
+ Functions0D::VertexOrientation2DF0D fun;
+ StrokeVertex* sv;
+ for(v=ioStroke.verticesBegin();
+ !v.isEnd();
+ ++v)
+ {
+ real thickness;
+ if (fun(v) < 0)
+ return -1;
+ Vec2f vertexOri(fun.result);
+ Vec2r ori2d(-vertexOri[1], vertexOri[0]);
+ ori2d.normalizeSafe();
+ real scal = ori2d * _orientation;
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ if (_clamp && (scal<0)) {
+ scal=0.0;
+ sv->attribute().setColor(1,1,1);
+ }
+ else {
+ scal=fabs(scal);
+ sv->attribute().setColor(0,0,0);
+ }
+ thickness=_minThickness+scal*(_maxThickness-_minThickness);
+ if (thickness<0.0)
+ thickness=0.0;
+ sv->attribute().setThickness(thickness/2.0,thickness/2.0);
+ }
+
+ return 0;
+}
+
+//void
+//TipRemoverShader::shade(Stroke &ioStroke) const
+//{
+//
+// StrokeInternal::StrokeVertexIterator v, vend;
+// for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
+// v!=vend;
+// ++v)
+// {
+// if (((*v)->curvilinearAbscissa()<_tipLength) ||
+// ((*v)->strokeLength()-(*v)->curvilinearAbscissa()<_tipLength))
+// {
+// (*v)->attribute().setThickness(0.0, 0.0);
+// (*v)->attribute().setColor(1,1,1);
+// }
+// }
+//
+//}
+
+
+
+/////////////////////////////////////////
+//
+// SPATIAL NOISE SHADER
+//
+/////////////////////////////////////////
+
+static const unsigned NB_VALUE_NOISE = 512;
+
+SpatialNoiseShader::SpatialNoiseShader (float ioamount, float ixScale, int nbOctave,
+ bool smooth, bool pureRandom)
+ : StrokeShader()
+{
+ _amount = ioamount;
+ if (ixScale==0) _xScale=0;
+ else _xScale=1.0/ixScale/real(NB_VALUE_NOISE);
+ _nbOctave=nbOctave;
+ _smooth=smooth;
+ _pureRandom=pureRandom;
+}
+int
+SpatialNoiseShader::shade(Stroke &ioStroke) const
+{
+ Interface0DIterator v, v2;
+ v=ioStroke.verticesBegin();
+ Vec2r p(v->getProjectedX(), v->getProjectedY());
+ v2=v; ++v2;
+ Vec2r p0(v2->getProjectedX(), v2->getProjectedY());
+ p0=p+2*(p-p0);
+ StrokeVertex* sv;
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ real initU = sv->strokeLength()*real(NB_VALUE_NOISE);
+ if (_pureRandom) initU+=RandGen::drand48()*real(NB_VALUE_NOISE);
+
+ Functions0D::VertexOrientation2DF0D fun;
+ while (!v.isEnd())
+ {
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ Vec2r p(sv->getPoint());
+ if (fun(v) < 0)
+ return -1;
+ Vec2r vertexOri(fun.result);
+ Vec2r ori2d(vertexOri[0], vertexOri[1]);
+ ori2d = Vec2r(p-p0);
+ ori2d.normalizeSafe();
+
+ PseudoNoise mynoise;
+ real bruit;
+
+ if (_smooth)
+ bruit=mynoise.turbulenceSmooth(_xScale*sv->curvilinearAbscissa()+initU,
+ _nbOctave);
+ else
+ bruit=mynoise.turbulenceLinear(_xScale*sv->curvilinearAbscissa()+initU,
+ _nbOctave);
+
+ Vec2r noise(-ori2d[1]*_amount*bruit,
+ ori2d[0]*_amount*bruit);
+
+ sv->setPoint(p[0]+noise[0], p[1]+noise[1]);
+ p0=p;
+
+ ++v;
+ }
+
+ return 0;
+}
+
+
+
+/////////////////////////////////////////
+//
+// SMOOTHING SHADER
+//
+/////////////////////////////////////////
+
+
+SmoothingShader::SmoothingShader (int ionbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor)
+ : StrokeShader()
+{
+ _nbIterations=ionbIteration;
+ _factorCurvature=ifactorCurvature;
+ _factorCurvatureDifference=iFactorCurvatureDifference;
+ _anisoNormal=iAnisoNormal;
+ _anisoCurvature=iAnisoCurvature;
+ _carricatureFactor=iCarricatureFactor;
+ _factorPoint=iFactorPoint;
+ _anisoPoint=iAnisoPoint;
+}
+
+
+
+int
+SmoothingShader::shade(Stroke &ioStroke) const
+{
+ //cerr<<" Smoothing a stroke "<<endl;
+
+ Smoother smoother(ioStroke);
+ smoother.smooth(_nbIterations, _factorPoint, _factorCurvature, _factorCurvatureDifference,
+ _anisoPoint, _anisoNormal, _anisoCurvature, _carricatureFactor);
+ return 0;
+}
+
+// SMOOTHER
+////////////////////////////
+
+Smoother::Smoother(Stroke &ioStroke)
+{
+ _stroke=&ioStroke;
+
+ _nbVertices=ioStroke.vertices_size();
+ _vertex=new Vec2r[_nbVertices];
+ _curvature=new real[_nbVertices];
+ _normal=new Vec2r[_nbVertices];
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ for(v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd();
+ v != vend;
+ ++v)
+ {
+ _vertex[i]=(v)->getPoint();
+ i++;
+ }
+ Vec2r vec_tmp(_vertex[0]-_vertex[_nbVertices-1]);
+ _isClosedCurve = (vec_tmp.norm() < M_EPSILON);
+
+ _safeTest=(_nbVertices>4);
+}
+
+void Smoother::smooth(int nbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor)
+{
+ _factorCurvature=ifactorCurvature;
+ _factorCurvatureDifference=iFactorCurvatureDifference;
+ _anisoNormal=iAnisoNormal;
+ _anisoCurvature=iAnisoCurvature;
+ _carricatureFactor=iCarricatureFactor;
+ _factorPoint=iFactorPoint;
+ _anisoPoint=iAnisoPoint;
+
+ for (int i=0; i<nbIteration; i++)
+ iteration ();
+ copyVertices();
+}
+
+real edgeStopping (real x, real sigma)
+{
+ if (sigma==0.0) return 1.0;
+ return exp(-x*x/(sigma*sigma));
+}
+
+void
+Smoother::iteration ()
+{
+ computeCurvature();
+ for (int i=1; i<_nbVertices-1; i++)
+ {
+ real motionNormal=_factorCurvature*_curvature[i]*
+ edgeStopping(_curvature[i], _anisoNormal);
+
+ real diffC1=_curvature[i]-_curvature[i-1];
+ real diffC2=_curvature[i]-_curvature[i+1];
+ real motionCurvature=edgeStopping(diffC1, _anisoCurvature)*diffC1 +
+ edgeStopping(diffC2, _anisoCurvature)*diffC2;//_factorCurvatureDifference;
+ motionCurvature*=_factorCurvatureDifference;
+ //motionCurvature=_factorCurvatureDifference*(diffC1+diffC2);
+ if (_safeTest)
+ _vertex[i]=Vec2r(_vertex[i]+(motionNormal+motionCurvature)*_normal[i]);
+ Vec2r v1(_vertex[i-1]-_vertex[i]);
+ Vec2r v2(_vertex[i+1]-_vertex[i]);
+ real d1 = v1.norm();
+ real d2 = v2.norm();
+ _vertex[i]=Vec2r(_vertex[i]+
+ _factorPoint*edgeStopping(d2, _anisoPoint)*(_vertex[i-1]-_vertex[i]) +
+ _factorPoint*edgeStopping(d1, _anisoPoint)*(_vertex[i+1]-_vertex[i]) );
+ }
+
+ if (_isClosedCurve)
+ {
+ real motionNormal=_factorCurvature*_curvature[0]*
+ edgeStopping(_curvature[0], _anisoNormal);
+
+ real diffC1=_curvature[0]-_curvature[_nbVertices-2];
+ real diffC2=_curvature[0]-_curvature[1];
+ real motionCurvature=edgeStopping(diffC1, _anisoCurvature)*diffC1 +
+ edgeStopping(diffC2, _anisoCurvature)*diffC2;//_factorCurvatureDifference;
+ motionCurvature*=_factorCurvatureDifference;
+ //motionCurvature=_factorCurvatureDifference*(diffC1+diffC2);
+ _vertex[0]=Vec2r(_vertex[0]+(motionNormal+motionCurvature)*_normal[0]);
+ _vertex[_nbVertices-1]=_vertex[0];
+ }
+}
+
+
+void
+Smoother::computeCurvature ()
+{
+ int i;
+ Vec2r BA, BC, normalCurvature;
+ for (i = 1; i < _nbVertices - 1; i++)
+ {
+ BA=_vertex[i-1]-_vertex[i];
+ BC=_vertex[i+1]-_vertex[i];
+ real lba=BA.norm(), lbc=BC.norm();
+ BA.normalizeSafe();
+ BC.normalizeSafe();
+ normalCurvature = BA + BC;
+
+ _normal[i]=Vec2r(-(BC-BA)[1], (BC-BA)[0]);
+ _normal[i].normalizeSafe();
+
+ _curvature[i] = normalCurvature * _normal[i];
+ if (lba+lbc > M_EPSILON)
+ _curvature[i]/=(0.5*lba+lbc);
+ }
+ _curvature[0]=_curvature[1];
+ _curvature[_nbVertices-1]=_curvature[_nbVertices-2];
+ Vec2r di(_vertex[1]-_vertex[0]);
+ _normal[0] = Vec2r(-di[1], di[0]);
+ _normal[0].normalizeSafe();
+ di=_vertex[_nbVertices-1]-_vertex[_nbVertices-2];
+ _normal[_nbVertices-1]=Vec2r(-di[1], di[0]);
+ _normal[_nbVertices-1].normalizeSafe();
+
+ if (_isClosedCurve)
+ {
+ BA=_vertex[_nbVertices-2]-_vertex[0];
+ BC=_vertex[1]-_vertex[0];
+ real lba=BA.norm(), lbc=BC.norm();
+ BA.normalizeSafe();
+ BC.normalizeSafe();
+ normalCurvature = BA + BC;
+
+ _normal[i]=Vec2r(-(BC-BA)[1], (BC-BA)[0]);
+ _normal[i].normalizeSafe();
+
+ _curvature[i] = normalCurvature * _normal[i];
+ if (lba+lbc > M_EPSILON)
+ _curvature[i]/=(0.5*lba+lbc);
+
+ _normal[_nbVertices-1]=_normal[0];
+ _curvature[_nbVertices-1]=_curvature[0];
+ }
+}
+
+void
+Smoother::copyVertices ()
+{
+ int i=0;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for(v=_stroke->strokeVerticesBegin(), vend=_stroke->strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ const Vec2r p0((v)->getPoint());
+ const Vec2r p1(_vertex[i]);
+ Vec2r p(p0 + _carricatureFactor * (p1 - p0));
+
+ (v)->setPoint(p[0], p[1]);
+ i++;
+ }
+
+}
+
+
+#if 0 // FIXME
+
+/////////////////////////////////////////
+//
+// OMISSION SHADER
+//
+/////////////////////////////////////////
+
+OmissionShader::OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat)
+{
+ _sizeWindow=sizeWindow;
+ _thresholdVariation=thrVari;
+ _thresholdFlat=thrFlat;
+ _lengthFlat=lFlat;
+}
+
+int
+OmissionShader::shade(Stroke &ioStroke) const
+{
+ Omitter omi(ioStroke);
+ omi.omit(_sizeWindow, _thresholdVariation, _thresholdFlat, _lengthFlat);
+
+ return 0;
+}
+
+
+// OMITTER
+///////////////////////////
+
+Omitter::Omitter (Stroke &ioStroke)
+ :Smoother (ioStroke)
+{
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ _u[i]=(v)->curvilinearAbscissa();
+ i++;
+ }
+
+}
+
+void
+Omitter::omit (real sizeWindow, real thrVari, real thrFlat, real lFlat)
+{
+ _sizeWindow=sizeWindow;
+ _thresholdVariation=thrVari;
+ _thresholdFlat=thrFlat;
+ _lengthFlat=lFlat;
+
+ for (int i=1; i<_nbVertices-1; i++)
+ {
+ if (_u[i]<_lengthFlat) continue;
+ // is the previous segment flat?
+ int j=i-1;
+ while ((j>=0) && (_u[i]-_u[j]<_lengthFlat))
+ {
+ if ((_normal[j] * _normal[i]) < _thresholdFlat)
+ ; // FIXME
+ j--;
+ }
+
+ }
+}
+
+#endif
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
new file mode 100755
index 00000000000..f2e56222cc0
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
@@ -0,0 +1,222 @@
+//
+// Filename : AdvancedStrokeShaders.h
+// Author : Fredo Durand
+// Purpose : Fredo's stroke shaders
+// Date of creation : 17/12/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ADVANCEDSTROKESHADERS_H
+# define ADVANCEDSTROKESHADERS_H
+
+# include "BasicStrokeShaders.h"
+
+/*! [ Thickness Shader ].
+ * Assigns thicknesses to the stroke vertices
+ * so that the stroke looks like made with a calligraphic tool.
+ * i.e. The stroke will be the thickest in a main direction,
+ * the thinest in the direction perpendicular to this one,
+ * and an interpolation inbetween.
+ */
+class LIB_STROKE_EXPORT CalligraphicShader : public StrokeShader
+{
+
+public:
+ /*! Builds the shader.
+ * \param iMinThickness
+ * The minimum thickness in the direction perpandicular
+ * to the main direction.
+ * \param iMaxThickness
+ * The maximum thickness in the main direction.
+ * \param iOrientation
+ * The 2D vector giving the main direction.
+ * \param clamp
+ * Tells ???
+ */
+ CalligraphicShader (real iMinThickness, real iMaxThickness,
+ const Vec2f &iOrientation, bool clamp);
+ /*! Destructor. */
+ virtual ~CalligraphicShader () {}
+ /*! The shading method */
+ virtual int shade(Stroke &ioStroke) const;
+protected:
+ real _maxThickness;
+ real _minThickness;
+ Vec2f _orientation;
+ bool _clamp;
+};
+
+/*! [ Geometry Shader ].
+ * Spatial Noise stroke shader.
+ * Moves the vertices to make the stroke more noisy.
+ * @see \htmlonly <a href=noise/noise.html>noise/noise.html</a> \endhtmlonly
+ */
+class LIB_STROKE_EXPORT SpatialNoiseShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param iAmount
+ * The amplitude of the noise.
+ * \param ixScale
+ * The noise frequency
+ * \param nbOctave
+ * The number of octaves
+ * \param smooth
+ * If you want the noise to be smooth
+ * \param pureRandom
+ * If you don't want any coherence
+ */
+ SpatialNoiseShader (float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom);
+ /*! Destructor. */
+ virtual ~SpatialNoiseShader () {}
+ /*! The shading method. */
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+
+ float _amount;
+ float _xScale;
+ int _nbOctave;
+ bool _smooth;
+ bool _pureRandom;
+};
+
+/*! [ Geometry Shader ].
+ * Smoothes the stroke.
+ * (Moves the vertices to make the stroke smoother).
+ * Uses curvature flow to converge towards a curve of constant
+ * curvature. The diffusion method we use is anisotropic
+ * to prevent the diffusion accross corners.
+ * @see \htmlonly <a href=/smoothing/smoothing.html>smoothing/smoothing.html</a> endhtmlonly
+ */
+class LIB_STROKE_EXPORT SmoothingShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param iNbIteration
+ * The number of iterations. (400)
+ * \param iFactorPoint
+ * 0
+ * \param ifactorCurvature
+ * 0
+ * \param iFactorCurvatureDifference
+ * 0.2
+ * \param iAnisoPoint
+ * 0
+ * \param iAnisNormal
+ * 0
+ * \param iAnisoCurvature
+ * 0
+ * \param icarricatureFactor
+ * 1
+ */
+ SmoothingShader (int iNbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor);
+ /*! Destructor. */
+ virtual ~SmoothingShader () {}
+
+ /*! The shading method. */
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+
+ int _nbIterations;
+ real _factorPoint;
+ real _factorCurvature;
+ real _factorCurvatureDifference;
+ real _anisoPoint;
+ real _anisoNormal;
+ real _anisoCurvature;
+ real _carricatureFactor;
+};
+
+class LIB_STROKE_EXPORT Smoother
+{
+public:
+ Smoother (Stroke &ioStroke);
+
+ virtual ~Smoother () {}
+
+ void smooth (int nbIterations, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor);
+ void computeCurvature ();
+
+protected:
+ real _factorPoint;
+ real _factorCurvature;
+ real _factorCurvatureDifference;
+ real _anisoPoint;
+ real _anisoNormal;
+ real _anisoCurvature;
+ real _carricatureFactor;
+
+ void iteration();
+ void copyVertices ();
+
+ Stroke *_stroke;
+ int _nbVertices;
+ Vec2r *_vertex;
+ Vec2r *_normal;
+ real *_curvature;
+ bool *_isFixedVertex;
+
+ bool _isClosedCurve;
+ bool _safeTest;
+};
+
+class LIB_STROKE_EXPORT Omitter : public Smoother
+{
+public:
+ Omitter (Stroke &ioStroke);
+ virtual ~Omitter () {}
+
+ void omit (real sizeWindow, real thrVari, real thrFlat, real lFlat);
+protected:
+ real *_u;
+
+ real _sizeWindow;
+ real _thresholdVariation;
+ real _thresholdFlat;
+ real _lengthFlat;
+};
+
+/*! Omission shader
+ */
+class LIB_STROKE_EXPORT OmissionShader : public StrokeShader
+{
+public:
+ OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat);
+ virtual ~OmissionShader () {}
+
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+
+ real _sizeWindow;
+ real _thresholdVariation;
+ real _thresholdFlat;
+ real _lengthFlat;
+};
+
+#endif // ADVANCEDSTROKESHADERS_H
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
new file mode 100755
index 00000000000..321dd5fe41f
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
@@ -0,0 +1,1170 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "StrokeRenderer.h"
+#include <fstream>
+#include "BasicStrokeShaders.h"
+#include "../system/PseudoNoise.h"
+#include "../system/RandGen.h"
+#include "../view_map/Functions0D.h"
+#include "../view_map/Functions1D.h"
+#include "AdvancedFunctions0D.h"
+#include "AdvancedFunctions1D.h"
+#include "StrokeIterators.h"
+#include "../system/StringUtils.h"
+#include "StrokeIO.h"
+
+//soc #include <qimage.h>
+//soc #include <QString>
+extern "C" {
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+}
+
+// Internal function
+
+// soc
+// void convert(const QImage& iImage, float **oArray, unsigned &oSize) {
+// oSize = iImage.width();
+// *oArray = new float[oSize];
+// for(unsigned i=0; i<oSize; ++i) {
+// QRgb rgb = iImage.pixel(i,0);
+// (*oArray)[i] = ((float)qBlue(rgb))/255.f;
+// }
+// }
+void convert(ImBuf *imBuf, float **oArray, unsigned &oSize) {
+ oSize = imBuf->x;
+ *oArray = new float[oSize];
+
+ char *pix;
+ for(unsigned i=0; i < oSize; ++i) {
+ pix = (char*) imBuf->rect + i*4;
+ (*oArray)[i] = ((float) pix[2] )/255.f;
+ }
+}
+
+namespace StrokeShaders {
+
+ //
+ // Thickness modifiers
+ //
+ //////////////////////////////////////////////////////////
+
+ int ConstantThicknessShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ int size = stroke.strokeVerticesSize();
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ if((1 == i) || (size-2 == i))
+ v->attribute().setThickness(_thickness/4.0,_thickness/4.0);
+ if((0 == i) || (size-1 == i))
+ v->attribute().setThickness(0,0);
+
+ v->attribute().setThickness(_thickness/2.0, _thickness/2.0);
+ }
+ return 0;
+ }
+
+ int ConstantExternThicknessShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ int size = stroke.strokeVerticesSize();
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ if((1 == i) || (size-2 == i))
+ v->attribute().setThickness(_thickness/2.0,0);
+ if((0 == i) || (size-1 == i))
+ v->attribute().setThickness(0,0);
+
+ v->attribute().setThickness(_thickness, 0);
+ }
+ return 0;
+ }
+
+ int IncreasingThicknessShader::shade(Stroke& stroke) const
+ {
+
+ int n=stroke.strokeVerticesSize()-1;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+
+ ++v)
+ {
+ float t;
+ if(i < (float)n/2.f)
+ t = (1.0-(float)i/(float)n)*_ThicknessMin + (float)i/(float)n*_ThicknessMax;
+ else
+ t = (1.0-(float)i/(float)n)*_ThicknessMax + (float)i/(float)n*_ThicknessMin;
+ v->attribute().setThickness(t/2.0, t/2.0);
+ ++i;
+ }
+ return 0;
+ }
+
+ int ConstrainedIncreasingThicknessShader::shade(Stroke& stroke) const
+ {
+ float slength = stroke.getLength2D();
+ float maxT = min(_ratio*slength,_ThicknessMax);
+ int n=stroke.strokeVerticesSize()-1;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+
+ ++v)
+ {
+ float t;
+ if(i < (float)n/2.f)
+ t = (1.0-(float)i/(float)n)*_ThicknessMin + (float)i/(float)n*maxT;
+ else
+ t = (1.0-(float)i/(float)n)*maxT + (float)i/(float)n*_ThicknessMin;
+ v->attribute().setThickness(t/2.0, t/2.0);
+ if(i == n-1)
+ v->attribute().setThickness(_ThicknessMin/2.0, _ThicknessMin/2.0);
+ ++i;
+ }
+ return 0;
+ }
+
+
+ int LengthDependingThicknessShader::shade(Stroke& stroke) const
+ {
+ float step = (_maxThickness-_minThickness)/3.f;
+ float l = stroke.getLength2D();
+ float thickness = 0.0;
+ if(l>300.f)
+ thickness = _minThickness+3.f*step;
+ else if((l< 300.f) && (l>100.f))
+ thickness = _minThickness+2.f*step;
+ else if((l<100.f) && (l>50.f))
+ thickness = _minThickness+1.f*step;
+ else if(l< 50.f)
+ thickness = _minThickness;
+
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ int size = stroke.strokeVerticesSize();
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ if((1 == i) || (size-2 == i))
+ v->attribute().setThickness(thickness/4.0,thickness/4.0);
+ if((0 == i) || (size-1 == i))
+ v->attribute().setThickness(0,0);
+
+ v->attribute().setThickness(thickness/2.0, thickness/2.0);
+ }
+ return 0;
+ }
+
+
+ ThicknessVariationPatternShader::ThicknessVariationPatternShader(const string pattern_name,
+ float iMinThickness,
+ float iMaxThickness,
+ bool stretch)
+ : StrokeShader() {
+ _stretch = stretch;
+ _minThickness = iMinThickness;
+ _maxThickness = iMaxThickness;
+ ImBuf *image = 0; //soc
+ vector<string> pathnames;
+ StringUtils::getPathName(TextureManager::Options::getPatternsPath(),
+ pattern_name,
+ pathnames);
+ for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
+ ifstream ifs(j->c_str());
+ if (ifs.is_open()) {
+ //soc image.load(j->c_str());
+ /* OCIO_TODO: support different input color space */
+ image = IMB_loadiffname(j->c_str(), 0, NULL);
+ break;
+ }
+ }
+ if (image == 0) //soc
+ cerr << "Error: cannot find pattern \"" << pattern_name
+ << "\" - check the path in the Options" << endl;
+ else
+ convert(image, &_aThickness, _size);
+ }
+
+ int ThicknessVariationPatternShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ float *array = 0;
+ int size;
+ array = _aThickness;
+ size = _size;
+ // }
+ int vert_size = stroke.strokeVerticesSize();
+ int sig = 0;
+ unsigned index;
+ const float* originalThickness;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ originalThickness = v->attribute().getThickness();
+ if (_stretch) {
+ float tmp = v->u()*(_size-1);
+ index = (unsigned)floor(tmp);
+ if((tmp-index) > (index+1-tmp))
+ ++index;
+ }
+ else
+ index = (unsigned)floor(v->curvilinearAbscissa());
+ index %= _size;
+ float thicknessR = array[index]*originalThickness[0];
+ float thicknessL = array[index]*originalThickness[1];
+ if(thicknessR+thicknessL < _minThickness)
+ {
+ thicknessL = _minThickness/2.f;
+ thicknessR = _minThickness/2.f;
+ }
+ if(thicknessR+thicknessL > _maxThickness)
+ {
+ thicknessL = _maxThickness/2.f;
+ thicknessR = _maxThickness/2.f;
+ }
+ if((sig==0) || (sig==vert_size-1))
+ v->attribute().setThickness(1, 1);
+ else
+ v->attribute().setThickness(thicknessR, thicknessL);
+ ++sig;
+ }
+ return 0;
+ }
+
+
+ static const unsigned NB_VALUE_NOISE = 512;
+ ThicknessNoiseShader::ThicknessNoiseShader()
+ :StrokeShader()
+ {_amplitude=1.f;_scale=1.f/2.f/(float)NB_VALUE_NOISE;}
+
+ ThicknessNoiseShader::ThicknessNoiseShader(float iAmplitude, float iPeriod)
+ :StrokeShader()
+ {_amplitude=iAmplitude;_scale=1.f/iPeriod/(float)NB_VALUE_NOISE;}
+
+
+ int ThicknessNoiseShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ real initU1=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE);
+ real initU2=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE);
+
+ real bruit, bruit2;
+ PseudoNoise mynoise, mynoise2;
+ for(;
+ v!=vend;
+ ++v)
+ {
+
+ bruit=mynoise.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU1,
+ 2); //2 : nbOctaves
+ bruit2=mynoise2.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU2,
+ 2); //2 : nbOctaves
+ const float *originalThickness = v->attribute().getThickness();
+ float r = bruit*_amplitude+originalThickness[0];
+ float l = bruit2*_amplitude+originalThickness[1];
+ v->attribute().setThickness(r,l);
+ }
+
+ return 0;
+ }
+
+ //
+ // Color shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ int ConstantColorShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ v->attribute().setColor(_color[0], _color[1], _color[2]);
+ v->attribute().setAlpha(_color[3]);
+ }
+ return 0;
+ }
+
+ int IncreasingColorShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int n=stroke.strokeVerticesSize()-1;
+ int yo=0;
+ float newcolor[4];
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+
+ ++v)
+ {
+ for(int i=0; i<4; ++i)
+ {
+ newcolor[i] = (1.0-(float)yo/(float)n)*_colorMin[i] + (float)yo/(float)n*_colorMax[i];
+ }
+ v->attribute().setColor(newcolor[0], newcolor[1], newcolor[2]);
+ v->attribute().setAlpha(newcolor[3]);
+ ++yo;
+ }
+ return 0;
+ }
+
+ ColorVariationPatternShader::ColorVariationPatternShader(const string pattern_name,
+ bool stretch)
+ : StrokeShader() {
+ _stretch = stretch;
+ ImBuf *image = 0; //soc
+ vector<string> pathnames;
+ StringUtils::getPathName(TextureManager::Options::getPatternsPath(),
+ pattern_name,
+ pathnames);
+ for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
+ ifstream ifs(j->c_str());
+ if (ifs.is_open()) {
+ /* OCIO_TODO: support different input color space */
+ image = IMB_loadiffname(j->c_str(), 0, NULL); //soc
+ break;
+ }
+ }
+ if (image == 0) //soc
+ cerr << "Error: cannot find pattern \"" << pattern_name
+ << "\" - check the path in the Options" << endl;
+ else
+ convert(image, &_aVariation, _size);
+ }
+
+ int ColorVariationPatternShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ unsigned index;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ const float *originalColor = v->attribute().getColor();
+ if (_stretch) {
+ float tmp = v->u()*(_size-1);
+ index = (unsigned)floor(tmp);
+ if((tmp-index) > (index+1-tmp))
+ ++index;
+ }
+ else
+ index = (unsigned)floor(v->curvilinearAbscissa());
+ index %= _size;
+ float r = _aVariation[index]*originalColor[0];
+ float g = _aVariation[index]*originalColor[1];
+ float b = _aVariation[index]*originalColor[2];
+ v->attribute().setColor(r,g,b);
+ }
+ return 0;
+ }
+
+ int MaterialColorShader::shade(Stroke& stroke) const
+ {
+ Interface0DIterator v, vend;
+ Functions0D::MaterialF0D fun;
+ StrokeVertex *sv;
+ for(v=stroke.verticesBegin(), vend=stroke.verticesEnd();
+ v!=vend;
+ ++v)
+ {
+ if (fun(v) < 0)
+ return -1;
+ const float *diffuse = fun.result.diffuse();
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ sv->attribute().setColor(diffuse[0]*_coefficient, diffuse[1]*_coefficient, diffuse[2]*_coefficient);
+ sv->attribute().setAlpha(diffuse[3]);
+ }
+ return 0;
+ }
+
+
+ int CalligraphicColorShader::shade(Stroke& stroke) const
+ {
+ Interface0DIterator v;
+ Functions0D::VertexOrientation2DF0D fun;
+ StrokeVertex* sv;
+ for(v=stroke.verticesBegin();
+ !v.isEnd();
+ ++v)
+ {
+ if (fun(v) < 0)
+ return -1;
+ Vec2f vertexOri(fun.result);
+ Vec2d ori2d(-vertexOri[1], vertexOri[0]);
+ ori2d.normalizeSafe();
+ real scal = ori2d * _orientation;
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ if ((scal<0))
+ sv->attribute().setColor(0,0,0);
+ else
+ sv->attribute().setColor(1,1,1);
+ }
+ return 0;
+ }
+
+
+ ColorNoiseShader::ColorNoiseShader()
+ :StrokeShader()
+ {_amplitude=1.f;_scale=1.f/2.f/(float)NB_VALUE_NOISE;}
+
+ ColorNoiseShader::ColorNoiseShader(float iAmplitude, float iPeriod)
+ :StrokeShader()
+ {_amplitude=iAmplitude;_scale=1.f/iPeriod/(float)NB_VALUE_NOISE;}
+
+
+ int ColorNoiseShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ real initU=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE);
+
+ real bruit;
+ PseudoNoise mynoise;
+ for(;
+ v!=vend;
+ ++v)
+ {
+
+ bruit=mynoise.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU,
+ 2); //2 : nbOctaves
+ const float *originalColor = v->attribute().getColor();
+ float r = bruit*_amplitude+originalColor[0];
+ float g = bruit*_amplitude+originalColor[1];
+ float b = bruit*_amplitude+originalColor[2];
+ v->attribute().setColor(r,g,b);
+ }
+
+ return 0;
+ }
+
+
+ //
+ // Texture Shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ int TextureAssignerShader::shade(Stroke& stroke) const
+ {
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+
+ TextureManager * instance = TextureManager::getInstance();
+ if(!instance)
+ return 0;
+ string pathname;
+ Stroke::MediumType mediumType;
+ bool hasTips = false;
+ switch(_textureId)
+ {
+ case 0:
+ //pathname = TextureManager::Options::getBrushesPath() + "/charcoalAlpha.bmp";
+ pathname = "/charcoalAlpha.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = false;
+ break;
+ case 1:
+ pathname = "/washbrushAlpha.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 2:
+ pathname = "/oil.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 3:
+ pathname = "/oilnoblend.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 4:
+ pathname = "/charcoalAlpha.bmp";
+ mediumType = Stroke::DRY_MEDIUM;
+ hasTips = false;
+ break;
+ case 5:
+ mediumType = Stroke::DRY_MEDIUM;
+ hasTips = true;
+ break;
+ case 6:
+ pathname = "/opaqueDryBrushAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = true;
+ break;
+ case 7:
+ pathname = "/opaqueBrushAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = true;
+ break;
+ default:
+ pathname = "/smoothAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = false;
+ break;
+ }
+ unsigned int texId = instance->getBrushTextureIndex(pathname, mediumType);
+ stroke.setMediumType(mediumType);
+ stroke.setTips(hasTips);
+ stroke.setTextureId(texId);
+ return 0;
+ }
+
+ // FIXME
+ int StrokeTextureShader::shade(Stroke& stroke) const
+ {
+ TextureManager * instance = TextureManager::getInstance();
+ if(!instance)
+ return 0;
+ string pathname = TextureManager::Options::getBrushesPath() + "/" + _texturePath;
+ unsigned int texId = instance->getBrushTextureIndex(pathname, _mediumType);
+ stroke.setMediumType(_mediumType);
+ stroke.setTips(_tips);
+ stroke.setTextureId(texId);
+ return 0;
+ }
+
+ //
+ // Geometry Shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ int BackboneStretcherShader::shade(Stroke& stroke) const
+ {
+ float l=stroke.getLength2D();
+ if(l <= 1e-6)
+ return 0;
+
+ StrokeInternal::StrokeVertexIterator v0=stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator v1=v0;++v1;
+ StrokeInternal::StrokeVertexIterator vn=stroke.strokeVerticesEnd();--vn;
+ StrokeInternal::StrokeVertexIterator vn_1=vn;--vn_1;
+
+
+ Vec2d first((v0)->x(), (v0)->y());
+ Vec2d last((vn)->x(), (vn)->y());
+
+ Vec2d d1(first-Vec2d((v1)->x(), (v1)->y()));
+ d1.normalize();
+ Vec2d dn(last-Vec2d((vn_1)->x(), (vn_1)->y()));
+ dn.normalize();
+
+ Vec2d newFirst(first+_amount*d1);
+ (v0)->setPoint(newFirst[0], newFirst[1]);
+ Vec2d newLast(last+_amount*dn);
+ (vn)->setPoint(newLast[0], newLast[1]);
+
+ stroke.UpdateLength();
+ return 0;
+ }
+
+ int SamplingShader::shade(Stroke& stroke) const
+ {
+ stroke.Resample(_sampling);
+ return 0;
+ }
+
+ int ExternalContourStretcherShader::shade(Stroke& stroke) const
+ {
+ //float l=stroke.getLength2D();
+ Interface0DIterator it=stroke.verticesBegin();
+ Functions0D::Normal2DF0D fun;
+ StrokeVertex* sv;
+ while (!it.isEnd())
+ {
+ if (fun(it) < 0)
+ return -1;
+ Vec2f n(fun.result);
+ sv = dynamic_cast<StrokeVertex*>(&(*it));
+ Vec2d newPoint(sv->x()+_amount*n.x(), sv->y()+_amount*n.y());
+ sv->setPoint(newPoint[0], newPoint[1]);
+ ++it;
+ }
+ stroke.UpdateLength();
+ return 0;
+ }
+
+ int BSplineShader::shade(Stroke& stroke) const
+ {
+ if(stroke.strokeVerticesSize() < 4)
+ return 0;
+
+ // Find the new vertices
+ vector<Vec2d> newVertices;
+ double t=0.f;
+ float _sampling = 5.f;
+
+ StrokeInternal::StrokeVertexIterator p0,p1,p2,p3, end;
+ p0 = stroke.strokeVerticesBegin();
+ p1 = p0;
+ p2 = p1;
+ p3 = p2;
+ end = stroke.strokeVerticesEnd();
+ double a[4],b[4];
+ int n=0;
+ while(p1 != end)
+ {
+ // if(p1 == end)
+ // p1 = p0;
+ if(p2 == end)
+ p2 = p1;
+ if(p3 == end)
+ p3 = p2;
+ // compute new matrix
+ a[0] = (-(p0)->x()+3*(p1)->x()-3*(p2)->x()+(p3)->x())/6.0;
+ a[1] = (3*(p0)->x()-6*(p1)->x()+3*(p2)->x())/6.0;
+ a[2] = (-3*(p0)->x()+3*(p2)->x())/6.0;
+ a[3] = ((p0)->x()+4*(p1)->x()+(p2)->x())/6.0;
+
+ b[0] = (-(p0)->y()+3*(p1)->y()-3*(p2)->y()+(p3)->y())/6.0;
+ b[1] = (3*(p0)->y()-6*(p1)->y()+3*(p2)->y())/6.0;
+ b[2] = (-3*(p0)->y()+3*(p2)->y())/6.0;
+ b[3] = ((p0)->y()+4*(p1)->y()+(p2)->y())/6.0;
+
+
+ // draw the spline depending on resolution:
+ Vec2d p1p2((p2)->x()-(p1)->x(), (p2)->y()-(p1)->y());
+ double norm = p1p2.norm();
+ //t = _sampling/norm;
+ t=0;
+ while(t<1)
+ {
+ newVertices.push_back(Vec2d((a[3] + t*(a[2] + t*(a[1] + t*a[0]))),
+ (b[3] + t*(b[2] + t*(b[1] + t*b[0])))));
+ t = t + _sampling/norm;
+ }
+ if(n > 2)
+ {
+ ++p0;
+ ++p1;
+ ++p2;
+ ++p3;
+ }
+ else
+ {
+ if(n==0)
+ ++p3;
+ if(n==1)
+ {++p2;++p3;}
+ if(n==2)
+ {++p1;++p2;++p3;}
+ ++n;
+ }
+ }
+ //last point:
+ newVertices.push_back(Vec2d((p0)->x(), (p0)->y()));
+
+ int originalSize = newVertices.size();
+ _sampling = stroke.ComputeSampling(originalSize);
+
+ // Resample and set x,y coordinates
+ stroke.Resample(_sampling);
+ int newsize = stroke.strokeVerticesSize();
+
+ int nExtraVertex=0;
+ if(newsize < originalSize)
+ cerr << "Warning: unsufficient resampling" << endl;
+ else
+ {
+ nExtraVertex = newsize - originalSize;
+ }
+
+ // assigns the new coordinates:
+ vector<Vec2d>::iterator p,pend;
+ p=newVertices.begin();pend=newVertices.end();
+ vector<Vec2d>::iterator last = p;
+ n=0;
+ StrokeInternal::StrokeVertexIterator it=stroke.strokeVerticesBegin(), itend=stroke.strokeVerticesEnd();
+ it=stroke.strokeVerticesBegin();
+ for(;
+ ((it!=itend) && (p!=pend));
+ ++it)
+ {
+ it->setX(p->x());
+ it->setY(p->y());
+ last = p;
+ ++p;
+ ++n;
+ }
+ // nExtraVertex should stay unassigned
+ for(int i=0; i< nExtraVertex; ++i)
+ {
+ it->setX(last->x());
+ it->setY(last->y());
+ if(it.isEnd())
+ cerr << "Warning: Problem encountered while creating B-spline" << endl;
+ ++it;
+ ++n;
+ }
+ stroke.UpdateLength();
+ return 0;
+ }
+
+ //!! Bezier curve stroke shader
+ int BezierCurveShader::shade(Stroke& stroke) const
+ {
+ if(stroke.strokeVerticesSize() < 4)
+ return 0;
+
+ // Build the Bezier curve from this set of data points:
+ vector<Vec2d> data;
+ StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ data.push_back(Vec2d(v->x(), v->y()));//first one
+ StrokeInternal::StrokeVertexIterator previous = v;++v;
+ for(;
+ v!=vend;
+ ++v)
+ {
+ if(!((fabs(v->x() -(previous)->x())<M_EPSILON) && ((fabs(v->y() - (previous)->y())<M_EPSILON))))
+ data.push_back(Vec2d(v->x(), v->y()));
+ previous = v;
+ }
+
+ // Vec2d tmp;bool equal=false;
+ // if(data.front() == data.back())
+ // {
+ // tmp = data.back();
+ // data.pop_back();
+ // equal=true;
+ // }
+ // here we build the bezier curve
+ BezierCurve bcurve(data, _error);
+
+ // bad performances are here !!! // FIXME
+ vector<Vec2d> CurveVertices;
+ vector<BezierCurveSegment*>& bsegments = bcurve.segments();
+ vector<BezierCurveSegment*>::iterator s=bsegments.begin(),send=bsegments.end();
+ vector<Vec2d>& segmentsVertices = (*s)->vertices();
+ vector<Vec2d>::iterator p,pend;
+ // first point
+ CurveVertices.push_back(segmentsVertices[0]);
+ for(;
+ s!=send;
+ ++s)
+ {
+ segmentsVertices = (*s)->vertices();
+ p=segmentsVertices.begin(); pend=segmentsVertices.end();
+ ++p;
+ for(;
+ p!=pend;
+ ++p)
+ {
+ CurveVertices.push_back((*p));
+ }
+ }
+
+ //if(equal)
+ // if(data.back() == data.front())
+ // {
+ // vector<Vec2d>::iterator d=data.begin(), dend=data.end();
+ // cout << "ending point = starting point" << endl;
+ // cout << "---------------DATA----------" << endl;
+ // for(;
+ // d!=dend;
+ // ++d)
+ // {
+ // cout << d->x() << "-" << d->y() << endl;
+ // }
+ // cout << "--------------BEZIER RESULT----------" << endl;
+ // d=CurveVertices.begin(), dend=CurveVertices.end();
+ // for(;d!=dend;++d)
+ // {
+ // cout << d->x() << "-" << d->y() << endl;
+ // }
+ // }
+
+ // Resample the Stroke depending on the number of
+ // vertices of the bezier curve:
+ int originalSize = CurveVertices.size();
+ //float sampling = stroke.ComputeSampling(originalSize);
+ //stroke.Resample(sampling);
+ stroke.Resample(originalSize);
+ int newsize = stroke.strokeVerticesSize();
+ int nExtraVertex=0;
+ if(newsize < originalSize)
+ cerr << "Warning: unsufficient resampling" << endl;
+ else
+ {
+ //cout << "Oversampling" << endl;
+ nExtraVertex = newsize - originalSize;
+ if(nExtraVertex != 0)
+ cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl;
+ }
+
+ // assigns the new coordinates:
+ p=CurveVertices.begin();pend=CurveVertices.end();
+ vector<Vec2d>::iterator last = p;
+ int n=0;
+ StrokeInternal::StrokeVertexIterator it=stroke.strokeVerticesBegin(), itend=stroke.strokeVerticesEnd();
+ // while(p!=pend)
+ // {
+ // ++n;
+ // ++p;
+ // }
+ it=stroke.strokeVerticesBegin();
+ for(;
+ ((it!=itend) && (p!=pend));
+ ++it)
+ {
+ it->setX(p->x());
+ it->setY(p->y());
+ // double x = p->x();
+ // double y = p->y();
+ // cout << "x = " << x << "-" << "y = " << y << endl;
+ last = p;
+ ++p;
+ ++n;
+ }
+ stroke.UpdateLength();
+
+ // Deal with extra vertices:
+ if(nExtraVertex == 0)
+ return 0;
+
+ // nExtraVertex should stay unassigned
+ vector<StrokeAttribute> attributes;
+ vector<StrokeVertex*> verticesToRemove;
+ for(int i=0; i< nExtraVertex; ++i)
+ {
+ verticesToRemove.push_back(&(*it));
+ if(it.isEnd())
+ cout << "fucked up" << endl;
+ ++it;
+ ++n;
+ }
+ it=stroke.strokeVerticesBegin();
+ for(;
+ it!=itend;
+ ++it)
+ {
+ attributes.push_back(it->attribute());
+ }
+
+ for(vector<StrokeVertex*>::iterator vr=verticesToRemove.begin(), vrend=verticesToRemove.end();
+ vr!=vrend;
+ ++vr)
+ {
+ stroke.RemoveVertex(*vr);
+ }
+ it=stroke.strokeVerticesBegin();
+ itend=stroke.strokeVerticesEnd();
+ vector<StrokeAttribute>::iterator a=attributes.begin(), aend=attributes.end();
+ int index = 0;
+ int index1 = (int)floor((float)originalSize/2.0);
+ int index2 = index1+nExtraVertex;
+ for(;
+ (it!=itend) && (a!=aend);
+ ++it)
+ {
+ (it)->setAttribute(*a);
+ if((index <= index1)||(index>index2))
+ ++a;
+ ++index;
+ }
+ return 0;
+ }
+
+ int InflateShader::shade(Stroke& stroke) const
+ {
+ // we're computing the curvature variance of the stroke.(Combo 5)
+ // If it's too high, forget about it
+ Functions1D::Curvature2DAngleF1D fun;
+ if (fun(stroke) < 0)
+ return -1;
+ if (fun.result > _curvatureThreshold)
+ return 0;
+
+ Functions0D::VertexOrientation2DF0D ori_fun;
+ Functions0D::Curvature2DAngleF0D curv_fun;
+ Functions1D::Normal2DF1D norm_fun;
+ Interface0DIterator it=stroke.verticesBegin();
+ StrokeVertex* sv;
+ while (!it.isEnd())
+ {
+ if (ori_fun(it) < 0)
+ return -1;
+ Vec2f ntmp(ori_fun.result);
+ Vec2f n(ntmp.y(), -ntmp.x());
+ if (norm_fun(stroke) < 0)
+ return -1;
+ Vec2f strokeN(norm_fun.result);
+ if(n*strokeN < 0)
+ {
+ n[0] = -n[0];
+ n[1] = -n[1];
+ }
+ sv = dynamic_cast<StrokeVertex*>(&(*it));
+ float u=sv->u();
+ float t = 4.f*(0.25f - (u-0.5)*(u-0.5));
+ if (curv_fun(it) < 0)
+ return -1;
+ float curvature_coeff = (M_PI-curv_fun.result)/M_PI;
+ Vec2d newPoint(sv->x()+curvature_coeff*t*_amount*n.x(), sv->y()+curvature_coeff*t*_amount*n.y());
+ sv->setPoint(newPoint[0], newPoint[1]);
+ ++it;
+ }
+ stroke.UpdateLength();
+ return 0;
+ }
+
+ class CurvePiece
+ {
+ public:
+ StrokeInternal::StrokeVertexIterator _begin;
+ StrokeInternal::StrokeVertexIterator _last;
+ Vec2d A;
+ Vec2d B;
+ int size;
+ float _error;
+
+ CurvePiece(StrokeInternal::StrokeVertexIterator b, StrokeInternal::StrokeVertexIterator l, int iSize)
+ {
+ _begin = b;
+ _last = l;
+ A = Vec2d((_begin)->x(),(_begin)->y());
+ B = Vec2d((_last)->x(),(_last)->y());
+ size = iSize;
+ }
+
+ float error()
+ {
+ float maxE = 0.f;
+ for(StrokeInternal::StrokeVertexIterator it=_begin;
+ it!=_last;
+ ++it)
+ {
+ Vec2d P(it->x(), it->y());
+ float d = GeomUtils::distPointSegment(P,A,B);
+ if(d > maxE)
+ maxE = d;
+ }
+ _error = maxE;
+ return maxE;
+ }
+ //! Subdivides the curve into two pieces.
+ // The first piece is this same object (modified)
+ // the second piece is returned by the method
+ CurvePiece * subdivide()
+ {
+ StrokeInternal::StrokeVertexIterator it=_begin;
+ int actualSize = 1;
+ for(int i=0; i<size/2; ++i)
+ {
+ ++it;
+ ++actualSize;
+ }
+ CurvePiece * second = new CurvePiece(it, _last, size-actualSize+1);
+ size = actualSize;
+ _last = it;
+ B = Vec2d((_last)->x(), (_last)->y());
+ return second;
+ }
+ };
+
+ int PolygonalizationShader::shade(Stroke& stroke) const
+ {
+ vector<CurvePiece*> _pieces;
+ vector<CurvePiece*> _results;
+ vector<CurvePiece*>::iterator cp,cpend;
+
+ // Compute first approx:
+ StrokeInternal::StrokeVertexIterator a=stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator b=stroke.strokeVerticesEnd();--b;
+ int size = stroke.strokeVerticesSize();
+
+ CurvePiece * piece = new CurvePiece(a,b,size);
+ _pieces.push_back(piece);
+
+ while(!_pieces.empty())
+ {
+ piece = _pieces.back();_pieces.pop_back();
+ if(piece->error() > _error)
+ {
+ CurvePiece * second = piece->subdivide();
+ _pieces.push_back(second);
+ _pieces.push_back(piece);
+ }
+ else
+ {
+ _results.push_back(piece);
+ }
+ }
+
+ // actually modify the geometry for each piece:
+ for(cp=_results.begin(), cpend=_results.end();
+ cp!=cpend;
+ ++cp)
+ {
+ a = (*cp)->_begin;
+ b = (*cp)->_last;
+ Vec2d u = (*cp)->B-(*cp)->A;
+ Vec2d n(u[1], -u[0]);n.normalize();
+ //Vec2d n(0,0);
+ float offset = ((*cp)->_error);
+ StrokeInternal::StrokeVertexIterator v,vlast;
+ for(v=a;
+ v!=b;
+ ++v)
+ {
+ v->setPoint((*cp)->A.x()+v->u()*u.x()+n.x()*offset, (*cp)->A.y()+v->u()*u.y()+n.y()*offset);
+ }
+ // u.normalize();
+ // (*a)->setPoint((*a)->x()-u.x()*10, (*a)->y()-u.y()*10);
+ }
+ stroke.UpdateLength();
+
+ // delete stuff
+ for(cp=_results.begin(), cpend=_results.end();
+ cp!=cpend;
+ ++cp)
+ {
+ delete (*cp);
+ }
+ _results.clear();
+ return 0;
+ }
+
+ int GuidingLinesShader::shade(Stroke& stroke) const
+ {
+ Functions1D::Normal2DF1D norm_fun;
+ StrokeInternal::StrokeVertexIterator a=stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator b=stroke.strokeVerticesEnd();--b;
+ int size = stroke.strokeVerticesSize();
+ CurvePiece piece(a,b,size);
+
+ Vec2d u = piece.B-piece.A;
+ Vec2f n(u[1], -u[0]);n.normalize();
+ if (norm_fun(stroke) < 0)
+ return -1;
+ Vec2f strokeN(norm_fun.result);
+ if(n*strokeN < 0)
+ {
+ n[0] = -n[0];
+ n[1] = -n[1];
+ }
+ float offset = (piece.error())/2.f*_offset;
+ StrokeInternal::StrokeVertexIterator v=a,vend=stroke.strokeVerticesEnd();
+ for(;
+ v!=vend;
+ ++v)
+ {
+ v->setPoint(piece.A.x()+v->u()*u.x()+n.x()*offset, piece.A.y()+v->u()*u.y()+n.y()*offset);
+ }
+ stroke.UpdateLength();
+ return 0;
+ }
+
+ /////////////////////////////////////////
+ //
+ // Tip Remover
+ //
+ /////////////////////////////////////////
+
+
+ TipRemoverShader::TipRemoverShader(real tipLength)
+ : StrokeShader()
+ {
+ _tipLength = tipLength;
+ }
+
+ int
+ TipRemoverShader::shade(Stroke& stroke) const
+ {
+ int originalSize = stroke.strokeVerticesSize();
+
+ if(originalSize<4)
+ return 0;
+
+ StrokeInternal::StrokeVertexIterator v, vend;
+ vector<StrokeVertex*> verticesToRemove;
+ vector<StrokeAttribute> oldAttributes;
+ v=stroke.strokeVerticesBegin(); vend=stroke.strokeVerticesEnd();
+ for(;
+ v!=vend;
+ ++v)
+ {
+ if ((v->curvilinearAbscissa()<_tipLength) ||
+ (v->strokeLength()-v->curvilinearAbscissa()<_tipLength))
+ {
+ verticesToRemove.push_back(&(*v));
+ }
+ oldAttributes.push_back(v->attribute());
+ }
+
+ if(originalSize-verticesToRemove.size() < 2)
+ return 0;
+
+ vector<StrokeVertex*>::iterator sv=verticesToRemove.begin(), svend=verticesToRemove.end();
+ for(;
+ sv!=svend;
+ ++sv)
+ {
+ stroke.RemoveVertex((*sv));
+ }
+
+ // Resample so that our new stroke have the same
+ // number of vertices than before
+ stroke.Resample(originalSize);
+
+ if((int)stroke.strokeVerticesSize() != originalSize) //soc
+ cerr << "Warning: resampling problem" << endl;
+
+ // assign old attributes to new stroke vertices:
+ v=stroke.strokeVerticesBegin(); vend=stroke.strokeVerticesEnd();
+ vector<StrokeAttribute>::iterator a=oldAttributes.begin(), aend=oldAttributes.end();
+ //cout << "-----------------------------------------------" << endl;
+ for(;(v!=vend)&&(a!=aend);++v,++a)
+ {
+ v->setAttribute(*a);
+ //cout << "thickness = " << (*a).getThickness()[0] << "-" << (*a).getThickness()[1] << endl;
+ }
+ // we're done!
+ return 0;
+ }
+
+ int streamShader::shade(Stroke& stroke) const{
+ cout << stroke << endl;
+ return 0;
+ }
+ int fstreamShader::shade(Stroke& stroke) const{
+ _stream << stroke << endl;
+ return 0;
+ }
+
+} // end of namespace StrokeShaders
+
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
new file mode 100755
index 00000000000..a0c0a44c9b6
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
@@ -0,0 +1,890 @@
+//
+// Filename : BasicStrokeShaders.h
+// Author : Stephane Grabli
+// Purpose : Class gathering basic stroke shaders
+// Date of creation : 17/12/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BASIC_STROKE_SHADERS_H
+# define BASIC_STROKE_SHADERS_H
+
+# include "Stroke.h"
+# include "../geometry/Geom.h"
+# include "../geometry/Bezier.h"
+# include "StrokeShader.h"
+# include <fstream>
+
+using namespace std;
+using namespace Geometry;
+
+namespace StrokeShaders {
+
+ //
+ // Thickness modifiers
+ //
+ //////////////////////////////////////////////////////
+ /*! [ Thickness Shader ].
+ * Assigns an absolute constant thickness to every
+ * vertices of the Stroke.
+ */
+ class LIB_STROKE_EXPORT ConstantThicknessShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader.
+ * \param thickness
+ * The thickness that must be assigned
+ * to the stroke.
+ */
+ ConstantThicknessShader(float thickness) : StrokeShader() {
+ _thickness = thickness;
+ }
+ /*! Destructor. */
+ virtual ~ConstantThicknessShader() {}
+ /*! Returns the string "ConstantThicknessShader".*/
+ virtual string getName() const {
+ return "ConstantThicknessShader";
+ }
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+ float _thickness;
+ };
+
+ /* [ Thickness Shader ].
+ * Assigns an absolute constant external thickness to every
+ * vertices of the Stroke. The external thickness of a point
+ * is its thickness from the point to the strip border
+ * in the direction pointing outside the object the
+ * Stroke delimitates.
+ */
+ class LIB_STROKE_EXPORT ConstantExternThicknessShader : public StrokeShader
+ {
+ public:
+
+ ConstantExternThicknessShader(float thickness) : StrokeShader() {
+ _thickness = thickness;
+ }
+
+ virtual ~ConstantExternThicknessShader() {}
+
+ virtual string getName() const {
+ return "ConstantExternThicknessShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float _thickness;
+ };
+
+ /*! [ Thickness Shader ].
+ * Assigns thicknesses values such as the thickness
+ * increases from a thickness value A to a thickness value B
+ * between the first vertex to the midpoint vertex and
+ * then decreases from B to a A between this midpoint vertex
+ * and the last vertex.
+ * The thickness is linearly interpolated from A to B.
+ */
+ class LIB_STROKE_EXPORT IncreasingThicknessShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader.
+ * \param iThicknessMin
+ * The first thickness value.
+ * \param iThicknessMax
+ * The second thickness value.
+ */
+ IncreasingThicknessShader(float iThicknessMin, float iThicknessMax)
+ : StrokeShader()
+ {
+ _ThicknessMin = iThicknessMin;
+ _ThicknessMax = iThicknessMax;
+ }
+ /*! Destructor.*/
+ virtual ~IncreasingThicknessShader() {}
+
+ virtual string getName() const {
+ return "IncreasingThicknessShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float _ThicknessMin;
+ float _ThicknessMax;
+ };
+
+ /*! [ Thickness shader ].
+ * Same as previous but
+ * here we allow the user to control the ratio thickness/length so that
+ * we don't get fat short lines
+ */
+ class LIB_STROKE_EXPORT ConstrainedIncreasingThicknessShader : public StrokeShader
+ {
+ private:
+ float _ThicknessMin;
+ float _ThicknessMax;
+ float _ratio;
+ public:
+ /*! Builds the shader.
+ * \param iThicknessMin
+ * The first thickness value.
+ * \param iThicknessMax
+ * The second thickness value.
+ * \param iRatio
+ * The ration thickness/length we don't want to
+ * exceed.
+ */
+ ConstrainedIncreasingThicknessShader(float iThicknessMin, float iThicknessMax, float iRatio)
+ : StrokeShader()
+ {
+ _ThicknessMin = iThicknessMin;
+ _ThicknessMax = iThicknessMax;
+ _ratio = iRatio;
+ }
+ /*! Destructor.*/
+ virtual ~ConstrainedIncreasingThicknessShader() {}
+
+ virtual string getName() const {
+ return "ConstrainedIncreasingThicknessShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /* [ Thickness Shader ].
+ * Modifys the thickness in a relative way
+ * depending on its length.
+ */
+ class LIB_STROKE_EXPORT LengthDependingThicknessShader : public StrokeShader
+ {
+ private:
+ float _minThickness;
+ float _maxThickness;
+ // We divide the strokes in 4 categories:
+ // l > 300
+ // 100 < l < 300
+ // 50 < l < 100
+ // l < 50
+ public:
+ LengthDependingThicknessShader(float iMinThickness, float iMaxThickness)
+ : StrokeShader()
+ {
+ _minThickness = iMinThickness;
+ _maxThickness = iMaxThickness;
+ }
+ virtual ~LengthDependingThicknessShader() {}
+
+ virtual string getName() const {
+ return "LengthDependingThicknessShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Thickness Shader ].
+ * Applys a pattern (texture) to vary thickness.
+ * The new thicknesses are the result of the multiplication
+ * of the pattern and the original thickness
+ */
+ class LIB_STROKE_EXPORT ThicknessVariationPatternShader : public StrokeShader
+ {
+ public:
+
+ /*! Builds the shader.
+ * \param pattern_name
+ * The texture file name.
+ * \param iMinThickness
+ * The minimum thickness we don't want to exceed.
+ * \param iMaxThickness
+ * The maximum thickness we don't want to exceed.
+ * \param stretch
+ * Tells whether the pattern texture must
+ * be stretched or repeted to fit the stroke.
+ */
+ ThicknessVariationPatternShader(const string pattern_name,
+ float iMinThickness = 1.f,
+ float iMaxThickness = 5.f,
+ bool stretch = true);
+ /*! Destructor.*/
+ virtual ~ThicknessVariationPatternShader()
+ {
+ if(0 != _aThickness)
+ {
+ delete [] _aThickness;
+ _aThickness = 0;
+ }
+ }
+
+ virtual string getName() const {
+ return "ThicknessVariationPatternShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float* _aThickness; // array of thickness values, in % of the max (i.e comprised between 0 and 1)
+ unsigned _size;
+ float _minThickness;
+ float _maxThickness;
+ bool _stretch;
+ };
+
+ /*! [ Thickness Shader ].
+ * Adds some noise to the stroke thickness.
+ * \see \htmlonly <a href=noise/noise.html>noise/noise.html</a>\endhtmlonly
+ */
+ class LIB_STROKE_EXPORT ThicknessNoiseShader : public StrokeShader
+ {
+ private:
+ float _amplitude;
+ float _scale;
+ public:
+ ThicknessNoiseShader();
+ /*! Builds a Thickness Noise Shader
+ * \param iAmplitude
+ * The amplitude of the noise signal
+ * \param iPeriod
+ * The period of the noise signal
+ */
+ ThicknessNoiseShader(float iAmplitude, float iPeriod);
+
+ virtual string getName() const {
+ return "ThicknessNoiseShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+
+ //
+ // Color shaders
+ //
+ /////////////////////////////////////////////////////////
+ /*! [ Color Shader ].
+ * Assigns a constant color to every vertices of the Stroke.
+ */
+ class LIB_STROKE_EXPORT ConstantColorShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader from a user-specified color.
+ * \param iR
+ * The red component
+ * \param iG
+ * The green component
+ * \param iB
+ * The blue component
+ * \param iAlpha
+ * The alpha value
+ */
+ ConstantColorShader(float iR, float iG, float iB, float iAlpha=1.f)
+ : StrokeShader()
+ {
+ _color[0] = iR;
+ _color[1] = iG;
+ _color[2] = iB;
+ _color[3] = iAlpha;
+ }
+
+ virtual string getName() const {
+ return "ConstantColorShader";
+ }
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float _color[4];
+ };
+
+ /*! [ Color Shader ].
+ * Assigns a varying color to the stroke.
+ * The user specifies 2 colors A and B. The stroke
+ * color will change linearly from A to B between the
+ * first and the last vertex.
+ */
+ class LIB_STROKE_EXPORT IncreasingColorShader : public StrokeShader
+ {
+ private:
+ float _colorMin[4];
+ float _colorMax[4];
+ public:
+ /*! Builds the shader from 2 user-specified colors.
+ * \param iRm
+ * The first color red component
+ * \param iGm
+ * The first color green component
+ * \param iBm
+ * The first color blue component
+ * \param iAlpham
+ * The first color alpha value
+ * \param iRM
+ * The second color red component
+ * \param iGM
+ * The second color green component
+ * \param iBM
+ * The second color blue component
+ * \param iAlphaM
+ * The second color alpha value
+ */
+ IncreasingColorShader(float iRm, float iGm, float iBm, float iAlpham,
+ float iRM, float iGM, float iBM, float iAlphaM)
+ : StrokeShader()
+ {
+ _colorMin[0] = iRm;
+ _colorMin[1] = iGm;
+ _colorMin[2] = iBm;
+ _colorMin[3] = iAlpham;
+
+ _colorMax[0] = iRM;
+ _colorMax[1] = iGM;
+ _colorMax[2] = iBM;
+ _colorMax[3] = iAlphaM;
+ }
+
+ virtual string getName() const {
+ return "IncreasingColorShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Color Shader ].
+ * Applys a pattern to vary original color.
+ * The new color is the result of the multiplication
+ * of the pattern and the original color
+ */
+ class LIB_STROKE_EXPORT ColorVariationPatternShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader from the pattern texture file name.
+ * \param pattern_name
+ * The file name of the texture file to use as pattern
+ * \param stretch
+ * Tells whether the texture must be strecthed or repeted
+ * to fit the stroke.
+ */
+ ColorVariationPatternShader(const string pattern_name, bool stretch = true);
+ /*! Destructor */
+ virtual ~ColorVariationPatternShader()
+ {
+ if(0 != _aVariation)
+ {
+ delete [] _aVariation;
+ _aVariation = 0;
+ }
+ }
+
+ virtual string getName() const {
+ return "ColorVariationPatternShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float* _aVariation; // array of coef values, in % of the max (i.e comprised between 0 and 1)
+ unsigned _size;
+ bool _stretch;
+ };
+
+ /* [ Color Shader ].
+ * Assigns a color to the stroke depending
+ * on the material of the shape to which ot belongs
+ * to. (Disney shader)
+ */
+ class LIB_STROKE_EXPORT MaterialColorShader : public StrokeShader
+ {
+ private:
+ float _coefficient;
+ public:
+ MaterialColorShader(float coeff=1.f)
+ : StrokeShader()
+ {_coefficient=coeff;}
+
+ virtual string getName() const {
+ return "MaterialColorShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ class LIB_STROKE_EXPORT CalligraphicColorShader : public StrokeShader
+ {
+ private:
+ int _textureId;
+ Vec2d _orientation;
+ public:
+ CalligraphicColorShader(
+ const Vec2d &iOrientation)
+ : StrokeShader()
+ {
+ _orientation=iOrientation;
+ _orientation.normalize();
+ }
+
+ virtual string getName() const {
+ return "CalligraphicColorShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+
+ };
+
+ /*! [ Color Shader ].
+ * Shader to add noise to the stroke colors.
+ */
+ class LIB_STROKE_EXPORT ColorNoiseShader : public StrokeShader
+ {
+ private:
+ float _amplitude;
+ float _scale;
+
+ public:
+ ColorNoiseShader();
+ /*! Builds a Color Noise Shader
+ * \param iAmplitude
+ * The amplitude of the noise signal
+ * \param iPeriod
+ * The period of the noise signal
+ */
+ ColorNoiseShader(float iAmplitude, float iPeriod);
+
+ virtual string getName() const {
+ return "ColorNoiseShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ //
+ // Texture Shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ /*! [ Texture Shader ].
+ * Assigns a texture to the stroke in order to simulate
+ * its marks system. This shader takes as input an integer value
+ * telling which texture and blending mode to use among a set of
+ * predefined textures.
+ * Here are the different presets:
+ * 0) -> /brushes/charcoalAlpha.bmp, HUMID_MEDIUM
+ * 1) -> /brushes/washbrushAlpha.bmp, HUMID_MEDIUM
+ * 2) -> /brushes/oil.bmp, HUMID_MEDIUM
+ * 3) -> /brushes/oilnoblend.bmp, HUMID_MEDIUM
+ * 4) -> /brushes/charcoalAlpha.bmp, DRY_MEDIUM
+ * 5) -> /brushes/washbrushAlpha.bmp, DRY_MEDIUM
+ * 6) -> /brushes/opaqueDryBrushAlpha.bmp, OPAQUE_MEDIUM
+ * 7) -> /brushes/opaqueBrushAlpha.bmp, Stroke::OPAQUE_MEDIUM
+ * Any other value will lead to the following preset:
+ * default) -> /brushes/smoothAlpha.bmp, OPAQUE_MEDIUM.
+ */
+ class LIB_STROKE_EXPORT TextureAssignerShader : public StrokeShader // FIXME
+ {
+ private:
+ int _textureId;
+ public:
+ /*! Builds the shader.
+ * \param id
+ * The number of the preset to use.
+ */
+ TextureAssignerShader(int id)
+ : StrokeShader()
+ {
+ _textureId = id;
+ }
+
+ virtual string getName() const {
+ return "TextureAssignerShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+
+ };
+ /*! [ Texture Shader ].
+ * Assigns a texture and a blending mode to the stroke
+ * in order to simulate its marks system.
+ */
+ class LIB_STROKE_EXPORT StrokeTextureShader : public StrokeShader
+ {
+ private:
+ string _texturePath;
+ Stroke::MediumType _mediumType;
+ bool _tips; // 0 or 1
+
+ public:
+ /*! Builds the shader from the texture file name and the blending mode to use.
+ * \param textureFile
+ * The the texture file name.
+ * \attention The textures must be placed in the $FREESTYLE_DIR/data/textures/brushes
+ * directory.
+ * \param mediumType
+ * The medium type and therefore, the blending mode that must
+ * be used for the rendering of this stroke.
+ * \param iTips
+ * Tells whether the texture includes tips or not.
+ * If it is the case, the texture image must respect the following
+ * format:
+ * \verbatim
+ * __________
+ * | |
+ * | A |
+ * |__________|
+ * | | |
+ * | B | C |
+ * |_____|____|
+ *
+ * \endverbatim
+ * - A : The stroke's corpus texture
+ * - B : The stroke's left extremity texture
+ * - C : The stroke's right extremity texture
+ */
+ StrokeTextureShader(const string textureFile, Stroke::MediumType mediumType = Stroke::OPAQUE_MEDIUM, bool iTips = false)
+ : StrokeShader()
+ {
+ _texturePath = textureFile;
+ _mediumType = mediumType;
+ _tips = iTips;
+ }
+
+ virtual string getName() const {
+ return "StrokeTextureShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+
+ };
+
+
+ //
+ // Geometry Shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ /*! [ Geometry Shader ].
+ * Stretches the stroke at its two extremities and following the
+ * respective directions: v(1)v(0) and v(n-1)v(n).
+ */
+ class LIB_STROKE_EXPORT BackboneStretcherShader : public StrokeShader
+ {
+ private:
+ float _amount;
+ public:
+ /*! Builds the shader.
+ * \param iAmount
+ * The stretching amount value.
+ */
+ BackboneStretcherShader(float iAmount=2.f)
+ : StrokeShader()
+ {
+ _amount = iAmount;
+ }
+
+ virtual string getName() const {
+ return "BackboneStretcherShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Geometry Shader. ]
+ * Resamples the stroke.
+ * @see Stroke::Resample(float).
+ */
+ class LIB_STROKE_EXPORT SamplingShader: public StrokeShader
+ {
+ private:
+ float _sampling;
+ public:
+ /*! Builds the shader.
+ * \param sampling
+ * The sampling to use for the
+ * stroke resampling
+ */
+ SamplingShader(float sampling)
+ : StrokeShader()
+ {
+ _sampling = sampling;
+ }
+
+ virtual string getName() const {
+ return "SamplingShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+
+ class LIB_STROKE_EXPORT ExternalContourStretcherShader : public StrokeShader
+ {
+ private:
+ float _amount;
+ public:
+ ExternalContourStretcherShader(float iAmount=2.f)
+ : StrokeShader()
+ {
+ _amount = iAmount;
+ }
+
+ virtual string getName() const {
+ return "ExternalContourStretcherShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ // B-Spline stroke shader
+ class LIB_STROKE_EXPORT BSplineShader: public StrokeShader
+ {
+ public:
+ BSplineShader()
+ : StrokeShader()
+ {}
+
+ virtual string getName() const {
+ return "BSplineShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+ };
+
+
+ // Bezier curve stroke shader
+ /*! [ Geometry Shader ].
+ * Transforms the stroke backbone geometry
+ * so that it corresponds to a Bezier Curve
+ * approximation of the original backbone geometry.
+ * @see \htmlonly <a href=bezier/bezier.html>bezier/bezier.html</a> \endhtmlonly
+ */
+ class LIB_STROKE_EXPORT BezierCurveShader : public StrokeShader
+ {
+ private:
+ float _error;
+ public:
+ /*! Builds the shader.
+ * \param error
+ * The error we're allowing for the approximation.
+ * This error is the max distance allowed between
+ * the new curve and the original geometry.
+ */
+ BezierCurveShader(float error = 4.0)
+ : StrokeShader()
+ {_error=error;}
+
+ virtual string getName() const {
+ return "BezierCurveShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /* Shader to inflate the curves. It keeps the extreme
+ * points positions and moves the other ones along
+ * the 2D normal. The displacement value is proportional
+ * to the 2d curvature at the considered point (the higher
+ * the curvature, the smaller the displacement) and to a value
+ * specified by the user.
+ */
+ class LIB_STROKE_EXPORT InflateShader : public StrokeShader
+ {
+ private:
+ float _amount;
+ float _curvatureThreshold;
+ public:
+ /*! Builds an inflate shader
+ * \param iAmount
+ * A multiplicative coefficient that
+ * acts on the amount and direction of displacement
+ * \param iThreshold
+ * The curves having a 2d curvature > iThreshold
+ * at one of their points is not inflated
+ */
+ InflateShader(float iAmount,float iThreshold)
+ : StrokeShader()
+ {
+ _amount = iAmount;
+ _curvatureThreshold = iThreshold;
+ }
+
+ virtual string getName() const {
+ return "InflateShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Geometry Shader ].
+ * Shader to modify the Stroke geometry so that
+ * it looks more "polygonal".
+ * The basic idea is to start from the
+ * minimal stroke approximation consisting in
+ * a line joining the first vertex to the last one and
+ * to subdivide using the original stroke vertices
+ * until a certain error is reached.
+ */
+ class LIB_STROKE_EXPORT PolygonalizationShader : public StrokeShader
+ {
+ private:
+ float _error;
+ public:
+ /*! Builds the shader.
+ * \param iError
+ * The error we want our polygonal approximation
+ * to have with respect to the original geometry.
+ * The smaller, the closer the new stroke to
+ * the orinal one.
+ * This error corresponds to the maximum distance
+ * between the new stroke and the old one.
+ */
+ PolygonalizationShader(float iError) : StrokeShader()
+ {_error = iError;}
+
+ virtual string getName() const {
+ return "PolygonalizationShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+
+ /*! [ Geometry Shader ].
+ * Shader to modify the Stroke geometry so that
+ * it corresponds to its main direction line.
+ * This shader must be used together with the
+ * splitting operator using the curvature criterion.
+ * Indeed, the precision of the approximation
+ * will depend on the size of the stroke's pieces.
+ * The bigger the pieces, the rougher the approximation.
+ */
+ class LIB_STROKE_EXPORT GuidingLinesShader : public StrokeShader
+ {
+ private:
+ float _offset;
+ public:
+ /*! Builds a Guiding Lines shader
+ * \param iOffset
+ * The line that replaces the stroke
+ * is initially in the middle
+ * of the initial stroke "bbox".
+ * iOffset is the value of the displacement
+ * which is applied to this line along its
+ * normal.
+ */
+ GuidingLinesShader(float iOffset) : StrokeShader()
+ {_offset = iOffset;}
+
+ virtual string getName() const {
+ return "GuidingLinesShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Geometry Shader ].
+ * Removes the stroke's extremities.
+ */
+ class LIB_STROKE_EXPORT TipRemoverShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader.
+ * \param tipLength
+ * The length of the piece of stroke
+ * we want to remove at each extremity.
+ */
+ TipRemoverShader (real tipLength);
+ /*! Destructor. */
+ virtual ~TipRemoverShader () {}
+ /*! The shading method */
+ virtual string getName() const {
+ return "TipRemoverShader";
+ }
+
+ virtual int shade(Stroke &stroke) const;
+
+ protected:
+
+ real _tipLength;
+ };
+
+ /*! [ output Shader ].
+ * streams the Stroke
+ */
+ class LIB_STROKE_EXPORT streamShader : public StrokeShader
+ {
+ public:
+ /*! Destructor. */
+ virtual ~streamShader() {}
+ /*! Returns the string "streamShader".*/
+ virtual string getName() const {
+ return "streamShader";
+ }
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ output Shader ].
+ * streams the Stroke in a file
+ */
+ class LIB_STROKE_EXPORT fstreamShader : public StrokeShader
+ {
+ protected:
+ mutable ofstream _stream;
+ public:
+ /*! Builds the shader from the output file name */
+ fstreamShader(const char *iFileName) : StrokeShader(){
+ _stream .open(iFileName);
+ if(!_stream.is_open()){
+ cout << "couldn't open file " << iFileName << endl;
+ }
+ }
+ /*! Destructor. */
+ virtual ~fstreamShader() {_stream.close();}
+ /*! Returns the string "fstreamShader".*/
+ virtual string getName() const {
+ return "fstreamShader";
+ }
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+} // end of namespace StrokeShaders
+
+#endif // BASIC_STROKE_SHADERS_H
diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp
new file mode 100755
index 00000000000..f2cfe6a855f
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Canvas.cpp
@@ -0,0 +1,455 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "StrokeRenderer.h"
+#include <vector>
+#include "../system/FreestyleConfig.h"
+#include "../system/TimeStamp.h"
+#include "../system/PseudoNoise.h"
+#include "Canvas.h"
+#include "../image/Image.h"
+#include "../image/GaussianFilter.h"
+#include "../image/ImagePyramid.h"
+#include "../view_map/SteerableViewMap.h"
+#include "StyleModule.h"
+
+//soc #include <qimage.h>
+//soc #include <QString>
+#include <sstream>
+
+extern "C" {
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+}
+
+using namespace std;
+
+LIB_STROKE_EXPORT
+Canvas * Canvas::_pInstance = 0;
+
+LIB_STROKE_EXPORT
+const char * Canvas::_MapsPath = 0;
+
+using namespace std;
+
+Canvas::Canvas()
+{
+ _SelectedFEdge = 0;
+ _pInstance = this;
+ PseudoNoise::init(42);
+ _Renderer = 0;
+ _current_sm = NULL;
+ _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP-1);
+ _basic = false;
+}
+
+Canvas::Canvas(const Canvas& iBrother)
+{
+ _SelectedFEdge = iBrother._SelectedFEdge;
+ _pInstance = this;
+ PseudoNoise::init(42);
+ _Renderer = iBrother._Renderer;
+ _current_sm = iBrother._current_sm;
+ _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap));
+ _basic = iBrother._basic;
+}
+
+Canvas::~Canvas()
+{
+ _pInstance = 0;
+
+ Clear();
+ if(_Renderer)
+ {
+ delete _Renderer;
+ _Renderer = 0;
+ }
+ // FIXME: think about an easy control
+ // for the maps memory management...
+ if(!_maps.empty()){
+ for(mapsMap::iterator m=_maps.begin(), mend=_maps.end();
+ m!=mend;
+ ++m){
+ delete ((*m).second);
+ }
+ _maps.clear();
+ }
+ if(_steerableViewMap)
+ delete _steerableViewMap;
+}
+
+void Canvas::preDraw() {}
+
+void Canvas::Draw()
+{
+ if(_StyleModules.empty())
+ return;
+ preDraw();
+ TimeStamp *timestamp = TimeStamp::instance();
+
+ for(unsigned i = 0; i < _StyleModules.size(); i++) {
+ _current_sm = _StyleModules[i];
+
+ if (i < _Layers.size() && _Layers[i])
+ delete _Layers[i];
+
+ _Layers[i] = _StyleModules[i]->execute();
+ if (!_Layers[i])
+ continue;
+
+ stroke_count += _Layers[i]->strokes_size();
+
+ timestamp->increment();
+ }
+ postDraw();
+}
+
+void Canvas::postDraw()
+{
+ update();
+}
+
+
+void Canvas::Clear()
+{
+ if(!_Layers.empty()) {
+ for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
+ sl != slend;
+ ++sl)
+ if (*sl)
+ delete (*sl);
+ _Layers.clear();
+ }
+
+ if(!_StyleModules.empty()) {
+ for (deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
+ s != send;
+ ++s)
+ if (*s)
+ delete (*s);
+ _StyleModules.clear();
+ }
+ if(_steerableViewMap)
+ _steerableViewMap->Reset();
+
+ stroke_count = 0;
+}
+
+void Canvas::Erase()
+{
+ if(!_Layers.empty())
+ {
+ for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
+ sl != slend;
+ ++sl)
+ if (*sl)
+ (*sl)->clear();
+ }
+ if(_steerableViewMap)
+ _steerableViewMap->Reset();
+ update();
+
+stroke_count = 0;
+}
+
+void Canvas::PushBackStyleModule(StyleModule *iStyleModule) {
+ StrokeLayer* layer = new StrokeLayer();
+ _StyleModules.push_back(iStyleModule);
+ _Layers.push_back(layer);
+}
+
+void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) {
+ unsigned size = _StyleModules.size();
+ StrokeLayer* layer = new StrokeLayer();
+ if((_StyleModules.empty()) || (index == size)) {
+ _StyleModules.push_back(iStyleModule);
+ _Layers.push_back(layer);
+ return;
+ }
+ _StyleModules.insert(_StyleModules.begin() + index, iStyleModule);
+ _Layers.insert(_Layers.begin()+index, layer);
+}
+
+void Canvas::RemoveStyleModule(unsigned index)
+{
+ unsigned i=0;
+ if (!_StyleModules.empty())
+ {
+ for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
+ s!=send;
+ ++s)
+ {
+ if(i == index)
+ {
+ // remove shader
+ if (*s)
+ delete *s;
+ _StyleModules.erase(s);
+ break;
+ }
+ ++i;
+ }
+ }
+ i=0;
+ if(!_Layers.empty())
+ {
+ for(deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
+ sl!=slend;
+ ++sl)
+ {
+ if(i == index)
+ {
+ // remove layer
+ if (*sl)
+ delete *sl;
+ _Layers.erase(sl);
+ break;
+ }
+ ++i;
+ }
+ }
+}
+
+
+void Canvas::SwapStyleModules(unsigned i1, unsigned i2)
+{
+ StyleModule* tmp;
+ tmp = _StyleModules[i1];
+ _StyleModules[i1] = _StyleModules[i2];
+ _StyleModules[i2] = tmp;
+
+ StrokeLayer* tmp2;
+ tmp2 = _Layers[i1];
+ _Layers[i1] = _Layers[i2];
+ _Layers[i2] = tmp2;
+}
+
+void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule)
+{
+ unsigned i=0;
+ for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
+ s != send;
+ ++s)
+ {
+ if(i == index)
+ {
+ if (*s)
+ delete *s;
+ *s = iStyleModule;
+ break;
+ }
+ ++i;
+ }
+}
+
+void Canvas::setVisible(unsigned index, bool iVisible) {
+ _StyleModules[index]->setDisplayed(iVisible);
+}
+
+void Canvas::setModified(unsigned index, bool iMod)
+{
+ _StyleModules[index]->setModified(iMod);
+}
+
+void Canvas::resetModified(bool iMod/* =false */)
+{
+ unsigned size = _StyleModules.size();
+ for(unsigned i = 0; i < size; ++i)
+ setModified(i,iMod);
+}
+
+void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) {
+ unsigned size = _StyleModules.size();
+
+ for(unsigned i = index; i < size; ++i)
+ if (_StyleModules[i]->getCausal())
+ vec.push_back(i);
+}
+
+void Canvas::Render(const StrokeRenderer *iRenderer)
+{
+ for (unsigned i = 0; i < _StyleModules.size(); i++) {
+ if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
+ continue;
+ _Layers[i]->Render(iRenderer);
+ }
+}
+
+void Canvas::RenderBasic(const StrokeRenderer *iRenderer)
+
+{
+ for (unsigned i = 0; i < _StyleModules.size(); i++) {
+ if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
+ continue;
+ _Layers[i]->RenderBasic(iRenderer);
+ }
+}
+
+void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma){
+ // check whether this map was already loaded:
+ if(!_maps.empty()){
+ mapsMap::iterator m = _maps.find(iMapName);
+ if(m!=_maps.end()){
+ // lazy check for size changes
+ ImagePyramid * pyramid = (*m).second;
+ if((pyramid->width() != width()) || (pyramid->height() != height())){
+ delete pyramid;
+ }else{
+ return;
+ }
+ }
+ }
+ string filePath;
+ if(_MapsPath){
+ filePath = _MapsPath;
+ filePath += iFileName;
+ }else{
+ filePath = iFileName;
+ }
+
+ //soc
+ // QImage *qimg;
+ // QImage newMap(filePath.c_str());
+ // if(newMap.isNull()){
+ // cout << "Could not load image file " << filePath << endl;
+ // return;
+ // }
+ // qimg = &newMap;
+ /* OCIO_TODO: support different input color space */
+ ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL);
+ if( qimg == 0 ){
+ cout << "Could not load image file " << filePath << endl;
+ return;
+ }
+
+ // soc
+ //resize
+ // QImage scaledImg;
+ // if((newMap.width()!=width()) || (newMap.height()!=height())){
+ // scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ // qimg = &scaledImg;
+ // }
+ ImBuf *scaledImg;
+ if( ( qimg->x != width() ) || ( qimg->y != height() ) ){
+ scaledImg = IMB_dupImBuf(qimg);
+ IMB_scaleImBuf(scaledImg, width(), height());
+ }
+
+
+ // deal with color image
+ // if(newMap->depth() != 8){
+ // int w = newMap->width();
+ // int h = newMap->height();
+ // QImage *tmp = new QImage(w, h, 8);
+ // for(unsigned y=0;y<h;++y){
+ // for(unsigned x=0;x<w;++x){
+ // int c = qGray(newMap->pixel(x,y));
+ // tmp->setPixel(x,y,c);
+ // }
+ // }
+ // delete newMap;
+ // newMap = tmp;
+ // }
+
+ int x,y;
+ int w = qimg->x;
+ int h = qimg->y;
+int rowbytes = w*4;
+ GrayImage tmp(w,h);
+ char *pix;
+
+ for(y=0; y<h;++y){
+ for(x=0;x<w;++x){
+ pix = (char*)qimg->rect + y*rowbytes + x*4;
+ float c = (pix[0]*11 + pix[1]*16 + pix[2]*5)/32;
+ tmp.setPixel(x,y,c);
+ }
+ }
+
+ // GrayImage blur(w,h);
+ // GaussianFilter gf(4.f);
+ // //int bound = gf.getBound();
+ // for(y=0; y<h;++y){
+ // for(x=0;x<w;++x){
+ // int c = gf.getSmoothedPixel<GrayImage>(&tmp, x,y);
+ // blur.setPixel(x,y,c);
+ // }
+ // }
+
+ GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma);
+ int ow = pyramid->width(0);
+ int oh = pyramid->height(0);
+ string base(iMapName); //soc
+ for(int i=0; i<pyramid->getNumberOfLevels(); ++i){
+ // save each image:
+ // w = pyramid.width(i);
+ // h = pyramid.height(i);
+
+ //soc QImage qtmp(ow, oh, QImage::Format_RGB32);
+ ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect);
+
+//int k = (1<<i);
+ for(y=0;y<oh;++y){
+ for(x=0;x<ow;++x){
+ int c = pyramid->pixel(x,y,i);//255*pyramid->pixel(x,y,i);
+ //soc qtmp.setPixel(x,y,qRgb(c,c,c));
+ pix = (char*)qtmp->rect + y*rowbytes + x*4;
+ pix[0] = pix [1] = pix[2] = c;
+ }
+ }
+ //soc qtmp.save(base+QString::number(i)+".bmp", "BMP");
+ stringstream filename;
+ filename << base;
+ filename << i << ".bmp";
+ qtmp->ftype= BMP;
+ IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0);
+
+ }
+ // QImage *qtmp = new QImage(w, h, 32);
+ // for(y=0;y<h;++y){
+ // for(x=0;x<w;++x){
+ // int c = (int)blur.pixel(x,y);
+ // qtmp->setPixel(x,y,qRgb(c,c,c));
+ // }
+ // }
+ // delete newMap;
+ // newMap = qtmp;
+ //
+ _maps[iMapName] = pyramid;
+ // newMap->save("toto.bmp", "BMP");
+}
+
+float Canvas::readMapPixel(const char *iMapName, int level, int x, int y){
+ if(_maps.empty()){
+ cout << "readMapPixel warning: no map was loaded "<< endl;
+ return -1;
+ }
+ mapsMap::iterator m = _maps.find(iMapName);
+ if(m==_maps.end()){
+ cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl;
+ return -1;
+ }
+ ImagePyramid *pyramid = (*m).second;
+ if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height()))
+ return 0;
+
+ return pyramid->pixel(x,height()-1-y,level);
+}
diff --git a/source/blender/freestyle/intern/stroke/Canvas.h b/source/blender/freestyle/intern/stroke/Canvas.h
new file mode 100755
index 00000000000..707455c87f6
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Canvas.h
@@ -0,0 +1,196 @@
+//
+// Filename : Canvas.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a canvas designed to draw style modules
+// Date of creation : 20/10/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef CANVAS_H
+# define CANVAS_H
+
+# include <cstring>
+# include <deque>
+# include <vector>
+# include <map>
+# include "../system/FreestyleConfig.h"
+# include "StrokeLayer.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+
+using namespace Geometry;
+
+struct ltstr
+{
+ bool operator()(const char* s1, const char* s2) const
+ {
+ return strcmp(s1, s2) < 0;
+ }
+};
+
+class InformationMap;
+class StrokeRenderer;
+class ViewMap;
+class ViewEdge;
+class FEdge;
+class RGBImage;
+class GrayImage;
+class QImage;
+class ImagePyramid;
+class SteerableViewMap;
+class StyleModule;
+
+/*! Class to define the canvas on which strokes are drawn.
+ * It's used to store state information about the drawing.
+ */
+class LIB_STROKE_EXPORT Canvas
+{
+public:
+ /*! Returns a pointer on the Canvas instance */
+ static Canvas * getInstance() {return _pInstance;}
+ typedef std::map<const char*, ImagePyramid*, ltstr> mapsMap ;
+ static const int NB_STEERABLE_VIEWMAP = 5;
+protected:
+ static Canvas *_pInstance;
+ std::deque<StrokeLayer*> _Layers;
+ std::deque<StyleModule*> _StyleModules;
+ FEdge *_SelectedFEdge;
+
+ StrokeRenderer *_Renderer;
+ StyleModule* _current_sm;
+ mapsMap _maps;
+ static const char * _MapsPath;
+ SteerableViewMap *_steerableViewMap;
+ bool _basic;
+
+public:
+ /* Builds the Canvas */
+ Canvas();
+ /* Copy constructor */
+ Canvas(const Canvas& iBrother);
+ /* Destructor */
+ virtual ~Canvas();
+
+ /* operations that need to be done before a draw */
+ virtual void preDraw();
+
+ /* Draw the canvas using the current shader */
+ virtual void Draw();
+
+ /* operations that need to be done after a draw */
+ virtual void postDraw();
+
+ /* Renders the created strokes */
+ virtual void Render(const StrokeRenderer *iRenderer);
+ /* Basic Renders the created strokes */
+ virtual void RenderBasic(const StrokeRenderer *iRenderer);
+ /* Renders a stroke */
+ virtual void RenderStroke(Stroke *iStroke) = 0;
+
+ /* init the canvas */
+ virtual void init() = 0;
+
+ /* Clears the Canvas (shaders stack, layers stack...)*/
+ void Clear();
+
+ /* Erases the layers */
+ virtual void Erase();
+
+ /* Reads a pixel area from the canvas */
+ virtual void readColorPixels(int x, int y,int w, int h, RGBImage& oImage) const = 0;
+ /* Reads a depth pixel area from the canvas */
+ virtual void readDepthPixels(int x, int y,int w, int h, GrayImage& oImage) const = 0;
+
+ /* update the canvas (display) */
+ virtual void update() = 0;
+
+ /* checks whether the canvas is empty or not */
+ bool isEmpty() const {return (_Layers.empty());}
+
+ /* Maps management */
+ /*! Loads an image map. The map will be scaled
+ * (without preserving the ratio in order
+ * to fit the actual canvas size.)
+ * The image must be a gray values image...
+ * \param iFileName
+ * The name of the image file
+ * \param iMapName
+ * The name that will be used to access
+ * this image
+ * \param iNbLevels
+ * The number of levels in the map pyramid. (default = 4).
+ * If iNbLevels == 0, the complete pyramid is built.
+ */
+ void loadMap(const char *iFileName, const char *iMapName, unsigned iNbLevels=4, float iSigma = 1.f);
+
+ /*! Reads a pixel value in a map.
+ * Returns a value between 0 and 1.
+ * \param iMapName
+ * The name of the map
+ * \param level
+ * The level of the pyramid from which the pixel must
+ * be read.
+ * \param x
+ * The abscissa of the desired pixel specified in level0 coordinate
+ * system. The origin is the lower left corner.
+ * \param y
+ * The ordinate of the desired pixel specified in level0 coordinate
+ * system. The origin is the lower left corner.
+ */
+ float readMapPixel(const char *iMapName, int level, int x, int y);
+
+ /*! Sets the steerable viewmap */
+ void loadSteerableViewMap(SteerableViewMap * iSVM) {_steerableViewMap = iSVM;}
+
+ /*! Returns the steerable VM */
+ SteerableViewMap * getSteerableViewMap() {return _steerableViewMap;}
+
+ /*! accessors */
+ inline const FEdge * selectedFEdge() const {return _SelectedFEdge;}
+ inline FEdge * selectedFEdge() {return _SelectedFEdge;}
+ virtual int width() const = 0;
+ virtual int height() const = 0;
+ virtual BBox<Vec3r> scene3DBBox() const = 0;
+ inline const StrokeRenderer * renderer() const {return _Renderer;}
+ inline StyleModule* getCurrentStyleModule() { return _current_sm; }
+ virtual bool getRecordFlag() const {return false;}
+ int stroke_count;
+
+ /*! modifiers */
+ inline void setSelectedFEdge(FEdge *iFEdge) {_SelectedFEdge = iFEdge;}
+ /*! inserts a shader at pos index+1 */
+ void PushBackStyleModule(StyleModule *iStyleModule);
+ void InsertStyleModule(unsigned index, StyleModule *iStyleModule);
+ void RemoveStyleModule(unsigned index);
+ void SwapStyleModules(unsigned i1, unsigned i2);
+ void ReplaceStyleModule(unsigned index, StyleModule *iStyleModule);
+ void setVisible(unsigned index, bool iVisible) ;
+ //inline void setDensityMap(InformationMap<RGBImage>* iMap) {_DensityMap = iMap;}
+ inline void AddLayer(StrokeLayer *iLayer) {_Layers.push_back(iLayer);}
+ void resetModified(bool iMod=false);
+ void causalStyleModules(std::vector<unsigned>& vec, unsigned index = 0);
+ void setModified(unsigned index, bool b);
+};
+
+#endif // CANVAS_H
diff --git a/source/blender/freestyle/intern/stroke/Chain.cpp b/source/blender/freestyle/intern/stroke/Chain.cpp
new file mode 100755
index 00000000000..bf61a3b32cb
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Chain.cpp
@@ -0,0 +1,151 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Chain.h"
+#include "../view_map/ViewMapIterators.h"
+#include "../view_map/ViewMapAdvancedIterators.h"
+
+void Chain::push_viewedge_back(ViewEdge *iViewEdge, bool orientation)
+{
+ ViewEdge::vertex_iterator v;
+ ViewEdge::vertex_iterator vend;
+ ViewEdge::vertex_iterator vfirst;
+ Vec3r previous, current;
+ if(true == orientation)
+ {
+ v=iViewEdge->vertices_begin();
+ vfirst = v;
+ vend=iViewEdge->vertices_end();
+ }
+ else
+ {
+ v=iViewEdge->vertices_last();
+ vfirst = v;
+ vend=iViewEdge->vertices_end();
+ }
+
+ if(!_Vertices.empty())
+ {
+ previous = _Vertices.back()->point2d();
+ if(orientation)
+ ++v;
+ else
+ --v;
+ // Ensure the continuity of underlying FEdges
+ CurvePoint *cp = _Vertices.back(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f);
+ SVertex *sv_first = (*vfirst);
+ FEdge *fe = _fedgeB->duplicate();
+ fe->setVertexB(sv_first);
+ fe->vertexA()->shape()->AddEdge(fe);
+ fe->vertexA()->AddFEdge(fe);
+ fe->vertexB()->AddFEdge(fe);
+ cp->setA(sv_first);
+ }
+ else
+ previous = (*v)->point2d();
+ do{
+ current = (*v)->point2d();
+ Curve::push_vertex_back(*v);
+ //_Length += (current-previous).norm();
+ previous = current;
+ if(orientation)
+ ++v;
+ else
+ --v;
+ }while((v!=vend) && (v!=vfirst));
+
+ if(v==vfirst)
+ {
+ //Add last one:
+ current = (*v)->point2d();
+ Curve::push_vertex_back(*v);
+ //_Length += (current-previous).norm();
+ }
+
+ _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA();
+}
+
+void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation)
+{
+ orientation = !orientation;
+ ViewEdge::vertex_iterator v;
+ ViewEdge::vertex_iterator vend;
+ ViewEdge::vertex_iterator vfirst;
+ Vec3r previous, current;
+ if(true == orientation)
+ {
+ v=iViewEdge->vertices_begin();
+ vfirst = v;
+ vend=iViewEdge->vertices_end();
+ }
+ else
+ {
+ v=iViewEdge->vertices_last();
+ vfirst = v;
+ vend=iViewEdge->vertices_end();
+ }
+
+ if(!_Vertices.empty())
+ {
+ previous = _Vertices.front()->point2d();
+ if(orientation)
+ ++v;
+ else
+ --v;
+ // Ensure the continuity of underlying FEdges
+ CurvePoint *cp = _Vertices.front(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f);
+ SVertex *sv_last = cp->A();
+ SVertex *sv_curr = (*v);
+ FEdge *fe = (orientation) ? iViewEdge->fedgeA() : iViewEdge->fedgeB();
+ FEdge *fe2 = fe->duplicate();
+ fe2->setVertexA(sv_curr);
+ fe2->setVertexB(sv_last);
+ sv_last->AddFEdge(fe2);
+ sv_curr->AddFEdge(fe2);
+ sv_curr->shape()->AddEdge(fe2);
+ }
+ else
+ previous = (*v)->point2d();
+ do{
+ current = (*v)->point2d();
+ Curve::push_vertex_front((*v));
+ //_Length += (current-previous).norm();
+ previous = current;
+ if(orientation)
+ ++v;
+ else
+ --v;
+ }while((v!=vend) && (v!=vfirst));
+
+ if(v==vfirst)
+ {
+ //Add last one:
+ current = (*v)->point2d();
+ Curve::push_vertex_front(*v);
+ //_Length += (current-previous).norm();
+ }
+
+ if (!_fedgeB)
+ _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA();
+}
+
+
+
diff --git a/source/blender/freestyle/intern/stroke/Chain.h b/source/blender/freestyle/intern/stroke/Chain.h
new file mode 100755
index 00000000000..0dc3dd21a28
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Chain.h
@@ -0,0 +1,87 @@
+//
+// Filename : Chain.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a chain of viewedges.
+// Date of creation : 09/01/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef CHAIN_H
+# define CHAIN_H
+
+# include "../view_map/ViewMap.h"
+# include "Curve.h"
+/*! Class to represent a 1D elements issued
+ * from the chaining process.
+ * A Chain is the last step before the Stroke and
+ * is used in the Splitting and Creation processes.
+ */
+class Chain : public Curve
+{
+protected:
+ // tmp
+ Id * _splittingId;
+ FEdge *_fedgeB; // the last FEdge of the ViewEdge passed to the last call for push_viewedge_back().
+public:
+ /*! Defult constructor. */
+ Chain() : Curve() {_splittingId=0;_fedgeB=0;}
+ /*! Builds a chain from its Id. */
+ Chain(const Id& id) : Curve(id) {_splittingId=0;_fedgeB=0;}
+ /*! Copy Constructor */
+ Chain(const Chain& iBrother) : Curve(iBrother) {_splittingId=iBrother._splittingId;_fedgeB=iBrother._fedgeB;}
+ /*! Destructor. */
+ virtual ~Chain() {
+ // only the last splitted deletes this id
+ if(_splittingId){
+ if(*_splittingId == _Id)
+ delete _splittingId;
+ }
+ }
+ /*! Returns the string "Chain" */
+ virtual string getExactTypeName() const {
+ return "Chain";
+ }
+
+ /*! Adds a ViewEdge at the end of the chain
+ * \param iViewEdge
+ * The ViewEdge that must be added.
+ * \param orientation
+ * The orientation with which this ViewEdge
+ * must be processed.
+ */
+ void push_viewedge_back(ViewEdge *iViewEdge, bool orientation) ;
+ /*! Adds a ViewEdge at the beginning of the chain
+ * \param iViewEdge
+ * The ViewEdge that must be added.
+ * \param orientation
+ * The orientation with which this ViewEdge
+ * must be processed.
+ */
+ void push_viewedge_front(ViewEdge *iViewEdge, bool orientation) ;
+
+ inline void setSplittingId(Id * sid){_splittingId = sid;}
+ inline Id* getSplittingId() {return _splittingId;}
+};
+
+#endif // CHAIN_H
diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.cpp b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp
new file mode 100755
index 00000000000..c54ee6ea1ee
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp
@@ -0,0 +1,170 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+#include "ChainingIterators.h"
+#include "../system/TimeStamp.h"
+
+ViewEdge* AdjacencyIterator::operator*() {
+ return (*_internalIterator).first;
+}
+bool AdjacencyIterator::isIncoming() const{
+ return (*_internalIterator).second;
+}
+
+int AdjacencyIterator::increment(){
+ ++_internalIterator;
+ while((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first)))
+ ++_internalIterator;
+ return 0;
+}
+
+bool AdjacencyIterator::isValid(ViewEdge* edge){
+ if(_restrictToSelection)
+ if(edge->getTimeStamp() != TimeStamp::instance()->getTimeStamp())
+ return false;
+ if(_restrictToUnvisited)
+ if(edge->getChainingTimeStamp() > TimeStamp::instance()->getTimeStamp())
+ return false;
+ return true;
+}
+
+int ChainingIterator::increment() {
+ _increment = true;
+ ViewVertex * vertex = getVertex();
+ if(!vertex){
+ _edge = 0;
+ return 0;
+ }
+ AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited);
+ if(it.isEnd()) {
+ _edge = 0;
+ return 0;
+ }
+ if (traverse(it) < 0)
+ return -1;
+ _edge = result;
+ if(_edge == 0)
+ return 0;
+ if(_edge->A() == vertex)
+ _orientation = true;
+ else
+ _orientation = false;
+ return 0;
+}
+
+int ChainingIterator::decrement() {
+ _increment = false;
+ ViewVertex * vertex = getVertex();
+ if(!vertex){
+ _edge = 0;
+ return 0;
+ }
+ AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited);
+ if(it.isEnd()) {
+ _edge = 0;
+ return 0;
+ }
+ if (traverse(it) < 0)
+ return -1;
+ _edge = result;
+ if(_edge == 0)
+ return 0;
+ if(_edge->B() == vertex)
+ _orientation = true;
+ else
+ _orientation = false;
+ return 0;
+}
+
+//
+// ChainSilhouetteIterators
+//
+///////////////////////////////////////////////////////////
+
+int ChainSilhouetteIterator::traverse(const AdjacencyIterator& ait){
+ AdjacencyIterator it(ait);
+ ViewVertex* nextVertex = getVertex();
+ // we can't get a NULL nextVertex here, it was intercepted
+ // before
+ if(nextVertex->getNature() & Nature::T_VERTEX){
+ TVertex * tvertex = (TVertex*)nextVertex;
+ ViewEdge *mate = (tvertex)->mate(getCurrentEdge());
+ while(!it.isEnd()){
+ ViewEdge *ve = *it;
+ if(ve == mate) {
+ result = ve;
+ return 0;
+ }
+ ++it;
+ }
+ result = 0;
+ return 0;
+ }
+ if(nextVertex->getNature() & Nature::NON_T_VERTEX){
+ //soc NonTVertex * nontvertex = (NonTVertex*)nextVertex;
+ ViewEdge * newEdge(0);
+ // we'll try to chain the edges by keeping the same nature...
+ // the preseance order is : SILHOUETTE, BORDER, CREASE, SUGGESTIVE, VALLEY, RIDGE
+ Nature::EdgeNature natures[6] = {Nature::SILHOUETTE, Nature::BORDER, Nature::CREASE, Nature::SUGGESTIVE_CONTOUR, Nature::VALLEY, Nature::RIDGE};
+ for(unsigned i=0; i<6; ++i){
+ if(getCurrentEdge()->getNature() & natures[i]){
+ int n = 0;
+ while(!it.isEnd()){
+ ViewEdge *ve = *it;
+ if(ve->getNature() & natures[i]){
+ ++n;
+ newEdge = ve;
+ }
+ ++it;
+ }
+ if(n == 1){
+ result = newEdge;
+ }else{
+ result = 0;
+ }
+ return 0;
+ }
+ }
+ }
+ result = 0;
+ return 0;
+}
+
+int ChainPredicateIterator::traverse(const AdjacencyIterator& ait){
+ AdjacencyIterator it(ait);
+ // Iterates over next edges to see if one of them
+ // respects the predicate:
+ while(!it.isEnd()) {
+ ViewEdge *ve = *it;
+ if (_unary_predicate->operator()(*ve) < 0)
+ return -1;
+ if (_unary_predicate->result) {
+ if (_binary_predicate->operator()(*(getCurrentEdge()), *(ve)) < 0)
+ return -1;
+ if (_binary_predicate->result) {
+ result = ve;
+ return 0;
+ }
+ }
+ ++it;
+ }
+ result = 0;
+ return 0;
+}
diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.h b/source/blender/freestyle/intern/stroke/ChainingIterators.h
new file mode 100755
index 00000000000..fec8d5ab6dc
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ChainingIterators.h
@@ -0,0 +1,394 @@
+//
+// Filename : ChainingIterators
+// Author : Stephane Grabli
+// Purpose : Chaining iterators
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+#ifndef CHAININGITERATORS_H
+# define CHAININGITERATORS_H
+
+# include "../view_map/ViewMap.h"
+# include "../view_map/ViewMapIterators.h"
+# include "../view_map/ViewMapAdvancedIterators.h"
+# include <iostream>
+# include "Predicates1D.h"
+
+#include "../system/Iterator.h" //soc
+
+# include "../python/Director.h"
+
+//using namespace ViewEdgeInternal;
+
+//
+// Adjacency iterator used in the chaining process
+//
+///////////////////////////////////////////////////////////
+class LIB_STROKE_EXPORT AdjacencyIterator : public Iterator {
+protected:
+ ViewVertexInternal::orientedViewEdgeIterator _internalIterator;
+ bool _restrictToSelection;
+ bool _restrictToUnvisited;
+public:
+ AdjacencyIterator(){
+ _restrictToSelection = true;
+ _restrictToUnvisited = true;
+ }
+ AdjacencyIterator(ViewVertex *iVertex, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true){
+ _restrictToSelection = iRestrictToSelection;
+ _restrictToUnvisited = iRestrictToUnvisited;
+ _internalIterator = iVertex->edgesBegin();
+ while((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first)))
+ ++_internalIterator;
+ }
+ AdjacencyIterator(const AdjacencyIterator& iBrother){
+ _internalIterator = iBrother._internalIterator;
+ _restrictToSelection = iBrother._restrictToSelection;
+ _restrictToUnvisited = iBrother._restrictToUnvisited;
+ }
+ AdjacencyIterator& operator=(const AdjacencyIterator& iBrother) {
+ _internalIterator = iBrother._internalIterator;
+ _restrictToSelection = iBrother._restrictToSelection;
+ _restrictToUnvisited = iBrother._restrictToUnvisited;
+ return *this;
+ }
+ virtual ~AdjacencyIterator(){
+ }
+
+ virtual string getExactTypeName() const {
+ return "AdjacencyIterator";
+ }
+
+ virtual inline bool isEnd() const {
+ return _internalIterator.isEnd();
+ }
+ virtual inline bool isBegin() const {
+ return _internalIterator.isBegin();
+ }
+ /*! Returns true if the current ViewEdge is is coming
+ * towards the iteration vertex. False otherwise.
+ */
+ bool isIncoming() const ;
+
+ /*! Returns a *pointer* to the pointed ViewEdge. */
+ virtual ViewEdge* operator*() ;
+ virtual ViewEdge* operator->() {return operator*();}
+ virtual AdjacencyIterator& operator++() {
+ increment();
+ return *this;
+ }
+ virtual AdjacencyIterator operator++(int) {
+ AdjacencyIterator tmp(*this);
+ increment();
+ return tmp;
+ }
+ virtual int increment();
+
+ virtual int decrement(){
+ cerr << "Warning: method decrement() not implemented" << endl;
+ return 0;
+ }
+
+protected:
+ bool isValid(ViewEdge* edge);
+};
+
+//
+// Base class for Chaining Iterators
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for chaining iterators.
+ * This class is designed to be overloaded
+ * in order to describe chaining rules.
+ * It makes the works of chaining rules description
+ * easier.
+ * The two main methods that need to overloaded are
+ * traverse() and init().
+ * traverse() tells which ViewEdge to follow, among the adjacent ones.
+ * If you specify restriction rules (such as "Chain only
+ * ViewEdges of the selection"), they will be included
+ * in the adjacency iterator. (i.e, the adjacent iterator
+ * will only stop on "valid" edges).
+ */
+class LIB_STROKE_EXPORT ChainingIterator : public ViewEdgeInternal::ViewEdgeIterator{
+protected:
+ bool _restrictToSelection;
+ bool _restrictToUnvisited;
+ bool _increment; //true if we're currently incrementing, false when decrementing
+
+public:
+
+ ViewEdge *result;
+ PyObject *py_c_it;
+
+ /*! Builds a Chaining Iterator from the first ViewEdge used for iteration
+ * and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within
+ * the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained
+ * must be ignored ot not.
+ * \param begin
+ * The ViewEdge from which to start the chain.
+ * \param orientation
+ * The direction to follow to explore the graph. If true,
+ * the direction indicated by the first ViewEdge is used.
+ */
+ ChainingIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = 0, bool orientation = true)
+ : ViewEdgeIterator(begin, orientation) {
+ _restrictToSelection = iRestrictToSelection;
+ _restrictToUnvisited = iRestrictToUnvisited;
+ _increment = true;
+ py_c_it = 0;
+ }
+
+ /*! Copy constructor */
+ ChainingIterator(const ChainingIterator& brother)
+ : ViewEdgeIterator(brother) {
+ _restrictToSelection = brother._restrictToSelection;
+ _restrictToUnvisited = brother._restrictToUnvisited;
+ _increment = brother._increment;
+ py_c_it = brother.py_c_it;
+ }
+
+ /*! Returns the string "ChainingIterator" */
+ virtual string getExactTypeName() const {
+ return "ChainingIterator";
+ }
+
+ /*! Inits the iterator context.
+ * This method is called each time
+ * a new chain is started.
+ * It can be used to reset some
+ * history information that you
+ * might want to keep.
+ */
+ virtual int init() {
+ return Director_BPy_ChainingIterator_init( this );
+ }
+
+ /*! This method iterates over the potential next
+ * ViewEdges and returns the one that will be
+ * followed next.
+ * returns the next ViewEdge to follow or
+ * 0 when the end of the chain is reached.
+ * \param it
+ * The iterator over the ViewEdges adjacent to
+ * the end vertex of the current ViewEdge.
+ * The Adjacency iterator reflects the restriction
+ * rules by only iterating over the valid ViewEdges.
+ */
+ virtual int traverse(const AdjacencyIterator &it){
+ return Director_BPy_ChainingIterator_traverse( this, const_cast<AdjacencyIterator &>(it) );
+ }
+
+ /* accessors */
+ /*! Returns true if the orientation of the current ViewEdge
+ * corresponds to its natural orientation
+ */
+ //inline bool getOrientation() const {}
+ /*! Returns the vertex which is the next crossing */
+ inline ViewVertex * getVertex() {
+ if(_increment){
+ if(_orientation){
+ return _edge->B();
+ }else{
+ return _edge->A();
+ }
+ }else{
+ if(_orientation){
+ return _edge->A();
+ }else{
+ return _edge->B();
+ }
+ }
+ }
+
+ /*! Returns true if the current iteration is an incrementation */
+ inline bool isIncrementing() const{
+ return _increment;
+ }
+
+ /* increments.*/
+ virtual int increment() ;
+ virtual int decrement() ;
+};
+
+//
+// Chaining iterators definitions
+//
+///////////////////////////////////////////////////////////
+
+/*! A ViewEdge Iterator used to follow ViewEdges the most naturally.
+ * For example, it will follow visible ViewEdges of same nature.
+ * As soon, as the nature or the visibility changes, the iteration
+ * stops (by setting the pointed ViewEdge to 0).
+ * In the case of an iteration over a set of ViewEdge that are both
+ * Silhouette and Crease, there will be a precedence of the silhouette
+ * over the crease criterion.
+ */
+class LIB_STROKE_EXPORT ChainSilhouetteIterator : public ChainingIterator
+{
+public:
+ /*! Builds a ChainSilhouetteIterator from the first ViewEdge used for iteration
+ * and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within
+ * the set of selected ViewEdges or not.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the
+ * ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding
+ * the ending ViewVertex of begin.
+ */
+ ChainSilhouetteIterator(bool iRestrictToSelection = true, ViewEdge* begin = NULL, bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, true, begin, orientation) {}
+
+ /*! Copy constructor */
+ ChainSilhouetteIterator(const ChainSilhouetteIterator& brother)
+ : ChainingIterator(brother) {}
+
+ /*! Returns the string "ChainSilhouetteIterator" */
+ virtual string getExactTypeName() const {
+ return "ChainSilhouetteIterator";
+ }
+
+ /*! This method iterates over the potential next
+ * ViewEdges and returns the one that will be
+ * followed next.
+ * When reaching the end of a chain, 0 is returned.
+ */
+ virtual int traverse(const AdjacencyIterator& it);
+
+ /*! Inits the iterator context */
+ virtual int init() {
+ return 0;
+ }
+};
+
+//
+// ChainPredicateIterator
+//
+///////////////////////////////////////////////////////////
+
+/*! A "generic" user-controlled ViewEdge iterator. This iterator
+ * is in particular built from a unary predicate and a binary predicate.
+ * First, the unary predicate is evaluated for all potential next ViewEdges
+ * in order to only keep the ones respecting a certain constraint.
+ * Then, the binary predicate is evaluated on the current ViewEdge
+ * together with each ViewEdge of the previous selection. The first
+ * ViewEdge respecting both the unary predicate and the binary predicate
+ * is kept as the next one. If none of the potential next ViewEdge respects
+ * these 2 predicates, 0 is returned.
+ */
+class LIB_STROKE_EXPORT ChainPredicateIterator : public ChainingIterator
+{
+protected:
+ BinaryPredicate1D *_binary_predicate; // the caller is responsible for the deletion of this object
+ UnaryPredicate1D *_unary_predicate; // the caller is responsible for the deletion of this object
+public:
+
+ /*! Builds a ChainPredicateIterator from a starting ViewEdge and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within
+ * the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained
+ * must be ignored ot not.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the
+ * ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding
+ * the ending ViewVertex of begin.
+ */
+ ChainPredicateIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = NULL, bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation) {
+ _binary_predicate = 0;
+ _unary_predicate = 0;
+ }
+
+ /*! Builds a ChainPredicateIterator from a unary predicate, a binary predicate, a starting ViewEdge and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within
+ * the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained
+ * must be ignored ot not.
+ * \param upred
+ * The unary predicate that the next ViewEdge must satisfy.
+ * \param bpred
+ * The binary predicate that the next ViewEdge must satisfy
+ * together with the actual pointed ViewEdge.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the
+ * ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding
+ * the ending ViewVertex of begin.
+ */
+ ChainPredicateIterator(UnaryPredicate1D& upred, BinaryPredicate1D& bpred, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = NULL, bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation) {
+ _unary_predicate = &upred;
+ _binary_predicate = &bpred;
+ }
+
+ /*! Copy constructor */
+ ChainPredicateIterator(const ChainPredicateIterator& brother)
+ : ChainingIterator(brother){
+ _unary_predicate = brother._unary_predicate;
+ _binary_predicate = brother._binary_predicate;
+ }
+
+ /*! Destructor. */
+ virtual ~ChainPredicateIterator(){
+ _unary_predicate = 0;
+ _binary_predicate = 0;
+ }
+
+ /*! Returns the string "ChainPredicateIterator" */
+ virtual string getExactTypeName() const {
+ return "ChainPredicateIterator";
+ }
+
+ /*! This method iterates over the potential next
+ * ViewEdges and returns the one that will be
+ * followed next.
+ * When reaching the end of a chain, 0 is returned.
+ */
+ virtual int traverse(const AdjacencyIterator &it);
+
+ /*! Inits the iterator context */
+ virtual int init() {
+ return 0;
+ }
+
+};
+
+#endif // CHAININGITERATORS_H
diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
new file mode 100755
index 00000000000..b55da1fb0f8
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
@@ -0,0 +1,60 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ContextFunctions.h"
+#include "../view_map/SteerableViewMap.h"
+#include "../system/TimeStamp.h"
+namespace ContextFunctions {
+
+ unsigned GetTimeStampCF(){
+ return TimeStamp::instance()->getTimeStamp();
+ }
+
+ unsigned GetCanvasWidthCF(){
+ return Canvas::getInstance()->width();
+ }
+
+ unsigned GetCanvasHeightCF(){
+ return Canvas::getInstance()->height();
+ }
+ void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels, float iSigma ){
+ return Canvas::getInstance()->loadMap(iFileName, iMapName, iNbLevels,iSigma);
+ }
+
+ float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y){
+ Canvas * canvas = Canvas::getInstance();
+ return canvas->readMapPixel(iMapName, level, x,y);
+ }
+
+ float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y){
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ return svm->readCompleteViewMapPixel(level,x,y);
+ }
+
+ float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y){
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ return svm->readSteerableViewMapPixel(iOrientation, level,x,y);
+ }
+
+ FEdge * GetSelectedFEdgeCF(){
+ return Canvas::getInstance()->selectedFEdge();
+ }
+}
diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.h b/source/blender/freestyle/intern/stroke/ContextFunctions.h
new file mode 100755
index 00000000000..37c98656fa7
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ContextFunctions.h
@@ -0,0 +1,124 @@
+//
+// Filename : AdvancedFunctions0D.h
+// Author(s) : Stephane Grabli
+// Purpose : Functions related to context queries
+// Date of creation : 20/12/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef CONTEXT_FUNCTIONS_HPP
+# define CONTEXT_FUNCTIONS_HPP
+
+# include "Canvas.h"
+# include "../image/Image.h"
+# include "../image/GaussianFilter.h"
+
+/*! \file ContextFunctions.h
+ * Interface to access the context related
+ * information.
+ */
+//
+// Context Functions definitions
+//
+///////////////////////////////////////////////////////////
+/*! namespace containing all the Context related functions */
+namespace ContextFunctions {
+
+ // GetTimeStamp
+ LIB_STROKE_EXPORT
+ /*! Returns the system time stamp */
+ unsigned GetTimeStampCF();
+
+ // GetCanvasWidth
+ /*! Returns the canvas width */
+ LIB_STROKE_EXPORT
+ unsigned GetCanvasWidthCF();
+
+ // GetCanvasHeight
+ /*! Returns the canvas width */
+ LIB_STROKE_EXPORT
+ unsigned GetCanvasHeightCF();
+
+ // Load map
+ /*! Loads an image map for further reading */
+ LIB_STROKE_EXPORT
+ void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels=4, float iSigma=1.f);
+
+ // ReadMapPixel
+ /*! Reads a pixel in a user-defined map
+ * \return the floating value stored for that pixel
+ * \param iMapName
+ * The name of the map
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ */
+ LIB_STROKE_EXPORT
+ float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y);
+
+ // ReadCompleteViewMapPixel
+ /*! Reads a pixel in the complete view map
+ * \return the floating value stored for that pixel
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ */
+ LIB_STROKE_EXPORT
+ float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y);
+
+ // ReadOrientedViewMapPixel
+ /*! Reads a pixel in one of the oriented view map images
+ * \return the floating value stored for that pixel
+ * \param iOrientation
+ * The number telling which orientation we want to check
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ */
+ LIB_STROKE_EXPORT
+ float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y);
+
+ // DEBUG
+ LIB_STROKE_EXPORT
+ FEdge * GetSelectedFEdgeCF();
+
+} // end of namespace ContextFunctions
+
+#endif // CONTEXT_FUNCTIONS_HPP
+
diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp
new file mode 100755
index 00000000000..4cca210161e
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Curve.cpp
@@ -0,0 +1,863 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Curve.h"
+#include "CurveIterators.h"
+#include "CurveAdvancedIterators.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* CurvePoint */
+ /* */
+ /* */
+ /**********************************/
+
+CurvePoint::CurvePoint()
+{
+ __A=0;
+ __B=0;
+ _t2d=0;
+}
+
+CurvePoint::CurvePoint(SVertex *iA, SVertex *iB, float t)
+{
+ __A=iA;
+ __B=iB;
+ _t2d=t;
+ if((iA == 0) && (t == 1.f))
+ {
+ _Point2d=__B->point2d();
+ _Point3d=__B->point3d();
+ }
+ else if((iB == 0) && (t == 0.f))
+ {
+ _Point2d=__A->point2d();
+ _Point3d=__A->point3d();
+ }
+ else
+ {
+ _Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->point2d());
+ _Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d());
+ }
+}
+
+CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3)
+{
+ __A = 0;
+ __B = 0;
+ float t1=iA->t2d();
+ float t2=iB->t2d();
+ if((iA->A() == iB->A()) && (iA->B() == iB->B()) && (iA->A() != 0) && (iA->B() != 0) && (iB->A() != 0) && (iB->B() != 0))
+ {
+ __A=iA->A();
+ __B=iB->B();
+ _t2d=t1+t2*t3-t1*t3;
+ }
+ else if((iA->B() == 0) && (iB->B() == 0))
+ {
+ __A = iA->A();
+ __B = iB->A();
+ _t2d = t3;
+ }
+ else if((iA->t2d() == 0) && (iB->t2d() == 0))
+ {
+ __A = iA->A();
+ __B = iB->A();
+ _t2d = t3;
+ }
+ else if(iA->A() == iB->A())
+ {
+iA_A_eq_iB_A:
+ if(iA->t2d() == 0){
+ __A = iB->A();
+ __B = iB->B();
+ _t2d = t3;
+ }else if(iB->t2d() == 0){
+ __A = iA->A();
+ __B = iA->B();
+ _t2d = t3;
+ }
+ }
+ else if(iA->B() == iB->B())
+ {
+iA_B_eq_iB_B:
+ if(iA->t2d() == 1){
+ __A = iB->A();
+ __B = iB->B();
+ _t2d = t3;
+ }else if(iB->t2d() == 1){
+ __A = iA->A();
+ __B = iA->B();
+ _t2d = t3;
+ }
+ }
+ else if(iA->B() == iB->A())
+ {
+iA_B_eq_iB_A:
+ if((iA->t2d() != 1.f) && (iB->t2d() == 0.f))
+ {
+ __A = iA->A();
+ __B = iA->B();
+ _t2d=t1+t3-t1*t3;
+ //_t2d = t3;
+ }
+ else if((iA->t2d() == 1.f) && (iB->t2d() != 0.f))
+ {
+ __A = iB->A();
+ __B = iB->B();
+ //_t2d = t3;
+ _t2d=t2*t3;
+ }
+ else if((iA->getPoint2D() - iA->getPoint2D()).norm() < 1e-6) {
+ __A = iB->A();
+ __B = iB->B();
+ //_t2d = t3;
+ _t2d=t2*t3;
+ }
+ }
+ else if(iA->A() != 0 && iB->A() != 0 && (iA->A()->point3d() - iB->A()->point3d()).norm() < 1e-6)
+ {
+ goto iA_A_eq_iB_A;
+ }
+ else if(iA->B() != 0 && iB->B() != 0 && (iA->B()->point3d() - iB->B()->point3d()).norm() < 1e-6)
+ {
+ goto iA_B_eq_iB_B;
+ }
+ else if(iA->B() != 0 && iB->A() != 0 && (iA->B()->point3d() - iB->A()->point3d()).norm() < 1e-6)
+ {
+ goto iA_B_eq_iB_A;
+ }
+ if (!__A || !__B) {
+ printf("iA A 0x%p p (%f, %f)\n", iA->A(), iA->A()->getPoint2D().x(), iA->A()->getPoint2D().y());
+ printf("iA B 0x%p p (%f, %f)\n", iA->B(), iA->B()->getPoint2D().x(), iA->B()->getPoint2D().y());
+ printf("iB A 0x%p p (%f, %f)\n", iB->A(), iB->A()->getPoint2D().x(), iB->A()->getPoint2D().y());
+ printf("iB B 0x%p p (%f, %f)\n", iB->B(), iB->B()->getPoint2D().x(), iB->B()->getPoint2D().y());
+ printf("iA t2d %f p (%f, %f)\n", iA->t2d(), iA->getPoint2D().x(), iA->getPoint2D().y());
+ printf("iB t2d %f p (%f, %f)\n", iB->t2d(), iB->getPoint2D().x(), iB->getPoint2D().y());
+ cerr << "Fatal error in CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3)" << endl;
+ }
+ assert(__A != 0 && __B != 0);
+
+ //_Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->point2d());
+ //_Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d());
+
+ _Point2d= iA->point2d()+t3*(iB->point2d()-iA->point2d());
+ _Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d());
+}
+
+CurvePoint::CurvePoint(const CurvePoint& iBrother)
+{
+ __A=iBrother.__A;
+ __B=iBrother.__B;
+ _t2d=iBrother._t2d;
+ _Point2d=iBrother._Point2d;
+ _Point3d=iBrother._Point3d;
+}
+
+CurvePoint& CurvePoint::operator=(const CurvePoint& iBrother)
+{
+ __A=iBrother.__A;
+ __B=iBrother.__B;
+ _t2d=iBrother._t2d;
+ _Point2d=iBrother._Point2d;
+ _Point3d=iBrother._Point3d;
+ return *this;
+}
+
+
+FEdge *CurvePoint::fedge()
+{
+ if(getNature() & Nature::T_VERTEX)
+ return 0;
+ return __A->fedge();
+}
+
+
+FEdge* CurvePoint::getFEdge(Interface0D& inter)
+{
+ CurvePoint* iVertexB = dynamic_cast<CurvePoint*>(&inter);
+ if (!iVertexB) {
+ cerr << "Warning: CurvePoint::getFEdge() failed to cast the given 0D element to CurvePoint." << endl;
+ return 0;
+ }
+ if(((__A == iVertexB->__A) && (__B == iVertexB->__B))
+ ||
+ ((__A == iVertexB->__B) && (__B == iVertexB->__A)))
+ return __A->getFEdge(*__B);
+ if(__B == 0)
+ {
+ if(iVertexB->__B == 0)
+ return __A->getFEdge(*(iVertexB->__A));
+ else if(iVertexB->__A == __A)
+ return __A->getFEdge(*(iVertexB->__B));
+ else if(iVertexB->__B == __A)
+ return __A->getFEdge(*(iVertexB->__A));
+ }
+ if(iVertexB->__B == 0)
+ {
+ if(iVertexB->__A == __A)
+ return __B->getFEdge(*(iVertexB->__A));
+ else if(iVertexB->__A == __B)
+ return __A->getFEdge(*(iVertexB->__A));
+ }
+ if(__B == iVertexB->__A)
+ {
+ if((_t2d != 1) && (iVertexB->_t2d == 0))
+ return __A->getFEdge(*__B);
+ if((_t2d == 1) && (iVertexB->_t2d != 0))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ }
+ if(__B == iVertexB->__B)
+ {
+ if((_t2d != 1) && (iVertexB->_t2d == 1))
+ return __A->getFEdge(*__B);
+ if((_t2d == 1) && (iVertexB->_t2d != 1))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ }
+ if(__A == iVertexB->__A)
+ {
+ if((_t2d == 0) && (iVertexB->_t2d != 0))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ if((_t2d != 0) && (iVertexB->_t2d == 0))
+ return __A->getFEdge(*__B);
+ }
+ if(__A == iVertexB->__B)
+ {
+ if((_t2d == 0) && (iVertexB->_t2d != 1))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ if((_t2d != 0) && (iVertexB->_t2d == 1))
+ return __A->getFEdge(*__B);
+ }
+#if 0
+ printf("__A 0x%p p (%f, %f)\n", __A, __A->getPoint2D().x(), __A->getPoint2D().y());
+ printf("__B 0x%p p (%f, %f)\n", __B, __B->getPoint2D().x(), __B->getPoint2D().y());
+ printf("iVertexB->A() 0x%p p (%f, %f)\n", iVertexB->A(), iVertexB->A()->getPoint2D().x(), iVertexB->A()->getPoint2D().y());
+ printf("iVertexB->B() 0x%p p (%f, %f)\n", iVertexB->B(), iVertexB->B()->getPoint2D().x(), iVertexB->B()->getPoint2D().y());
+ printf("_t2d %f p (%f, %f)\n", _t2d, getPoint2D().x(), getPoint2D().y());
+ printf("iVertexB->t2d() %f p (%f, %f)\n", iVertexB->t2d(), iVertexB->getPoint2D().x(), iVertexB->getPoint2D().y());
+#endif
+ cerr << "Warning: CurvePoint::getFEdge() failed." << endl;
+
+ return 0;
+}
+
+
+ Vec3r CurvePoint::normal() const
+{
+ if(__B == 0)
+ return __A->normal();
+ if(__A == 0)
+ return __B->normal();
+ Vec3r Na = __A->normal();
+ if(Exception::getException())
+ Na = Vec3r(0,0,0);
+ Vec3r Nb = __B->normal();
+ if(Exception::getException())
+ Nb = Vec3r(0,0,0);
+ // compute t3d:
+ real t3d = SilhouetteGeomEngine::ImageToWorldParameter(__A->getFEdge(*__B),_t2d);
+ return ((1-t3d)*Na+t3d*Nb);
+}
+
+
+ // Material CurvePoint::material() const
+ //{
+ // if(__A == 0)
+ // return __B->material();
+ // return __A->material();
+ //}
+
+
+// Id CurvePoint::shape_id() const
+// {
+// if(__A == 0)
+// return __B->shape_id();
+// return __A->shape_id();
+// }
+
+
+ const SShape * CurvePoint::shape() const
+{
+ if(__A == 0)
+ return __B->shape();
+ return __A->shape();
+}
+
+
+
+// float CurvePoint::shape_importance() const
+// {
+
+// if(__A == 0)
+
+// return __B->shape_importance();
+// return __A->shape_importance();
+// }
+
+
+ // const unsigned CurvePoint::qi() const
+ //{
+ // if(__A == 0)
+ // return __B->qi();
+ // if(__B == 0)
+ // return __A->qi();
+ // return __A->getFEdge(*__B)->qi();
+ //}
+
+
+ occluder_container::const_iterator CurvePoint::occluders_begin() const
+{
+ if(__A == 0)
+ return __B->occluders_begin();
+ if(__B == 0)
+ return __A->occluders_begin();
+ return __A->getFEdge(*__B)->occluders_begin();
+}
+
+ occluder_container::const_iterator CurvePoint::occluders_end() const
+{
+ if(__A == 0)
+ return __B->occluders_end();
+ if(__B == 0)
+ return __A->occluders_end();
+ return __A->getFEdge(*__B)->occluders_end();
+}
+
+ bool CurvePoint::occluders_empty() const
+{
+ if(__A == 0)
+ return __B->occluders_empty();
+ if(__B == 0)
+ return __A->occluders_empty();
+ return __A->getFEdge(*__B)->occluders_empty();
+}
+
+ int CurvePoint::occluders_size() const
+{
+ if(__A == 0)
+ return __B->occluders_size();
+ if(__B == 0)
+ return __A->occluders_size();
+ return __A->getFEdge(*__B)->occluders_size();
+}
+
+ const SShape * CurvePoint::occluded_shape() const
+{
+ if(__A == 0)
+ return __B->occluded_shape();
+ if(__B == 0)
+ return __A->occluded_shape();
+ return __A->getFEdge(*__B)->occluded_shape();
+}
+
+ const Polygon3r& CurvePoint::occludee() const
+{
+ if(__A == 0)
+ return __B->occludee();
+ if(__B == 0)
+ return __A->occludee();
+ return __A->getFEdge(*__B)->occludee();
+}
+
+ const bool CurvePoint::occludee_empty() const
+{
+ if(__A == 0)
+ return __B->occludee_empty();
+ if(__B == 0)
+ return __A->occludee_empty();
+ return __A->getFEdge(*__B)->occludee_empty();
+}
+
+ real CurvePoint::z_discontinuity() const
+{
+ if(__A == 0)
+ return __B->z_discontinuity();
+ if(__B == 0)
+ return __A->z_discontinuity();
+ if(__A->getFEdge(*__B) == 0)
+ return 0.0;
+
+ return __A->getFEdge(*__B)->z_discontinuity();
+}
+//
+// float CurvePoint::local_average_depth() const
+//{
+// return local_average_depth_function<CurvePoint >(this);
+//}
+//
+// float CurvePoint::local_depth_variance() const
+//{
+// return local_depth_variance_function<CurvePoint >(this);
+//}
+//
+// real CurvePoint::local_average_density(float sigma) const
+//{
+// //return local_average_density<CurvePoint >(this);
+//
+// return density_function<CurvePoint >(this);
+//}
+// Vec3r shaded_color() const ;
+//
+// Vec3r CurvePoint::orientation2d() const
+// {
+// if(__A == 0)
+// return __B->orientation2d();
+// if(__B == 0)
+// return __A->orientation2d();
+// return __B->point2d()-__A->point2d();
+// }
+//
+// Vec3r CurvePoint::orientation3d() const
+// {
+// if(__A == 0)
+// return __B->orientation3d();
+// if(__B == 0)
+// return __A->orientation3d();
+// return __B->point3d()-__A->point3d();
+// }
+
+// real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);}
+//
+// Vec3r CurvePoint::curvature2d_as_vector() const
+//{
+// // Vec3r edgeA = (_FEdges[0])->orientation2d().normalize();
+// // Vec3r edgeB = (_FEdges[1])->orientation2d().normalize();
+// // return edgeA+edgeB;
+// //
+// if(__A == 0)
+// return __B->curvature2d_as_vector();
+// if(__B == 0)
+// return __A->curvature2d_as_vector();
+// return ((1-_t2d)*__A->curvature2d_as_vector()+_t2d*__B->curvature2d_as_vector());
+//}
+//
+// real CurvePoint::curvature2d_as_angle() const
+//{
+// // Vec3r edgeA = (_FEdges[0])->orientation2d();
+// // Vec3r edgeB = (_FEdges[1])->orientation2d();
+// // Vec2d N1(-edgeA.y(), edgeA.x());N1.normalize();
+// // Vec2d N2(-edgeB.y(), edgeB.x());N2.normalize();
+// // return acos((N1*N2));
+//
+// if(__A == 0)
+// return __B->curvature2d_as_angle();
+// if(__B == 0)
+// return __A->curvature2d_as_angle();
+// return ((1-_t2d)*__A->curvature2d_as_angle()+_t2d*__B->curvature2d_as_angle());
+//}
+
+
+real CurvePoint::curvatureFredo() const
+{
+ if(__A == 0)
+ return __B->curvatureFredo();
+ if(__B == 0)
+ return __A->curvatureFredo();
+ return ((1-_t2d)*__A->curvatureFredo()+_t2d*__B->curvatureFredo());
+}
+
+Vec2d CurvePoint::directionFredo () const
+{
+ if(__A == 0)
+ return __B->directionFredo();
+ if(__B == 0)
+ return __A->directionFredo();
+ return ((1-_t2d)*__A->directionFredo()+_t2d*__B->directionFredo());
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* Curve */
+ /* */
+ /* */
+ /**********************************/
+
+/* for functions */
+
+
+Curve::~Curve()
+{
+ if(!_Vertices.empty())
+ {
+ for(vertex_container::iterator it=_Vertices.begin(), itend =_Vertices.end();
+ it!=itend;
+ ++it)
+ {
+ delete (*it);
+ }
+ _Vertices.clear();
+ }
+}
+
+/*! iterators access */
+Curve::point_iterator Curve::points_begin(float step)
+{
+ vertex_container::iterator second = _Vertices.begin();++second;
+ return point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.f, 0.f);
+ //return point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f);
+}
+Curve::const_point_iterator Curve::points_begin(float step) const
+{
+ vertex_container::const_iterator second = _Vertices.begin();++second;
+ return const_point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.f, 0.f);
+ //return const_point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f);
+}
+Curve::point_iterator Curve::points_end(float step)
+{
+ return point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length);
+ //return point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _Length);
+}
+Curve::const_point_iterator Curve::points_end(float step) const
+{
+ return const_point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length);
+ //return const_point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _Length);
+}
+
+// Adavnced Iterators access
+Curve::point_iterator Curve::vertices_begin(){return points_begin(0);}
+Curve::const_point_iterator Curve::vertices_begin() const {return points_begin(0);}
+Curve::point_iterator Curve::vertices_end(){return points_end(0);}
+Curve::const_point_iterator Curve::vertices_end() const {return points_end(0);}
+
+// specialized iterators access
+CurveInternal::CurvePointIterator Curve::curvePointsBegin(float t){
+ vertex_container::iterator second = _Vertices.begin();++second;
+ return CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), 0, _nSegments, _Length, t, 0.f, 0.f);
+}
+
+CurveInternal::CurvePointIterator Curve::curvePointsEnd(float t){
+ vertex_container::iterator last = _Vertices.end();--last;
+ return CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, _nSegments, _Length, t, 0.f, _Length);
+}
+
+CurveInternal::CurvePointIterator Curve::curveVerticesBegin(){
+ return curvePointsBegin(0);
+}
+
+CurveInternal::CurvePointIterator Curve::curveVerticesEnd(){
+ return curvePointsEnd(0);
+}
+
+Interface0DIterator Curve::pointsBegin(float t){
+ vertex_container::iterator second = _Vertices.begin();++second;
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), 0, _nSegments, _Length, t, 0.f, 0.f));
+ return ret;
+}
+
+Interface0DIterator Curve::pointsEnd(float t){
+ vertex_container::iterator last = _Vertices.end();--last;
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, _nSegments, _Length, t, 0.f, _Length));
+ return ret;
+}
+
+Interface0DIterator Curve::verticesBegin(){
+ return pointsBegin(0);
+}
+
+Interface0DIterator Curve::verticesEnd(){
+ return pointsEnd(0);
+}
+
+
+// Vec3r shaded_color(int iCombination = 0) const ;
+//
+// Vec3r Curve::orientation2d(point_iterator it) const
+//{
+// return (*it)->orientation2d();
+//}
+/* template <class BaseVertex> */
+/* Vec3r Curve::orientation2d(int iCombination) const */
+/* { */
+/* return edge_orientation2d_function<Curve >(this, iCombination); */
+/* } */
+//
+// Vec3r Curve::orientation3d(point_iterator it) const
+//{
+// return (*it)->orientation3d();
+//}
+/* */
+/* Vec3r Curve::orientation3d(int iCombination) const */
+/* { */
+/* return edge_orientation3d_function<Curve >(this, iCombination); */
+/* } */
+// real curvature2d(point_iterator it) const {return (*it)->curvature2d();}
+// real curvature2d(int iCombination = 0) const ;
+
+// Material Curve::material() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const Material& mat = (*v)->material();
+// for(;v!=vend;++v)
+// {
+// if((*v)->material() != mat)
+// Exception::raiseException();
+// }
+// return mat;
+//}
+
+// int Curve::qi() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// int qi_= (*v)->qi();
+// for(;v!=vend;++v)
+// {
+// if((*v)->qi() != qi_)
+// Exception::raiseException();
+// }
+// return qi_;
+//}
+// occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();}
+// occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();}
+
+//int Curve::occluders_size() const
+//{
+// return qi();
+//}
+
+// bool Curve::occluders_empty() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// bool empty = (*v)->occluders_empty();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occluders_empty() != empty)
+// Exception::raiseException();
+// }
+// return empty;
+//}
+// const Polygon3r& occludee() const {return *(_FEdgeA->aFace());}
+
+// const SShape * Curve::occluded_shape() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const SShape *sshape = (*v)->occluded_shape();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occluded_shape() != sshape)
+// Exception::raiseException();
+// }
+// return sshape;
+//}
+
+
+// const bool Curve::occludee_empty() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// bool empty = (*v)->occludee_empty();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occludee_empty() != empty)
+// Exception::raiseException();
+// }
+// return empty;
+//}
+/* */
+/* real Curve::z_discontinuity(int iCombination) const */
+/* { */
+/* return z_discontinuity_edge_function<Curve >(this, iCombination); */
+/* } */
+
+// int Curve::shape_id() const
+// {
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// Id id = (*v)->shape_id();
+// for(;v!=vend;++v)
+// {
+// if((*v)->shape_id() != id)
+// Exception::raiseException();
+// }
+// return id.first;
+// }
+
+
+// const SShape * Curve::shape() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const SShape *sshape = (*v)->shape();
+// for(;v!=vend;++v)
+// {
+// if((*v)->shape() != sshape)
+// Exception::raiseException();
+// }
+// return sshape;
+//}
+
+
+// occluder_container::const_iterator Curve::occluders_begin() const
+//{
+// const_vertex_iterator v=vertices_begin();
+// return (*v)->occluders_begin();
+//}
+//
+//
+// occluder_container::const_iterator Curve::occluders_end() const
+//{
+// const_vertex_iterator v=vertices_end();
+// return (*v)->occluders_end();
+//}
+
+/* */
+/* Vec3r Curve::curvature2d_as_vector(int iCombination) const */
+/* { */
+/* return curvature2d_as_vector_edge_function<Curve >(this, iCombination); */
+/* } */
+/* */
+/* real Curve::curvature2d_as_angle(int iCombination) const */
+/* { */
+/* return curvature2d_as_angle_edge_function<Curve >(this, iCombination); */
+/* } */
+
+/* */
+/* float Curve::shape_importance(int iCombination) const */
+/* { */
+/* return shape_importance_edge_function<Curve >(this, iCombination); */
+/* } */
+
+/* */
+/* float Curve::local_average_depth(int iCombination) const */
+/* { */
+/* return local_average_depth_edge_function<Curve >(this, iCombination); */
+/* } */
+/* */
+/* float Curve::local_depth_variance(int iCombination ) const */
+/* { */
+/* return local_depth_variance_edge_function<Curve >(this, iCombination); */
+/* // local_depth_variance_functor<Point> functor; */
+/* // float result; */
+/* // Evaluate<float, local_depth_variance_functor<Point> >(&functor, iCombination, result); */
+/* // return result; */
+/* } */
+
+/* */
+/* real Curve::local_average_density(float sigma, int iCombination ) const */
+/* { */
+/* return density_edge_function<Curve >(this, iCombination); */
+/* // density_functor<Point> functor; */
+/* // real result; */
+/* // Evaluate<real, density_functor<Point> >(&functor, iCombination, result); */
+/* // return result; */
+/* } */
+
+#define EPS_CURVA_DIR 0.01
+
+
+void Curve::computeCurvatureAndOrientation ()
+{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end(), v2, prevV, v0;
+// Vec2d p0, p1, p2;
+// Vec3r p;
+
+// p=(*v)->point2d();
+// p0=Vec2d(p[0], p[1]);
+// prevV=v; ++v;
+// p=(*v)->point2d();
+// p1=Vec2d(p[0], p[1]);
+// Vec2d prevDir(p1-p0);
+
+// for(;v!=vend;++v)
+// {
+// v2=v; ++v2;
+// if (v2==vend) break;
+// Vec3r p2=(*v2)->point2d();
+
+// Vec2d BA=p0-p1;
+// Vec2d BC=p2-p1;
+// real lba=BA.norm(), lbc=BC.norm();
+// BA.normalizeSafe();
+// BC.normalizeSafe();
+// Vec2d normalCurvature=BA+BC;
+// Vec2d dir=Vec2d(BC-BA);
+// Vec2d normal=Vec2d(-dir[1], dir[0]);
+
+// normal.normalizeSafe();
+// real curvature=normalCurvature*normal;
+// if (lba+lbc > MY_EPSILON)
+// curvature/=(0.5*lba+lbc);
+// if (dir.norm() < MY_EPSILON)
+// dir=0.1*prevDir;
+// (*v)->setCurvatureFredo(curvature);
+// (*v)->setDirectionFredo(dir);
+
+// prevV=v; p0=p1; p1=p2; prevDir=dir; prevDir.normalize();
+// }
+// (*v)->setCurvatureFredo((*prevV)->curvatureFredo());
+// (*v)->setDirectionFredo((*v)->point2d()-(*prevV)->point2d());
+// v0=vertices_begin(); v2=v0; ++v2;
+// (*v0)->setCurvatureFredo((*v2)->curvatureFredo());
+// (*v0)->setDirectionFredo((*v2)->point2d()-(*v0)->point2d());
+
+// //closed curve case one day...
+
+// //
+// return;
+
+// //numerical degeneracy verification.. we'll see later
+// const_vertex_iterator vLastReliable=vertices_begin();
+
+// v=vertices_begin();
+// p=(*v)->point2d();
+// p0=Vec2d(p[0], p[1]);
+// prevV=v; ++v;
+// p=(*v)->point2d();
+// p1=Vec2d(p[0], p[1]);
+// bool isReliable=false;
+// if ((p1-p0).norm>EPS_CURVA)
+// {
+// vLastReliable=v;
+// isReliable=true;
+// }
+
+// for(;v!=vend;++v)
+// {
+// v2=v; ++v2;
+// if (v2==vend) break;
+// Vec3r p2=(*v2)->point2d();
+
+// Vec2d BA=p0-p1;
+// Vec2d BC=p2-p1;
+// real lba=BA.norm(), lbc=BC.norm();
+
+// if ((lba+lbc)<EPS_CURVA)
+// {
+// isReliable=false;
+// cerr<<"/";
+// }
+// else
+// {
+// if (!isReliable)//previous points were not reliable
+// {
+// const_vertex_iterator vfix=vLastReliable;
+// vfix++;
+// for (; vfix!=v; ++vfix)
+// {
+// (*vfix)->setCurvatureFredo((*v)->curvatureFredo());
+// (*vfix)->setDirectionFredo((*v)->directionFredo());
+// }
+// }
+// isReliable=true;
+// vLastReliable=v;
+// }
+// prevV=v; p0=p1; p1=p2;
+// }
+
+}
diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h
new file mode 100755
index 00000000000..60bc9815cb4
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Curve.h
@@ -0,0 +1,467 @@
+//
+// Filename : Curve.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a container for curves
+// Date of creation : 11/01/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef CURVE_H
+# define CURVE_H
+
+# include "../view_map/Silhouette.h"
+# include <deque>
+# include "../system/BaseIterator.h"
+# include "../geometry/Geom.h"
+//# include "../scene_graph/FrsMaterial.h"
+# include "../view_map/SilhouetteGeomEngine.h"
+# include "../view_map/Interface0D.h"
+# include "../view_map/Interface1D.h"
+
+using namespace std;
+using namespace Geometry;
+
+ /**********************************/
+ /* */
+ /* */
+ /* CurvePoint */
+ /* */
+ /* */
+ /**********************************/
+
+/*! Class to represent a point of a curve.
+ * A CurvePoint can be any point of a 1D curve
+ * (it doesn't have to be a vertex of the curve).
+ * Any Interface1D is built upon ViewEdges, themselves
+ * built upon FEdges. Therefore, a curve is basically
+ * a polyline made of a list SVertex.
+ * Thus, a CurvePoint is built by lineraly interpolating
+ * two SVertex.
+ * CurvePoint can be used as virtual points while
+ * querying 0D information along a curve at a given resolution.
+ */
+class LIB_STROKE_EXPORT CurvePoint : public Interface0D
+{
+public: // Implementation of Interface0D
+ /*! Returns the string "CurvePoint"*/
+ virtual string getExactTypeName() const {
+ return "CurvePoint";
+ }
+
+ // Data access methods
+ /*! Returns the 3D X coordinate of the point */
+ virtual real getX() const {
+ return _Point3d.x();
+ }
+ /*! Returns the 3D Y coordinate of the point */
+ virtual real getY() const {
+ return _Point3d.y();
+ }
+ /*! Returns the 3D Z coordinate of the point */
+ virtual real getZ() const {
+ return _Point3d.z();
+ }
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const {
+ return _Point3d;
+ }
+ /*! Returns the projected 3D X coordinate of the point */
+ virtual real getProjectedX() const {
+ return _Point2d.x();
+ }
+ /*! Returns the projected 3D Y coordinate of the point */
+ virtual real getProjectedY() const {
+ return _Point2d.y();
+ }
+ /*! Returns the projected 3D Z coordinate of the point */
+ virtual real getProjectedZ() const {
+ return _Point2d.z();
+ }
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const {
+ return Vec2f((float)_Point2d.x(),(float)_Point2d.y());
+ }
+
+ virtual FEdge* getFEdge(Interface0D& inter);
+ /*! Returns the CurvePoint's Id */
+ virtual Id getId() const {
+ Id id;
+ if(_t2d == 0)
+ return __A->getId();
+ else if(_t2d == 1)
+ return __B->getId();
+ return id;
+ }
+ /*! Returns the CurvePoint's Nature */
+ virtual Nature::VertexNature getNature() const {
+ Nature::VertexNature nature = Nature::POINT;
+ if(_t2d == 0)
+ nature |= __A->getNature();
+ else if(_t2d == 1)
+ nature |= __B->getNature();
+ return nature;
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex(){
+ if(_t2d == 0)
+ return __A;
+ else if(_t2d == 1)
+ return __B;
+ return Interface0D::castToSVertex();
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ if(_t2d == 0)
+ return __A->castToViewVertex();
+ else if(_t2d == 1)
+ return __B->castToViewVertex();
+ return Interface0D::castToViewVertex();
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex(){
+ if(_t2d == 0)
+ return __A->castToNonTVertex();
+ else if(_t2d == 1)
+ return __B->castToNonTVertex();
+ return Interface0D::castToNonTVertex();
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex(){
+ if(_t2d == 0)
+ return __A->castToTVertex();
+ else if(_t2d == 1)
+ return __B->castToTVertex();
+ return Interface0D::castToTVertex();
+ }
+public:
+ typedef SVertex vertex_type;
+protected:
+ SVertex *__A;
+ SVertex *__B;
+ float _t2d;
+ //float _t3d;
+ Vec3r _Point2d;
+ Vec3r _Point3d;
+public:
+ /*! Defult Constructor. */
+ CurvePoint();
+ /*! Builds a CurvePoint from two SVertex and an interpolation
+ * parameter.
+ * \param iA
+ * The first SVertex
+ * \param iB
+ * The second SVertex
+ * \param t2d
+ * A 2D interpolation parameter
+ * used to linearly interpolate \a iA and \a iB
+ */
+ CurvePoint(SVertex *iA, SVertex *iB, float t2d) ;
+ /*! Builds a CurvePoint from two CurvePoint and an interpolation parameter.
+ * \param iA
+ * The first CurvePoint
+ * \param iB
+ * The second CurvePoint
+ * \param t2d
+ * The 2D interpolation parameter used
+ * to linearly interpolate \a iA and \a iB.
+ */
+ CurvePoint(CurvePoint *iA, CurvePoint *iB, float t2d) ;
+ // CurvePoint(SVertex *iA, SVertex *iB, float t2d, float t3d) ;
+ /*! Copy Constructor. */
+ CurvePoint(const CurvePoint& iBrother) ;
+ /*! Operator = */
+ CurvePoint& operator=(const CurvePoint& iBrother) ;
+ /*! Destructor */
+ virtual ~CurvePoint() {}
+ /*! Operator == */
+ bool operator==(const CurvePoint& b){
+ return ((__A==b.__A) && (__B==b.__B) && (_t2d==b._t2d));
+ }
+
+ /* accessors */
+ /*! Returns the first SVertex upon which
+ * the CurvePoint is built. */
+ inline SVertex * A() {return __A;}
+ /*! Returns the second SVertex upon which
+ * the CurvePoint is built. */
+ inline SVertex * B() {return __B;}
+ /*! Returns the interpolation parameter. */
+ inline float t2d() const {return _t2d;}
+ //inline const float t3d() const {return _t3d;}
+
+ /* modifiers */
+ /*! Sets the first SVertex upon which to build
+ * the CurvePoint.
+ */
+ inline void setA(SVertex *iA) {__A = iA;}
+ /*! Sets the second SVertex upon which to build
+ * the CurvePoint.
+ */
+ inline void setB(SVertex *iB) {__B = iB;}
+ /*! Sets the 2D interpolation parameter to use.
+ */
+ inline void setT2d(float t) {_t2d = t;}
+ //inline void SetT3d(float t) {_t3d = t;}
+
+ /* Information access interface */
+
+ FEdge *fedge() ;
+ inline const Vec3r& point2d() const {return _Point2d;}
+ inline const Vec3r& point3d() const {return _Point3d;}
+ Vec3r normal() const ;
+ //FrsMaterial material() const ;
+ // Id shape_id() const ;
+ const SShape * shape() const ;
+ // float shape_importance() const ;
+
+ //const unsigned qi() const ;
+ occluder_container::const_iterator occluders_begin() const ;
+ occluder_container::const_iterator occluders_end() const ;
+ bool occluders_empty() const ;
+ int occluders_size() const ;
+ const Polygon3r& occludee() const ;
+ const SShape * occluded_shape() const ;
+ const bool occludee_empty() const ;
+ real z_discontinuity() const ;
+ // float local_average_depth() const ;
+ // float local_depth_variance() const ;
+ // real local_average_density(float sigma = 2.3f) const ;
+ // Vec3r shaded_color() const ;
+// Vec3r orientation2d() const ;
+// Vec3r orientation3d() const ;
+ // // real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);}
+ // Vec3r curvature2d_as_vector() const ;
+ // /*! angle in radians */
+ // real curvature2d_as_angle() const ;
+
+ real curvatureFredo () const;
+ Vec2d directionFredo () const;
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* Curve */
+ /* */
+ /* */
+ /**********************************/
+
+namespace CurveInternal {
+ class CurvePoint_const_traits;
+ class CurvePoint_nonconst_traits;
+ template<class Traits> class __point_iterator;
+ class CurvePointIterator;
+} // end of namespace CurveInternal
+
+/*! Base class for curves made of CurvePoints.
+ * SVertex is the type of the initial curve vertices.
+ * A Chain is a specialization of a Curve.
+ */
+class LIB_STROKE_EXPORT Curve : public Interface1D
+{
+public:
+ typedef CurvePoint Vertex;
+ typedef CurvePoint Point;
+ typedef Point point_type;
+ typedef Vertex vertex_type;
+ typedef deque<Vertex*> vertex_container;
+
+ /* Iterator to iterate over a vertex edges */
+
+ typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_nonconst_traits > point_iterator;
+ typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_const_traits > const_point_iterator;
+ typedef point_iterator vertex_iterator ;
+ typedef const_point_iterator const_vertex_iterator ;
+
+protected:
+ vertex_container _Vertices;
+ double _Length;
+ Id _Id;
+ unsigned _nSegments; // number of segments
+
+public:
+ /*! Default Constructor. */
+ Curve() {_Length = 0;_Id = 0;_nSegments=0;}
+ /*! Builds a Curve from its id */
+ Curve(const Id& id) {_Length = 0;_Id = id;_nSegments=0;}
+ /*! Copy Constructor. */
+ Curve(const Curve& iBrother) {_Length = iBrother._Length;_Vertices = iBrother._Vertices;_Id=iBrother._Id;_nSegments=0;}
+ /*! Destructor. */
+ virtual ~Curve() ;
+ /*! Returns the string "Curve" */
+ virtual string getExactTypeName() const {
+ return "Curve";
+ }
+
+ /*
+ fredo's curvature storage
+ */
+ void computeCurvatureAndOrientation ();
+
+ /*! Adds a single vertex (CurvePoint) at the end of the Curve */
+ inline void push_vertex_back(Vertex *iVertex)
+ {
+ if(!_Vertices.empty())
+ {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex * new_vertex = new Vertex(*iVertex);
+ _Vertices.push_back(new_vertex);
+ }
+ /*! Adds a single vertex (SVertex) at the end of the Curve */
+ inline void push_vertex_back(SVertex *iVertex)
+ {
+ if(!_Vertices.empty())
+ {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex *new_vertex = new Vertex(iVertex, 0,0);
+ _Vertices.push_back(new_vertex);
+ }
+ /*! Adds a single vertex (CurvePoint) at the front of the Curve */
+ inline void push_vertex_front(Vertex *iVertex)
+ {
+ if(!_Vertices.empty())
+ {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex * new_vertex = new Vertex(*iVertex);
+ _Vertices.push_front(new_vertex);
+ }
+ /*! Adds a single vertex (SVertex) at the front of the Curve */
+ inline void push_vertex_front(SVertex *iVertex)
+ {
+ if(!_Vertices.empty())
+ {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex *new_vertex = new Vertex(iVertex, 0,0);
+ _Vertices.push_front(new_vertex);
+ }
+ /*! Returns true is the Curve doesn't have any Vertex yet. */
+ inline bool empty() const {return _Vertices.empty();}
+ /*! Returns the 2D length of the Curve.*/
+ inline real getLength2D() const {return _Length;}
+ /*! Returns the Id of the 1D element .*/
+ virtual Id getId() const {
+ return _Id;
+ }
+ /*! Returns the number of segments in the
+ * oplyline constituing the Curve.
+ */
+ inline unsigned int nSegments() const {return _nSegments;}
+
+ inline void setId(const Id& id){_Id = id;}
+ /* Information access interface */
+
+
+ //inline Vec3r shaded_color(int iCombination = 0) const ;
+ // inline Vec3r orientation2d(point_iterator it) const ;
+ //Vec3r orientation2d(int iCombination = 0) const ;
+ // Vec3r orientation3d(point_iterator it) const ;
+ //Vec3r orientation3d(int iCombination = 0) const ;
+ // real curvature2d(point_iterator it) const {return (*it)->curvature2d();}
+ // real curvature2d(int iCombination = 0) const ;
+ //FrsMaterial material() const ;
+ //int qi() const ;
+ // occluder_container::const_iterator occluders_begin() const ;
+ // occluder_container::const_iterator occluders_end() const ;
+ //int occluders_size() const;
+ //bool occluders_empty() const ;
+ // const Polygon3r& occludee() const {return *(_FEdgeA->aFace());}
+ //const SShape * occluded_shape() const;
+ //const bool occludee_empty() const ;
+ //real z_discontinuity(int iCombination = 0) const ;
+ // int shape_id() const ;
+ //const SShape * shape() const ;
+ //float shape_importance(int iCombination=0) const ;
+ //float local_average_depth(int iCombination = 0) const;
+ //float local_depth_variance(int iCombination = 0) const ;
+ //real local_average_density(float sigma = 2.3f, int iCombination = 0) const ;
+ //Vec3r curvature2d_as_vector(int iCombination=0) const ;
+ /*! angle in radians */
+ //real curvature2d_as_angle(int iCombination=0) const ;
+
+ /* advanced iterators access */
+ point_iterator points_begin(float step = 0);
+ const_point_iterator points_begin(float step = 0) const;
+ point_iterator points_end(float step = 0);
+ const_point_iterator points_end(float step = 0) const;
+
+ // methods given for convenience */
+ point_iterator vertices_begin();
+ const_point_iterator vertices_begin() const;
+ point_iterator vertices_end();
+ const_point_iterator vertices_end() const;
+
+ // specialized iterators access
+ CurveInternal::CurvePointIterator curvePointsBegin(float t=0.f);
+ CurveInternal::CurvePointIterator curvePointsEnd(float t=0.f);
+
+ CurveInternal::CurvePointIterator curveVerticesBegin();
+ CurveInternal::CurvePointIterator curveVerticesEnd();
+
+ // Iterators access
+ /*! Returns an Interface0DIterator pointing onto
+ * the first vertex of the Curve and that can iterate
+ * over the \a vertices of the Curve.
+ */
+ virtual Interface0DIterator verticesBegin();
+ /*! Returns an Interface0DIterator pointing after
+ * the last vertex of the Curve and that can iterate
+ * over the \a vertices of the Curve.
+ */
+ virtual Interface0DIterator verticesEnd();
+ /*! Returns an Interface0DIterator pointing onto
+ * the first point of the Curve and that can iterate
+ * over the \a points of the Curve at any resolution.
+ * At each iteration a virtual temporary CurvePoint
+ * is created.
+ */
+ virtual Interface0DIterator pointsBegin(float t=0.f);
+ /*! Returns an Interface0DIterator pointing after
+ * the last point of the Curve and that can iterate
+ * over the \a points of the Curve at any resolution.
+ * At each iteration a virtual temporary CurvePoint
+ * is created.
+ */
+ virtual Interface0DIterator pointsEnd(float t=0.f);
+};
+
+
+
+#endif
diff --git a/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h
new file mode 100755
index 00000000000..dfc9f2719f8
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h
@@ -0,0 +1,378 @@
+//
+// Filename : CurveAdvancedIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the elements of the Curve
+// Can't be used in python
+// Date of creation : 01/08/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ADVANCEDCURVEITERATORS_H
+# define ADVANCEDCURVEITERATORS_H
+
+# include "Stroke.h"
+
+namespace CurveInternal {
+
+ class CurvePoint_const_traits : public Const_traits<CurvePoint*> {
+ public:
+ typedef deque<CurvePoint*> vertex_container;
+ typedef vertex_container::const_iterator vertex_container_iterator;
+ typedef SVertex vertex_type;
+ };
+
+ class CurvePoint_nonconst_traits : public Nonconst_traits<CurvePoint*> {
+ public:
+ typedef deque<CurvePoint*> vertex_container;
+ typedef vertex_container::iterator vertex_container_iterator ;
+ typedef SVertex vertex_type;
+ };
+
+ /**********************************/
+ /* */
+ /* */
+ /* CurvePoint Iterator */
+ /* */
+ /* */
+ /**********************************/
+
+
+ /*! iterator on a curve. Allows an iterating outside
+ * initial vertices. A CurvePoint is instanciated an returned
+ * when the iterator is dereferenced.
+ */
+
+ template<class Traits>
+ class __point_iterator : public IteratorBase<Traits, BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef __point_iterator <Traits> Self;
+ typedef typename Traits::vertex_container_iterator vertex_container_iterator;
+ typedef typename Traits::vertex_type vertex_type;
+ typedef CurvePoint Point;
+ typedef Point point_type;
+
+ typedef __point_iterator<CurvePoint_nonconst_traits > iterator;
+ typedef __point_iterator<CurvePoint_const_traits > const_iterator;
+
+ // public:
+ // typedef Vertex vertex_type ;
+ // typedef vertex_container_iterator vertex_iterator_type;
+ // typedef CurvePoint<Vertex> Point;
+ // typedef Point point_type;
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+ //# if defined(__GNUC__) && (__GNUC__ < 3)
+ // typedef bidirectional_iterator<CurvePoint<Vertex>,ptrdiff_t> bidirectional_point_iterator;
+ //# else
+ // typedef iterator<bidirectional_iterator_tag, CurvePoint<Vertex>,ptrdiff_t> bidirectional_point_iterator;
+ //# endif
+ friend class Curve;
+ //friend class Curve::vertex_iterator;
+ //friend class __point_iterator<CurvePoint_nonconst_traits >;
+ //friend class iterator;
+ //protected:
+ public:
+ float _CurvilinearLength;
+ float _step;
+ vertex_container_iterator __A;
+ vertex_container_iterator __B;
+ vertex_container_iterator _begin;
+ vertex_container_iterator _end;
+ int _n;
+ int _currentn;
+ float _t;
+ mutable Point *_Point;
+
+ public:
+
+ public:
+ inline __point_iterator(float step = 0.f)
+ : parent_class()
+ {
+ _step = step;
+ _CurvilinearLength = 0.f;
+ _t = 0.f;
+ _Point = 0;
+ _n = 0;
+ _currentn = 0;
+ }
+
+ inline __point_iterator(const iterator& iBrother)
+ : parent_class()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if(iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ }
+ inline __point_iterator(const const_iterator& iBrother)
+ : parent_class()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if(iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ }
+ inline Self& operator=(const Self& iBrother)
+ {
+ //((bidirectional_point_iterator*)this)->operator=(iBrother);
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if(iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ return *this;
+ }
+ virtual ~__point_iterator()
+ {
+ if(_Point != 0)
+ delete _Point;
+ }
+ //protected://FIXME
+ public:
+ inline __point_iterator(vertex_container_iterator iA,
+ vertex_container_iterator iB,
+ vertex_container_iterator ibegin,
+ vertex_container_iterator iend,
+ int currentn,
+ int n,
+ float step, float t=0.f, float iCurvilinearLength = 0.f)
+ : parent_class()
+ {
+ __A = iA;
+ __B = iB;
+ _begin = ibegin;
+ _end = iend;
+ _CurvilinearLength = iCurvilinearLength;
+ _step = step;
+ _t = t;
+ _Point = 0;
+ _n = n;
+ _currentn = currentn;
+ }
+
+ public:
+
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ decrement();
+ return *this;
+ }
+ inline Self operator--(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ decrement(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return ((__A!=b.__A) || (__B!=b.__B) || (_t != b._t));
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual typename Traits::reference operator*() const
+ {
+ if(_Point != 0)
+ {
+ delete _Point;
+ _Point = 0;
+ }
+ if((_currentn < 0) || (_currentn >= _n))
+ return _Point; // 0 in this case
+ return (_Point = new Point(*__A,*__B,_t));
+ }
+ virtual typename Traits::pointer operator->() const { return &(operator*());}
+
+ public:
+ virtual bool begin() const
+ {
+ if((__A == _begin) && (_t < (float)M_EPSILON))
+ return true;
+ return false;
+ }
+ virtual bool end() const
+ {
+ if((__B == _end))
+ return true;
+ return false;
+ }
+ protected:
+ virtual void increment()
+ {
+ if(_Point != 0)
+ {
+ delete _Point;
+ _Point = 0;
+ }
+ if((_currentn == _n-1) && (_t == 1.f))
+ {
+ // we're setting the iterator to end
+ ++__A;
+ ++__B;
+ ++_currentn;
+ _t = 0.f;
+ return;
+ }
+
+ if(0 == _step) // means we iterate over initial vertices
+ {
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength += vec_tmp.norm();
+ if(_currentn == _n-1)
+ {
+ _t = 1.f;
+ return;
+ }
+ ++__B;
+ ++__A;
+ ++_currentn;
+ return;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = vec_tmp2.norm();
+
+ if(normAB > M_EPSILON)
+ {
+ _CurvilinearLength += _step;
+ _t = _t + _step/normAB;
+ }
+ else
+ _t = 1.f; // AB is a null segment, we're directly at its end
+ //if normAB ~= 0, we don't change these values
+ if(_t >= 1)
+ {
+ _CurvilinearLength -= normAB*(_t-1);
+ if(_currentn == _n-1)
+ _t=1.f;
+ else
+ {
+ _t = 0.f;
+ ++_currentn;
+ ++__A;++__B;
+ }
+ }
+ }
+ virtual void decrement()
+ {
+ if(_Point != 0)
+ {
+ delete _Point;
+ _Point = 0;
+ }
+
+ if(_t == 0.f) //we're at the beginning of the edge
+ {
+ _t = 1.f;
+ --_currentn;
+ --__A; --__B;
+ if(_currentn == _n-1)
+ return;
+ }
+
+ if(0 == _step) // means we iterate over initial vertices
+ {
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength -= vec_tmp.norm();
+ _t = 0;
+ return;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = vec_tmp2.norm();
+
+ if(normAB >M_EPSILON)
+ {
+ _CurvilinearLength -= _step;
+ _t = _t - _step/normAB;
+ }
+ else
+ _t = -1.f; // We just need a negative value here
+
+ // round value
+ if(fabs(_t) < (float)M_EPSILON)
+ _t = 0.0;
+ if(_t < 0)
+ {
+ if(_currentn == 0)
+ _CurvilinearLength = 0.f;
+ else
+ _CurvilinearLength += normAB*(-_t);
+ _t = 0.f;
+ }
+ }
+ };
+
+
+
+} // end of namespace StrokeInternal
+
+
+#endif // ADVANCEDCURVEITERATORS_H
diff --git a/source/blender/freestyle/intern/stroke/CurveIterators.h b/source/blender/freestyle/intern/stroke/CurveIterators.h
new file mode 100755
index 00000000000..a45ef4bfdaf
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/CurveIterators.h
@@ -0,0 +1,299 @@
+//
+// Filename : CurveIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the elements of the Curve
+// Date of creation : 01/08/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef CURVEITERATORS_H
+# define CURVEITERATORS_H
+
+#include "Stroke.h"
+#include "Curve.h"
+
+namespace CurveInternal {
+
+ /*! iterator on a curve. Allows an iterating outside
+ * initial vertices. A CurvePoint is instanciated an returned
+ * when the iterator is dereferenced.
+ */
+
+ class CurvePointIterator : public Interface0DIteratorNested
+ {
+ public:
+ friend class ::Curve;
+ public:
+ float _CurvilinearLength;
+ float _step;
+ ::Curve::vertex_container::iterator __A;
+ ::Curve::vertex_container::iterator __B;
+ ::Curve::vertex_container::iterator _begin;
+ ::Curve::vertex_container::iterator _end;
+ int _n;
+ int _currentn;
+ float _t;
+ mutable CurvePoint _Point;
+ float _CurveLength;
+
+ public:
+
+ public:
+ inline CurvePointIterator(float step = 0.f)
+ : Interface0DIteratorNested()
+ {
+ _step = step;
+ _CurvilinearLength = 0.f;
+ _t = 0.f;
+ //_Point = 0;
+ _n = 0;
+ _currentn = 0;
+ _CurveLength=0;
+ }
+
+ inline CurvePointIterator(const CurvePointIterator& iBrother)
+ : Interface0DIteratorNested()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ _Point = iBrother._Point;
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ _CurveLength = iBrother._CurveLength;
+ }
+ inline CurvePointIterator& operator=(const CurvePointIterator& iBrother)
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ _Point = iBrother._Point;
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ _CurveLength = iBrother._CurveLength;
+ return *this;
+ }
+ virtual ~CurvePointIterator()
+ {
+ }
+ protected:
+ inline CurvePointIterator(::Curve::vertex_container::iterator iA,
+ ::Curve::vertex_container::iterator iB,
+ ::Curve::vertex_container::iterator ibegin,
+ ::Curve::vertex_container::iterator iend,
+ int currentn,
+ int n,
+ float iCurveLength,
+ float step, float t=0.f, float iCurvilinearLength = 0.f)
+ : Interface0DIteratorNested()
+ {
+ __A = iA;
+ __B = iB;
+ _begin = ibegin;
+ _end = iend;
+ _CurvilinearLength = iCurvilinearLength;
+ _step = step;
+ _t = t;
+ _n = n;
+ _currentn = currentn;
+ _CurveLength = iCurveLength;
+ }
+
+ public:
+
+ virtual CurvePointIterator* copy() const {
+ return new CurvePointIterator(*this);
+ }
+
+ inline Interface0DIterator castToInterface0DIterator() const{
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(*this));
+ return ret;
+ }
+ virtual string getExactTypeName() const {
+ return "CurvePointIterator";
+ }
+
+ // operators
+ inline CurvePointIterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+
+ inline CurvePointIterator& operator--() // operator corresponding to ++i
+ {
+ decrement();
+ return *this;
+ }
+
+ // comparibility
+ virtual bool operator==(const Interface0DIteratorNested& b) const
+ {
+ const CurvePointIterator* it_exact = dynamic_cast<const CurvePointIterator*>(&b);
+ if (!it_exact)
+ return false;
+ return ((__A==it_exact->__A) && (__B==it_exact->__B) && (_t == it_exact->_t));
+ }
+
+ // dereferencing
+ virtual CurvePoint& operator*()
+ {
+ return (_Point = CurvePoint(*__A,*__B,_t));
+ }
+ virtual CurvePoint* operator->() { return &(operator*());}
+ public:
+ virtual bool isBegin() const
+ {
+ if((__A == _begin) && (_t < (float)M_EPSILON))
+ return true;
+ return false;
+ }
+ virtual bool isEnd() const
+ {
+ if(__B == _end)
+ return true;
+ return false;
+ }
+
+// protected:
+
+ virtual int increment()
+ {
+ if((_currentn == _n-1) && (_t == 1.f))
+ {
+ // we're setting the iterator to end
+ ++__A;
+ ++__B;
+ ++_currentn;
+ _t = 0.f;
+ return 0;
+ }
+
+ if(0 == _step) // means we iterate over initial vertices
+ {
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength += (float)vec_tmp.norm();
+ if(_currentn == _n-1)
+ {
+ _t = 1.f;
+ return 0;
+ }
+ ++__B;
+ ++__A;
+ ++_currentn;
+ return 0;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = (float)vec_tmp2.norm();
+
+ if(normAB > M_EPSILON)
+ {
+ _CurvilinearLength += _step;
+ _t = _t + _step/normAB;
+ }
+ else
+ _t = 1.f; // AB is a null segment, we're directly at its end
+ //if normAB ~= 0, we don't change these values
+ if(_t >= 1)
+ {
+ _CurvilinearLength -= normAB*(_t-1);
+ if(_currentn == _n-1)
+ _t=1.f;
+ else
+ {
+ _t = 0.f;
+ ++_currentn;
+ ++__A;++__B;
+ }
+ }
+ return 0;
+ }
+ virtual int decrement()
+ {
+ if(_t == 0.f) //we're at the beginning of the edge
+ {
+ _t = 1.f;
+ --_currentn;
+ --__A; --__B;
+ if(_currentn == _n-1)
+ return 0;
+ }
+
+ if(0 == _step) // means we iterate over initial vertices
+ {
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength -= (float)vec_tmp.norm();
+ _t = 0;
+ return 0;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = (float)vec_tmp2.norm();
+
+ if(normAB >M_EPSILON)
+ {
+ _CurvilinearLength -= _step;
+ _t = _t - _step/normAB;
+ }
+ else
+ _t = -1.f; // We just need a negative value here
+
+ // round value
+ if(fabs(_t) < (float)M_EPSILON)
+ _t = 0.0;
+ if(_t < 0)
+ {
+ if(_currentn == 0)
+ _CurvilinearLength = 0.f;
+ else
+ _CurvilinearLength += normAB*(-_t);
+ _t = 0.f;
+ }
+ return 0;
+ }
+
+ virtual float t() const{
+ return _CurvilinearLength;
+ }
+ virtual float u() const{
+ return _CurvilinearLength/_CurveLength;
+ }
+ };
+
+
+
+} // end of namespace StrokeInternal
+
+#endif // CURVEITERATORS_H
diff --git a/source/blender/freestyle/intern/stroke/Modifiers.h b/source/blender/freestyle/intern/stroke/Modifiers.h
new file mode 100755
index 00000000000..21bebebc6f8
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Modifiers.h
@@ -0,0 +1,71 @@
+//
+// Filename : Modifiers.h
+// Author : Stephane Grabli
+// Purpose : modifiers...
+// Date of creation : 05/01/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef MODIFIERS_H
+# define MODIFIERS_H
+
+# include "TimeStamp.h"
+
+/* ----------------------------------------- *
+ * *
+ * modifiers *
+ * *
+ * ----------------------------------------- */
+/*! Base class for modifiers.
+ * Modifiers are used in the
+ * Operators in order to "mark"
+ * the processed Interface1D.
+ */
+template<class Edge>
+struct EdgeModifier : public unary_function<Edge,void>
+{
+ /*! Default construction */
+ EdgeModifier() : unary_function<Edge,void>() {}
+ /*! the () operator */
+ virtual void operator()(Edge& iEdge) {}
+};
+
+/*! Modifier that sets the time stamp
+ * of an Interface1D to the time stamp
+ * of the system.
+ */
+template<class Edge>
+struct TimestampModifier : public EdgeModifier<Edge>
+{
+ /*! Default constructor */
+ TimestampModifier() : EdgeModifier<Edge>() {}
+ /*! The () operator. */
+ virtual void operator()(Edge& iEdge)
+ {
+ TimeStamp *timestamp = TimeStamp::instance();
+ iEdge.setTimeStamp(timestamp->getTimeStamp());
+ }
+};
+
+#endif // MODIFIERS_H
diff --git a/source/blender/freestyle/intern/stroke/Module.h b/source/blender/freestyle/intern/stroke/Module.h
new file mode 100755
index 00000000000..591bb157392
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Module.h
@@ -0,0 +1,72 @@
+//
+// Filename : Module.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Set the type of the module
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef MODULE_H
+# define MODULE_H
+
+# include "Canvas.h"
+# include "StyleModule.h"
+
+class Module
+{
+public:
+
+ static void setAlwaysRefresh(bool b = true) {
+ getCurrentStyleModule()->setAlwaysRefresh(b);
+ }
+
+ static void setCausal(bool b = true) {
+ getCurrentStyleModule()->setCausal(b);
+ }
+
+ static void setDrawable(bool b = true) {
+ getCurrentStyleModule()->setDrawable(b);
+ }
+
+ static bool getAlwaysRefresh() {
+ return getCurrentStyleModule()->getAlwaysRefresh();
+ }
+
+ static bool getCausal() {
+ return getCurrentStyleModule()->getCausal();
+ }
+
+ static bool getDrawable() {
+ return getCurrentStyleModule()->getDrawable();
+ }
+
+private:
+
+ static StyleModule* getCurrentStyleModule() {
+ Canvas* canvas = Canvas::getInstance();
+ return canvas->getCurrentStyleModule();
+ }
+};
+
+#endif // MODULE_H
diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp
new file mode 100755
index 00000000000..09833bf4b4a
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Operators.cpp
@@ -0,0 +1,1236 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Operators.h"
+#include <algorithm>
+#include <stdexcept>
+#include "Canvas.h"
+#include "Stroke.h"
+
+LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_view_edges_set;
+LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_chains_set;
+LIB_STROKE_EXPORT Operators::I1DContainer* Operators::_current_set = NULL;
+LIB_STROKE_EXPORT Operators::StrokesContainer Operators::_current_strokes_set;
+
+int Operators::select(UnaryPredicate1D& pred) {
+ if (!_current_set)
+ return 0;
+ if(_current_set->empty())
+ return 0;
+ I1DContainer new_set;
+ I1DContainer rejected;
+ Functions1D::ChainingTimeStampF1D cts;
+ Functions1D::TimeStampF1D ts;
+ I1DContainer::iterator it = _current_set->begin();
+ I1DContainer::iterator itbegin = it;
+ while (it != _current_set->end()) {
+ Interface1D * i1d = *it;
+ cts(*i1d); // mark everyone's chaining time stamp anyway
+ if(pred(*i1d) < 0){
+ new_set.clear();
+ rejected.clear();
+ return -1;
+ }
+ if(pred.result){
+ new_set.push_back(i1d);
+ ts(*i1d);
+ }else{
+ rejected.push_back(i1d);
+ }
+ ++it;
+ }
+ if((*itbegin)->getExactTypeName() != "ViewEdge"){
+ for (it = rejected.begin();
+ it != rejected.end();
+ ++it)
+ delete *it;
+ }
+ rejected.clear();
+ _current_set->clear();
+ *_current_set = new_set;
+ return 0;
+}
+
+
+int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it,
+ UnaryPredicate1D& pred,
+ UnaryFunction1D_void& modifier) {
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ ViewEdge* edge;
+ I1DContainer new_chains_set;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge) {
+ if (pred(**it_edge) < 0)
+ goto error;
+ if (pred.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+
+ Chain* new_chain = new Chain(id);++id;
+ for (;;) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ if (modifier(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ ++it;
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred.result)
+ break;
+ }
+ new_chains_set.push_back(new_chain);
+ }
+
+ if (!new_chains_set.empty()) {
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ _current_chains_set.push_back(*it);
+ }
+ new_chains_set.clear();
+ _current_set = &_current_chains_set;
+ }
+ return 0;
+
+error:
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ delete (*it);
+ }
+ new_chains_set.clear();
+ return -1;
+}
+
+
+int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it,
+ UnaryPredicate1D& pred) {
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1);
+ ViewEdge* edge;
+ I1DContainer new_chains_set;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge) {
+ if (pred(**it_edge) < 0)
+ goto error;
+ if (pred.result)
+ continue;
+ if (pred_ts(**it_edge) < 0)
+ goto error;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+
+ Chain* new_chain = new Chain(id);++id;
+ for (;;) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ ++it;
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred.result)
+ break;
+ if (pred_ts(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred_ts.result)
+ break;
+ }
+ new_chains_set.push_back(new_chain);
+ }
+
+ if (!new_chains_set.empty()) {
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ _current_chains_set.push_back(*it);
+ }
+ new_chains_set.clear();
+ _current_set = &_current_chains_set;
+ }
+ return 0;
+
+error:
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ delete (*it);
+ }
+ new_chains_set.clear();
+ return -1;
+}
+
+
+//void Operators::bidirectionalChain(ViewEdgeIterator& it,
+// UnaryPredicate1D& pred,
+// UnaryFunction1D_void& modifier) {
+// if (_current_view_edges_set.empty())
+// return;
+//
+// unsigned id = 0;
+// ViewEdge* edge;
+// Chain* new_chain;
+//
+// for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+// it_edge != _current_view_edges_set.end();
+// ++it_edge) {
+// if (pred(**it_edge))
+// continue;
+//
+// edge = dynamic_cast<ViewEdge*>(*it_edge);
+// it.setBegin(edge);
+// it.setCurrentEdge(edge);
+//
+// Chain* new_chain = new Chain(id);++id;
+// //ViewEdgeIterator it_back(it);--it_back; // FIXME
+// do {
+// new_chain->push_viewedge_back(*it, it.getOrientation());
+// modifier(**it);
+// ++it;
+// } while (!it.isEnd() && !pred(**it));
+// it.setBegin(edge);
+// it.setCurrentEdge(edge);
+// --it;
+// while (!it.isEnd() && !pred(**it)) {
+// new_chain->push_viewedge_front(*it, it.getOrientation());
+// modifier(**it);
+// --it;
+// }
+//
+// _current_chains_set.push_back(new_chain);
+// }
+//
+// if (!_current_chains_set.empty())
+// _current_set = &_current_chains_set;
+//}
+//
+//void Operators::bidirectionalChain(ViewEdgeIterator& it,
+// UnaryPredicate1D& pred) {
+// if (_current_view_edges_set.empty())
+// return;
+//
+// unsigned id = 0;
+// Functions1D::IncrementChainingTimeStampF1D ts;
+// Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1);
+//
+// ViewEdge* edge;
+// Chain* new_chain;
+//
+// for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+// it_edge != _current_view_edges_set.end();
+// ++it_edge) {
+// if (pred(**it_edge) || pred_ts(**it_edge))
+// continue;
+//
+// edge = dynamic_cast<ViewEdge*>(*it_edge);
+// it.setBegin(edge);
+// it.setCurrentEdge(edge);
+ //
+ // Chain* new_chain = new Chain(id);++id;
+ // //ViewEdgeIterator it_back(it);--it_back;//FIXME
+ // do {
+ // new_chain->push_viewedge_back(*it, it.getOrientation());
+ // ts(**it);
+ // ++it;
+ // } while (!it.isEnd() && !pred(**it) && !pred_ts(**it));
+ // it.setBegin(edge);
+ // it.setCurrentEdge(edge);
+ // --it;
+ // while (!it.isEnd() && !pred(**it) && !pred_ts(**it)) {
+ // new_chain->push_viewedge_front(*it, it.getOrientation());
+ // ts(**it);
+ // --it;
+ // }
+ //
+ // _current_chains_set.push_back(new_chain);
+ // }
+ //
+ // if (!_current_chains_set.empty())
+ // _current_set = &_current_chains_set;
+ //}
+
+int Operators::bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred) {
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1);
+ ViewEdge* edge;
+ I1DContainer new_chains_set;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge) {
+ if (pred(**it_edge) < 0)
+ goto error;
+ if (pred.result)
+ continue;
+ if (pred_ts(**it_edge) < 0)
+ goto error;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ // re-init iterator
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.init() < 0)
+ goto error;
+
+ Chain* new_chain = new Chain(id);++id;
+ //ViewEdgeIterator it_back(it);--it_back;//FIXME
+ for (;;) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ if (it.increment() < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred.result)
+ break;
+ }
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.decrement() < 0) {
+ delete new_chain;
+ goto error;
+ }
+ while (!it.isEnd()) {
+ if (pred(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred.result)
+ break;
+ new_chain->push_viewedge_front(*it, it.getOrientation());
+ ts(**it);
+ if (it.decrement() < 0) {
+ delete new_chain;
+ goto error;
+ }
+ }
+ new_chains_set.push_back(new_chain);
+ }
+
+ if (!new_chains_set.empty()) {
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ _current_chains_set.push_back(*it);
+ }
+ new_chains_set.clear();
+ _current_set = &_current_chains_set;
+ }
+ return 0;
+
+error:
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ delete (*it);
+ }
+ new_chains_set.clear();
+ return -1;
+}
+
+int Operators::bidirectionalChain(ChainingIterator& it) {
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1);
+ ViewEdge* edge;
+ I1DContainer new_chains_set;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge) {
+ if (pred_ts(**it_edge) < 0)
+ goto error;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ // re-init iterator
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.init() < 0)
+ goto error;
+
+ Chain* new_chain = new Chain(id);++id;
+ //ViewEdgeIterator it_back(it);--it_back;//FIXME
+ do {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ if (it.increment() < 0) { // FIXME
+ delete new_chain;
+ goto error;
+ }
+ } while (!it.isEnd());
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.decrement() < 0) { // FIXME
+ delete new_chain;
+ goto error;
+ }
+ while (!it.isEnd()) {
+ new_chain->push_viewedge_front(*it, it.getOrientation());
+ ts(**it);
+ if (it.decrement() < 0) { // FIXME
+ delete new_chain;
+ goto error;
+ }
+ }
+ new_chains_set.push_back(new_chain);
+ }
+
+ if (!new_chains_set.empty()) {
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ _current_chains_set.push_back(*it);
+ }
+ new_chains_set.clear();
+ _current_set = &_current_chains_set;
+ }
+ return 0;
+
+error:
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ delete (*it);
+ }
+ new_chains_set.clear();
+ return -1;
+}
+
+int Operators::sequentialSplit(UnaryPredicate0D& pred,
+ float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ CurvePoint *point;
+ Chain * new_curve;
+ I1DContainer splitted_chains;
+ Interface0DIterator first;
+ Interface0DIterator end;
+ Interface0DIterator last;
+ Interface0DIterator it;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (;
+ cit != citend;
+ ++cit) {
+
+ Id currentId = (*cit)->getId();
+ new_curve = new Chain(currentId);
+ first = (*cit)->pointsBegin(sampling);
+ end = (*cit)->pointsEnd(sampling);
+ last = end;--last;
+ it = first;
+
+ point = dynamic_cast<CurvePoint*>(&(*it));
+ new_curve->push_vertex_back(point);++it;
+ for(; it!= end; ++it)
+ {
+ point = dynamic_cast<CurvePoint*>(&(*it));
+ new_curve->push_vertex_back(point);
+ if(pred(it) < 0)
+ {
+ delete new_curve;
+ goto error;
+ }
+ if(pred.result && (it!=last))
+ {
+ splitted_chains.push_back(new_curve);
+ currentId.setSecond(currentId.getSecond()+1);
+ new_curve = new Chain(currentId);
+ new_curve->push_vertex_back(point);
+ }
+ }
+ if(new_curve->nSegments() == 0){
+ delete new_curve;
+ return 0;
+ }
+
+ splitted_chains.push_back(new_curve);
+ }
+
+ // Update the current set of chains:
+ cit = _current_chains_set.begin();
+ for(;
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ _current_chains_set.clear();
+#if 0
+ _current_chains_set = splitted_chains;
+#else
+ for (cit = splitted_chains.begin(), citend = splitted_chains.end();
+ cit != citend;
+ ++cit) {
+ if ((*cit)->getLength2D() < M_EPSILON) {
+ delete (*cit);
+ continue;
+ }
+ _current_chains_set.push_back(*cit);
+ }
+#endif
+ splitted_chains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+
+error:
+ cit = splitted_chains.begin();
+ citend = splitted_chains.end();
+ for(;
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ return -1;
+}
+
+int Operators::sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred,
+ float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ CurvePoint *point;
+ Chain * new_curve;
+ I1DContainer splitted_chains;
+ Interface0DIterator first;
+ Interface0DIterator end;
+ Interface0DIterator last;
+ Interface0DIterator itStart;
+ Interface0DIterator itStop;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (;
+ cit != citend;
+ ++cit) {
+ Id currentId = (*cit)->getId();
+ first = (*cit)->pointsBegin(sampling);
+ end = (*cit)->pointsEnd(sampling);
+ last = end;--last;
+ itStart = first;
+ do{
+ itStop = itStart;++itStop;
+
+ new_curve = new Chain(currentId);
+ currentId.setSecond(currentId.getSecond()+1);
+
+ point = dynamic_cast<CurvePoint*>(&(*itStart));
+ new_curve->push_vertex_back(point);
+ do{
+ point = dynamic_cast<CurvePoint*>(&(*itStop));
+ new_curve->push_vertex_back(point);
+ ++itStop;
+ if(itStop == end)
+ break;
+ if(stoppingPred(itStop) < 0){
+ delete new_curve;
+ goto error;
+ }
+ }while(!stoppingPred.result);
+ if(itStop!=end){
+ point = dynamic_cast<CurvePoint*>(&(*itStop));
+ new_curve->push_vertex_back(point);
+ }
+ if(new_curve->nSegments() == 0){
+ delete new_curve;
+ }else{
+ splitted_chains.push_back(new_curve);
+ }
+ // find next start
+ do{
+ ++itStart;
+ if(itStart == end)
+ break;
+ if(startingPred(itStart) < 0)
+ goto error;
+ }while(!startingPred.result);
+ }while((itStart!=end) && (itStart!=last));
+ }
+
+ // Update the current set of chains:
+ cit = _current_chains_set.begin();
+ for(;
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ _current_chains_set.clear();
+#if 0
+ _current_chains_set = splitted_chains;
+#else
+ for (cit = splitted_chains.begin(), citend = splitted_chains.end();
+ cit != citend;
+ ++cit) {
+ if ((*cit)->getLength2D() < M_EPSILON) {
+ delete (*cit);
+ continue;
+ }
+ _current_chains_set.push_back(*cit);
+ }
+#endif
+ splitted_chains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+
+error:
+ cit = splitted_chains.begin();
+ citend = splitted_chains.end();
+ for(;
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ return -1;
+}
+
+#include "CurveIterators.h"
+
+// Internal function
+int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling,
+ Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains)
+{
+ if(((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)){
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling);
+ CurveInternal::CurvePointIterator second = first; ++second;
+ CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling);
+ CurveInternal::CurvePointIterator it = second;
+ CurveInternal::CurvePointIterator split = second;
+ Interface0DIterator it0d = it.castToInterface0DIterator();
+ real _min = FLT_MAX;++it;//func(it0d);++it;
+ CurveInternal::CurvePointIterator next = it;++next;
+
+ bool bsplit = false;
+ for(; ((it != end) && (next != end)); ++it,++next){
+ it0d = it.castToInterface0DIterator();
+ if (func(it0d) < 0)
+ return -1;
+ if(func.result < _min){
+ _min = func.result;
+ split = it;
+ bsplit = true;
+ }
+ }
+
+ if(!bsplit){ // we didn't find any minimum
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ // retrieves the current splitting id
+ Id * newId = _curve->getSplittingId();
+ if(newId == 0){
+ newId = new Id(_curve->getId());
+ _curve->setSplittingId(newId);
+ }
+
+ Chain *new_curve_a = new Chain(*newId);
+ newId->setSecond(newId->getSecond()+1);
+ new_curve_a->setSplittingId(newId);
+ Chain *new_curve_b = new Chain(*newId);
+ newId->setSecond(newId->getSecond()+1);
+ new_curve_b->setSplittingId(newId);
+
+ CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend=_curve->curveVerticesEnd();
+ CurveInternal::CurvePointIterator vnext = vit; ++vnext;
+
+
+ for(; (vit!=vitend)&&(vnext!=vitend)&&(vnext._CurvilinearLength<split._CurvilinearLength); ++vit,++vnext){
+ new_curve_a->push_vertex_back(&(*vit));
+ }
+ if((vit==vitend) || (vnext == vitend)){
+ cout << "The split takes place in bad location" << endl;
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+
+ // build the two resulting chains
+ new_curve_a->push_vertex_back(&(*vit));
+ new_curve_a->push_vertex_back(&(*split));
+ new_curve_b->push_vertex_back(&(*split));
+
+ for(vit=vnext;vit!=vitend;++vit)
+ new_curve_b->push_vertex_back(&(*vit));
+
+ // let's check whether one or two of the two new curves
+ // satisfy the stopping condition or not.
+ // (if one of them satisfies it, we don't split)
+ if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
+ delete new_curve_a;
+ delete new_curve_b;
+ return -1;
+ }
+ if(pred.result){
+ // we don't actually create these two chains
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+ // here we know we'll split _curve:
+ splitted_chains.push_back(_curve);
+
+ __recursiveSplit(new_curve_a, func, pred, sampling, newChains, splitted_chains);
+ __recursiveSplit(new_curve_b, func, pred, sampling, newChains, splitted_chains);
+ return 0;
+}
+
+int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+
+ Chain *currentChain = 0;
+ I1DContainer splitted_chains;
+ I1DContainer newChains;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (;
+ cit != citend;
+ ++cit) {
+ currentChain = dynamic_cast<Chain*>(*cit);
+ if(!currentChain)
+ continue;
+ // let's check the first one:
+ if (pred(*currentChain) < 0)
+ return -1;
+ if(!pred.result){
+ __recursiveSplit(currentChain, func, pred, sampling, newChains, splitted_chains);
+ }else{
+ newChains.push_back(currentChain);
+ }
+ }
+ // Update the current set of chains:
+ if(!splitted_chains.empty()){
+ for(cit = splitted_chains.begin(), citend = splitted_chains.end();
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ }
+
+ _current_chains_set.clear();
+#if 0
+ _current_chains_set = newChains;
+#else
+ for (cit = newChains.begin(), citend = newChains.end();
+ cit != citend;
+ ++cit) {
+ if ((*cit)->getLength2D() < M_EPSILON) {
+ delete (*cit);
+ continue;
+ }
+ _current_chains_set.push_back(*cit);
+ }
+#endif
+ newChains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+
+
+// recursive split with pred 0D
+int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling,
+ Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains)
+{
+ if(((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)){
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling);
+ CurveInternal::CurvePointIterator second = first; ++second;
+ CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling);
+ CurveInternal::CurvePointIterator it = second;
+ CurveInternal::CurvePointIterator split = second;
+ Interface0DIterator it0d = it.castToInterface0DIterator();
+ //real _min = func(it0d);++it;
+ real _min = FLT_MAX;++it;
+ real mean = 0.f;
+ //soc unused - real variance = 0.f;
+ unsigned count = 0;
+ CurveInternal::CurvePointIterator next = it;++next;
+
+ bool bsplit = false;
+ for(; ((it != end) && (next != end)); ++it,++next){
+ ++count;
+ it0d = it.castToInterface0DIterator();
+ if(pred0d(it0d) < 0)
+ return -1;
+ if(!pred0d.result)
+ continue;
+ if(func(it0d) < 0)
+ return -1;
+ mean += func.result;
+ if(func.result < _min){
+ _min = func.result;
+ split = it;
+ bsplit = true;
+ }
+ }
+ mean /= (float)count;
+
+ //if((!bsplit) || (mean-_min>mean)){ // we didn't find any minimum
+ if(!bsplit){ // we didn't find any minimum
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ // retrieves the current splitting id
+ Id * newId = _curve->getSplittingId();
+ if(newId == 0){
+ newId = new Id(_curve->getId());
+ _curve->setSplittingId(newId);
+ }
+
+ Chain *new_curve_a = new Chain(*newId);
+ newId->setSecond(newId->getSecond()+1);
+ new_curve_a->setSplittingId(newId);
+ Chain *new_curve_b = new Chain(*newId);
+ newId->setSecond(newId->getSecond()+1);
+ new_curve_b->setSplittingId(newId);
+
+ CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend=_curve->curveVerticesEnd();
+ CurveInternal::CurvePointIterator vnext = vit; ++vnext;
+
+
+ for(; (vit!=vitend)&&(vnext!=vitend)&&(vnext._CurvilinearLength<split._CurvilinearLength); ++vit,++vnext){
+ new_curve_a->push_vertex_back(&(*vit));
+ }
+ if((vit==vitend) || (vnext == vitend)){
+ cout << "The split takes place in bad location" << endl;
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+
+ // build the two resulting chains
+ new_curve_a->push_vertex_back(&(*vit));
+ new_curve_a->push_vertex_back(&(*split));
+ new_curve_b->push_vertex_back(&(*split));
+
+ for(vit=vnext;vit!=vitend;++vit)
+ new_curve_b->push_vertex_back(&(*vit));
+
+ // let's check whether one or two of the two new curves
+ // satisfy the stopping condition or not.
+ // (if one of them satisfies it, we don't split)
+ if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
+ delete new_curve_a;
+ delete new_curve_b;
+ return -1;
+ }
+ if(pred.result){
+ // we don't actually create these two chains
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+ // here we know we'll split _curve:
+ splitted_chains.push_back(_curve);
+
+ __recursiveSplit(new_curve_a, func, pred0d, pred, sampling, newChains, splitted_chains);
+ __recursiveSplit(new_curve_b, func, pred0d, pred, sampling, newChains, splitted_chains);
+ return 0;
+}
+
+int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+
+ Chain *currentChain = 0;
+ I1DContainer splitted_chains;
+ I1DContainer newChains;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (;
+ cit != citend;
+ ++cit) {
+ currentChain = dynamic_cast<Chain*>(*cit);
+ if(!currentChain)
+ continue;
+ // let's check the first one:
+ if(pred(*currentChain) < 0)
+ return -1;
+ if(!pred.result){
+ __recursiveSplit(currentChain, func, pred0d, pred, sampling, newChains, splitted_chains);
+ }else{
+ newChains.push_back(currentChain);
+ }
+ }
+ // Update the current set of chains:
+ if(!splitted_chains.empty()){
+ for(cit = splitted_chains.begin(), citend = splitted_chains.end();
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ }
+
+ _current_chains_set.clear();
+#if 0
+ _current_chains_set = newChains;
+#else
+ for (cit = newChains.begin(), citend = newChains.end();
+ cit != citend;
+ ++cit) {
+ if ((*cit)->getLength2D() < M_EPSILON) {
+ delete (*cit);
+ continue;
+ }
+ _current_chains_set.push_back(*cit);
+ }
+#endif
+ newChains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+// Internal class
+class PredicateWrapper
+{
+public:
+
+ inline PredicateWrapper(BinaryPredicate1D& pred) {
+ _pred = &pred;
+ }
+
+ inline bool operator()(Interface1D* i1, Interface1D* i2) {
+ if ((*_pred)(*i1, *i2) < 0)
+ throw std::runtime_error("comparison failed");
+ return _pred->result;
+ }
+
+private:
+
+ BinaryPredicate1D* _pred;
+};
+
+int Operators::sort(BinaryPredicate1D& pred) {
+ if (!_current_set)
+ return 0;
+ PredicateWrapper wrapper(pred);
+ try {
+ std::sort(_current_set->begin(), _current_set->end(), wrapper);
+ }
+ catch (std::runtime_error &e) {
+ cerr << "Warning: Operator.sort(): " << e.what() << endl;
+ return -1;
+ }
+ return 0;
+}
+
+Stroke* createStroke(Interface1D& inter) {
+ Stroke* stroke = new Stroke;
+ stroke->setId(inter.getId());
+
+ float currentCurvilignAbscissa = 0.f;
+
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ Interface0DIterator itfirst = it;
+
+ Vec2r current(it->getPoint2D());
+ Vec2r previous = current;
+ SVertex* sv;
+ CurvePoint* cp;
+ StrokeVertex* stroke_vertex = NULL;
+ bool hasSingularity = false;
+
+ do {
+ cp = dynamic_cast<CurvePoint*>(&(*it));
+ if (!cp) {
+ sv = dynamic_cast<SVertex*>(&(*it));
+ if (!sv) {
+ cerr << "Warning: unexpected Vertex type" << endl;
+ continue;
+ }
+ stroke_vertex = new StrokeVertex(sv);
+ }
+ else
+ stroke_vertex = new StrokeVertex(cp);
+ current = stroke_vertex->getPoint2D();
+ Vec2r vec_tmp(current - previous);
+ real dist = vec_tmp.norm();
+ if (dist < 1e-6) hasSingularity = true;
+ currentCurvilignAbscissa += dist;
+ stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa);
+ stroke->push_back(stroke_vertex);
+ previous = current;
+ ++it;
+ } while((it != itend) && (it != itfirst));
+
+ if (it == itfirst) {
+ // Add last vertex:
+ cp = dynamic_cast<CurvePoint*>(&(*it));
+ if (!cp) {
+ sv = dynamic_cast<SVertex*>(&(*it));
+ if (!sv)
+ cerr << "Warning: unexpected Vertex type" << endl;
+ else
+ stroke_vertex = new StrokeVertex(sv);
+ }
+ else
+ stroke_vertex = new StrokeVertex(cp);
+ current = stroke_vertex->getPoint2D();
+ Vec2r vec_tmp(current - previous);
+ real dist = vec_tmp.norm();
+ if (dist < 1e-6) hasSingularity = true;
+ currentCurvilignAbscissa += dist;
+ stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa);
+ stroke->push_back(stroke_vertex);
+ }
+ // Discard the stroke if the number of stroke vertices is less than two
+ if (stroke->strokeVerticesSize() < 2) {
+ delete stroke;
+ return NULL;
+ }
+ stroke->setLength(currentCurvilignAbscissa);
+ if (hasSingularity) {
+ // Try to address singular points such that the distance between two
+ // subsequent vertices are smaller than epsilon.
+ Interface0DIterator v = stroke->verticesBegin();
+ Interface0DIterator vnext = v; ++vnext;
+ Vec2r next((*v).getPoint2D());
+ while (!vnext.isEnd()) {
+ current = next;
+ next = (*vnext).getPoint2D();
+ if ((next - current).norm() < 1e-6) {
+ Interface0DIterator vprevious = v;
+ if (!vprevious.isBegin())
+ --vprevious;
+
+ // collect a set of overlapping vertices (except the first one)
+ std::vector<Interface0D *> overlapping_vertices;
+ do {
+ overlapping_vertices.push_back(&(*vnext));
+ current = next;
+ ++v; ++vnext;
+ if (vnext.isEnd())
+ break;
+ next = (*vnext).getPoint2D();
+ } while ((next - current).norm() < 1e-6);
+
+ Vec2r target;
+ bool reverse;
+ if (!vnext.isEnd()) {
+ target = (*vnext).getPoint2D();
+ reverse = false;
+ } else if (!vprevious.isBegin()) {
+ target = (*vprevious).getPoint2D();
+ reverse = true;
+ } else {
+ // Discard the stroke because all stroke vertices are overlapping
+ delete stroke;
+ return NULL;
+ }
+ Vec2r dir(target - current);
+ real dist = dir.norm();
+ real len = 1e-3; // default offset length
+ int nvert = overlapping_vertices.size();
+ if (dist < len * nvert) {
+ len = dist / (nvert + 1);
+ }
+ dir.normalize();
+ Vec2r offset(dir * len);
+ //cout << "#vert " << nvert << " len " << len << " reverse? " << reverse << endl;
+
+ // add the offset to the overlapping vertices
+ StrokeVertex* sv;
+ std::vector<Interface0D *>::iterator it = overlapping_vertices.begin(),
+ itend = overlapping_vertices.end();
+ if (!reverse) {
+ int n = 1;
+ for (; it != itend; ++it) {
+ sv = dynamic_cast<StrokeVertex*>(*it);
+ sv->setPoint(sv->getPoint() + offset * n);
+ ++n;
+ }
+ } else {
+ int n = nvert;
+ for (; it != itend; ++it) {
+ sv = dynamic_cast<StrokeVertex*>(*it);
+ sv->setPoint(sv->getPoint() + offset * n);
+ --n;
+ }
+ }
+
+ if (vnext.isEnd())
+ break;
+ }
+ ++v; ++vnext;
+ }
+ }
+ {
+ // Check if the stroke no longer contains singular points
+ Interface0DIterator v = stroke->verticesBegin();
+ Interface0DIterator vnext = v; ++vnext;
+ Vec2r next((*v).getPoint2D());
+ bool warning = false;
+ while (!vnext.isEnd()) {
+ current = next;
+ next = (*vnext).getPoint2D();
+ if ((next - current).norm() < 1e-6) {
+ warning = true;
+ break;
+ }
+ ++v; ++vnext;
+ }
+ if (warning) {
+ printf("Warning: stroke contains singular points.\n");
+ }
+ }
+ return stroke;
+}
+
+
+inline int applyShading(Stroke& stroke, vector<StrokeShader*>& shaders) {
+ for (vector<StrokeShader*>::iterator it = shaders.begin(); it != shaders.end(); ++it) {
+ if ((*it)->shade(stroke) < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+int Operators::create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders) {
+ //Canvas* canvas = Canvas::getInstance();
+ if (!_current_set) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ StrokesContainer new_strokes_set;
+ for (Operators::I1DContainer::iterator it = _current_set->begin();
+ it != _current_set->end();
+ ++it) {
+ if (pred(**it) < 0)
+ goto error;
+ if (!pred.result)
+ continue;
+
+ Stroke* stroke = createStroke(**it);
+ if (stroke) {
+ if (applyShading(*stroke, shaders) < 0) {
+ delete stroke;
+ goto error;
+ }
+ //canvas->RenderStroke(stroke);
+ new_strokes_set.push_back(stroke);
+ }
+ }
+
+ for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); ++it) {
+ _current_strokes_set.push_back(*it);
+ }
+ new_strokes_set.clear();
+ return 0;
+
+error:
+ for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); ++it) {
+ delete (*it);
+ }
+ new_strokes_set.clear();
+ return -1;
+}
+
+
+void Operators::reset() {
+ ViewMap* vm = ViewMap::getInstance();
+ if (!vm) {
+ cerr << "Error: no ViewMap computed yet" << endl;
+ return;
+ }
+ _current_view_edges_set.clear();
+ for (I1DContainer::iterator it = _current_chains_set.begin();
+ it != _current_chains_set.end();
+ ++it)
+ delete *it;
+ _current_chains_set.clear();
+#if 0
+ _current_view_edges_set.insert(_current_view_edges_set.begin(),
+ vm->ViewEdges().begin(),
+ vm->ViewEdges().end());
+#else
+ ViewMap::viewedges_container& vedges = vm->ViewEdges();
+ ViewMap::viewedges_container::iterator ve=vedges.begin(), veend=vedges.end();
+ for (; ve != veend; ++ve) {
+ if ((*ve)->getLength2D() < M_EPSILON)
+ continue;
+ _current_view_edges_set.push_back(*ve);
+ }
+#endif
+ _current_set = &_current_view_edges_set;
+ _current_strokes_set.clear();
+}
diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h
new file mode 100755
index 00000000000..d705d5af5b2
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Operators.h
@@ -0,0 +1,311 @@
+//
+// Filename : Operators.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class gathering stroke creation algorithms
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef OPERATORS_H
+# define OPERATORS_H
+
+# include "../view_map/Interface1D.h"
+# include <vector>
+# include <iostream>
+# include "Predicates1D.h"
+# include "Predicates0D.h"
+# include "../view_map/ViewMap.h"
+# include "Chain.h"
+# include "ChainingIterators.h"
+# include "../system/TimeStamp.h"
+# include "StrokeShader.h"
+
+/*! Class defining the operators used in a style module.
+ * There are 4 classes of operators: Selection, Chaining,
+ * Splitting and Creating. All these operators are user controlled
+ * in the scripting language through Functors, Predicates and Shaders
+ * that are taken as arguments.
+ */
+class LIB_STROKE_EXPORT Operators {
+
+public:
+
+ typedef vector<Interface1D*> I1DContainer;
+ typedef vector<Stroke*> StrokesContainer;
+
+
+ //
+ // Operators
+ //
+ ////////////////////////////////////////////////
+
+ /*! Selects the ViewEdges of the ViewMap verifying
+ * a specified condition.
+ * \param pred The predicate expressing this condition
+ */
+ static int select(UnaryPredicate1D& pred);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list starts a new chain. The chaining
+ * operator then iterates over the ViewEdges of the ViewMap using the
+ * user specified iterator.
+ * This operator only iterates using the increment operator and is
+ * therefore unidirectional.
+ * \param it
+ * The iterator on the ViewEdges of the ViewMap. It contains
+ * the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping
+ * condition.
+ * \param modifier
+ * A function that takes a ViewEdge as argument and that
+ * is used to modify the processed ViewEdge state (the timestamp
+ * incrementation is a typical illustration of such a modifier)
+ */
+ static int chain(ViewEdgeInternal::ViewEdgeIterator& it,
+ UnaryPredicate1D& pred,
+ UnaryFunction1D_void& modifier);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list starts a new chain. The chaining
+ * operator then iterates over the ViewEdges of the ViewMap using the
+ * user specified iterator.
+ * This operator only iterates using the increment operator and is
+ * therefore unidirectional.
+ * This chaining operator is different from the previous one because
+ * it doesn't take any modifier as argument. Indeed, the time stamp (insuring
+ * that a ViewEdge is processed one time) is automatically managed in this case.
+ * \param it
+ * The iterator on the ViewEdges of the ViewMap. It contains
+ * the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping
+ * condition.
+ */
+ static int chain(ViewEdgeInternal::ViewEdgeIterator& it,
+ UnaryPredicate1D& pred);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list potentially starts a new chain. The chaining
+ * operator then iterates over the ViewEdges of the ViewMap using the
+ * user specified iterator.
+ * This operator iterates both using the increment and decrement operators and is
+ * therefore bidirectional.
+ * This operator works with a ChainingIterator which contains the
+ * chaining rules. It is this last one which can be told
+ * to chain only edges that belong to the selection or not to
+ * process twice a ViewEdge during the chaining.
+ * Each time a ViewEdge is added to a chain, its chaining time stamp
+ * is incremented. This allows you to keep track of
+ * the number of chains to which a ViewEdge belongs to.
+ * \param it
+ * The ChainingIterator on the ViewEdges of the ViewMap. It contains
+ * the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping
+ * condition.
+ */
+ static int bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred);
+
+ /*! The only difference with the above bidirectional chaining algorithm is
+ * that we don't need to pass a stopping criterion. This might be desirable
+ * when the stopping criterion is already contained in the iterator
+ * definition.
+ * Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list potentially starts a new chain. The chaining
+ * operator then iterates over the ViewEdges of the ViewMap using the
+ * user specified iterator.
+ * This operator iterates both using the increment and decrement operators and is
+ * therefore bidirectional.
+ * This operator works with a ChainingIterator which contains the
+ * chaining rules. It is this last one which can be told
+ * to chain only edges that belong to the selection or not to
+ * process twice a ViewEdge during the chaining.
+ * Each time a ViewEdge is added to a chain, its chaining time stamp
+ * is incremented. This allows you to keep track of
+ * the number of chains to which a ViewEdge belongs to.
+ * \param it
+ * The ChainingIterator on the ViewEdges of the ViewMap. It contains
+ * the chaining rule.
+ */
+ static int bidirectionalChain(ChainingIterator& it);
+
+ /*! Splits each chain of the current set of chains in a sequential way.
+ * The points of each chain are processed (with a specified sampling) sequentially.
+ * Each time a user specified starting condition is verified, a new chain begins and
+ * ends as soon as a user-defined stopping predicate is verified.
+ * This allows chains overlapping rather than chains partitioning.
+ * The first point of the initial chain is the first point of one of the
+ * resulting chains.
+ * The splitting ends when no more chain can start.
+ * \param startingPred
+ * The predicate on a point that expresses the starting
+ * condition
+ * \param stoppingPred
+ * The predicate on a point that expresses the stopping
+ * condition
+ * \param sampling
+ * The resolution used to sample the chain for the predicates
+ * evaluation. (The chain is not actually resampled, a virtual point
+ * only progresses along the curve using this resolution)
+ */
+ static int sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred,
+ float sampling = 0.f);
+
+ /*! Splits each chain of the current set of chains in a sequential way.
+ * The points of each chain are processed (with a specified sampling) sequentially
+ * and each time a user specified condition is verified, the chain is split into two chains.
+ * The resulting set of chains is a partition of the initial chain
+ * \param pred
+ * The predicate on a point that expresses the splitting
+ * condition
+ * \param sampling
+ * The resolution used to sample the chain for the predicate
+ * evaluation. (The chain is not actually resampled, a virtual point
+ * only progresses along the curve using this resolution)
+ */
+ static int sequentialSplit(UnaryPredicate0D& pred,
+ float sampling = 0.f);
+
+ /*! Splits the current set of chains in a recursive way.
+ * We process the points of each chain (with a specified sampling) to find
+ * the point minimizing a specified function. The chain is split in two at this
+ * point and the two new chains are processed in the same way.
+ * The recursivity level is controlled through a predicate 1D that expresses a stopping condition
+ * on the chain that is about to be processed.
+ * \param func
+ * The Unary Function evaluated at each point of the chain.
+ * The splitting point is the point minimizing this function
+ * \param pred
+ * The Unary Predicate ex pressing the recursivity stopping condition.
+ * This predicate is evaluated for each curve before it actually gets
+ * split. If pred(chain) is true, the curve won't be split anymore.
+ * \param sampling
+ * The resolution used to sample the chain for the predicates
+ * evaluation. (The chain is not actually resampled, a virtual point
+ * only progresses along the curve using this resolution)
+ */
+ static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling = 0);
+
+ /*! Splits the current set of chains in a recursive way.
+ * We process the points of each chain (with a specified sampling) to find
+ * the point minimizing a specified function. The chain is split in two at this
+ * point and the two new chains are processed in the same way.
+ * The user can specify a 0D predicate to make a first selection
+ * on the points that can potentially be split.
+ * A point that doesn't verify the 0D predicate won't be candidate
+ * in realizing the min.
+ * The recursivity level is controlled through a predicate 1D that expresses a stopping condition
+ * on the chain that is about to be processed.
+ * \param func
+ * The Unary Function evaluated at each point of the chain.
+ * The splitting point is the point minimizing this function
+ * \param pred0d
+ * The Unary Predicate 0D used to select the candidate points
+ * where the split can occur.
+ * For example, it is very likely that would rather have
+ * your chain splitting around its middle point than around
+ * one of its extremities. A 0D predicate working on
+ * the curvilinear abscissa allows to add this kind of constraints.
+ * \param pred
+ * The Unary Predicate ex pressing the recursivity stopping condition.
+ * This predicate is evaluated for each curve before it actually gets
+ * split. If pred(chain) is true, the curve won't be split anymore.
+ * \param sampling
+ * The resolution used to sample the chain for the predicates
+ * evaluation. (The chain is not actually resampled, a virtual point
+ * only progresses along the curve using this resolution)
+ *
+ */
+ static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling = 0);
+
+ /*! Sorts the current set of chains (or viewedges) according to the
+ * comparison predicate given as argument.
+ * \param pred
+ * The binary predicate used for the comparison
+ */
+ static int sort(BinaryPredicate1D& pred);
+
+ /*! Creates and shades the strokes from the current set of chains.
+ * A predicate can be specified to make a selection pass on the
+ * chains.
+ * \param pred
+ * The predicate that a chain must verify in order to
+ * be transform as a stroke
+ * \param shaders
+ * The list of shaders used to shade the strokes
+ */
+ static int create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders);
+
+ //
+ // Data access
+ //
+ ////////////////////////////////////////////////
+
+ static ViewEdge* getViewEdgeFromIndex(unsigned i) {
+ return dynamic_cast<ViewEdge*>(_current_view_edges_set[i]);
+ }
+
+ static Chain* getChainFromIndex(unsigned i) {
+ return dynamic_cast<Chain*>(_current_chains_set[i]);
+ }
+
+ static Stroke* getStrokeFromIndex(unsigned i) {
+ return _current_strokes_set[i];
+ }
+
+ static unsigned getViewEdgesSize() {
+ return _current_view_edges_set.size();
+ }
+
+ static unsigned getChainsSize() {
+ return _current_chains_set.size();
+ }
+
+ static unsigned getStrokesSize() {
+ return _current_strokes_set.size();
+ }
+
+ //
+ // Not exported in Python
+ //
+ //////////////////////////////////////////////////
+
+ static StrokesContainer* getStrokesSet() {
+ return &_current_strokes_set;
+ }
+
+ static void reset();
+
+private:
+
+ Operators() {}
+
+ static I1DContainer _current_view_edges_set;
+ static I1DContainer _current_chains_set;
+ static I1DContainer* _current_set;
+ static StrokesContainer _current_strokes_set;
+};
+
+#endif // OPERATORS_H
diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp
new file mode 100755
index 00000000000..dc9c94e0e11
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp
@@ -0,0 +1,89 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "PSStrokeRenderer.h"
+# include "Canvas.h"
+
+PSStrokeRenderer::PSStrokeRenderer(const char* iFileName)
+:StrokeRenderer(){
+ if(!iFileName)
+ iFileName = "freestyle.ps";
+ // open the stream:
+ _ofstream.open(iFileName, ios::out);
+ if(!_ofstream.is_open()){
+ cerr << "couldn't open the output file " << iFileName << endl;
+ }
+ _ofstream << "%!PS-Adobe-2.0 EPSF-2.0" << endl;
+ _ofstream << "%%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl;
+ _ofstream << "%%BoundingBox: " << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << Canvas::getInstance()->height() << endl;
+ _ofstream << "%%EndComments" << endl;
+}
+
+PSStrokeRenderer::~PSStrokeRenderer(){
+ Close();
+}
+
+void PSStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void PSStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ Vec3r color[3];
+ for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
+ s!=send;
+ ++s){
+ Strip::vertex_container& vertices = (*s)->vertices();
+ v[0] = vertices.begin();
+ v[1] = v[0];++(v[1]);
+ v[2] = v[1]; ++(v[2]);
+
+ while(v[2]!=vertices.end()){
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+
+ color[0] = svRep[0]->color();
+ //color[1] = svRep[1]->color();
+ //color[2] = svRep[2]->color();
+
+ _ofstream << "newpath" << endl;
+ _ofstream << (color[0])[0] << " " << (color[0])[1] << " " << (color[0])[2] << " setrgbcolor" <<endl;
+ _ofstream << svRep[0]->point2d()[0] << " " <<svRep[0]->point2d()[1] << " moveto" << endl;
+ _ofstream << svRep[1]->point2d()[0] << " " <<svRep[1]->point2d()[1] << " lineto" << endl;
+ _ofstream << svRep[2]->point2d()[0] << " " <<svRep[2]->point2d()[1] << " lineto" << endl;
+ _ofstream << "closepath" << endl;
+ _ofstream << "fill" << endl;
+
+ ++v[0];
+ ++v[1];
+ ++v[2];
+ }
+ }
+}
+
+void PSStrokeRenderer::Close(){
+ if(_ofstream.is_open())
+ _ofstream.close();
+}
+
diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h
new file mode 100755
index 00000000000..b30949845ab
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h
@@ -0,0 +1,63 @@
+//
+// Filename : PSStrokeRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the Postscript rendering of a stroke
+// Date of creation : 10/26/2004
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef PSSTROKERENDERER_H
+# define PSSTROKERENDERER_H
+
+# include "StrokeRenderer.h"
+# include "../system/FreestyleConfig.h"
+# include <fstream>
+
+/**********************************/
+/* */
+/* */
+/* PSStrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+class LIB_STROKE_EXPORT PSStrokeRenderer : public StrokeRenderer
+{
+public:
+ PSStrokeRenderer(const char * iFileName = 0);
+ virtual ~PSStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ /*! Closes the output PS file */
+ void Close();
+
+protected:
+ mutable ofstream _ofstream;
+};
+
+#endif // PSSTROKERENDERER_H
+
diff --git a/source/blender/freestyle/intern/stroke/Predicates0D.h b/source/blender/freestyle/intern/stroke/Predicates0D.h
new file mode 100755
index 00000000000..2f5d9551b3a
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Predicates0D.h
@@ -0,0 +1,172 @@
+//
+// Filename : Predicates0D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class gathering stroke creation algorithms
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef PREDICATES0D_H
+# define PREDICATES0D_H
+
+# include "../view_map/Functions0D.h"
+
+# include "../python/Director.h"
+
+//
+// UnaryPredicate0D (base class for predicates in 0D)
+//
+///////////////////////////////////////////////////////////
+/*! Base class for Unary Predicates that work
+ * on Interface0DIterator.
+ * A UnaryPredicate0D is a functor that evaluates
+ * a condition on a Interface0DIterator and returns
+ * true or false depending on whether this condition is
+ * satisfied or not.
+ * The UnaryPredicate0D is used by calling its () operator.
+ * Any inherited class must overload the () operator.
+ */
+class UnaryPredicate0D
+{
+public:
+
+ bool result;
+ PyObject *py_up0D;
+
+ /*! Default constructor. */
+ UnaryPredicate0D() { py_up0D = 0; }
+ /*! Destructor. */
+ virtual ~UnaryPredicate0D() {}
+ /*! Returns the string of the name
+ * of the UnaryPredicate0D.
+ */
+ virtual string getName() const {
+ return "UnaryPredicate0D";
+ }
+ /*! The () operator. Must be overload
+ * by inherited classes.
+ * \param it
+ * The Interface0DIterator pointing onto the
+ * Interface0D at which we wish to evaluate
+ * the predicate.
+ * \return true if the condition is satisfied,
+ * false otherwise.
+ */
+ virtual int operator()(Interface0DIterator& it) {
+ return Director_BPy_UnaryPredicate0D___call__(this, it);
+ }
+
+};
+
+
+//
+// BinaryPredicate0D (base class for predicates in 0D)
+//
+///////////////////////////////////////////////////////////
+/*! Base class for Binary Predicates working on Interface0D.
+ * A BinaryPredicate0D is typically an ordering relation
+ * between two Interface0D.
+ * It evaluates a relation between 2 Interface0D and
+ * returns true or false.
+ * It is used by calling the () operator.
+ */
+class BinaryPredicate0D
+{
+public:
+
+ bool result;
+ PyObject *py_bp0D;
+
+ /*! Default constructor. */
+ BinaryPredicate0D() { py_bp0D = 0; }
+ /*! Destructor. */
+ virtual ~BinaryPredicate0D() {}
+ /*! Returns the string of the name of the
+ * binary predicate.
+ */
+ virtual string getName() const {
+ return "BinaryPredicate0D";
+ }
+
+ /*! The () operator. Must be overload by inherited classes.
+ * It evaluates a relation between 2 Interface0D.
+ * \param inter1
+ * The first Interface0D.
+ * \param inter2
+ * The second Interface0D.
+ * \return true or false.
+ */
+ virtual int operator()(Interface0D& inter1, Interface0D& inter2) {
+ return Director_BPy_BinaryPredicate0D___call__(this, inter1, inter2);
+ }
+
+};
+
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates0D {
+
+ // TrueUP0D
+ /*! Returns true any time */
+ class TrueUP0D : public UnaryPredicate0D
+ {
+ public:
+ /*! Default constructor. */
+ TrueUP0D() {}
+ /*! Returns the string "TrueUP0D"*/
+ string getName() const {
+ return "TrueUP0D";
+ }
+ /*! The () operator. */
+ int operator()(Interface0DIterator&) {
+ result = true;
+ return 0;
+ }
+ };
+
+ // FalseUP0D
+ /*! Returns false any time */
+ class FalseUP0D : public UnaryPredicate0D
+ {
+ public:
+ /*! Default constructor. */
+ FalseUP0D() {}
+ /*! Returns the string "FalseUP0D"*/
+ string getName() const {
+ return "FalseUP0D";
+ }
+ /*! The () operator. */
+ int operator()(Interface0DIterator&) {
+ result = false;
+ return 0;
+ }
+ };
+
+} // end of namespace Predicates0D
+
+#endif // PREDICATES0D_H
diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.h b/source/blender/freestyle/intern/stroke/Predicates1D.h
new file mode 100755
index 00000000000..b1159a8332e
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Predicates1D.h
@@ -0,0 +1,540 @@
+//
+// Filename : Predicates1D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class gathering stroke creation algorithms
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef PREDICATES1D_H
+# define PREDICATES1D_H
+
+# include <string>
+# include "../system/TimeStamp.h"
+# include "../view_map/Interface1D.h"
+# include "../view_map/Functions1D.h"
+# include "AdvancedFunctions1D.h"
+
+# include "../python/Director.h"
+
+//
+// UnaryPredicate1D (base class for predicates in 1D)
+//
+///////////////////////////////////////////////////////////
+/*! Base class for Unary Predicates that work
+ * on Interface1D.
+ * A UnaryPredicate1D is a functor that evaluates
+ * a condition on a Interface1D and returns
+ * true or false depending on whether this condition is
+ * satisfied or not.
+ * The UnaryPredicate1D is used by calling its () operator.
+ * Any inherited class must overload the () operator.
+ */
+class UnaryPredicate1D
+{
+public:
+
+ bool result;
+ PyObject *py_up1D;
+
+ /*! Default constructor. */
+ UnaryPredicate1D() { py_up1D = 0; }
+ /*! Destructor. */
+ virtual ~UnaryPredicate1D() {}
+ /*! Returns the string of the name
+ * of the UnaryPredicate1D.
+ */
+ virtual string getName() const {
+ return "UnaryPredicate1D";
+ }
+ /*! The () operator. Must be overload
+ * by inherited classes.
+ * \param inter
+ * The Interface1D on which we wish to evaluate
+ * the predicate.
+ * \return true if the condition is satisfied,
+ * false otherwise.
+ */
+ virtual int operator()(Interface1D& inter) {
+ return Director_BPy_UnaryPredicate1D___call__(this, inter);
+ }
+
+};
+
+
+//
+// BinaryPredicate1D (base class for predicates in 1D)
+//
+///////////////////////////////////////////////////////////
+/*! Base class for Binary Predicates working on Interface1D.
+ * A BinaryPredicate1D is typically an ordering relation
+ * between two Interface1D.
+ * It evaluates a relation between 2 Interface1D and
+ * returns true or false.
+ * It is used by calling the () operator.
+ */
+class BinaryPredicate1D
+{
+public:
+
+ bool result;
+ PyObject *py_bp1D;
+
+ /*! Default constructor. */
+ BinaryPredicate1D() { py_bp1D = 0; }
+ /*! Destructor. */
+ virtual ~BinaryPredicate1D() {}
+ /*! Returns the string of the name of the
+ * binary predicate.
+ */
+ virtual string getName() const {
+ return "BinaryPredicate1D";
+ }
+ /*! The () operator. Must be overload by inherited classes.
+ * It evaluates a relation between 2 Interface1D.
+ * \param inter1
+ * The first Interface1D.
+ * \param inter2
+ * The second Interface1D.
+ * \return true or false.
+ */
+ virtual int operator()(Interface1D& inter1, Interface1D& inter2) {
+ return Director_BPy_BinaryPredicate1D___call__(this, inter1, inter2);
+ }
+
+};
+
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates1D {
+
+ // TrueUP1D
+ /*! Returns true */
+ class TrueUP1D : public UnaryPredicate1D
+ {
+ public:
+ /*! Constructor */
+ TrueUP1D() {}
+ /*! Returns the string "TrueUP1D"*/
+ string getName() const {
+ return "TrueUP1D";
+ }
+ /*! the () operator */
+ int operator()(Interface1D&) {
+ result = true;
+ return 0;
+ }
+ };
+
+ // FalseUP1D
+ /*! Returns false */
+ class FalseUP1D : public UnaryPredicate1D
+ {
+ public:
+ /*! Constructor */
+ FalseUP1D() {}
+ /*! Returns the string "FalseUP1D"*/
+ string getName() const {
+ return "FalseUP1D";
+ }
+ /*! the () operator */
+ int operator()(Interface1D&) {
+ result = false;
+ return 0;
+ }
+ };
+
+ // QuantitativeInvisibilityUP1D
+ /*! Returns true if the Quantitative Invisibility evaluated
+ * at an Interface1D, using the QuantitativeInvisibilityF1D
+ * functor, equals a certain user-defined value.
+ */
+ class QuantitativeInvisibilityUP1D : public UnaryPredicate1D
+ {
+ public:
+ /*! Builds the Predicate.
+ * \param qi
+ * The Quantitative Invisibility you want
+ * the Interface1D to have
+ */
+ QuantitativeInvisibilityUP1D(unsigned qi = 0) : _qi(qi) {}
+ /*! Returns the string "QuantitativeInvisibilityUP1D"*/
+ string getName() const {
+ return "QuantitativeInvisibilityUP1D";
+ }
+ /*! the () operator */
+ int operator()(Interface1D& inter) {
+ Functions1D::QuantitativeInvisibilityF1D func;
+ if (func(inter) < 0)
+ return -1;
+ result = (func.result == _qi);
+ return 0;
+ }
+ private:
+ unsigned _qi;
+ };
+
+ // ContourUP1D
+ /*! Returns true if the Interface1D is a contour.
+ * An Interface1D is a contour if it is borded
+ * by a different shape on each of its sides.
+ */
+ class ContourUP1D : public UnaryPredicate1D
+ {
+ private:
+ Functions1D::CurveNatureF1D _getNature;
+ public:
+ /*! Returns the string "ContourUP1D"*/
+ string getName() const {
+ return "ContourUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ if (_getNature(inter) < 0)
+ return -1;
+ if((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)){
+ Interface0DIterator it=inter.verticesBegin();
+ for(; !it.isEnd(); ++it){
+ if(Functions0D::getOccludeeF0D(it) != Functions0D::getShapeF0D(it)) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ // ExternalContourUP1D
+ /*! Returns true if the Interface1D is an external contour.
+ * An Interface1D is an external contour if it is borded
+ * by no shape on one of its sides.
+ */
+ class ExternalContourUP1D : public UnaryPredicate1D
+ {
+ private:
+ Functions1D::CurveNatureF1D _getNature;
+ public:
+ /*! Returns the string "ExternalContourUP1D"*/
+ string getName() const {
+ return "ExternalContourUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ if (_getNature(inter) < 0)
+ return -1;
+ if((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)){
+ set<ViewShape*> occluded;
+ Functions1D::getOccludeeF1D(inter, occluded);
+ for(set<ViewShape*>::iterator os=occluded.begin(), osend=occluded.end();
+ os!=osend;
+ ++os){
+ if((*os) == 0) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ // EqualToTimeStampUP1D
+ /*! Returns true if the Interface1D's time stamp
+ * is equal to a certain user-defined value.
+ */
+ class EqualToTimeStampUP1D : public UnaryPredicate1D
+ {
+ protected:
+ unsigned _timeStamp;
+ public:
+ EqualToTimeStampUP1D(unsigned ts) : UnaryPredicate1D(){
+ _timeStamp = ts;
+ }
+ /*! Returns the string "EqualToTimeStampUP1D"*/
+ string getName() const {
+ return "EqualToTimeStampUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ result = (inter.getTimeStamp() == _timeStamp);
+ return 0;
+ }
+ };
+
+ // EqualToChainingTimeStampUP1D
+ /*! Returns true if the Interface1D's time stamp
+ * is equal to a certain user-defined value.
+ */
+ class EqualToChainingTimeStampUP1D : public UnaryPredicate1D
+ {
+ protected:
+ unsigned _timeStamp;
+ public:
+ EqualToChainingTimeStampUP1D(unsigned ts) : UnaryPredicate1D(){
+ _timeStamp = ts;
+ }
+ /*! Returns the string "EqualToChainingTimeStampUP1D"*/
+ string getName() const {
+ return "EqualToChainingTimeStampUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ ViewEdge* edge = dynamic_cast<ViewEdge*>(&inter);
+ if (!edge) {
+ result = false;
+ return 0;
+ }
+ result = (edge->getChainingTimeStamp() >= _timeStamp);
+ return 0;
+ }
+ };
+
+ // ShapeUP1D
+ /*! Returns true if the shape to which the Interface1D
+ * belongs to has the same Id as the one specified by the
+ * user.
+ */
+ class ShapeUP1D: public UnaryPredicate1D
+ {
+ private:
+ Id _id;
+ public:
+ /*! Builds the Predicate.
+ * \param idFirst
+ * The first Id component.
+ * \param idSecond
+ * The second Id component.
+ */
+ ShapeUP1D(unsigned idFirst, unsigned idSecond=0)
+ : UnaryPredicate1D(){
+ _id = Id(idFirst, idSecond);
+ }
+ /*! Returns the string "ShapeUP1D"*/
+ string getName() const {
+ return "ShapeUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ set<ViewShape*> shapes;
+ Functions1D::getShapeF1D(inter, shapes);
+ for(set<ViewShape*>::iterator s=shapes.begin(), send=shapes.end();
+ s!=send;
+ ++s){
+ if((*s)->getId() == _id) {
+ result = true;
+ return 0;
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ // WithinImageBoundaryUP1D
+ /*! Returns true if the Interface1D is (partly) within the image boundary.
+ */
+ class WithinImageBoundaryUP1D: public UnaryPredicate1D
+ {
+ private:
+ real _xmin, _ymin, _xmax, _ymax;
+ public:
+ /*! Builds the Predicate.
+ * \param xmin
+ * The X lower bound of the image boundary.
+ * \param ymin
+ * The Y lower bound of the image boundary.
+ * \param xmax
+ * The X upper bound of the image boundary.
+ * \param ymax
+ * The Y upper bound of the image boundary.
+ */
+ WithinImageBoundaryUP1D(const real xmin, const real ymin, const real xmax, const real ymax) :
+ _xmin(xmin), _ymin(ymin), _xmax(xmax), _ymax(ymax) {}
+ /*! Returns the string "WithinImageBoundaryUP1D"*/
+ string getName() const {
+ return "WithinImageBoundaryUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ // 1st pass: check if a point is within the image boundary.
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ for (; it != itend; ++it) {
+ real x = (*it).getProjectedX();
+ real y = (*it).getProjectedY();
+ if (_xmin <= x && x <= _xmax && _ymin <= y && y <= _ymax) {
+ result = true;
+ return 0;
+ }
+ }
+ // 2nd pass: check if a line segment intersects with the image boundary.
+ it = inter.verticesBegin();
+ if (it != itend) {
+ Vec2r pmin(_xmin, _ymin);
+ Vec2r pmax(_xmax, _ymax);
+ Vec2r prev((*it).getPoint2D());
+ ++it;
+ for (; it != itend; ++it) {
+ Vec2r p((*it).getPoint2D());
+ if (GeomUtils::intersect2dSeg2dArea (pmin, pmax, prev, p)) {
+ result = true;
+ return 0;
+ }
+ prev = p;
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ //
+ // Binary Predicates definitions
+ //
+ ///////////////////////////////////////////////////////////
+
+ // TrueBP1D
+ /*! Returns true. */
+ class TrueBP1D : public BinaryPredicate1D
+ {
+ public:
+ /*! Returns the string "TrueBP1D"*/
+ string getName() const {
+ return "TrueBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ result = true;
+ return 0;
+ }
+ };
+
+ // FalseBP1D
+ /*! Returns false. */
+ class FalseBP1D : public BinaryPredicate1D
+ {
+ public:
+ /*! Returns the string "FalseBP1D"*/
+ string getName() const {
+ return "FalseBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ result = false;
+ return 0;
+ }
+ };
+
+ // Length2DBP1D
+ /*! Returns true if the 2D length of the Interface1D i1
+ * is less than the 2D length of the Interface1D i2.
+ */
+ class Length2DBP1D : public BinaryPredicate1D
+ {
+ public:
+ /*! Returns the string "Length2DBP1D"*/
+ string getName() const {
+ return "Length2DBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ result = (i1.getLength2D() > i2.getLength2D());
+ return 0;
+ }
+ };
+
+ // SameShapeIdBP1D
+ /*! Returns true if the Interface1D i1 and i2 belong
+ * to the same shape.
+ */
+ class SameShapeIdBP1D : public BinaryPredicate1D
+ {
+ public:
+ /*! Returns the string "SameShapeIdBP1D"*/
+ string getName() const {
+ return "SameShapeIdBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ set<ViewShape*> shapes1;
+ Functions1D::getShapeF1D(i1, shapes1);
+ set<ViewShape*> shapes2;
+ Functions1D::getShapeF1D(i2, shapes2);
+ // FIXME:// n2 algo, can do better...
+ for(set<ViewShape*>::iterator s=shapes1.begin(), send=shapes1.end();
+ s!=send;
+ ++s){
+ Id current = (*s)->getId();
+ for(set<ViewShape*>::iterator s2=shapes2.begin(), s2end=shapes2.end();
+ s2!=s2end;
+ ++s2){
+ if((*s2)->getId() == current) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ // ViewMapGradientNormBP1D
+ /*! Returns true if the evaluation of the
+ * Gradient norm Function is higher for Interface1D i1
+ * than for i2.
+ */
+ class ViewMapGradientNormBP1D : public BinaryPredicate1D
+ {
+ private:
+ Functions1D::GetViewMapGradientNormF1D _func;
+ public:
+ ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0)
+ : BinaryPredicate1D(), _func(level, iType, sampling) {
+ }
+ /*! Returns the string "ViewMapGradientNormBP1D"*/
+ string getName() const {
+ return "ViewMapGradientNormBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ if (_func(i1) < 0)
+ return -1;
+ real n1 = _func.result;
+ if (_func(i2) < 0)
+ return -1;
+ real n2 = _func.result;
+ result = (n1 > n2);
+ return 0;
+ }
+ };
+} // end of namespace Predicates1D
+
+#endif // PREDICATES1D_H
diff --git a/source/blender/freestyle/intern/stroke/QInformationMap.h b/source/blender/freestyle/intern/stroke/QInformationMap.h
new file mode 100755
index 00000000000..ef068f15061
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/QInformationMap.h
@@ -0,0 +1,58 @@
+//
+// Filename : QInformationMap.h
+// Author : Stephane Grabli
+// Purpose : Class defining an information map using a QImage
+// Date of creation : 04/01/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef QINFORMATIONMAP_H
+# define QINFORMATIONMAP_H
+
+# include <qimage.h>
+# include "InformationMap.h"
+
+class QInformationMap : public InformationMap
+{
+private:
+ QImage _map; // the image or a piece of image
+
+public:
+ QInformationMap();
+ QInformationMap(const QImage&);
+ QInformationMap(const QInformationMap&);
+ QInformationMap& operator=(const QInformationMap&);
+
+ //float getSmoothedPixel(int x, int y, float sigma = 0.2f)
+ virtual float getMean(int x, int y) ;
+ virtual void retrieveMeanAndVariance(int x, int y, float &oMean, float &oVariance) ;
+
+ inline const QImage& map() const {return _map;}
+ inline void setMap(const QImage& iMap, float iw, float ih) {_map = iMap.copy();_w=iw;_h=ih;}
+
+protected:
+ virtual float computeGaussian(int x, int y);
+};
+
+#endif // QINFORMATIONMAP_H
diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp
new file mode 100755
index 00000000000..b42e673b4be
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -0,0 +1,947 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Stroke.h"
+#include "StrokeRenderer.h"
+#include "StrokeIterators.h"
+#include "StrokeAdvancedIterators.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* StrokeAttribute */
+ /* */
+ /* */
+ /**********************************/
+
+StrokeAttribute::StrokeAttribute()
+{
+ int i;
+ _alpha = 1.f;
+ _thickness[0] = 1.f;
+ _thickness[1] = 1.f;
+ for(i=0; i<3; ++i)
+ _color[i] = 0.2f;
+ _color[0]=0.8;
+ _userAttributesReal = 0;
+ _userAttributesVec2f = 0;
+ _userAttributesVec3f = 0;
+ _visible = true;
+}
+StrokeAttribute::StrokeAttribute(const StrokeAttribute& iBrother)
+{
+ _alpha = iBrother._alpha;
+ _thickness[0] = iBrother._thickness[0];
+ _thickness[1] = iBrother._thickness[1];
+ for(int i=0; i<3; ++i)
+ _color[i] = iBrother._color[i];
+ _visible = iBrother._visible;
+ if(iBrother._userAttributesReal)
+ _userAttributesReal = new realMap(*iBrother._userAttributesReal);
+ else
+ _userAttributesReal = 0;
+ if(iBrother._userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f);
+ else
+ _userAttributesVec2f = 0;
+ if(iBrother._userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f);
+ else
+ _userAttributesVec3f = 0;
+}
+StrokeAttribute::StrokeAttribute( float iRColor, float iGColor, float iBColor,
+ float iAlpha,
+ float iRThickness, float iLThickness)
+{
+ _color[0] = iRColor;
+ _color[1] = iGColor;
+ _color[2] = iBColor;
+
+ _alpha = iAlpha;
+
+ _thickness[0] = iRThickness;
+ _thickness[1] = iLThickness;
+
+ _visible = true;
+
+ _userAttributesReal = 0;
+ _userAttributesVec2f = 0;
+ _userAttributesVec3f = 0;
+}
+StrokeAttribute::StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t)
+
+{
+
+ _alpha = (1-t)*a1._alpha + t*a2._alpha;
+ _thickness[0] = (1-t)*a1._thickness[0] + t*a2._thickness[0];
+ _thickness[1] = (1-t)*a1._thickness[1] + t*a2._thickness[1];
+ for(int i=0; i<3; ++i)
+ _color[i] = (1-t)*a1._color[i] + t*a2._color[i];
+
+ _visible = true;
+
+ // FIXME: a verifier (et a ameliorer)
+ if((a1._userAttributesReal) && (a2._userAttributesReal)){
+ if(a1._userAttributesReal->size() == a2._userAttributesReal->size()){
+ _userAttributesReal = new realMap;
+ realMap::iterator it1=a1._userAttributesReal->begin(), it1end=a1._userAttributesReal->end();
+ realMap::iterator it2=a2._userAttributesReal->begin(), it2end=a2._userAttributesReal->end();
+ for(; (it1!=it1end); ++it1){
+ (*_userAttributesReal)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second);
+ }
+ }
+ }else{
+ _userAttributesReal = 0;
+ }
+ if((a1._userAttributesVec2f) && (a2._userAttributesVec2f)){
+ if(a1._userAttributesVec2f->size() == a2._userAttributesVec2f->size()){
+ _userAttributesVec2f = new Vec2fMap;
+ Vec2fMap::iterator it1=a1._userAttributesVec2f->begin(), it1end=a1._userAttributesVec2f->end();
+ Vec2fMap::iterator it2=a2._userAttributesVec2f->begin(), it2end=a2._userAttributesVec2f->end();
+ for(; (it1!=it1end); ++it1){
+ (*_userAttributesVec2f)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second);
+ }
+ }
+ }else{
+ _userAttributesVec2f = 0;
+ }
+ if((a1._userAttributesVec3f) && (a2._userAttributesVec3f)){
+ if(a1._userAttributesVec3f->size() == a2._userAttributesVec3f->size()){
+ _userAttributesVec3f = new Vec3fMap;
+ Vec3fMap::iterator it1=a1._userAttributesVec3f->begin(), it1end=a1._userAttributesVec3f->end();
+ Vec3fMap::iterator it2=a2._userAttributesVec3f->begin(), it2end=a2._userAttributesVec3f->end();
+ for(; (it1!=it1end); ++it1){
+ (*_userAttributesVec3f)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second);
+ }
+ }
+ }else{
+ _userAttributesVec3f = 0;
+ }
+}
+
+StrokeAttribute::~StrokeAttribute()
+{
+ if(_userAttributesReal){
+ _userAttributesReal->clear();
+ delete _userAttributesReal;
+ }
+ if(_userAttributesVec2f){
+ _userAttributesVec2f->clear();
+ delete _userAttributesVec2f;
+ }
+ if(_userAttributesVec3f){
+ _userAttributesVec3f->clear();
+ delete _userAttributesVec3f;
+ }
+}
+
+StrokeAttribute& StrokeAttribute::operator=(const StrokeAttribute& iBrother)
+{
+ int i;
+ _alpha = iBrother._alpha;
+ _thickness[0] = iBrother._thickness[0];
+ _thickness[1] = iBrother._thickness[1];
+ for(i=0; i<3; ++i)
+ _color[i] = iBrother._color[i];
+ _visible = iBrother._visible;
+ if(iBrother._userAttributesReal){
+ if(!_userAttributesReal)
+ _userAttributesReal = new realMap;
+ _userAttributesReal = new realMap(*(iBrother._userAttributesReal));
+ }else{
+ _userAttributesReal = 0;
+ }
+ if(iBrother._userAttributesVec2f){
+ if(!_userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap;
+ _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f));
+ }else{
+ _userAttributesVec2f = 0;
+ }
+ if(iBrother._userAttributesVec3f){
+ if(!_userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap;
+ _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f));
+ }else{
+ _userAttributesVec3f = 0;
+ }
+ return *this;
+}
+
+float StrokeAttribute::getAttributeReal(const char *iName) const{
+ if(!_userAttributesReal){
+ cout << "StrokeAttribute warning: no real attribute was defined"<< endl;
+ return 0;
+ }
+ realMap::iterator a = _userAttributesReal->find(iName);
+ if(a ==_userAttributesReal->end()){
+ cout << "StrokeAttribute warning: no real attribute was added with the name " << iName << endl;
+ return 0;
+ }
+ return (*a).second;
+}
+Vec2f StrokeAttribute::getAttributeVec2f(const char *iName) const{
+ if(!_userAttributesVec2f){
+ cout << "StrokeAttribute warning: no Vec2f attribute was defined "<< endl;
+ return 0;
+ }
+ Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
+ if(a ==_userAttributesVec2f->end()){
+ cout << "StrokeAttribute warning: no Vec2f attribute was added with the name " << iName << endl;
+ return 0;
+ }
+ return (*a).second;
+}
+Vec3f StrokeAttribute::getAttributeVec3f(const char *iName) const{
+ if(!_userAttributesVec3f){
+ cout << "StrokeAttribute warning: no Vec3f attribute was defined"<< endl;
+ return 0;
+ }
+ Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
+ if(a ==_userAttributesVec3f->end()){
+ cout << "StrokeAttribute warning: no Vec3f attribute was added with the name " << iName << endl;
+ return 0;
+ }
+ return (*a).second;
+}
+bool StrokeAttribute::isAttributeAvailableReal(const char *iName) const{
+ if(!_userAttributesReal){
+ return false;
+ }
+ realMap::iterator a = _userAttributesReal->find(iName);
+ if(a ==_userAttributesReal->end()){
+ return false;
+ }
+ return true;
+}
+bool StrokeAttribute::isAttributeAvailableVec2f(const char *iName) const{
+ if(!_userAttributesVec2f){
+ return false;
+ }
+ Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
+ if(a ==_userAttributesVec2f->end()){
+ return false;
+ }
+ return true;
+}
+bool StrokeAttribute::isAttributeAvailableVec3f(const char *iName) const{
+ if(!_userAttributesVec3f){
+ return false;
+ }
+ Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
+ if(a ==_userAttributesVec3f->end()){
+ return false;
+ }
+ return true;
+}
+void StrokeAttribute::setAttributeReal(const char *iName, float att){
+ if(!_userAttributesReal)
+ _userAttributesReal = new realMap;
+ (*_userAttributesReal)[iName] = att;
+}
+void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f& att){
+ if(!_userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap;
+ (*_userAttributesVec2f)[iName] = att;
+}
+void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f& att){
+ if(!_userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap;
+ (*_userAttributesVec3f)[iName] = att;
+}
+ /**********************************/
+ /* */
+ /* */
+ /* StrokeVertex */
+ /* */
+ /* */
+ /**********************************/
+
+StrokeVertex::StrokeVertex()
+
+:CurvePoint()
+{
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+}
+
+
+
+StrokeVertex::StrokeVertex(const StrokeVertex& iBrother)
+
+:CurvePoint(iBrother)
+{
+ _Attribute = iBrother._Attribute;
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+}
+StrokeVertex::StrokeVertex(SVertex *iSVertex)
+
+:CurvePoint(iSVertex,0,0.f)
+
+{
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+
+}
+
+
+
+StrokeVertex::StrokeVertex(CurvePoint *iPoint)
+
+:CurvePoint(*iPoint)
+
+{
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+
+}
+
+
+
+StrokeVertex::StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3)
+
+:CurvePoint(iA,iB,t3)
+
+{
+
+ // interpolate attributes:
+
+ _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3);
+ _CurvilignAbscissa = (1-t3)*iA->curvilinearAbscissa()+t3*iB->curvilinearAbscissa();
+ _StrokeLength = iA->strokeLength();
+
+}
+
+
+
+StrokeVertex::StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute)
+
+:CurvePoint(iSVertex,0,0.f)
+
+{
+
+ _Attribute = iAttribute;
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+
+}
+StrokeVertex::~StrokeVertex()
+{
+}
+
+StrokeVertex& StrokeVertex::operator=(const StrokeVertex& iBrother)
+{
+ ((CurvePoint*)this)->operator=(iBrother);
+ _Attribute = iBrother._Attribute;
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+ return *this;
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* Stroke */
+ /* */
+ /* */
+ /**********************************/
+
+Stroke::Stroke()
+{
+ _Length = 0;
+ _id = 0;
+ _sampling = FLT_MAX;
+ //_mediumType = DEFAULT_STROKE;
+ _mediumType = OPAQUE_MEDIUM;
+ _textureId = 0;
+ _tips = false;
+ _rep = 0;
+}
+
+Stroke::Stroke(const Stroke& iBrother)
+{
+ for(vertex_container::const_iterator v=iBrother._Vertices.begin(), vend=iBrother._Vertices.end();
+ v!=vend;
+ v++)
+ {
+ _Vertices.push_back(*v);
+ }
+ _Length = 0;
+ _id = iBrother._id;
+ _ViewEdges = iBrother._ViewEdges;
+ _sampling = iBrother._sampling;
+ _mediumType = iBrother._mediumType;
+ _textureId = iBrother._textureId;
+ _tips = iBrother._tips;
+ if(iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ else
+ _rep = 0;
+
+}
+
+Stroke::~Stroke()
+{
+ if(!_Vertices.empty())
+ {
+ for(vertex_container::iterator v=_Vertices.begin(), vend=_Vertices.end();
+ v!=vend;
+ v++)
+ {
+ delete (*v);
+ }
+ _Vertices.clear();
+ }
+
+ _ViewEdges.clear();
+ if(_rep != 0)
+ {
+ delete _rep;
+ _rep = 0;
+ }
+}
+
+Stroke& Stroke::operator=(const Stroke& iBrother)
+{
+ if(!_Vertices.empty())
+ _Vertices.clear();
+
+ for(vertex_container::const_iterator v=iBrother._Vertices.begin(), vend=iBrother._Vertices.end();
+ v!=vend;
+ v++)
+ {
+ _Vertices.push_back(*v);
+ }
+ _Length = iBrother._Length;
+ _id = iBrother._id;
+ _ViewEdges = iBrother._ViewEdges;
+ _sampling = iBrother._sampling;
+ if(_rep) delete _rep;
+ if(iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ return *this;
+}
+
+
+void Stroke::setLength(float iLength)
+{
+ _Length = iLength;
+ for(vertex_container::iterator v=_Vertices.begin(), vend=_Vertices.end();
+ v!=vend;
+ ++v)
+ {
+ (*v)->setStrokeLength(iLength);
+ }
+}
+
+float Stroke::ComputeSampling(int iNVertices)
+{
+ if(iNVertices <= (int)_Vertices.size()) //soc
+ return _sampling;
+
+ float sampling = _Length/(float)(iNVertices-_Vertices.size()+1);
+ return sampling;
+}
+
+class StrokeSegment
+{
+public:
+ StrokeInternal::StrokeVertexIterator _begin;
+ StrokeInternal::StrokeVertexIterator _end;
+ float _length;
+ int _n;
+ float _sampling;
+ bool _resampled;
+
+ StrokeSegment(StrokeInternal::StrokeVertexIterator ibegin,
+ StrokeInternal::StrokeVertexIterator iend,
+ float ilength,
+ int in,
+ float isampling)
+ {
+ _begin=ibegin;
+ _end=iend;
+ _length=ilength;
+ _n=in;
+ _sampling = isampling;
+ _resampled = false;
+ }
+};
+
+void Stroke::Resample(int iNPoints)
+{
+ int vertsize = strokeVerticesSize();
+ if(iNPoints <= vertsize)
+ return;
+
+ StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator next = it;++next;
+ StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd();
+
+ vertex_container newVertices;
+ real t=0.f;
+ StrokeVertex * newVertex = 0;
+ vector<StrokeSegment> strokeSegments;
+ int N=0;
+ float meanlength = 0;
+ int nsegments = 0;
+ while(((it!=itend)&&(next!=itend)))
+ {
+ Vec2r a((it)->getPoint());
+ Vec2r b((next)->getPoint());
+ Vec2r vec_tmp(b - a);
+ real norm_var = vec_tmp.norm();
+ int numberOfPointsToAdd = (int)floor((iNPoints-strokeVerticesSize())*norm_var/_Length);
+ float csampling = norm_var/(float)(numberOfPointsToAdd+1);
+ strokeSegments.push_back(StrokeSegment(it,next,norm_var,numberOfPointsToAdd, csampling));
+ N+=numberOfPointsToAdd;
+ meanlength += norm_var;
+ ++nsegments;
+ ++it; ++next;
+ }
+ meanlength /= (float)nsegments;
+
+ // if we don't have enough points let's resample
+ // finer some segments
+ int NPointsToAdd = iNPoints-vertsize;
+ bool checkEveryone = false;
+ while(N < NPointsToAdd)
+ {
+ for(vector<StrokeSegment>::iterator s=strokeSegments.begin(), send=strokeSegments.end();
+ s!=send;
+ ++s)
+ {
+ if(s->_sampling == 0.f)
+ continue;
+
+ if(s->_resampled == false)
+ {
+ if((!checkEveryone) && (s->_length < meanlength))
+ continue;
+ //resample
+ s->_n = s->_n+1;
+ s->_sampling = s->_length/(float)(s->_n+1);
+ s->_resampled = true;
+ N++;
+ if(N == NPointsToAdd)
+ break;
+ }
+ }
+ checkEveryone = true;
+ }
+ //actually resample:
+ for(vector<StrokeSegment>::iterator s=strokeSegments.begin(), send=strokeSegments.end();
+ s!=send;
+ ++s)
+ {
+ newVertices.push_back(&(*(s->_begin)));
+ if(s->_sampling < _sampling)
+ _sampling = s->_sampling;
+
+ t = s->_sampling/s->_length;
+ for(int i=0; i<s->_n; ++i)
+ {
+ newVertex = new StrokeVertex(&(*(s->_begin)),&(*(s->_end)),t);
+ newVertices.push_back(newVertex);
+ t += s->_sampling/s->_length;
+ }
+ it=s->_begin;
+ next=s->_end;
+ }
+
+ // add last:
+ ++it;++next;
+ if((it != itend) && (next == itend))// && (t == 0.f))
+ newVertices.push_back(&(*it));
+
+ int newsize = newVertices.size();
+ if(newsize != iNPoints)
+ cerr << "Warning: incorrect points number" << endl;
+
+ _Vertices.clear();
+ _Vertices = newVertices;
+ newVertices.clear();
+
+ if(_rep)
+ {
+ delete _rep;
+ _rep = new StrokeRep(this);
+ }
+}
+
+
+void Stroke::Resample(float iSampling)
+{
+ // cerr<<"old size :"<<strokeVerticesSize()<<endl;
+ if(iSampling == 0)
+
+ return;
+ if(iSampling >= _sampling)
+ return ;
+
+ _sampling = iSampling;
+ // Resample...
+ //real curvilinearLength = 0.f;
+ vertex_container newVertices;
+ real t=0.f;
+ StrokeVertex * newVertex = 0;
+ StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator next = it;++next;
+ StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd();
+ while(((it!=itend)&&(next!=itend)))
+ {
+ newVertices.push_back(&(*it));
+ Vec3r a((it)->point2d());
+ Vec3r b((next)->point2d());
+ Vec3r vec_tmp(b - a);
+ real norm_var = vec_tmp.norm();
+ if(norm_var <= _sampling)
+ {
+ //curvilinearLength += norm_var;
+ ++it; ++next;
+ continue;
+ }
+
+ //curvilinearLength += _sampling;
+ t = _sampling/norm_var;
+ float limit = 0.99f;
+ while(t<limit)
+ {
+ newVertex = new StrokeVertex(&(*it),&(*next),t);
+ //newVertex->setCurvilinearAbscissa(curvilinearLength);
+ newVertices.push_back(newVertex);
+ t = t + _sampling/norm_var;
+ }
+ ++it; ++next;
+ }
+ // add last:
+ if((it != itend) && (next == itend))// && (t == 0.f))
+ newVertices.push_back(&(*it));
+
+ _Vertices.clear();
+ _Vertices = newVertices;
+ newVertices.clear();
+
+ if(_rep)
+ {
+ delete _rep;
+ _rep = new StrokeRep(this);
+ }
+}
+
+void Stroke::RemoveVertex(StrokeVertex *iVertex)
+{
+ vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end();
+ for(;
+ it!=itend;
+ ++it)
+ {
+ if((*it) == iVertex)
+ {
+ delete iVertex;
+ it = _Vertices.erase(it); // it is now the element just after the erased element
+ break;
+ }
+ }
+ UpdateLength();
+}
+
+void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next)
+{
+ vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end();
+
+ vertex_container::iterator itnext = next.getIt();
+ _Vertices.insert(itnext, iVertex);
+ UpdateLength();
+}
+
+void Stroke::UpdateLength()
+{
+ // recompute various values (length, curvilign abscissa)
+ float curvabsc = 0.f;
+ vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end();
+ vertex_container::iterator previous=it;
+ for(;
+ (it!=itend);
+ ++it)
+ {
+ curvabsc += ((*it)->point2d()-(*previous)->point2d()).norm();
+ (*it)->setCurvilinearAbscissa(curvabsc);
+ previous = it;
+ }
+ _Length = curvabsc;
+ for(;
+ (it!=itend);
+ ++it)
+ {
+ (*it)->setStrokeLength(_Length);
+ }
+}
+
+//! embedding vertex iterator
+Stroke::const_vertex_iterator Stroke::vertices_begin() const { return const_vertex_iterator(_Vertices.begin(),_Vertices.begin(), _Vertices.end()); }
+Stroke::const_vertex_iterator Stroke::vertices_end() const { return const_vertex_iterator(_Vertices.end(),_Vertices.begin(), _Vertices.end()); }
+Stroke::vertex_iterator Stroke::vertices_end() { return vertex_iterator(_Vertices.end(),_Vertices.begin(), _Vertices.end()); }
+
+StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesBegin(float t) {
+ if((t!=0) && (t < _sampling))
+ Resample(t);
+ return StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end());
+}
+
+StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesEnd() {
+ return StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end());
+}
+
+Interface0DIterator Stroke::verticesBegin() {
+ Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(),
+ this->_Vertices.begin(),
+ this->_Vertices.end()));
+ return ret;
+}
+
+Interface0DIterator Stroke::verticesEnd() {
+ Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.end(),
+ this->_Vertices.begin(),
+ this->_Vertices.end()));
+ return ret;
+}
+
+Interface0DIterator Stroke::pointsBegin(float t) {
+ return verticesBegin(); // FIXME
+}
+
+Interface0DIterator Stroke::pointsEnd(float t) {
+ return verticesEnd();
+}
+
+void Stroke::ScaleThickness(float iFactor)
+{
+ for(vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end();
+ it!=itend;
+ ++it)
+ {
+ StrokeAttribute& attr = (*it)->attribute();
+ attr.setThickness(iFactor * attr.getThicknessR(), iFactor * attr.getThicknessL());
+ }
+}
+
+void Stroke::Render(const StrokeRenderer *iRenderer)
+{
+ if(!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_rep);
+}
+
+void Stroke::RenderBasic(const StrokeRenderer *iRenderer)
+{
+ if(!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRepBasic(_rep);
+}
+
+Stroke::vertex_iterator Stroke::vertices_begin(float sampling)
+{
+ // Resample if necessary
+ if((sampling != 0) && (sampling < _sampling))
+ Resample(sampling);
+ return vertex_iterator(_Vertices.begin(),_Vertices.begin(),_Vertices.end());
+ //return _Vertices.begin();
+}
+//
+//Stroke::vertex_iterator Stroke::vertices_last()
+//{
+// vertex_iterator res = vertices_begin();
+// vertex_iterator next = res;++next;
+// while(!next.end())
+// {
+// ++next;
+// ++res;
+// }
+// return res;
+//}
+//
+//Stroke::const_vertex_iterator Stroke::vertices_last() const
+//{
+// const_vertex_iterator res = vertices_begin();
+// const_vertex_iterator next = res;++next;
+// while(!next.end())
+// {
+// ++next;
+// ++res;
+// }
+// return res;
+//}
+
+//Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling)
+//{
+// // Resample if necessary
+// if(sampling < _sampling)
+// Resample(sampling);
+// return _Vertices.rbegin();
+//}
+
+
+//inline Vec3r shaded_color(int iCombination = 0) const ;
+//inline Vec<3,real> Stroke::orientation2d(const_vertex_iterator it) const
+//{
+// return iterator_edge_orientation2d_function<Stroke, const_vertex_iterator>(this, it);
+//}
+// Vec3r Stroke::orientation2d(int iCombination) const
+// {
+// return edge_orientation2d_function<Stroke>(*this, iCombination);
+// }
+//inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const
+//{
+// return iterator_edge_orientation3d_function<Stroke, const_vertex_iterator>(*this, it);
+//}
+// Vec3r Stroke::orientation3d(int iCombination) const
+// {
+// return edge_orientation3d_function<Stroke>(*this, iCombination);
+// }
+
+//Material Stroke::material() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=strokeVerticesEnd();
+// Material mat = (*v)->material();
+// for(;v!=vend;++v)
+// {
+// if(mat != (*v)->material())
+// Exception::raiseException();
+// }
+// return mat;
+//}
+
+//int Stroke::qi() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// int qi_= (*v)->qi();
+// for(;v!=vend;++v)
+// {
+// if((*v)->qi() != qi_)
+// Exception::raiseException();
+// }
+// return qi_;
+//}
+//inline occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();}
+//inline occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();}
+
+//int Stroke::occluders_size() const
+//{
+// return qi();
+//}
+//
+//bool Stroke::occluders_empty() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// bool empty = (*v)->occluders_empty();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occluders_empty() != empty)
+// Exception::raiseException();
+// }
+// return empty;
+//}
+////inline const polygon3d& occludee() const {return *(_FEdgeA->aFace());}
+//const SShape * Stroke::occluded_shape() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const SShape *sshape = (*v)->occluded_shape();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occluded_shape() != sshape)
+// Exception::raiseException();
+// }
+// return sshape;
+//}
+//
+//const bool Stroke::occludee_empty() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// bool empty = (*v)->occludee_empty();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occludee_empty() != empty)
+// Exception::raiseException();
+// }
+// return empty;
+//}
+
+//const SShape * Stroke::shape() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const SShape *sshape = (*v)->shape();
+// for(;v!=vend;++v)
+// {
+// if((*v)->shape() != sshape)
+// Exception::raiseException();
+// }
+// return sshape;
+//}
+
+// real Stroke::z_discontinuity(int iCombination) const
+// {
+// return z_discontinuity_edge_function<Stroke>(*this, iCombination);
+// }
+
+// Vec3r Stroke::curvature2d_as_vector(int iCombination) const
+// {
+// return curvature2d_as_vector_edge_function<Stroke>(*this, iCombination);
+// }
+
+// real Stroke::curvature2d_as_angle(int iCombination) const
+// {
+// return curvature2d_as_angle_edge_function<Stroke>(*this, iCombination);
+// }
+
+// float Stroke::shape_importance(int iCombination) const
+// {
+// return shape_importance_edge_function<Stroke>(*this, iCombination);
+// }
+
+
+// float Stroke::local_average_depth(int iCombination ) const
+// {
+// return local_average_depth_edge_function<Stroke >(*this, iCombination);
+// }
+
+// float Stroke::local_depth_variance(int iCombination) const
+// {
+// return local_depth_variance_edge_function<Stroke>(*this, iCombination);
+// }
+
+// real Stroke::local_average_density(float sigma , int iCombination ) const
+// {
+// return density_edge_function<Stroke>(*this, iCombination);
+// }
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h
new file mode 100755
index 00000000000..5b20bcac896
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -0,0 +1,592 @@
+//
+// Filename : Stroke.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define a stroke
+// Date of creation : 09/09/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STROKE_H
+# define STROKE_H
+
+# include "../view_map/Silhouette.h"
+# include <vector>
+# include <map>
+# include "../system/FreestyleConfig.h"
+# include "Curve.h"
+# include "../view_map/Interface1D.h"
+# include "../system/StringUtils.h"
+
+
+//
+// StrokeAttribute
+//
+////////////////////////////////////////////////////////
+
+/*! Class to define an attribute associated to a Stroke Vertex.
+ * This attribute stores the color, alpha and thickness values
+ * for a Stroke Vertex.
+ */
+class LIB_STROKE_EXPORT StrokeAttribute
+{
+public:
+
+ /*! default constructor */
+ StrokeAttribute();
+ /*! Copy constructor */
+ StrokeAttribute(const StrokeAttribute& iBrother);
+ /*! Builds a stroke vertex attribute from
+ * a set of parameters.
+ * \param iRColor
+ * The Red Component value.
+ * \param iGColor
+ * The Green Component value.
+ * \param iBColor
+ * The Blue Component value.
+ * \param iAlpha
+ * The transparency value
+ * \param iRThickness
+ * The thickness of the stroke on the right
+ * \param iLThickness
+ * The Thickness of the stroke on the left
+ */
+ StrokeAttribute(float iRColor, float iGColor, float iBColor,
+ float iAlpha,
+ float iRThickness, float iLThickness);
+
+ /*! Interpolation constructor.
+ * Builds a StrokeAttribute from two
+ * StrokeAttributes and an interpolation parameter.
+ * \param a1
+ * The first Attribute.
+ * \param a2
+ * The second parameter.
+ * \param t
+ * The interpolation parameter.
+ */
+ StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t);
+
+ /*! destructor */
+ virtual ~StrokeAttribute();
+
+ /* operators */
+ /*! operator = */
+ StrokeAttribute& operator=(const StrokeAttribute& iBrother);
+
+ /* accessors */
+ /*! Returns the attribute's color.
+ * \return The array of 3 floats containing the R,G,B values
+ * of the attribute's color.
+ */
+ inline const float* getColor() const { return _color; }
+ /*! Returns the R color component. */
+ inline const float getColorR() const { return _color[0]; }
+ /*! Returns the G color component. */
+ inline const float getColorG() const { return _color[1]; }
+ /*! Returns the B color component. */
+ inline const float getColorB() const { return _color[2]; }
+ /*! Returns the RGB color components. */
+ inline Vec3f getColorRGB() const { return Vec3f(_color[0], _color[1], _color[2]); }
+ /*! Returns the alpha color component. */
+ inline float getAlpha() const { return _alpha; }
+ /*! Returns the attribute's thickness.
+ * \return an array of 2 floats. the first value is
+ * the thickness on the right of the vertex when following
+ * the stroke, the second one is the thickness on the left.
+ */
+ inline const float* getThickness() const { return _thickness; }
+ /*! Returns the thickness on the right of the vertex when following the
+ * stroke. */
+ inline const float getThicknessR() const { return _thickness[0]; }
+ /*! Returns the thickness on the left of the vertex when following the
+ * stroke. */
+ inline const float getThicknessL() const { return _thickness[1]; }
+ /*! Returns the thickness on the right and on the left of the vertex when following the
+ * stroke. */
+ inline Vec2f getThicknessRL() const { return Vec2f(_thickness[0], _thickness[1]); }
+
+ /*! Returns true if the strokevertex is visible, false otherwise */
+ inline bool isVisible() const {return _visible;}
+
+ /*! Returns an attribute of type real
+ * \param iName
+ * The name of the attribute
+ */
+ float getAttributeReal(const char *iName) const;
+ /*! Returns an attribute of type Vec2f
+ * \param iName
+ * The name of the attribute
+ */
+ Vec2f getAttributeVec2f(const char *iName) const;
+ /*! Returns an attribute of type Vec3f
+ * \param iName
+ * The name of the attribute
+ */
+ Vec3f getAttributeVec3f(const char *iName) const;
+
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableReal(const char *iName) const ;
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableVec2f(const char *iName) const ;
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableVec3f(const char *iName) const ;
+
+ /* modifiers */
+ /*! sets the attribute's color.
+ * \param r
+ * The new R value.
+ * \param g
+ * The new G value.
+ * \param b
+ * The new B value.
+ */
+ inline void setColor(float r, float g, float b) { _color[0]=r; _color[1]=g; _color[2]=b; }
+ /*! sets the attribute's color.
+ * \param iRGB
+ * The new RGB values.
+ */
+ inline void setColor(const Vec3f& iRGB) { _color[0]=iRGB[0]; _color[1]=iRGB[1]; _color[2]=iRGB[2]; }
+ /*! sets the attribute's alpha value.
+ * \param alpha
+ * The new alpha value.
+ */
+ inline void setAlpha(float alpha) { _alpha = alpha; }
+ /*! sets the attribute's thickness.
+ * \param tr
+ * The thickness on the right of the vertex when following the stroke.
+ * \param tl
+ * The thickness on the left of the vertex when following the stroke.
+ */
+ inline void setThickness(float tr, float tl) { _thickness[0]=tr; _thickness[1]=tl; }
+ /*! sets the attribute's thickness.
+ * \param tRL
+ * The thickness on the right and on the left of the vertex when following the stroke.
+ */
+ inline void setThickness(const Vec2f& tRL) { _thickness[0]=tRL[0]; _thickness[1]=tRL[1]; }
+
+ /*! sets the visible flag. True means visible. */
+ inline void setVisible(bool iVisible){ _visible = iVisible; }
+
+ /*! Adds a user defined attribute of type real
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeReal(const char *iName, float att);
+ /*! Adds a user defined attribute of type Vec2f
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeVec2f(const char *iName, const Vec2f& att);
+ /*! Adds a user defined attribute of type Vec3f
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeVec3f(const char *iName, const Vec3f& att);
+
+private:
+
+ typedef std::map<const char*, float, StringUtils::ltstr> realMap ;
+ typedef std::map<const char*, Vec2f, StringUtils::ltstr> Vec2fMap ;
+ typedef std::map<const char*, Vec3f, StringUtils::ltstr> Vec3fMap ;
+
+ float _color[3]; //! the color
+ float _alpha; //! alpha
+ float _thickness[2]; //! the thickness on the right and on the left of the backbone vertex (the stroke is oriented)
+ bool _visible;
+ realMap *_userAttributesReal;
+ Vec2fMap *_userAttributesVec2f;
+ Vec3fMap *_userAttributesVec3f;
+};
+
+
+//
+// StrokeVertex
+//
+////////////////////////////////////////////////////////
+
+/*! Class to define a stroke vertex.
+ */
+class LIB_STROKE_EXPORT StrokeVertex : public CurvePoint
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "StrokeVertex"*/
+ virtual string getExactTypeName() const {
+ return "StrokeVertex";
+ }
+
+private:
+
+ StrokeAttribute _Attribute; //! The attribute associated to the vertex
+ float _CurvilignAbscissa; //! the curvilign abscissa
+ float _StrokeLength; // stroke length
+
+public:
+
+ /*! default constructor */
+ StrokeVertex();
+ /*! Copy constructor */
+ StrokeVertex(const StrokeVertex& iBrother);
+ /*! Builds a stroke vertex from a SVertex */
+ StrokeVertex(SVertex *iSVertex);
+ /*! Builds a stroke vertex from a CurvePoint */
+ StrokeVertex(CurvePoint *iPoint);
+ /*! Builds Stroke Vertex from 2 stroke vertices and an interpolation parameter*/
+ StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3);
+ /*! Builds a stroke from a view vertex and an attribute */
+ StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute);
+ /*! destructor */
+ virtual ~StrokeVertex();
+
+ /* operators */
+ /*! operator = */
+ StrokeVertex& operator=(const StrokeVertex& iBrother);
+
+ /* accessors */
+ /*! Returns the 2D point x coordinate */
+ inline real x() const { return _Point2d[0]; }
+ /*! Returns the 2D point y coordinate */
+ inline real y() const { return _Point2d[1]; }
+ /*! Returns the 2D point coordinates as a Vec2d */
+ Vec2f getPoint () {return Vec2f((float)point2d()[0], (float)point2d()[1]);}
+ /*! Returns the ith 2D point coordinate (i=0 or 1)*/
+ inline real operator[](const int i) const { return _Point2d[i]; }
+ /*! Returns the StrokeAttribute for this StrokeVertex */
+ inline const StrokeAttribute& attribute() const { return _Attribute; }
+ /*! Returns a non-const reference to the StrokeAttribute of this StrokeVertex */
+ inline StrokeAttribute& attribute() {return _Attribute;}
+ /*! Returns the curvilinear abscissa */
+ inline float curvilinearAbscissa() const {return _CurvilignAbscissa;}
+ /*! Returns the length of the Stroke to which this StrokeVertex belongs */
+ inline float strokeLength() const {return _StrokeLength;}
+ /*! Returns the curvilinear abscissa of this StrokeVertex in the Stroke */
+ inline float u() const {return _CurvilignAbscissa/_StrokeLength;}
+
+ /* modifiers */
+ /*! sets the 2D x value */
+ inline void setX(real x) { _Point2d[0]=x; }
+ /*! sets the 2D y value */
+ inline void setY(real y) { _Point2d[1]=y; }
+ /*! sets the 2D x and y values */
+ inline void setPoint(real x, real y) { _Point2d[0]=x; _Point2d[1]=y;}
+ /*! sets the 2D x and y values */
+ inline void setPoint(const Vec2f& p) { _Point2d[0] = p[0];_Point2d[1] = p[1];}
+ /*! Returns a reference to the ith 2D point coordinate (i=0 or 1) */
+ inline real& operator[](const int i) { return _Point2d[i]; }
+ /*! sets the attribute. */
+ inline void setAttribute(const StrokeAttribute& iAttribute) { _Attribute = iAttribute; }
+ /*! sets the curvilinear abscissa of this StrokeVertex in the Stroke */
+ inline void setCurvilinearAbscissa(float iAbscissa) {_CurvilignAbscissa = iAbscissa;}
+ /*! sets the Stroke's length (it's only a value stored by the Stroke Vertex, it won't
+ * change the real Stroke's length.)
+ */
+ inline void setStrokeLength(float iLength) {_StrokeLength = iLength;}
+
+ /* interface definition */
+ /* inherited */
+
+};
+
+
+//
+// Stroke
+//
+////////////////////////////////////////////////////////
+
+class StrokeRenderer;
+class StrokeRep;
+
+namespace StrokeInternal {
+ class vertex_const_traits ;
+ class vertex_nonconst_traits ;
+ template<class Traits> class vertex_iterator_base;
+ class StrokeVertexIterator;
+} // end of namespace StrokeInternal
+
+/*! Class to define a stroke.
+ * A stroke is made of a set of 2D vertices (StrokeVertex), regularly spaced out.
+ * This set of vertices defines the stroke's backbone geometry.
+ * Each of these stroke vertices defines the stroke's shape and appearance
+ * at this vertex position.
+ */
+class LIB_STROKE_EXPORT Stroke : public Interface1D
+{
+public: // Implementation of Interface1D
+
+ /*! Returns the string "Stroke" */
+ virtual string getExactTypeName() const {
+ return "Stroke";
+ }
+
+ // Data access methods
+
+ /*! Returns the Id of the Stroke */
+ virtual Id getId() const {
+ return _id;
+ }
+ /*! The different blending modes
+ * available to similate the interaction
+ * media-medium.
+ */
+ typedef enum{
+ DRY_MEDIUM,/*!< To simulate a dry medium such as Pencil or Charcoal.*/
+ HUMID_MEDIUM,/*!< To simulate ink painting (color substraction blending).*/
+ OPAQUE_MEDIUM, /*!< To simulate an opaque medium (oil, spray...).*/
+ } MediumType;
+
+
+public:
+ typedef std::deque<StrokeVertex*> vertex_container; // the vertices container
+ typedef std::vector<ViewEdge*> viewedge_container; // the viewedges container
+ typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_nonconst_traits > vertex_iterator;
+ typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_const_traits> const_vertex_iterator;
+
+public:
+ //typedef StrokeVertex vertex_type;
+private:
+ vertex_container _Vertices; //! The stroke's backbone vertices
+ Id _id;
+ float _Length; // The stroke length
+ viewedge_container _ViewEdges;
+ float _sampling;
+ StrokeRenderer *_renderer; // mark implementation OpenGL renderer
+ MediumType _mediumType;
+ unsigned int _textureId;
+ bool _tips;
+ Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity
+ StrokeRep *_rep;
+
+public:
+ /*! default constructor */
+ Stroke();
+ /*! copy constructor */
+ Stroke(const Stroke& iBrother);
+ /*! Builds a stroke from a set of StrokeVertex.
+ * This constructor is templated by an iterator type.
+ * This iterator type must allow the vertices parsing
+ * using the ++ operator.
+ * \param iBegin
+ * The iterator pointing to the first vertex.
+ * \param iEnd
+ * The iterator pointing to the end of the vertex list.
+ */
+ template<class InputVertexIterator>
+ Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd);
+
+ /*! Destructor */
+ virtual ~Stroke();
+
+ /* operators */
+ /*! operator = */
+ Stroke& operator=(const Stroke& iBrother);
+
+ /*! Compute the sampling needed to get iNVertices
+ * vertices.
+ * If the specified number of vertices is less than the
+ * actual number of vertices, the actual sampling value is returned.
+ * (To remove Vertices, use the RemoveVertex() method of this class).
+ * \param iNVertices
+ * The number of StrokeVertices we eventually want
+ * in our Stroke.
+ * \return the sampling that must be used in the Resample(float) method.
+ * @see Resample(int)
+ * @see Resample(float)
+ */
+ float ComputeSampling(int iNVertices);
+
+ /*! Resampling method.
+ * Resamples the curve so that it eventually
+ * has iNPoints. That means it is going
+ * to add iNPoints-vertices_size, if vertices_size
+ * is the number of points we already have.
+ * Is vertices_size >= iNPoints, no resampling is done.
+ * \param iNPoints
+ * The number of vertices we eventually want in our stroke.
+ */
+ void Resample(int iNPoints);
+
+ /*! Resampling method.
+ * Resamples the curve with a given sampling.
+ * If this sampling is < to the actual sampling
+ * value, no resampling is done.
+ * \param iSampling
+ * The new sampling value.
+ */
+ void Resample(float iSampling);
+
+ /*! Removes the stroke vertex iVertex
+ * from the stroke.
+ * The length and curvilinear abscissa are updated
+ * consequently.
+ */
+ void RemoveVertex(StrokeVertex *iVertex);
+
+ /*! Inserts the stroke vertex iVertex
+ * in the stroke before next.
+ * The length, curvilinear abscissa are updated
+ * consequently.
+ * \param iVertex
+ * The StrokeVertex to insert in the Stroke.
+ * \param next
+ * A StrokeVertexIterator pointing to the StrokeVeretx before
+ * which iVertex must be inserted.
+ */
+ void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next);
+
+ /*! Updates the 2D length of the Stroke */
+ void UpdateLength();
+
+ /* Render method */
+ void ScaleThickness(float iFactor);
+ void Render(const StrokeRenderer *iRenderer );
+ void RenderBasic(const StrokeRenderer *iRenderer );
+
+ /* Iterator definition */
+
+ /* accessors */
+ /*! Returns the 2D length of the Stroke */
+ inline real getLength2D() const {return _Length;}
+ /*! Returns a reference to the time stamp value of the stroke. */
+ /*! Returns the MediumType used for this Stroke. */
+ inline MediumType getMediumType() const {return _mediumType;}
+ /*! Returns the id of the texture used to simulate th marks system
+ * for this Stroke
+ */
+ inline unsigned int getTextureId() {return _textureId;}
+ /*! Returns true if this Stroke uses a texture with tips, false
+ * otherwise.
+ */
+ inline bool hasTips() const {return _tips;}
+ /* these advanced iterators are used only in C++ */
+ inline int vertices_size() const {return _Vertices.size();}
+ inline viewedge_container::const_iterator viewedges_begin() const {return _ViewEdges.begin();}
+ inline viewedge_container::iterator viewedges_begin() {return _ViewEdges.begin();}
+ inline viewedge_container::const_iterator viewedges_end() const {return _ViewEdges.end();}
+ inline viewedge_container::iterator viewedges_end() {return _ViewEdges.end();}
+ inline int viewedges_size() const {return _ViewEdges.size();}
+
+ inline Vec2r getBeginningOrientation() const {return _extremityOrientations[0];}
+ inline real getBeginningOrientationX() const {return _extremityOrientations[0].x();}
+ inline real getBeginningOrientationY() const {return _extremityOrientations[0].y();}
+ inline Vec2r getEndingOrientation() const {return _extremityOrientations[1];}
+ inline real getEndingOrientationX() const {return _extremityOrientations[1].x();}
+ inline real getEndingOrientationY() const {return _extremityOrientations[1].y();}
+
+
+ /* modifiers */
+ /*! sets the Id of the Stroke. */
+ inline void setId(const Id& id) {_id = id;}
+ /*! sets the 2D length of the Stroke. */
+ void setLength(float iLength);
+ /*! sets the medium type that must be used for this Stroke. */
+ inline void setMediumType(MediumType iType) {_mediumType = iType;}
+ /*! sets the texture id to be used to simulate the marks system for this Stroke. */
+ inline void setTextureId(unsigned int id) {_textureId = id;}
+ /*! sets the flag telling whether this stroke is using a texture with
+ * tips or not.
+ */
+ inline void setTips(bool iTips) {_tips = iTips;}
+
+ inline void push_back(StrokeVertex* iVertex) { _Vertices.push_back(iVertex); }
+ inline void push_front(StrokeVertex* iVertex) { _Vertices.push_front(iVertex); }
+ inline void AddViewEdge(ViewEdge *iViewEdge) {_ViewEdges.push_back(iViewEdge);}
+ inline void setBeginningOrientation(const Vec2r& iOrientation) {_extremityOrientations[0] = iOrientation;}
+ inline void setBeginningOrientation(real x, real y) {_extremityOrientations[0] = Vec2r(x,y);}
+ inline void setEndingOrientation(const Vec2r& iOrientation) {_extremityOrientations[1] = iOrientation;}
+ inline void setEndingOrientation(real x, real y) {_extremityOrientations[1] = Vec2r(x,y);}
+
+ /* Information access interface */
+
+ // embedding vertex iterator
+ const_vertex_iterator vertices_begin() const;
+ vertex_iterator vertices_begin(float t=0.f);
+ const_vertex_iterator vertices_end() const;
+ vertex_iterator vertices_end();
+
+ /*! Returns a StrokeVertexIterator pointing on the first StrokeVertex of the
+ * Stroke. One can specifly a sampling value to resample the Stroke
+ * on the fly if needed.
+ * \param t
+ * The resampling value with which we want our Stroke to be resampled.
+ * If 0 is specified, no resampling is done.
+ */
+ StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t=0.f);
+ /*! Returns a StrokeVertexIterator pointing after the last StrokeVertex of the
+ * Stroke.
+ */
+ StrokeInternal::StrokeVertexIterator strokeVerticesEnd();
+ /*! Returns the number of StrokeVertex constituing the Stroke. */
+ inline unsigned int strokeVerticesSize() const {return _Vertices.size();}
+
+ /*! Returns the i-th StrokeVertex constituting the Stroke. */
+ inline StrokeVertex& strokeVerticeAt(unsigned int i) {return *(_Vertices.at(i));}
+
+ // Iterator access (Interface1D)
+ /*! Returns an Interface0DIterator pointing on the first StrokeVertex of the
+ * Stroke.
+ */
+ virtual Interface0DIterator verticesBegin();
+ /*! Returns an Interface0DIterator pointing after the last StrokeVertex of the
+ * Stroke.
+ */
+ virtual Interface0DIterator verticesEnd();
+
+ virtual Interface0DIterator pointsBegin(float t=0.f);
+ virtual Interface0DIterator pointsEnd(float t=0.f);
+};
+
+
+
+//
+// Implementation
+//
+////////////////////////////////////////////////////////
+
+
+template<class InputVertexIterator>
+Stroke::Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd)
+{
+ for(InputVertexIterator v=iBegin, vend=iEnd;
+ v!=vend;
+ v++)
+ {
+ _Vertices.push_back(*v);
+ }
+ _Length = 0;
+ _id = 0;
+}
+
+#endif // STROKE_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h
new file mode 100755
index 00000000000..279a0b12089
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h
@@ -0,0 +1,142 @@
+//
+// Filename : StrokeAdvancedIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the elements of the Stroke
+// Can't be used in python
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STROKEADVANCEDITERATORS_H
+# define STROKEADVANCEDITERATORS_H
+
+# include "Stroke.h"
+
+namespace StrokeInternal {
+
+ class vertex_const_traits : public Const_traits<StrokeVertex*> {
+ public:
+ typedef std::deque<StrokeVertex*> vertex_container;
+ typedef vertex_container::const_iterator vertex_container_iterator ;
+ };
+ class vertex_nonconst_traits : public Nonconst_traits<StrokeVertex*> {
+ public:
+ typedef std::deque<StrokeVertex*> vertex_container; //! the vertices container
+ typedef vertex_container::iterator vertex_container_iterator ;
+ };
+
+
+ template<class Traits>
+ class vertex_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef vertex_iterator_base<Traits> Self;
+ protected:
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+ typedef typename Traits::vertex_container_iterator vertex_container_iterator;
+ typedef vertex_iterator_base<vertex_nonconst_traits> iterator;
+ typedef vertex_iterator_base<vertex_const_traits> const_iterator;
+ //protected:
+ public:
+ vertex_container_iterator _it;
+ vertex_container_iterator _begin;
+ vertex_container_iterator _end;
+ public:
+ friend class Stroke;
+ //friend class vertex_iterator;
+ inline vertex_iterator_base()
+ : parent_class()
+ {}
+ inline vertex_iterator_base(const iterator& iBrother)
+ : parent_class()
+ {_it = iBrother._it;_begin = iBrother._begin;_end = iBrother._end;}
+ inline vertex_iterator_base(const const_iterator& iBrother)
+ : parent_class()
+ {_it = iBrother._it;_begin = iBrother._begin;_end = iBrother._end;}
+ //protected://FIXME
+ public:
+ inline vertex_iterator_base(vertex_container_iterator it, vertex_container_iterator begin, vertex_container_iterator end)
+ : parent_class()
+ {
+ _it = it;
+ _begin = begin;
+ _end = end;
+ }
+
+ public:
+ virtual ~vertex_iterator_base() {}
+
+ virtual bool begin() const {return _it==_begin? true : false;}
+ virtual bool end() const {return _it==_end ? true : false;}
+
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ ++_it;
+ return *(this);
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ {
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ ++_it; // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ --_it;
+ return *(this);
+ }
+ inline Self operator--(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ --_it; // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_it != b._it);
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual typename Traits::reference operator*() const {return *(_it);}
+ virtual typename Traits::pointer operator->() const { return &(operator*());}
+
+ /*! accessors */
+ inline vertex_container_iterator it() const {return _it;}
+ inline vertex_container_iterator getBegin() const {return _begin;}
+ inline vertex_container_iterator getEnd() const {return _end;}
+ };
+
+} // end of namespace StrokeInternal
+
+
+#endif // STROKEADVANCEDITERATORS_H
+
+
diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.cpp b/source/blender/freestyle/intern/stroke/StrokeIO.cpp
new file mode 100755
index 00000000000..903a198adc2
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIO.cpp
@@ -0,0 +1,55 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "StrokeIO.h"
+#include "StrokeAdvancedIterators.h"
+
+
+ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute){
+ out << " StrokeAttribute" << endl;
+ out << " color : (" << iStrokeAttribute.getColorR() << "," << iStrokeAttribute.getColorG() << "," << iStrokeAttribute.getColorB() << ")" << endl;
+ out << " alpha : " << iStrokeAttribute.getAlpha() << endl;
+ out << " thickness : " << iStrokeAttribute.getThicknessR() << ", " << iStrokeAttribute.getThicknessL() << endl;
+ out << " visible : " << iStrokeAttribute.isVisible() << endl;
+ return out;
+}
+
+ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex){
+ out << " StrokeVertex" << endl;
+ out << " id : " << iStrokeVertex.getId() << endl;
+ out << " curvilinear length : " << iStrokeVertex.curvilinearAbscissa() << endl;
+ out << " 2d coordinates : (" << iStrokeVertex.getProjectedX() << "," << iStrokeVertex.getProjectedY() << "," << iStrokeVertex.getProjectedZ() << ")" << endl;
+ out << " 3d coordinates : (" << iStrokeVertex.getX() << "," << iStrokeVertex.getY() << "," << iStrokeVertex.getZ() << ")"<< endl;
+ out << iStrokeVertex.attribute() << endl;
+ return out;
+}
+
+ostream& operator<<(ostream& out, const Stroke& iStroke){
+ out << "Stroke" << endl;
+ out << " id : " << iStroke.getId() << endl;
+ out << " length : " << iStroke.getLength2D() << endl;
+ out << " medium type : " << iStroke.getMediumType() << endl;
+ for(Stroke::const_vertex_iterator v=iStroke.vertices_begin(), vend=iStroke.vertices_end();
+ v!=vend;
+ ++v){
+ out << *(*v) << endl;
+ }
+ return out;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.h b/source/blender/freestyle/intern/stroke/StrokeIO.h
new file mode 100755
index 00000000000..150c8340778
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIO.h
@@ -0,0 +1,47 @@
+//
+// Filename : StrokeIO.h
+// Author(s) : Stephane Grabli
+// Purpose : Functions to manage I/O for the stroke
+// Date of creation : 03/02/2004
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STROKEIO_H
+# define STROKEIO_H
+
+# include "Stroke.h"
+# include <iostream>
+# include "../system/FreestyleConfig.h"
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute);
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex);
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const Stroke& iStroke);
+
+
+#endif // STROKEIO_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeIterators.h b/source/blender/freestyle/intern/stroke/StrokeIterators.h
new file mode 100755
index 00000000000..b51189f3990
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIterators.h
@@ -0,0 +1,229 @@
+//
+// Filename : StrokeIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the elements of the Stroke
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STROKEITERATORS_H
+# define STROKEITERATORS_H
+
+# include "Stroke.h"
+
+namespace StrokeInternal {
+
+ //
+ // StrokeVertexIterator
+ //
+ /////////////////////////////////////////////////
+
+ /*! Class defining an iterator designed to iterate over
+ * the StrokeVertex of a Stroke.
+ * An instance of a StrokeVertexIterator can only be obtained
+ * from a Stroke by calling strokeVerticesBegin() or strokeVerticesEnd().
+ * It is iterating over the same vertices as an Interface0DIterator.
+ * The difference resides in the object access. Indeed, an Interface0DIterator
+ * allows only an access to an Interface0D whereas we could need
+ * to access the specialized StrokeVertex type. In this case, one
+ * should use a StrokeVertexIterator.
+ * The castToInterface0DIterator() method is useful to get an Interface0DIterator
+ * from a StrokeVertexIterator in order to call any functions of the
+ * type UnaryFunction0D.
+ * \attention In the scripting language, you must call
+ * \code it2 = StrokeVertexIterator(it1) \endcode instead of
+ * \code it2 = it1 \endcode
+ * where \a it1 and \a it2 are 2 StrokeVertexIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+ class StrokeVertexIterator : public Interface0DIteratorNested
+ {
+ public:
+
+ /*! Default constructor. */
+ StrokeVertexIterator() {}
+
+ /*! Copy constructor. */
+ StrokeVertexIterator(const StrokeVertexIterator& vi) {
+ _it = vi._it;
+ _begin = vi._begin;
+ _end = vi._end;
+ }
+
+ StrokeVertexIterator(const ::Stroke::vertex_container::iterator& it,
+ const ::Stroke::vertex_container::iterator& begin,
+ const ::Stroke::vertex_container::iterator& end) {
+ _it = it;
+ _begin = begin;
+ _end = end;
+ }
+
+ virtual ~StrokeVertexIterator() {}
+
+ /*! Casts this StrokeVertexIterator into an Interface0DIterator.
+ * Useful for any call to a function of the type UnaryFunction0D.
+ */
+ inline Interface0DIterator castToInterface0DIterator() const {
+ Interface0DIterator ret(new StrokeVertexIterator(*this));
+ return ret;
+ }
+ /*! operator=
+ * \attention In the scripting language, you must call
+ * \code it2 = StrokeVertexIterator(it1) \endcode instead of
+ * \code it2 = it1 \endcode
+ * where \a it1 and \a it2 are 2 StrokeVertexIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ *
+ */
+ StrokeVertexIterator& operator=(const StrokeVertexIterator& vi) {
+ _it = vi._it;
+ _begin = vi._begin;
+ _end = vi._end;
+ return *this;
+ }
+
+ /*! Returns the string "StrokeVertexIterator". */
+ virtual string getExactTypeName() const {
+ return "StrokeVertexIterator";
+ }
+
+ /*! Returns a reference to the pointed StrokeVertex.
+ * In the scripting language, you must call
+ * "getObject()"instead.
+ */
+ virtual StrokeVertex& operator*() {
+ return **_it;
+ }
+
+ /*! Returns a pointer to the pointed StrokeVertex.
+ * Can't be called in the scripting language.
+ */
+ virtual StrokeVertex* operator->() {
+ return &(operator*());
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ virtual StrokeVertexIterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ virtual StrokeVertexIterator operator++(int) {
+ StrokeVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ virtual StrokeVertexIterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ virtual StrokeVertexIterator operator--(int) {
+ StrokeVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ /*! Increments. */
+ virtual int increment() {
+ ++_it;
+ return 0;
+ }
+
+ /*! Decrements. */
+ virtual int decrement() {
+ --_it;
+ return 0;
+ }
+
+ /*! Returns true if the pointed StrokeVertex is the
+ * first of the Stroke.
+ */
+ bool isBegin() const {
+ return _it == _begin;
+ }
+
+ /*! Returns true if the pointed StrokeVertex is after the
+ * last StrokeVertex of the Stroke.
+ */
+ bool isEnd() const {
+ return _it == _end;
+ }
+
+ /*! operator == */
+ virtual bool operator==(const Interface0DIteratorNested& it) const {
+ const StrokeVertexIterator* it_exact = dynamic_cast<const StrokeVertexIterator*>(&it);
+ if (!it_exact)
+ return false;
+ return (_it == it_exact->_it);
+ }
+
+ /*! Returns the curvilinear abscissa of the current point */
+ virtual float t() const{
+ return (*_it)->curvilinearAbscissa();
+ }
+ /*! Returns the point's parameter in the stroke */
+ virtual float u() const{
+ return (*_it)->u();
+ }
+
+ /*! Cloning method */
+ virtual StrokeVertexIterator* copy() const {
+ return new StrokeVertexIterator(*this);
+ }
+
+ //
+ // Not exported in Python
+ //
+ //////////////////////////////////////////////////
+
+ const ::Stroke::vertex_container::iterator& getIt() {
+ return _it;
+ }
+
+ private:
+
+ ::Stroke::vertex_container::iterator _it;
+ ::Stroke::vertex_container::iterator _begin;
+ ::Stroke::vertex_container::iterator _end;
+ };
+
+} // end of namespace StrokeInternal
+
+
+#endif // STROKEITERATORS_H
+
+
diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.cpp b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp
new file mode 100755
index 00000000000..93d695be406
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp
@@ -0,0 +1,64 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Stroke.h"
+#include "StrokeLayer.h"
+#include "Canvas.h"
+
+StrokeLayer::~StrokeLayer()
+{
+ clear();
+}
+
+void StrokeLayer::ScaleThickness(float iFactor)
+{
+ for(StrokeLayer::stroke_container::iterator s=_strokes.begin(), send=_strokes.end();
+ s!=send;
+ ++s){
+ (*s)->ScaleThickness(iFactor);
+ }
+}
+
+void StrokeLayer::Render(const StrokeRenderer *iRenderer )
+{
+ for(StrokeLayer::stroke_container::iterator s=_strokes.begin(), send=_strokes.end();
+ s!=send;
+ ++s){
+ (*s)->Render(iRenderer);
+ }
+}
+
+void StrokeLayer::RenderBasic(const StrokeRenderer *iRenderer )
+{
+ for(StrokeLayer::stroke_container::iterator s=_strokes.begin(), send=_strokes.end();
+ s!=send;
+ ++s){
+ (*s)->RenderBasic(iRenderer);
+ }
+}
+void StrokeLayer::clear()
+{
+ for(stroke_container::iterator s=_strokes.begin(), send=_strokes.end();
+ s!=send;
+ ++s)
+ delete *s;
+ _strokes.clear();
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.h b/source/blender/freestyle/intern/stroke/StrokeLayer.h
new file mode 100755
index 00000000000..eb8e7891bdd
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeLayer.h
@@ -0,0 +1,76 @@
+//
+// Filename : StrokeLayer.h
+// Author : Stephane Grabli
+// Purpose : Class to define a layer of strokes.
+// Date of creation : 18/12/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STROKELAYER_H
+# define STROKELAYER_H
+
+# include <deque>
+
+class Stroke;
+class StrokeRenderer;
+class StrokeLayer
+{
+public:
+ typedef std::deque<Stroke*> stroke_container;
+
+protected:
+ stroke_container _strokes;
+public:
+ StrokeLayer() {}
+ StrokeLayer(const stroke_container& iStrokes)
+ {
+ _strokes = iStrokes;
+ }
+ StrokeLayer(const StrokeLayer& iBrother)
+ {
+ _strokes = iBrother._strokes;
+ }
+ virtual ~StrokeLayer() ;
+
+ /*! Render method */
+ void ScaleThickness(float iFactor);
+ void Render(const StrokeRenderer *iRenderer );
+ void RenderBasic(const StrokeRenderer *iRenderer );
+
+ /*! clears the layer */
+ void clear() ;
+
+ /*! accessors */
+ inline stroke_container::iterator strokes_begin() {return _strokes.begin();}
+ inline stroke_container::iterator strokes_end() {return _strokes.end();}
+ inline int strokes_size() const {return _strokes.size();}
+ inline bool empty() const {return _strokes.empty();}
+
+ /*! modifiers */
+ inline void setStrokes(stroke_container& iStrokes) {_strokes = iStrokes;}
+ inline void AddStroke(Stroke *iStroke) {_strokes.push_back(iStroke);}
+
+};
+
+#endif // STROKELAYER_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
new file mode 100755
index 00000000000..19e5ba35fed
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
@@ -0,0 +1,121 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "StrokeRenderer.h"
+#include "../geometry/GeomUtils.h"
+using namespace std;
+
+/**********************************/
+/* */
+/* */
+/* StrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+LIB_STROKE_EXPORT
+TextureManager *StrokeRenderer::_textureManager = 0;
+
+StrokeRenderer::StrokeRenderer ()
+{
+}
+
+StrokeRenderer::~StrokeRenderer ()
+{
+}
+
+bool StrokeRenderer::loadTextures()
+{
+ _textureManager->load();
+ return true;
+}
+
+
+/**********************************/
+/* */
+/* */
+/* TextureManager */
+/* */
+/* */
+/**********************************/
+
+
+LIB_STROKE_EXPORT
+TextureManager* TextureManager::_pInstance = 0;
+
+LIB_STROKE_EXPORT
+string TextureManager::_patterns_path;
+
+LIB_STROKE_EXPORT
+string TextureManager::_brushes_path;
+
+TextureManager::TextureManager ()
+{
+ _hasLoadedTextures=false;
+ _pInstance = this;
+ _defaultTextureId = 0;
+}
+
+TextureManager::~TextureManager ()
+{
+ if(!_brushesMap.empty())
+ _brushesMap.clear();
+ _pInstance = 0;
+}
+
+void TextureManager::load()
+{
+ if(_hasLoadedTextures)
+ return;
+ loadStandardBrushes();
+ _hasLoadedTextures = true;
+}
+
+unsigned TextureManager::getBrushTextureIndex(string name, Stroke::MediumType loadingMode)
+{
+ BrushTexture bt(name,loadingMode);
+ brushesMap::iterator b = _brushesMap.find(bt);
+ if(b == _brushesMap.end()){
+ unsigned texId = loadBrush(name, loadingMode);
+ _brushesMap[bt] = texId;
+ return texId;
+ cout << "brush file " << name << " not found" << endl;
+ return 0;
+ }else{
+ return _brushesMap[bt];
+ }
+}
+
+void TextureManager::Options::setPatternsPath(const string& path) {
+ _patterns_path = path;
+}
+
+string TextureManager::Options::getPatternsPath() {
+ return _patterns_path;
+}
+
+void TextureManager::Options::setBrushesPath(const string& path) {
+ _brushes_path = path;
+}
+
+string TextureManager::Options::getBrushesPath() {
+ return _brushes_path;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.h b/source/blender/freestyle/intern/stroke/StrokeRenderer.h
new file mode 100755
index 00000000000..c7c6df635d5
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.h
@@ -0,0 +1,132 @@
+//
+// Filename : StrokeRenderer.h
+// Author(s) : Fredo Durand
+// Purpose : Classes to render a stroke with OpenGL
+// Date of creation : 09/09/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STROKE_RENDERER_H
+# define STROKE_RENDERER_H
+
+# include "Stroke.h"
+# include <vector>
+# include <map>
+# include <utility>
+# include "../system/FreestyleConfig.h"
+# include "StrokeRep.h"
+# include <string.h>
+
+
+/**********************************/
+/* */
+/* */
+/* TextureManager */
+/* */
+/* */
+/**********************************/
+
+
+/*! Class to load textures
+ */
+class LIB_STROKE_EXPORT TextureManager
+{
+public:
+
+ TextureManager ();
+ virtual ~TextureManager ();
+ static TextureManager * getInstance() {return _pInstance;}
+ void load () ;
+ unsigned getBrushTextureIndex(string name, Stroke::MediumType iType = Stroke::OPAQUE_MEDIUM) ;
+
+ inline bool hasLoaded() const {return _hasLoadedTextures;}
+ inline unsigned int getDefaultTextureId() const {return _defaultTextureId;}
+
+ struct LIB_STROKE_EXPORT Options
+ {
+
+ static void setPatternsPath(const string& path);
+ static string getPatternsPath();
+
+ static void setBrushesPath(const string& path);
+ static string getBrushesPath();
+ };
+
+ protected:
+ virtual void loadStandardBrushes() = 0;
+ virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM) = 0;
+
+ typedef std::pair<string,Stroke::MediumType> BrushTexture;
+ struct cmpBrushTexture{
+ bool operator()(const BrushTexture& bt1, const BrushTexture& bt2) const{
+ int r = strcmp(bt1.first.c_str(), bt2.first.c_str());
+ if(r != 0)
+ return (r<0);
+ else
+ return (bt1.second < bt2.second);
+ }
+ };
+ typedef std::map<BrushTexture, unsigned, cmpBrushTexture> brushesMap;
+
+ static TextureManager * _pInstance;
+ bool _hasLoadedTextures;
+ brushesMap _brushesMap;
+ static string _patterns_path;
+ static string _brushes_path;
+ unsigned int _defaultTextureId;
+};
+
+
+/**********************************/
+/* */
+/* */
+/* StrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+/*! Class to render a stroke.
+ Creates a triangle strip and stores it
+ strip is lazily created at the first rendering
+*/
+class LIB_STROKE_EXPORT StrokeRenderer
+{
+ public:
+ StrokeRenderer();
+ virtual ~StrokeRenderer ();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const = 0;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const = 0;
+
+ // initializes the texture manager
+ // lazy, checks if it has already been done
+ static bool loadTextures() ;
+
+ //static unsigned int getTextureIndex(unsigned int index) ;
+ static TextureManager *_textureManager;
+};
+
+
+#endif // STROKE_RENDERER_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
new file mode 100755
index 00000000000..18142233672
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
@@ -0,0 +1,751 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Stroke.h"
+#include "StrokeRep.h"
+#include "StrokeRenderer.h"
+#include "StrokeAdvancedIterators.h"
+#include "StrokeIterators.h"
+
+using namespace std;
+
+//
+// STROKE VERTEX REP
+/////////////////////////////////////
+StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother){
+ _point2d = iBrother._point2d;
+ _texCoord = iBrother._texCoord;
+ _color = iBrother._color;
+ _alpha = iBrother._alpha;
+}
+
+//
+// STRIP
+/////////////////////////////////////
+
+Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTips, bool beginTip, bool endTip){
+ createStrip(iStrokeVertices);
+ if (!hasTips)
+ computeTexCoord (iStrokeVertices);
+ else
+ computeTexCoordWithTips (iStrokeVertices, beginTip, endTip);
+}
+Strip::Strip(const Strip& iBrother){
+ if(!iBrother._vertices.empty()){
+ for(vertex_container::const_iterator v=iBrother._vertices.begin(), vend=iBrother._vertices.end();
+ v!=vend;
+ ++v){
+ _vertices.push_back(new StrokeVertexRep(**v));
+ }
+ }
+ _averageThickness = iBrother._averageThickness;
+}
+
+Strip::~Strip(){
+ if(!_vertices.empty()){
+ for(vertex_container::iterator v=_vertices.begin(), vend=_vertices.end();
+ v!=vend;
+ ++v){
+ delete (*v);
+ }
+ _vertices.clear();
+ }
+}
+
+//////////////////////////
+// Strip creation
+//////////////////////////
+#define EPS_SINGULARITY_RENDERER 0.05
+#define ZERO 0.00001
+#define MAX_RATIO_LENGTH_SINGU 2
+#define HUGE_COORD 1e4
+
+bool notValid (Vec2r p)
+{
+ return (p[0]!=p[0]) || (p[1]!=p[1]) || (fabs(p[0])>HUGE_COORD) || (fabs(p[1])>HUGE_COORD)
+ || (p[0] <-HUGE_COORD) || (p[1]<-HUGE_COORD);
+}
+
+real crossP(const Vec2r& A, const Vec2r& B){
+ return A[0]*B[1] - A[1]*B[0];
+}
+
+void
+Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
+{
+ //computeParameterization();
+ if (iStrokeVertices.size() <2)
+ {
+ cerr << "Warning: strip has less than 2 vertices" << endl;
+ return;
+ }
+ _vertices.reserve(2*iStrokeVertices.size());
+ if(!_vertices.empty()){
+ for(vertex_container::iterator v=_vertices.begin(), vend=_vertices.end();
+ v!=vend;
+ ++v){
+ delete (*v);
+ }
+ _vertices.clear();
+ }
+ _averageThickness=0.0;
+
+ vector<StrokeVertex*>::const_iterator v ,vend, v2, vPrev;
+ StrokeVertex *sv, *sv2, *svPrev;
+
+ //special case of first vertex
+ v=iStrokeVertices.begin();
+ sv=*v;
+ vPrev=v; //in case the stroke has only 2 vertices;
+ ++v; sv2=*v;
+ Vec2r dir(sv2->getPoint()-sv->getPoint());
+ Vec2r orthDir(-dir[1], dir[0]);
+ if (orthDir.norm() > ZERO)
+ orthDir.normalize();
+ Vec2r stripDir(orthDir);
+ // check whether the orientation was user defined
+ if(sv->attribute().isAttributeAvailableVec2f("orientation")){
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir*orthDir;
+ if(dp<0)
+ userDir = userDir*(-1.f);
+ stripDir = userDir;
+ }
+ const float *thickness = sv->attribute().getThickness();
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint()+thickness[1]*stripDir));
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint()-thickness[0]*stripDir));
+
+ // Vec2r userDir = _stroke->getBeginningOrientation();
+ // if(userDir != Vec2r(0,0)){
+ // userDir.normalize();
+ // real o1 = (orthDir*userDir);
+ // real o2 = crossP(orthDir,userDir);
+ // real orientation = o1 * o2;
+ // if(orientation > 0){
+ // // then the vertex to move is v0
+ // if(o1 > 0)
+ // _vertex[0]=_vertex[1]+userDir;
+ // else
+ // _vertex[0]=_vertex[1]-userDir;
+ // }
+ // if(orientation < 0){
+ // // then we must move v1
+ // if(o1 < 0)
+ // _vertex[1]=_vertex[0]+userDir;
+ // else
+ // _vertex[1]=_vertex[0]-userDir;
+ // }
+ // }
+
+ int i=2; //2 because we have already processed the first vertex
+
+ for(vend=iStrokeVertices.end();
+ v!=vend;
+ v++){
+ v2=v; ++v2;
+ if (v2==vend) break;
+ sv= (*v); sv2 = (*v2); svPrev=(*vPrev);
+ Vec2r p(sv->getPoint()), p2(sv2->getPoint()), pPrev(svPrev->getPoint());
+
+ //direction and orthogonal vector to the next segment
+ Vec2r dir(p2-p);
+ float dirNorm=dir.norm();
+ dir.normalize();
+ Vec2r orthDir(-dir[1], dir[0]);
+ Vec2r stripDir = orthDir;
+ if(sv->attribute().isAttributeAvailableVec2f("orientation")){
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir*orthDir;
+ if(dp<0)
+ userDir = userDir*(-1.f);
+ stripDir = userDir;
+ }
+
+ //direction and orthogonal vector to the previous segment
+ Vec2r dirPrev(p-pPrev);
+ float dirPrevNorm=dirPrev.norm();
+ dirPrev.normalize();
+ Vec2r orthDirPrev(-dirPrev[1], dirPrev[0]);
+ Vec2r stripDirPrev = orthDirPrev;
+ if(svPrev->attribute().isAttributeAvailableVec2f("orientation")){
+ Vec2r userDir = svPrev->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir*orthDir;
+ if(dp<0)
+ userDir = userDir*(-1.f);
+ stripDirPrev = userDir;
+ }
+
+ const float *thickness = sv->attribute().getThickness();
+ _averageThickness+=thickness[0]+thickness[1];
+ Vec2r pInter;
+ int interResult;
+
+ interResult=GeomUtils::intersect2dLine2dLine(Vec2r(pPrev+thickness[1]*stripDirPrev), Vec2r(p+thickness[1]*stripDirPrev),
+ Vec2r(p+thickness[1]*stripDir), Vec2r(p2+thickness[1]*stripDir),
+ pInter);
+
+ if (interResult==GeomUtils::DO_INTERSECT)
+ _vertices.push_back(new StrokeVertexRep(pInter));
+ else
+ _vertices.push_back(new StrokeVertexRep(p+thickness[1]*stripDir));
+ ++i;
+
+ interResult=GeomUtils::intersect2dLine2dLine(Vec2r(pPrev-thickness[0]*stripDirPrev), Vec2r(p-thickness[0]*stripDirPrev),
+ Vec2r(p-thickness[0]*stripDir), Vec2r(p2-thickness[0]*stripDir),
+ pInter);
+ if (interResult==GeomUtils::DO_INTERSECT)
+ _vertices.push_back(new StrokeVertexRep(pInter));
+ else
+ _vertices.push_back(new StrokeVertexRep(p-thickness[0]*stripDir));
+ ++i;
+
+ // if the angle is obtuse, we simply average the directions to avoid the singularity
+ stripDir=stripDir+stripDirPrev;
+ if ((dirNorm<ZERO) || (dirPrevNorm<ZERO) || (stripDir.norm() < ZERO)) {
+ stripDir[0] = 0;
+ stripDir[1] = 0;
+ }else
+ stripDir.normalize();
+
+ Vec2r vec_tmp(_vertices[i-2]->point2d()-p);
+ if ((vec_tmp.norm() > thickness[1]*MAX_RATIO_LENGTH_SINGU) ||
+ (dirNorm<ZERO) || (dirPrevNorm<ZERO) ||
+ notValid(_vertices[i-2]->point2d())
+ || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER))
+ _vertices[i-2]->setPoint2d(p+thickness[1]*stripDir);
+
+ vec_tmp = _vertices[i-1]->point2d()-p;
+ if ((vec_tmp.norm() > thickness[0]*MAX_RATIO_LENGTH_SINGU) ||
+ (dirNorm<ZERO) || (dirPrevNorm<ZERO) ||
+ notValid(_vertices[i-1]->point2d())
+ || (fabs(stripDir * dir)<EPS_SINGULARITY_RENDERER))
+ _vertices[i-1]->setPoint2d(p-thickness[0]*stripDir);
+
+ vPrev=v;
+ } // end of for
+
+ //special case of last vertex
+ sv=*v;
+ sv2=*vPrev;
+ dir=Vec2r (sv->getPoint()-sv2->getPoint());
+ orthDir=Vec2r(-dir[1], dir[0]);
+ if (orthDir.norm() > ZERO)
+ orthDir.normalize();
+ Vec2r stripDirLast(orthDir);
+ // check whether the orientation was user defined
+ if(sv->attribute().isAttributeAvailableVec2f("orientation")){
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir*orthDir;
+ if(dp<0)
+ userDir = userDir*(-1.f);
+ stripDirLast = userDir;
+ }
+ const float *thicknessLast = sv->attribute().getThickness();
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint()+thicknessLast[1]*stripDirLast));
+ ++i;
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint()-thicknessLast[0]*stripDirLast));
+ int n = i;
+ ++i;
+
+ // check whether the orientation of the extremity
+ // was user defined
+ // userDir = _stroke->getEndingOrientation();
+ // if(userDir != Vec2r(0,0)){
+ // userDir.normalize();
+ // real o1 = (orthDir*userDir);
+ // real o2 = crossP(orthDir,userDir);
+ // real orientation = o1 * o2;
+ // if(orientation > 0){
+ // // then the vertex to move is vn
+ // if(o1 < 0)
+ // _vertex[n]=_vertex[n-1]+userDir;
+ // else
+ // _vertex[n]=_vertex[n-1]-userDir;
+ // }
+ // if(orientation < 0){
+ // // then we must move vn-1
+ // if(o1 > 0)
+ // _vertex[n-1]=_vertex[n]+userDir;
+ // else
+ // _vertex[n-1]=_vertex[n]-userDir;
+ // }
+ // }
+
+ _averageThickness/=float(iStrokeVertices.size()-2);
+ //I did not use the first and last vertex for the average
+ if (iStrokeVertices.size()<3)
+ _averageThickness=0.5*(thicknessLast[1]+thicknessLast[0]+thickness[0]+thickness[1]);
+
+ if (i != 2*(int)iStrokeVertices.size())
+ cerr << "Warning: problem with stripe size\n";
+
+ cleanUpSingularities (iStrokeVertices);
+}
+
+// CLEAN UP
+/////////////////////////
+
+void
+Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices)
+{
+ int k;
+ int sizeStrip = _vertices.size();
+
+ for (k=0; k<sizeStrip; k++)
+ if (notValid(_vertices[k]->point2d()))
+ {
+ cerr << "Warning: strip vertex " << k << " non valid" << endl;
+ return;
+ }
+
+ //return;
+ if (iStrokeVertices.size()<2) return;
+ int i=0, j;
+ vector<StrokeVertex*>::const_iterator v ,vend, v2, vPrev;
+StrokeVertex *sv, *sv2; //soc unused - *svPrev;
+
+ bool singu1=false, singu2=false;
+ int timeSinceSingu1=0, timeSinceSingu2=0;
+
+ //special case of first vertex
+ v=iStrokeVertices.begin();
+ for(vend=iStrokeVertices.end();
+ v!=vend;
+ v++)
+ {
+ v2=v; ++v2;
+ if (v2==vend) break;
+ sv= (*v); sv2 = (*v2);
+ Vec2r p(sv->getPoint()), p2(sv2->getPoint());
+
+ Vec2r dir(p2-p);
+ if (dir.norm() > ZERO)
+ dir.normalize();
+ Vec2r dir1, dir2;
+ dir1=_vertices[2*i+2]->point2d()-_vertices[2*i]->point2d();
+ dir2=_vertices[2*i+3]->point2d()-_vertices[2*i+1]->point2d();
+
+ if ((dir1 * dir) < -ZERO)
+ {
+ singu1=true;
+ timeSinceSingu1++;
+ }
+ else
+ {
+ if (singu1)
+ {
+ int toto=i-timeSinceSingu1;
+ if (toto<0)
+ cerr << "Stephane dit \"Toto\"" << endl;
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0,0.0);
+ for (j=i-timeSinceSingu1; j<i+1; j++)
+ avP=Vec2r(avP+_vertices[2*j]->point2d());
+ avP=Vec2r(1.0/float(timeSinceSingu1+1)*avP);
+ for (j=i-timeSinceSingu1; j<i+1; j++)
+ _vertices[2*j]->setPoint2d(avP);
+ //_vertex[2*j]=_vertex[2*i];
+ singu1=false; timeSinceSingu1=0;
+ }
+ }
+ if ((dir2 * dir) < -ZERO)
+ {
+ singu2=true;
+ timeSinceSingu2++;
+ }
+ else
+ {
+ if (singu2)
+ {
+ int toto=i-timeSinceSingu2;
+ if (toto<0)
+ cerr << "Stephane dit \"Toto\"" << endl;
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0,0.0);
+ for (j=i-timeSinceSingu2; j<i+1; j++)
+ avP=Vec2r(avP+_vertices[2*j+1]->point2d());
+ avP=Vec2r(1.0/float(timeSinceSingu2+1)*avP);
+ for (j=i-timeSinceSingu2; j<i+1; j++)
+ _vertices[2*j+1]->setPoint2d(avP);
+ //_vertex[2*j+1]=_vertex[2*i+1];
+ singu2=false; timeSinceSingu2=0;
+ }
+ }
+ i++;
+ }
+
+ if (singu1)
+ {
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0,0.0);
+ for (j=i-timeSinceSingu1; j<i; j++)
+ avP=Vec2r(avP+_vertices[2*j]->point2d());
+ avP=Vec2r(1.0/float(timeSinceSingu1)*avP);
+ for (j=i-timeSinceSingu1; j<i; j++)
+ _vertices[2*j]->setPoint2d(avP);
+ }
+ if (singu2)
+ {
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0,0.0);
+ for (j=i-timeSinceSingu2; j<i; j++)
+ avP=Vec2r(avP+_vertices[2*j+1]->point2d());
+ avP=Vec2r(1.0/float(timeSinceSingu2)*avP);
+ for (j=i-timeSinceSingu2; j<i; j++)
+ _vertices[2*j+1]->setPoint2d(avP);
+ }
+
+
+ for (k=0; k<sizeStrip; k++)
+ if (notValid(_vertices[k]->point2d()))
+ {
+ cerr << "Warning: strip vertex " << k << " non valid after cleanup"<<endl;
+ return;
+ }
+}
+
+
+// Texture coordinates
+////////////////////////////////
+
+void
+Strip::computeTexCoord (const vector<StrokeVertex*>& iStrokeVertices)
+{
+ vector<StrokeVertex*>::const_iterator v ,vend;
+ StrokeVertex *sv;
+ int i=0;
+ for(v=iStrokeVertices.begin(), vend=iStrokeVertices.end();
+ v!=vend; v++)
+ {
+ sv= (*v);
+ _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness),0));
+ _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ _vertices[i]->setAlpha(sv->attribute().getAlpha());
+ i++;
+ _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness),1));
+ _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ _vertices[i]->setAlpha(sv->attribute().getAlpha());
+ i++;
+ // cerr<<"col=("<<sv->attribute().getColor()[0]<<", "
+ // <<sv->attribute().getColor()[1]<<", "<<sv->attribute().getColor()[2]<<")"<<endl;
+ }
+}
+
+void
+Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd)
+{
+ //soc unused - unsigned int sizeStrip = _vertices.size()+8; //for the transition between the tip and the body
+ vector<StrokeVertex*>::const_iterator v ,vend;
+ StrokeVertex *sv = 0;
+
+ v=iStrokeVertices.begin();
+ vend=iStrokeVertices.end();
+ float l=(*v)->strokeLength()/_averageThickness;
+ int tiles=int(l);
+ float fact=(float(tiles)+0.5)/l;
+ //soc unused - float uTip2=float(tiles)+0.25;
+ float u=0;
+ float uPrev=0;
+ int i=0;
+ float t;
+ StrokeVertexRep *tvRep1, *tvRep2;
+
+ // cerr<<"l="<<l<<" tiles="<<tiles<<" _averageThicnkess="
+ // <<_averageThickness<<" strokeLength="<<(*v)->strokeLength()<<endl;
+ //
+ vector<StrokeVertexRep*>::iterator currentSV = _vertices.begin();
+ StrokeVertexRep *svRep;
+ if(tipBegin){
+ for(;v!=vend; v++)
+ {
+ sv= (*v);
+ svRep = *currentSV;
+ u=sv->curvilinearAbscissa()/_averageThickness*fact;
+ if (u>0.25) break;
+
+
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 1));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+ uPrev=u;
+ }
+ //first transition vertex
+
+ if (fabs(u-uPrev)>ZERO)
+ t= (0.25-uPrev)/(u-uPrev);
+ else t=0;
+ //if (!tiles) t=0.5;
+ tvRep1 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d()));
+ tvRep1->setTexCoord(Vec2r(0.25,0.5));
+ tvRep1->setColor(Vec3r((1-t)*_vertices[i-2]->color()+
+ t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])));
+ tvRep1->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d()));
+ tvRep2->setTexCoord(Vec2r(0.25,1));
+ tvRep2->setColor(Vec3r((1-t)*_vertices[i-2]->color()+
+ t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])));
+ tvRep2->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ //copy the vertices with different texture coordinates
+ tvRep1 = new StrokeVertexRep(_vertices[i-2]->point2d());
+ tvRep1->setTexCoord(Vec2r(0.25,0));
+ tvRep1->setColor(_vertices[i-2]->color());
+ tvRep1->setAlpha(_vertices[i-2]->alpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(_vertices[i-2]->point2d());
+ tvRep2->setTexCoord(Vec2r(0.25,0.5));
+ tvRep2->setColor(_vertices[i-2]->color());
+ tvRep2->setAlpha(_vertices[i-2]->alpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+ }
+ uPrev=0;
+
+ //body of the stroke
+ for(;v!=vend; v++)
+ {
+ sv= (*v);
+ svRep = *currentSV;
+ u=sv->curvilinearAbscissa()/_averageThickness*fact-0.25;
+ if (u>tiles) break;
+
+ svRep->setTexCoord(Vec2r((real)u, 0));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ uPrev=u;
+ }
+ if(tipEnd){
+ //second transition vertex
+ if ((fabs(u-uPrev)>ZERO))
+ t= (float(tiles)-uPrev)/(u-uPrev);
+ else t=0;
+
+ tvRep1 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d()));
+ tvRep1->setTexCoord(Vec2r((real)tiles,0));
+ tvRep1->setColor(Vec3r((1-t)*_vertices[i-2]->color()+
+ t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])));
+ tvRep1->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d()));
+ tvRep2->setTexCoord(Vec2r((real)tiles,0.5));
+ tvRep2->setColor(Vec3r((1-t)*_vertices[i-2]->color()+
+ t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])));
+ tvRep2->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ //copy the vertices with different texture coordinates
+ tvRep1 = new StrokeVertexRep(_vertices[i-2]->point2d());
+ tvRep1->setTexCoord(Vec2r(0.75,0.5));
+ tvRep1->setColor(_vertices[i-2]->color());
+ tvRep1->setAlpha(_vertices[i-2]->alpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(_vertices[i-2]->point2d());
+ tvRep2->setTexCoord(Vec2r(0.75,1));
+ tvRep2->setColor(_vertices[i-2]->color());
+ tvRep2->setAlpha(_vertices[i-2]->alpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ //end tip
+ for(;v!=vend; v++)
+ {
+ sv= (*v);
+ svRep = *currentSV;
+ u=0.75+sv->curvilinearAbscissa()/_averageThickness*fact-float(tiles)-0.25;
+
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 1));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+ }
+ }
+ //cerr<<"u="<<u<<" i="<<i<<"/"<<_sizeStrip<<endl;;
+
+ // for (i=0; i<_sizeStrip; i++)
+ // _alpha[i]=1.0;
+
+ // for (i=0; i<_sizeStrip; i++)
+ // cerr<<"("<<_texCoord[i][0]<<", "<<_texCoord[i][1]<<") ";
+ // cerr<<endl;
+
+
+ // Vec2r vec_tmp;
+ // for (i=0; i<_sizeStrip/2; i++)
+ // vec_tmp = _vertex[2*i] - _vertex[2*i+1];
+ // if (vec_tmp.norm() > 4*_averageThickness)
+ // cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl;
+}
+
+//
+// StrokeRep
+/////////////////////////////////////
+
+StrokeRep::StrokeRep()
+{
+ _stroke = 0;
+ _strokeType=Stroke::OPAQUE_MEDIUM;
+ TextureManager * ptm = TextureManager::getInstance();
+ if(ptm)
+ _textureId = ptm->getDefaultTextureId();
+ // _averageTextureAlpha=0.5; //default value
+ // if (_strokeType==OIL_STROKE)
+ // _averageTextureAlpha=0.75;
+ // if (_strokeType>=NO_BLEND_STROKE)
+ // _averageTextureAlpha=1.0
+}
+
+StrokeRep::StrokeRep(Stroke *iStroke)
+{
+ _stroke = iStroke;
+ _strokeType = iStroke->getMediumType();
+ _textureId = iStroke->getTextureId();
+ if(_textureId == 0){
+ TextureManager * ptm = TextureManager::getInstance();
+ if(ptm)
+ _textureId = ptm->getDefaultTextureId();
+ }
+
+ // _averageTextureAlpha=0.5; //default value
+ // if (_strokeType==OIL_STROKE)
+ // _averageTextureAlpha=0.75;
+ // if (_strokeType>=NO_BLEND_STROKE)
+ // _averageTextureAlpha=1.0;
+ create();
+}
+
+StrokeRep::StrokeRep(const StrokeRep& iBrother)
+{
+ //soc unused - int i=0;
+ _stroke = iBrother._stroke;
+ _strokeType=iBrother._strokeType;
+ _textureId = iBrother._textureId;
+ for(vector<Strip*>::const_iterator s=iBrother._strips.begin(), send=iBrother._strips.end();
+ s!=send;
+ ++s){
+ _strips.push_back(new Strip(**s));
+ }
+}
+
+
+StrokeRep::~StrokeRep()
+{
+ if(!_strips.empty()){
+ for(vector<Strip*>::iterator s=_strips.begin(), send=_strips.end();
+ s!=send;
+ ++s){
+ delete (*s);
+ }
+ _strips.clear();
+ }
+}
+
+void StrokeRep::create(){
+ vector<StrokeVertex*> strip;
+ StrokeInternal::StrokeVertexIterator v = _stroke->strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator vend = _stroke->strokeVerticesEnd();
+
+ bool first=true;
+ bool end=false;
+ while(v!=vend){
+ while((v!=vend) && (!(*v).attribute().isVisible())){
+ ++v;
+ first = false;
+ }
+ while( (v!=vend) && ((*v).attribute().isVisible()) ) {
+ strip.push_back(&(*v));
+ ++v;
+ }
+ if(v!=vend){
+ // add the last vertex and create
+ strip.push_back(&(*v));
+ }else{
+ end=true;
+ }
+ if((!strip.empty()) && (strip.size()>1) ){
+ _strips.push_back(new Strip(strip, _stroke->hasTips(), first, end));
+ strip.clear();
+ }
+ first = false;
+ }
+}
+
+void StrokeRep::Render(const StrokeRenderer *iRenderer)
+{
+ iRenderer->RenderStrokeRep(this);
+}
+
+
+
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h
new file mode 100755
index 00000000000..d8a8dc2d609
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.h
@@ -0,0 +1,138 @@
+//
+// Filename : StrokeRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the representation of a stroke
+// (for display purpose)
+// Date of creation : 05/03/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STROKEREP_H
+# define STROKEREP_H
+
+# include "../geometry/Geom.h"
+using namespace Geometry;
+
+//symbolic constant to call the appropriate renderers and textures
+// # define NO_TEXTURE_WITH_BLEND_STROKE -2
+// # define NO_TEXTURE_STROKE -1
+// # define PSEUDO_CHARCOAL_STROKE 0
+// # define WASH_BRUSH_STROKE 1
+// # define OIL_STROKE 2
+// # define NO_BLEND_STROKE 3
+// # define CHARCOAL_MIN_STROKE 4
+// # define BRUSH_MIN_STROKE 5
+// # define OPAQUE_DRY_STROKE 6
+// # define OPAQUE_STROKE 7
+//
+// # define DEFAULT_STROKE 0
+//
+// # define NUMBER_STROKE_RENDERER 8
+
+#include "Stroke.h"
+
+class StrokeVertexRep{
+public:
+ StrokeVertexRep(){}
+ StrokeVertexRep(const Vec2r& iPoint2d){_point2d=iPoint2d;}
+ StrokeVertexRep(const StrokeVertexRep& iBrother);
+ virtual ~StrokeVertexRep(){}
+
+ inline Vec2r& point2d() {return _point2d;}
+ inline Vec2r& texCoord() {return _texCoord;}
+ inline Vec3r& color() {return _color;}
+ inline float alpha() {return _alpha;}
+
+ inline void setPoint2d(const Vec2r& p){_point2d = p;}
+ inline void setTexCoord(const Vec2r& p){_texCoord = p;}
+ inline void setColor(const Vec3r& p){_color = p;}
+ inline void setAlpha(float a){_alpha = a;}
+protected:
+ Vec2r _point2d;
+ Vec2r _texCoord;
+ Vec3r _color;
+ float _alpha;
+};
+
+class Strip{
+public:
+ typedef std::vector<StrokeVertexRep*> vertex_container;
+protected:
+ vertex_container _vertices;
+ float _averageThickness;
+
+
+public:
+ Strip(const std::vector<StrokeVertex*>& iStrokeVertices, bool hasTips=false, bool tipBegin=false, bool tipEnd=false) ;
+ Strip(const Strip& iBrother);
+ virtual ~Strip() ;
+
+protected:
+ void createStrip(const std::vector<StrokeVertex*>& iStrokeVertices);
+ void cleanUpSingularities(const std::vector<StrokeVertex*>& iStrokeVertices);
+ void computeTexCoord (const std::vector<StrokeVertex*>& iStrokeVertices);
+ void computeTexCoordWithTips (const std::vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd);
+public:
+ inline int sizeStrip() const {return _vertices.size();}
+ inline vertex_container& vertices() {return _vertices;}
+};
+
+class StrokeRep
+{
+protected:
+ Stroke *_stroke;
+ vector<Strip*> _strips;
+ Stroke::MediumType _strokeType;
+ unsigned int _textureId;
+
+ // float _averageTextureAlpha;
+
+
+public:
+ StrokeRep();
+ StrokeRep(const StrokeRep&);
+ StrokeRep(Stroke *iStroke);
+ virtual ~StrokeRep();
+
+ /*! Creates the strips */
+ virtual void create() ;
+
+ /*! Renders the stroke using a Renderer */
+ virtual void Render(const StrokeRenderer *iRenderer) ;
+
+ /*! accessors */
+ inline Stroke::MediumType getMediumType() const {return _strokeType;}
+ inline unsigned getTextureId() const {return _textureId;}
+ inline vector<Strip*>& getStrips() {return _strips;}
+ inline unsigned int getNumberOfStrips() const {return _strips.size();}
+ inline Stroke * getStroke() {return _stroke;}
+
+ /*! modifiers */
+ inline void setMediumType(Stroke::MediumType itype) {_strokeType=itype;}
+ inline void setTextureId(unsigned textureId) {_textureId = textureId;}
+
+
+};
+
+#endif // STROKEREP_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.h b/source/blender/freestyle/intern/stroke/StrokeShader.h
new file mode 100755
index 00000000000..63185438e91
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeShader.h
@@ -0,0 +1,124 @@
+//
+// Filename : StrokeShader.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class defining StrokeShader
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SHADERS_H
+# define SHADERS_H
+
+# include <iostream>
+# include <vector>
+
+# include "../python/Director.h"
+
+//
+// StrokeShader base class
+//
+//////////////////////////////////////////////////////
+
+class Stroke;
+/*! Base class for Stroke Shaders.
+ * Any Stroke Shader must inherit from
+ * this class and overload the shade() method.
+ * A StrokeShader is designed to modify any
+ * Stroke's attribute such as Thickness, Color,
+ * Geometry, Texture, Blending mode...
+ * The basic way to achieve this operation consists
+ * in iterating over the StrokeVertices of the Stroke
+ * and to modify each one's StrokeAttribute.
+ * Here is a python code example of such an iteration:
+ * \code
+ * it = ioStroke.strokeVerticesBegin()
+ * while it.isEnd() == 0:
+ * att = it.getObject().attribute()
+ * ## perform here any attribute modification
+ * it.increment()
+ * \endcode
+ * Here is a C++ code example of such an iteration:
+ * \code
+ * for(StrokeInternal::StrokeVertexIterator v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
+ * v!=vend;
+ * ++v){
+ * StrokeAttribute& att = v->attribute();
+ * // perform any attribute modification here...
+ * }
+ * \endcode
+ */
+class LIB_STROKE_EXPORT StrokeShader
+{
+public:
+
+ PyObject *py_ss;
+
+ /*! Default constructor. */
+ StrokeShader() { py_ss = 0; }
+ /*! Destructor. */
+ virtual ~StrokeShader() {}
+ /*! Returns the string corresponding to the
+ * shader's name.
+ */
+ virtual string getName() const {
+ return "StrokeShader";
+ }
+ /*! The shading method. This method must
+ * be overloaded by inherited classes.
+ * The shading method is designed to modify any
+ * Stroke's attribute such as Thickness, Color,
+ * Geometry, Texture, Blending mode...
+ * The basic way to achieve this operation consists
+ * in iterating over the StrokeVertices of the Stroke
+ * and to modify each one's StrokeAttribute.
+ * Here is a python code example of such an iteration:
+ * \code
+ * it = ioStroke.strokeVerticesBegin()
+ * while it.isEnd() == 0:
+ * att = it.getObject().attribute()
+ * ## perform here any attribute modification
+ * it.increment()
+ * \endcode
+ * Here is a C++ code example of such an iteration:
+ * \code
+ * for(StrokeInternal::StrokeVertexIterator v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
+ * v!=vend;
+ * ++v){
+ * StrokeAttribute& att = v->attribute();
+ * // perform any attribute modification here...
+ * }
+ * \endcode
+ * \param ioStroke
+ * The stroke we wish to shade. this Stroke
+ * is modified by the Shader (which typically
+ * modifies the Stroke's attribute's values such
+ * as Color, Thickness, Geometry...)
+ */
+ virtual int shade(Stroke& ioStroke) const {
+ return Director_BPy_StrokeShader_shade( const_cast<StrokeShader *>(this), ioStroke );
+ }
+
+};
+
+# endif // SHADERS_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp
new file mode 100755
index 00000000000..a8b71f9f3c3
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp
@@ -0,0 +1,88 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "StrokeTesselator.h"
+#include "../scene_graph/OrientedLineRep.h"
+#include "../scene_graph/NodeGroup.h"
+#include "../scene_graph/NodeShape.h"
+#include "StrokeAdvancedIterators.h"
+
+LineRep* StrokeTesselator::Tesselate(Stroke *iStroke)
+{
+ if(0 == iStroke)
+ return 0;
+
+ LineRep* line;
+ line = new OrientedLineRep();
+
+ Stroke::vertex_iterator v,vend;
+ if(2 == iStroke->vertices_size())
+ {
+ line->setStyle(LineRep::LINES);
+ v = iStroke->vertices_begin();
+ StrokeVertex *svA= (*v);
+ v++;
+ StrokeVertex *svB = (*v);
+ Vec3r A((*svA)[0], (*svA)[1], 0);
+ Vec3r B((*svB)[0], (*svB)[1], 0);
+ line->AddVertex(A);
+ line->AddVertex(B);
+ }
+ else
+ {
+ if(_overloadFrsMaterial)
+ line->setFrsMaterial(_FrsMaterial);
+
+ line->setStyle(LineRep::LINE_STRIP);
+
+ for(v=iStroke->vertices_begin(), vend=iStroke->vertices_end();
+ v!=vend;
+ v++)
+ {
+ StrokeVertex *sv= (*v);
+ Vec3r V((*sv)[0], (*sv)[1], 0);
+ line->AddVertex(V);
+ }
+ }
+ line->setId(iStroke->getId());
+ line->ComputeBBox();
+
+ return line;
+}
+
+template<class StrokeVertexIterator>
+NodeGroup* StrokeTesselator::Tesselate(StrokeVertexIterator begin, StrokeVertexIterator end)
+{
+ NodeGroup *group = new NodeGroup;
+ NodeShape *tshape = new NodeShape;
+ group->AddChild(tshape);
+ //tshape->material().setDiffuse(0.f, 0.f, 0.f, 1.f);
+ tshape->setFrsMaterial(_FrsMaterial);
+
+ for(StrokeVertexIterator c=begin, cend=end;
+ c!=cend;
+ c++)
+ {
+ tshape->AddRep(Tesselate((*c)));
+ }
+
+ return group;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.h b/source/blender/freestyle/intern/stroke/StrokeTesselator.h
new file mode 100755
index 00000000000..671df00ef84
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.h
@@ -0,0 +1,67 @@
+//
+// Filename : StrokeTesselator.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build a Node Tree designed to be displayed
+// from a set of strokes structure.
+// Date of creation : 26/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STROKETESSELATOR_H
+# define STROKETESSELATOR_H
+
+# include "Stroke.h"
+# include "../scene_graph/LineRep.h"
+
+class StrokeTesselator
+{
+public:
+
+ inline StrokeTesselator() {_FrsMaterial.setDiffuse(0,0,0,1);_overloadFrsMaterial=false;}
+ virtual ~StrokeTesselator() {}
+
+ /*! Builds a line rep contained from a Stroke
+ */
+ LineRep* Tesselate(Stroke* iStroke) ;
+
+ /*! Builds a set of lines rep contained under a
+ * a NodeShape, itself contained under a NodeGroup from a
+ * set of strokes
+ */
+ template<class StrokeIterator>
+ NodeGroup* Tesselate(StrokeIterator begin, StrokeIterator end) ;
+
+
+
+ inline void setFrsMaterial(const FrsMaterial& iMaterial) {_FrsMaterial=iMaterial;_overloadFrsMaterial=true;}
+ inline const FrsMaterial& frs_material() const {return _FrsMaterial;}
+
+private:
+
+ FrsMaterial _FrsMaterial;
+ bool _overloadFrsMaterial;
+};
+
+#endif // STROKETESSELATOR_H
+
diff --git a/source/blender/freestyle/intern/stroke/StyleModule.h b/source/blender/freestyle/intern/stroke/StyleModule.h
new file mode 100755
index 00000000000..c97a8d7f999
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StyleModule.h
@@ -0,0 +1,172 @@
+//
+// Filename : StyleModule.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class representing a style module
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STYLE_MODULE_H
+# define STYLE_MODULE_H
+
+# include <iostream>
+# include <string>
+# include "../system/StringUtils.h"
+# include "StrokeLayer.h"
+# include "../system/Interpreter.h"
+# include "Operators.h"
+# include "StrokeShader.h"
+
+using namespace std;
+
+class StyleModule
+{
+public:
+
+ StyleModule(const string& file_name,
+ Interpreter* inter) : _file_name(file_name) {
+ _always_refresh = false;
+ _causal = false;
+ _drawable = true;
+ _modified = true;
+ _displayed = true;
+ _inter = inter;
+ }
+
+ virtual ~StyleModule() {}
+
+ StrokeLayer* execute() {
+ if (!_inter) {
+ cerr << "Error: no interpreter was found to execute the script" << endl;
+ return NULL;
+ }
+
+ if (!_drawable) {
+ cerr << "Error: not drawable" << endl;
+ return NULL;
+ }
+
+ Operators::reset();
+
+ if( interpret() ) {
+ cerr << "Error: interpretation failed" << endl;
+ Operators::reset();
+ return NULL;
+ }
+
+ Operators::StrokesContainer* strokes_set = Operators::getStrokesSet();
+ if( strokes_set->empty() ) {
+ cerr << "Error: strokes set empty" << endl;
+ Operators::reset();
+ return NULL;
+ }
+
+ StrokeLayer* sl = new StrokeLayer;
+ for (Operators::StrokesContainer::iterator it = strokes_set->begin();
+ it != strokes_set->end();
+ ++it)
+ sl->AddStroke(*it);
+
+ Operators::reset();
+
+ return sl;
+ }
+
+protected:
+
+ virtual int interpret() {
+ return _inter->interpretFile(_file_name);
+ }
+
+public:
+
+ // accessors
+
+ const string getFileName() const {
+ return _file_name;
+ }
+
+ bool getAlwaysRefresh() const {
+ return _always_refresh;
+ }
+
+ bool getCausal() const {
+ return _causal;
+ }
+
+ bool getDrawable() const {
+ return _drawable;
+ }
+
+ bool getModified() const {
+ return _modified;
+ }
+
+ bool getDisplayed() const {
+ return _displayed;
+ }
+
+ // modifiers
+
+ void setFileName(const string& file_name) {
+ _file_name = file_name;
+ }
+
+ void setAlwaysRefresh(bool b = true) {
+ _always_refresh = b;
+ }
+
+ void setCausal(bool b = true) {
+ _causal = b;
+ }
+
+ void setDrawable(bool b = true) {
+ _drawable = b;
+ }
+
+ void setModified(bool b = true) {
+ if (_always_refresh)
+ return;
+ _modified = b;
+ }
+
+ void setDisplayed(bool b = true) {
+ _displayed = b;
+ }
+
+private:
+
+ string _file_name;
+ bool _always_refresh;
+ bool _causal;
+ bool _drawable;
+ bool _modified;
+ bool _displayed;
+
+protected:
+
+ Interpreter* _inter;
+};
+
+#endif // STYLE_MODULE_H
diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
new file mode 100755
index 00000000000..ea5af287bbe
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
@@ -0,0 +1,73 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "TextStrokeRenderer.h"
+# include "Canvas.h"
+# include "StrokeIterators.h"
+
+TextStrokeRenderer::TextStrokeRenderer(const char* iFileName)
+:StrokeRenderer(){
+ if(!iFileName)
+ iFileName = "freestyle.txt";
+ // open the stream:
+ _ofstream.open(iFileName, ios::out);
+ if(!_ofstream.is_open()){
+ cerr << "couldn't open the output file " << iFileName << endl;
+ }
+ _ofstream << "%!FREESTYLE" << endl;
+ _ofstream << "%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl;
+ // Bounding box
+ _ofstream << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << Canvas::getInstance()->height() << endl;
+ _ofstream << "%u x y z tleft tright r g b ..." << endl;
+}
+
+TextStrokeRenderer::~TextStrokeRenderer(){
+ Close();
+}
+
+void TextStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void TextStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{
+ Stroke *stroke = iStrokeRep->getStroke();
+ if(!stroke){
+ cerr << "no stroke associated with Rep" << endl;
+ return;
+ }
+
+ StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin();
+ StrokeAttribute att;
+ while(!v.isEnd()){
+ att = v->attribute();
+ _ofstream << v->u() << " " << v->getProjectedX() << " " << v->getProjectedY() << " " << v->getProjectedZ() << " " \
+ << att.getThicknessL() << " " << att.getThicknessR() << " " \
+ << att.getColorR() << " " << att.getColorG() << " " << att.getColorB() << " ";
+ ++v;
+ }
+ _ofstream << endl;
+}
+
+void TextStrokeRenderer::Close(){
+ if(_ofstream.is_open())
+ _ofstream.close();
+}
+
diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
new file mode 100755
index 00000000000..8b4b6bc80d7
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
@@ -0,0 +1,68 @@
+//
+// Filename : TextStrokeRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the text rendering of a stroke
+// Format:
+// x y width height // bbox
+// //list of vertices :
+// t x y z t1 t2 r g b alpha ...
+// ...
+// Date of creation : 01/14/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TEXTSTROKERENDERER_H
+# define TEXTSTROKERENDERER_H
+
+# include "StrokeRenderer.h"
+# include "../system/FreestyleConfig.h"
+# include <fstream>
+
+/**********************************/
+/* */
+/* */
+/* TextStrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+class LIB_STROKE_EXPORT TextStrokeRenderer : public StrokeRenderer
+{
+public:
+ TextStrokeRenderer(const char * iFileName = 0);
+ virtual ~TextStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ /*! Closes the output file */
+ void Close();
+
+protected:
+ mutable ofstream _ofstream;
+};
+
+#endif // TEXTSTROKERENDERER_H
+
diff --git a/source/blender/freestyle/intern/system/BaseIterator.h b/source/blender/freestyle/intern/system/BaseIterator.h
new file mode 100755
index 00000000000..45cc19df4fe
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseIterator.h
@@ -0,0 +1,90 @@
+//
+// Filename : BaseIterator.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes defining the basic "Iterator" design pattern
+// Date of creation : 18/03/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BASEITERATOR_H
+# define BASEITERATOR_H
+
+# include <iterator>
+
+// use for iterators defintions
+template <class Element>
+class Nonconst_traits;
+
+template <class Element>
+class Const_traits {
+public:
+ typedef Element value_type;
+ typedef const Element& reference;
+ typedef const Element* pointer;
+ typedef ptrdiff_t difference_type;
+ typedef Nonconst_traits<Element> Non_const_traits;
+};
+
+template <class Element>
+class Nonconst_traits {
+public:
+ typedef Element value_type;
+ typedef Element& reference;
+ typedef Element* pointer;
+ typedef ptrdiff_t difference_type;
+ typedef Nonconst_traits<Element> Non_const_traits;
+};
+
+class InputIteratorTag_Traits {
+public:
+ typedef std::input_iterator_tag iterator_category;
+};
+
+class BidirectionalIteratorTag_Traits {
+public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+};
+
+template<class Traits, class IteratorTagTraits>
+class IteratorBase
+{
+public:
+
+ virtual ~IteratorBase() {}
+
+ virtual bool begin() const = 0;
+ virtual bool end() const = 0;
+
+ typedef typename IteratorTagTraits::iterator_category iterator_category;
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+
+protected:
+
+ IteratorBase() {}
+};
+
+#endif // BASEITERATOR_H
diff --git a/source/blender/freestyle/intern/system/BaseObject.cpp b/source/blender/freestyle/intern/system/BaseObject.cpp
new file mode 100755
index 00000000000..0cf1c917195
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseObject.cpp
@@ -0,0 +1 @@
+#include "BaseObject.h"
diff --git a/source/blender/freestyle/intern/system/BaseObject.h b/source/blender/freestyle/intern/system/BaseObject.h
new file mode 100755
index 00000000000..a8515f98385
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseObject.h
@@ -0,0 +1,73 @@
+//
+// Filename : BaseObject.h
+// Author(s) : Stephane Grabli
+// Purpose : Base Class for most shared objects (Node, Rep).
+// Defines the addRef, release system.
+// Inspired by COM IUnknown system.
+// Date of creation : 06/02/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BASEOBJECT_H
+# define BASEOBJECT_H
+
+#include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT BaseObject
+{
+public:
+
+ inline BaseObject() {
+ _ref_counter = 0;
+ }
+
+ virtual ~BaseObject() {}
+
+ /*! At least makes a release on this.
+ * The BaseObject::destroy method must be
+ * explicitely called at the end of any
+ * overloaded destroy
+ */
+ virtual int destroy() {
+ return release();
+ }
+
+ /*! Increments the reference counter */
+ inline int addRef() {
+ return ++_ref_counter;
+ }
+
+ /*! Decrements the reference counter */
+ inline int release() {
+ if (_ref_counter)
+ _ref_counter--;
+ return _ref_counter;
+ }
+
+private:
+
+ unsigned _ref_counter;
+};
+
+#endif // BASEOBJECT_H
diff --git a/source/blender/freestyle/intern/system/Cast.h b/source/blender/freestyle/intern/system/Cast.h
new file mode 100755
index 00000000000..15af767443e
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Cast.h
@@ -0,0 +1,44 @@
+//
+// Filename : Cast.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Cast function
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef CAST_HPP
+# define CAST_HPP
+
+namespace Cast {
+
+ template <class T, class U>
+ U* cast(T* in) {
+ if (!in)
+ return NULL;
+ return dynamic_cast<U*>(in);
+ }
+
+} // end of namespace Cast
+
+#endif // CAST_HPP
diff --git a/source/blender/freestyle/intern/system/Exception.cpp b/source/blender/freestyle/intern/system/Exception.cpp
new file mode 100755
index 00000000000..d1d12d18297
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Exception.cpp
@@ -0,0 +1,24 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Exception.h"
+
+Exception::exception_type Exception::_exception = Exception::NO_EXCEPTION;
diff --git a/source/blender/freestyle/intern/system/Exception.h b/source/blender/freestyle/intern/system/Exception.h
new file mode 100755
index 00000000000..378de6b558f
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Exception.h
@@ -0,0 +1,64 @@
+//
+// Filename : Exception.h
+// Author(s) : Stephane Grabli
+// Purpose : Singleton to manage exceptions
+// Date of creation : 10/01/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef EXCEPTION_H
+# define EXCEPTION_H
+
+# include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT Exception
+{
+public:
+
+ typedef enum {
+ NO_EXCEPTION,
+ UNDEFINED
+ } exception_type;
+
+ static int getException() {
+ exception_type e = _exception;
+ _exception = NO_EXCEPTION;
+ return e;
+ }
+
+ static int raiseException(exception_type exception = UNDEFINED) {
+ _exception = exception;
+ return _exception;
+ }
+
+ static void reset() {
+ _exception = NO_EXCEPTION;
+ }
+
+private:
+
+ static exception_type _exception;
+};
+
+#endif // EXCEPTION_H
diff --git a/source/blender/freestyle/intern/system/FreestyleConfig.h b/source/blender/freestyle/intern/system/FreestyleConfig.h
new file mode 100755
index 00000000000..f06b9928d1d
--- /dev/null
+++ b/source/blender/freestyle/intern/system/FreestyleConfig.h
@@ -0,0 +1,90 @@
+//
+// Filename : Config.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Configuration definitions
+// Date of creation : 25/02/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef CONFIG_H
+# define CONFIG_H
+
+# include <string>
+# include "BLI_math.h"
+
+using namespace std;
+
+namespace Config {
+
+ // Directory separators
+# ifdef WIN32
+ static const string DIR_SEP("\\");
+ static const string PATH_SEP(";");
+# else
+ static const string DIR_SEP("/");
+ static const string PATH_SEP(":");
+# endif // WIN32
+
+ // DLL import/export macros for Win32
+
+# ifndef LIB_SYSTEM_EXPORT
+# define LIB_SYSTEM_EXPORT
+# endif // LIB_SYSTEM_EXPORT
+
+# ifndef LIB_IMAGE_EXPORT
+# define LIB_IMAGE_EXPORT
+# endif // LIB_IMAGE_EXPORT
+
+# ifndef LIB_GEOMETRY_EXPORT
+# define LIB_GEOMETRY_EXPORT
+# endif // LIB_GEOMETRY_EXPORT
+
+# ifndef LIB_SCENE_GRAPH_EXPORT
+# define LIB_SCENE_GRAPH_EXPORT
+# endif // LIB_SCENE_GRAPH_EXPORT
+
+# ifndef LIB_WINGED_EDGE_EXPORT
+# define LIB_WINGED_EDGE_EXPORT
+# endif // LIB_WINGED_EDGE_EXPORT
+
+# ifndef LIB_VIEW_MAP_EXPORT
+# define LIB_VIEW_MAP_EXPORT
+# endif // LIB_VIEW_MAP_EXPORT
+
+# ifndef LIB_STROKE_EXPORT
+# define LIB_STROKE_EXPORT
+# endif // LIB_STROKE_EXPORT
+
+# ifndef LIB_RENDERING_EXPORT
+# define LIB_RENDERING_EXPORT
+# endif // LIB_RENDERING_EXPORT
+
+# ifndef LIB_WRAPPER_EXPORT
+# define LIB_WRAPPER_EXPORT
+# endif // LIB_WRAPPER_EXPORT
+
+} // end of namespace Config
+
+#endif // CONFIG_H
diff --git a/source/blender/freestyle/intern/system/Id.h b/source/blender/freestyle/intern/system/Id.h
new file mode 100755
index 00000000000..1f2206ed337
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Id.h
@@ -0,0 +1,126 @@
+//
+// Filename : Id.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Identification system
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ID_H
+# define ID_H
+
+/*! Class used to tag any object by an id .
+ * It is made of two unsigned integers.
+ */
+class Id
+{
+public:
+
+ typedef unsigned id_type;
+
+ /*! Default constructor */
+ Id() {
+ _first = 0;
+ _second = 0;
+ }
+
+ /*! Builds an Id from an integer.
+ * The second number is set to 0.
+ */
+ Id(id_type id) {
+ _first = id;
+ _second = 0;
+ }
+
+ /*! Builds the Id from the two numbers */
+ Id(id_type ifirst, id_type isecond) {
+ _first = ifirst;
+ _second = isecond;
+ }
+
+ /*! Copy constructor */
+ Id(const Id& iBrother) {
+ _first = iBrother._first;
+ _second = iBrother._second;
+ }
+
+ /*! Operator= */
+ Id& operator=(const Id& iBrother) {
+ _first = iBrother._first;
+ _second = iBrother._second;
+ return *this;
+ }
+
+ /*! Returns the first Id number */
+ id_type getFirst() const {
+ return _first;
+ }
+
+ /*! Returns the second Id number */
+ id_type getSecond() const {
+ return _second;
+ }
+
+ /*! Sets the first number constituing the Id */
+ void setFirst(id_type first) {
+ _first = first;
+ }
+
+ /*! Sets the second number constituing the Id */
+ void setSecond(id_type second) {
+ _second = second;
+ }
+
+ /*! Operator== */
+ bool operator==(const Id& id) const {
+ return ((_first == id._first) && (_second == id._second));
+ }
+
+ /*! Operator!= */
+ bool operator!=(const Id& id) const {
+ return !((*this)==id);
+ }
+
+ /*! Operator< */
+ bool operator<(const Id& id) const {
+ if (_first < id._first)
+ return true;
+ if (_first == id._first && _second < id._second)
+ return true;
+ return false;
+}
+
+private:
+
+ id_type _first;
+ id_type _second;
+};
+
+// stream operator
+inline std::ostream& operator<<(std::ostream& s, const Id& id) {
+ s << "[" << id.getFirst() << ", " << id.getSecond() << "]";
+ return s;
+}
+
+# endif // ID_H
diff --git a/source/blender/freestyle/intern/system/Interpreter.h b/source/blender/freestyle/intern/system/Interpreter.h
new file mode 100755
index 00000000000..75aaa2ccd18
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Interpreter.h
@@ -0,0 +1,56 @@
+//
+// Filename : Interpreter.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Base Class of all script interpreters
+// Date of creation : 17/04/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef INTERPRETER_H
+# define INTERPRETER_H
+
+# include <string>
+
+using namespace std;
+
+class LIB_SYSTEM_EXPORT Interpreter
+{
+ public:
+
+ Interpreter() { _language = "Unknown"; }
+
+ virtual ~Interpreter() {}; //soc
+
+ virtual int interpretFile(const string& filename) = 0;
+
+ virtual string getLanguage() const { return _language; }
+
+ virtual void reset() = 0;
+
+ protected:
+
+ string _language;
+};
+
+#endif // INTERPRETER_H
diff --git a/source/blender/freestyle/intern/system/Iterator.cpp b/source/blender/freestyle/intern/system/Iterator.cpp
new file mode 100644
index 00000000000..67acc893589
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Iterator.cpp
@@ -0,0 +1 @@
+#include "Iterator.h"
diff --git a/source/blender/freestyle/intern/system/Iterator.h b/source/blender/freestyle/intern/system/Iterator.h
new file mode 100644
index 00000000000..1801c1e3b2f
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Iterator.h
@@ -0,0 +1,41 @@
+#ifndef ITERATOR_H
+#define ITERATOR_H
+
+#include <iostream>
+#include <string>
+using namespace std;
+
+
+class Iterator
+{
+public:
+
+ virtual ~Iterator() {}
+
+ virtual string getExactTypeName() const {
+ return "Iterator";
+ }
+
+ virtual int increment() {
+ cerr << "Warning: increment() not implemented" << endl;
+ return 0;
+ }
+
+ virtual int decrement() {
+ cerr << "Warning: decrement() not implemented" << endl;
+ return 0;
+ }
+
+ virtual bool isBegin() const {
+ cerr << "Warning: isBegin() not implemented" << endl;
+ return false;
+ }
+
+ virtual bool isEnd() const {
+ cerr << "Warning: isEnd() not implemented" << endl;
+ return false;
+ }
+
+};
+
+#endif // ITERATOR_H
diff --git a/source/blender/freestyle/intern/system/PointerSequence.h b/source/blender/freestyle/intern/system/PointerSequence.h
new file mode 100644
index 00000000000..72c6aa458fd
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PointerSequence.h
@@ -0,0 +1,97 @@
+//
+// Filename : PointerSequence.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 22/11/2010
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// Simple RAII wrappers for std:: sequential containers
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// PointerSequence
+//
+// Produces a wrapped version of a sequence type (std::vector, std::deque, std::list)
+// that will take ownership of pointers tht it stores. Those pointers will be deleted
+// in its destructor.
+//
+// Because the contained pointers are wholly owned by the sequence, you cannot make a
+// copy of the sequence. Making a copy would result in a double free.
+//
+// This is a no-frills class that provides no additional facilities. The user is
+// responsible for managing any pointers that are removed from the list, and for making
+// sure that any pointers contained in the class are not deleted elsewhere. Because
+// this class does no reference counting, the user must also make sure that any pointer
+// appears only once in the sequence.
+//
+// If more sophisticated facilities are needed, use tr1::shared_ptr or boost::shared_ptr.
+// This class is only intended to allow one to eke by in projects where tr1 or boost are
+// not available.
+//
+// Usage: The template takes two parameters, the standard container, and the class held
+// in the container. This is a limitation of C++ templates, where T::iterator is not a
+// type when T is a template parameter. If anyone knows a way around this
+// limitation, then the second parameter can be eliminated.
+//
+// Example:
+// PointerSequence<vector<Widget*>, Widget*> v;
+// v.push_back(new Widget);
+// cout << v[0] << endl; // operator[] is provided by std::vector, not by PointerSequence
+// v.destroy(); // Deletes all pointers in sequence and sets them to NULL.
+//
+// The idiom for removing a pointer from a sequence is:
+// Widget* w = v[3];
+// v.erase(v.begin() + 3); // or v[3] = 0;
+// The user is now responsible for disposing of w properly.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef POINTERSEQUENCE_H
+# define POINTERSEQUENCE_H
+
+#include <algorithm>
+
+template <typename C, typename T>
+class PointerSequence : public C {
+ PointerSequence (PointerSequence& other);
+ PointerSequence& operator= (PointerSequence& other);
+ static void destroyer (T t) {
+ delete t;
+ }
+public:
+ PointerSequence () {};
+ ~PointerSequence () {
+ destroy();
+ }
+ void destroy () {
+ for_each (this->begin(), this->end(), destroyer);
+ }
+};
+
+#endif // POINTERSEQUENCE_H
+
diff --git a/source/blender/freestyle/intern/system/Precision.h b/source/blender/freestyle/intern/system/Precision.h
new file mode 100755
index 00000000000..24327a280df
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Precision.h
@@ -0,0 +1,39 @@
+//
+// Filename : Precision.h
+// Author(s) : Stephane Grabli
+// Purpose : Define the float precision used in the program
+// Date of creation : 30/07/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef PRECISION_H
+# define PRECISION_H
+
+typedef double real;
+
+# ifndef SWIG
+static const real M_EPSILON = 0.00000001;
+# endif // SWIG
+
+#endif // PRECISION_H
diff --git a/source/blender/freestyle/intern/system/ProgressBar.h b/source/blender/freestyle/intern/system/ProgressBar.h
new file mode 100755
index 00000000000..5b61f936c90
--- /dev/null
+++ b/source/blender/freestyle/intern/system/ProgressBar.h
@@ -0,0 +1,85 @@
+//
+// Filename : ProgressBar.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to encapsulate a progress bar
+// Date of creation : 27/08/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef PROGRESSBAR_H
+# define PROGRESSBAR_H
+
+# include <string>
+
+using namespace std;
+
+class ProgressBar
+{
+public:
+
+ inline ProgressBar() {
+ _numtotalsteps = 0;
+ _progress = 0;
+ }
+
+ virtual ~ProgressBar() {}
+
+ virtual void reset() {
+ _numtotalsteps = 0;
+ _progress = 0;
+ }
+
+ virtual void setTotalSteps(unsigned n) {
+ _numtotalsteps = n;
+ }
+
+ virtual void setProgress(unsigned i) {
+ _progress = i;
+ }
+
+ virtual void setLabelText(const string& s) {
+ _label = s;
+ }
+
+ /*! accessors */
+ inline unsigned int getTotalSteps() const {
+ return _numtotalsteps;
+ }
+
+ inline unsigned int getProgress() const {
+ return _progress;
+ }
+
+ inline string getLabelText() const {
+ return _label;
+ }
+
+protected:
+
+ unsigned _numtotalsteps;
+ unsigned _progress;
+ string _label;
+};
+
+#endif // PROGRESSBAR_H
diff --git a/source/blender/freestyle/intern/system/PseudoNoise.cpp b/source/blender/freestyle/intern/system/PseudoNoise.cpp
new file mode 100755
index 00000000000..7a5fee2da4f
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PseudoNoise.cpp
@@ -0,0 +1,109 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <math.h>
+#include "RandGen.h"
+#include "PseudoNoise.h"
+
+static const unsigned NB_VALUE_NOISE = 512;
+
+real *PseudoNoise::_values;
+
+PseudoNoise::PseudoNoise ()
+{
+}
+
+void
+PseudoNoise::init (long seed)
+{
+ _values = new real[NB_VALUE_NOISE];
+ RandGen::srand48(seed);
+ for (unsigned int i=0; i<NB_VALUE_NOISE; i++)
+ _values[i] = -1.0 + 2.0 * RandGen::drand48();
+}
+
+real
+PseudoNoise::linearNoise (real x)
+{
+ real tmp;
+ int i = modf(x, &tmp) * NB_VALUE_NOISE;
+ real x1=_values[i], x2=_values[(i+1)%NB_VALUE_NOISE];
+ real t = modf(x * NB_VALUE_NOISE, &tmp);
+ return x1*(1-t)+x2*t;
+}
+
+real
+LanczosWindowed(real t)
+{
+ if (fabs(t)>2) return 0;
+ if (fabs(t)<M_EPSILON) return 1.0;
+ return sin(M_PI*t)/(M_PI*t) * sin(M_PI*t/2.0)/(M_PI*t/2.0);
+}
+
+real
+PseudoNoise::smoothNoise (real x)
+{
+ real tmp;
+ int i = modf(x, &tmp) * NB_VALUE_NOISE;
+ int h = i - 1;
+ if (h < 0)
+ {
+ h = NB_VALUE_NOISE + h;
+ }
+
+ real x1=_values[i], x2=_values[(i+1)%NB_VALUE_NOISE];
+ real x0=_values[h], x3=_values[(i+2)%NB_VALUE_NOISE];
+
+ real t = modf(x * NB_VALUE_NOISE, &tmp);
+ real y0=LanczosWindowed(-1-t);
+ real y1=LanczosWindowed(-t);
+ real y2=LanczosWindowed(1-t);
+ real y3=LanczosWindowed(2-t);
+ // cerr<<"x0="<<x0<<" x1="<<x1<<" x2="<<x2<<" x3="<<x3<<endl;
+ // cerr<<"y0="<<y0<<" y1="<<y1<<" y2="<<y2<<" y3="<<y3<<" :";
+ return (x0*y0+x1*y1+x2*y2+x3*y3)/(y0+y1+y2+y3);
+}
+
+real
+PseudoNoise::turbulenceSmooth (real x, unsigned nbOctave)
+{
+ real y=0;
+ real k=1.0;
+ for (unsigned i=0; i<nbOctave; i++)
+ {
+ y=y+k*smoothNoise(x*k);
+ k=k/2.0;
+ }
+ return y;
+}
+
+real
+PseudoNoise::turbulenceLinear (real x, unsigned nbOctave)
+{
+ real y=0;
+ real k=1.0;
+ for (unsigned i=0; i<nbOctave; i++)
+ {
+ y=y+k*linearNoise(x*k);
+ k=k/2.0;
+ }
+ return y;
+}
diff --git a/source/blender/freestyle/intern/system/PseudoNoise.h b/source/blender/freestyle/intern/system/PseudoNoise.h
new file mode 100755
index 00000000000..43143865600
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PseudoNoise.h
@@ -0,0 +1,58 @@
+//
+// Filename : PseudoNoise.h
+// Author(s) : Fredo Durand
+// Purpose : Class to define a pseudo Perlin noise
+// Date of creation : 16/06/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef PSEUDONOISE_H
+# define PSEUDONOISE_H
+
+# include "FreestyleConfig.h"
+# include "Precision.h"
+
+class LIB_SYSTEM_EXPORT PseudoNoise
+{
+public:
+
+ PseudoNoise ();
+
+ virtual ~PseudoNoise () {}
+
+ real smoothNoise (real x);
+ real linearNoise (real x);
+
+ real turbulenceSmooth (real x, unsigned nbOctave = 8);
+ real turbulenceLinear (real x, unsigned nbOctave = 8);
+
+ static void init (long seed);
+
+protected:
+
+ static real *_values;
+};
+
+#endif // PSEUDONOISE_H
+
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.cpp b/source/blender/freestyle/intern/system/PythonInterpreter.cpp
new file mode 100755
index 00000000000..821bd32b40b
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.cpp
@@ -0,0 +1,25 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "PythonInterpreter.h"
+
+string PythonInterpreter::_path = "";
+bool PythonInterpreter::_initialized = false;
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h
new file mode 100755
index 00000000000..81e2f70c82e
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.h
@@ -0,0 +1,180 @@
+//
+// Filename : PythonInterpreter.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Python Interpreter
+// Date of creation : 17/04/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef PYTHON_INTERPRETER_H
+# define PYTHON_INTERPRETER_H
+
+# include <Python.h>
+# include <iostream>
+# include "StringUtils.h"
+# include "Interpreter.h"
+
+//soc
+extern "C" {
+#include "MEM_guardedalloc.h"
+#include "DNA_text_types.h"
+#include "BKE_main.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_report.h"
+#include "BKE_text.h"
+#include "BKE_library.h"
+#include "BPY_extern.h"
+}
+
+class LIB_SYSTEM_EXPORT PythonInterpreter : public Interpreter
+{
+ public:
+
+ PythonInterpreter() {
+ _language = "Python";
+ _context = 0;
+ //Py_Initialize();
+ }
+
+ virtual ~PythonInterpreter() {
+ //Py_Finalize();
+ }
+
+ void setContext(bContext *C) {
+ _context = C;
+ }
+
+ int interpretFile(const string& filename) {
+
+ initPath();
+
+ ReportList* reports = CTX_wm_reports(_context);
+ BKE_reports_clear(reports);
+ char *fn = const_cast<char*>(filename.c_str());
+#if 0
+ int status = BPY_filepath_exec(_context, fn, reports);
+#else
+ int status;
+ Text *text = BKE_text_load(fn, G.main->name);
+ if (text) {
+ status = BPY_text_exec(_context, text, reports, false);
+ BKE_text_unlink(G.main, text);
+ BKE_libblock_free(&G.main->text, text);
+ } else {
+ BKE_reportf(reports, RPT_ERROR, "Cannot open file: %s", fn);
+ status = 0;
+ }
+#endif
+
+ if (status != 1) {
+ cout << "\nError executing Python script from PythonInterpreter::interpretFile" << endl;
+ cout << "File: " << fn << endl;
+ cout << "Errors: " << endl;
+ BKE_reports_print(reports, RPT_ERROR);
+ return 1;
+ }
+
+ // cleaning up
+ BKE_reports_clear(reports);
+
+ return 0;
+ }
+
+ int interpretText(struct Text *text, const string& name) {
+
+ initPath();
+
+ ReportList* reports = CTX_wm_reports(_context);
+
+ BKE_reports_clear(reports);
+
+ if (!BPY_text_exec(_context, text, reports, false)) {
+ cout << "\nError executing Python script from PythonInterpreter::interpretText" << endl;
+ cout << "Name: " << name << endl;
+ cout << "Errors: " << endl;
+ BKE_reports_print(reports, RPT_ERROR);
+ return 1;
+ }
+
+ BKE_reports_clear(reports);
+
+ return 0;
+ }
+
+ struct Options
+ {
+ static void setPythonPath(const string& path) {
+ _path = path;
+ }
+
+ static string getPythonPath() {
+ return _path;
+ }
+ };
+
+ void reset() {
+ Py_Finalize();
+ Py_Initialize();
+ _initialized = false;
+ }
+
+private:
+
+ bContext* _context;
+
+ void initPath() {
+ if (_initialized)
+ return;
+
+ vector<string> pathnames;
+ StringUtils::getPathName(_path, "", pathnames);
+
+ struct Text *text = BKE_text_add("tmp_freestyle_initpath.txt");
+ string cmd = "import sys\n";
+ txt_insert_buf(text, const_cast<char*>(cmd.c_str()));
+
+ for (vector<string>::const_iterator it = pathnames.begin(); it != pathnames.end();++it) {
+ if ( !it->empty() ) {
+ cout << "Adding Python path: " << *it << endl;
+ cmd = "sys.path.append(r\"" + *it + "\")\n";
+ txt_insert_buf(text, const_cast<char*>(cmd.c_str()));
+ }
+ }
+
+ BPY_text_exec(_context, text, NULL, false);
+
+ // cleaning up
+ BKE_text_unlink(G.main, text);
+ BKE_libblock_free(&G.main->text, text);
+
+ //PyRun_SimpleString("from Freestyle import *");
+ _initialized = true;
+ }
+
+ static bool _initialized;
+ static string _path;
+};
+
+#endif // PYTHON_INTERPRETER_H
diff --git a/source/blender/freestyle/intern/system/RandGen.cpp b/source/blender/freestyle/intern/system/RandGen.cpp
new file mode 100755
index 00000000000..a328cb7f583
--- /dev/null
+++ b/source/blender/freestyle/intern/system/RandGen.cpp
@@ -0,0 +1,86 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "RandGen.h"
+
+//
+// Macro definitions
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#define N 16
+#define MASK ((unsigned)(1 << (N - 1)) + (1 << (N - 1)) - 1)
+#define X0 0x330E
+#define X1 0xABCD
+#define X2 0x1234
+#define A0 0xE66D
+#define A1 0xDEEC
+#define A2 0x5
+#define C 0xB
+#define HI_BIT (1L << (2 * N - 1))
+
+#define LOW(x) ((unsigned)(x) & MASK)
+#define HIGH(x) LOW((x) >> N)
+#define MUL(x, y, z) { long l = (long)(x) * (long)(y); \
+ (z)[0] = LOW(l); (z)[1] = HIGH(l); }
+#define CARRY(x, y) ((unsigned long)((long)(x) + (long)(y)) > MASK)
+#define ADDEQU(x, y, z) (z = CARRY(x, (y)), x = LOW(x + (y)))
+#define SET3(x, x0, x1, x2) ((x)[0] = (x0), (x)[1] = (x1), (x)[2] = (x2))
+#define SETLOW(x, y, n) SET3(x, LOW((y)[n]), LOW((y)[(n)+1]), LOW((y)[(n)+2]))
+#define SEED(x0, x1, x2) (SET3(x, x0, x1, x2), SET3(a, A0, A1, A2), c = C)
+#define REST(v) for (i = 0; i < 3; i++) { xsubi[i] = x[i]; x[i] = temp[i]; } \
+ return (v);
+#define NEST(TYPE, f, F) TYPE f(register unsigned short *xsubi) { \
+ register int i; register TYPE v; unsigned temp[3]; \
+ for (i = 0; i < 3; i++) { temp[i] = x[i]; x[i] = LOW(xsubi[i]); } \
+ v = F(); REST(v); }
+
+static unsigned x[3] = { X0, X1, X2 }, a[3] = { A0, A1, A2 }, c = C;
+
+//
+// Methods implementation
+//
+///////////////////////////////////////////////////////////////////////////////
+
+real RandGen::drand48() {
+ static real two16m = 1.0 / (1L << N);
+ next();
+ return (two16m * (two16m * (two16m * x[0] + x[1]) + x[2]));
+}
+
+void RandGen::srand48(long seedval) {
+ SEED(X0, LOW(seedval), HIGH(seedval));
+}
+
+void RandGen::next() {
+ unsigned p[2], q[2], r[2], carry0, carry1;
+
+ MUL(a[0], x[0], p);
+ ADDEQU(p[0], c, carry0);
+ ADDEQU(p[1], carry0, carry1);
+ MUL(a[0], x[1], q);
+ ADDEQU(p[1], q[0], carry0);
+ MUL(a[1], x[0], r);
+ x[2] = LOW(carry0 + carry1 + CARRY(p[1], r[0]) + q[1] + r[1] +
+ a[0] * x[2] + a[1] * x[1] + a[2] * x[0]);
+ x[1] = LOW(p[1] + r[0]);
+ x[0] = LOW(p[0]);
+}
diff --git a/source/blender/freestyle/intern/system/RandGen.h b/source/blender/freestyle/intern/system/RandGen.h
new file mode 100755
index 00000000000..409d3b79609
--- /dev/null
+++ b/source/blender/freestyle/intern/system/RandGen.h
@@ -0,0 +1,48 @@
+//
+// Filename : RandGen.h
+// Author(s) : Fredo Durand
+// Purpose : Pseudo-random number generator
+// Date of creation : 20/05/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef RAND_GEN_H
+# define RAND_GEN_H
+
+# include "FreestyleConfig.h"
+# include "../system/Precision.h"
+
+class LIB_SYSTEM_EXPORT RandGen
+{
+public:
+
+ static real drand48();
+ static void srand48(long value);
+
+private:
+
+ static void next();
+};
+
+#endif // RAND_GEN_H
diff --git a/source/blender/freestyle/intern/system/RenderMonitor.h b/source/blender/freestyle/intern/system/RenderMonitor.h
new file mode 100644
index 00000000000..7d148e65c90
--- /dev/null
+++ b/source/blender/freestyle/intern/system/RenderMonitor.h
@@ -0,0 +1,47 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef RENDERMONITOR_H
+#define RENDERMONITOR_H
+
+extern "C" {
+#include "render_types.h"
+}
+
+class RenderMonitor
+{
+public:
+
+ inline RenderMonitor(Render *re) {
+ _re = re;
+ }
+
+ virtual ~RenderMonitor() {}
+
+ inline bool testBreak() {
+ return _re && _re->test_break(_re->tbh);
+ }
+
+protected:
+
+ Render *_re;
+};
+
+#endif // RENDERMONITOR_H
diff --git a/source/blender/freestyle/intern/system/StringUtils.cpp b/source/blender/freestyle/intern/system/StringUtils.cpp
new file mode 100755
index 00000000000..58798daf42a
--- /dev/null
+++ b/source/blender/freestyle/intern/system/StringUtils.cpp
@@ -0,0 +1,74 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//soc #include <qfileinfo.h>
+#include "FreestyleConfig.h"
+#include "StringUtils.h"
+
+namespace StringUtils {
+
+ void getPathName(const string& path, const string& base, vector<string>& pathnames) {
+ string dir;
+ string res;
+ char cleaned[FILE_MAX];
+ unsigned size = path.size();
+
+ pathnames.push_back(base);
+
+ for ( unsigned pos = 0, sep = path.find(Config::PATH_SEP, pos);
+ pos < size;
+ pos = sep + 1, sep = path.find(Config::PATH_SEP, pos)) {
+
+ if (sep == (unsigned)string::npos)
+ sep = size;
+
+ dir = path.substr(pos, sep - pos);
+
+ BLI_strncpy(cleaned, dir.c_str(), FILE_MAX);
+ BLI_cleanup_file(NULL, cleaned);
+ res = toAscii( string(cleaned) );
+
+ if (!base.empty())
+ res += Config::DIR_SEP + base;
+
+ pathnames.push_back(res);
+ }
+ }
+
+ string toAscii( const string &str ){
+ stringstream out("");
+ char s;
+
+ for(unsigned int i=0; i < str.size() ; i++){
+ s = ((char)(str.at(i) & 0x7F));
+ out << s;
+ }
+
+ return out.str();
+ }
+
+ const char* toAscii( const char *str ){
+ return toAscii(string(str)).c_str();
+ }
+
+
+
+} // end of namespace StringUtils
diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h
new file mode 100755
index 00000000000..d44d3f62732
--- /dev/null
+++ b/source/blender/freestyle/intern/system/StringUtils.h
@@ -0,0 +1,62 @@
+//
+// Filename : StringUtils.h
+// Author(s) : Emmanuel Turquin
+// Purpose : String utilities
+// Date of creation : 20/05/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef STRING_UTILS_H
+# define STRING_UTILS_H
+
+# include <cstring>
+# include <vector>
+# include <string>
+# include <sstream>
+# include <iostream>
+# include "FreestyleConfig.h"
+
+//soc
+extern "C" {
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+}
+
+using namespace std;
+
+namespace StringUtils {
+
+ LIB_SYSTEM_EXPORT
+ void getPathName(const string& path, const string& base, vector<string>& pathnames);
+ string toAscii( const string &str );
+ const char* toAscii( const char *str );
+
+ // STL related
+ struct ltstr{
+ bool operator()(const char* s1, const char* s2) const{
+ return strcmp(s1, s2) < 0;
+ }
+};
+
+} // end of namespace StringUtils
+
+#endif // STRING_UTILS_H
diff --git a/source/blender/freestyle/intern/system/TimeStamp.cpp b/source/blender/freestyle/intern/system/TimeStamp.cpp
new file mode 100755
index 00000000000..c66e1131611
--- /dev/null
+++ b/source/blender/freestyle/intern/system/TimeStamp.cpp
@@ -0,0 +1,25 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "TimeStamp.h"
+
+LIB_SYSTEM_EXPORT
+TimeStamp* TimeStamp::_instance = 0;
diff --git a/source/blender/freestyle/intern/system/TimeStamp.h b/source/blender/freestyle/intern/system/TimeStamp.h
new file mode 100755
index 00000000000..568a7851e30
--- /dev/null
+++ b/source/blender/freestyle/intern/system/TimeStamp.h
@@ -0,0 +1,71 @@
+//
+// Filename : TimeStamp.h
+// Author(s) : Stephane Grabli
+// Purpose : Class defining a singleton used as timestamp
+// Date of creation : 12/12/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TIMESTAMP_H
+# define TIMESTAMP_H
+
+# include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT TimeStamp
+{
+ public:
+
+ static inline TimeStamp* instance() {
+ if (_instance == 0)
+ _instance = new TimeStamp;
+ return _instance;
+ }
+
+ inline unsigned getTimeStamp() const {
+ return _time_stamp;
+ }
+
+ inline void increment() {
+ ++_time_stamp;
+ }
+
+ inline void reset() {
+ _time_stamp = 1;
+ }
+
+ protected:
+
+ TimeStamp() {
+ _time_stamp = 1;
+ }
+
+ TimeStamp(const TimeStamp&) {}
+
+ private:
+
+ static TimeStamp* _instance;
+ unsigned _time_stamp;
+};
+
+#endif // TIMESTAMP_H
diff --git a/source/blender/freestyle/intern/system/TimeUtils.h b/source/blender/freestyle/intern/system/TimeUtils.h
new file mode 100755
index 00000000000..99dd5b0a669
--- /dev/null
+++ b/source/blender/freestyle/intern/system/TimeUtils.h
@@ -0,0 +1,58 @@
+//
+// Filename : TimeUtils.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to measure ellapsed time
+// Date of creation : 10/04/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TIMEUTILS_H
+# define TIMEUTILS_H
+
+#include <time.h>
+#include "FreestyleConfig.h"
+
+class Chronometer
+{
+ public:
+
+ inline Chronometer() {}
+ inline ~Chronometer() {}
+
+ inline clock_t start() {
+ _start = clock();
+ return _start;
+ }
+
+ inline double stop() {
+ clock_t stop = clock();
+ return (double)(stop - _start) / CLOCKS_PER_SEC ;
+ }
+
+ private:
+
+ clock_t _start;
+};
+
+#endif // TIMEUTILS_H
diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
new file mode 100644
index 00000000000..15b2b3343cc
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
@@ -0,0 +1,108 @@
+//
+// Filename : ArbitraryGridDensityProvider.cpp
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-5
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ArbitraryGridDensityProvider.h"
+
+ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numCells)
+ : GridDensityProvider(source), numCells(numCells)
+{
+ initialize (proscenium);
+}
+
+ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform, unsigned numCells)
+ : GridDensityProvider(source), numCells(numCells)
+{
+ real proscenium[4];
+ calculateQuickProscenium(transform, bbox, proscenium);
+
+ initialize (proscenium);
+}
+
+ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, unsigned numCells)
+ : GridDensityProvider(source), numCells(numCells)
+{
+ real proscenium[4];
+ calculateOptimalProscenium(source, proscenium);
+
+ initialize (proscenium);
+}
+
+ArbitraryGridDensityProvider::~ArbitraryGridDensityProvider () {}
+
+void ArbitraryGridDensityProvider::initialize (const real proscenium[4])
+{
+ float prosceniumWidth = (proscenium[1] - proscenium[0]);
+ float prosceniumHeight = (proscenium[3] - proscenium[2]);
+ real cellArea = prosceniumWidth * prosceniumHeight / numCells;
+ cout << prosceniumWidth << " x " << prosceniumHeight << " grid with cells of area " << cellArea << "." << endl;
+
+ _cellSize = sqrt(cellArea);
+ // Now we know how many cells make each side of our grid
+ _cellsX = ceil(prosceniumWidth / _cellSize);
+ _cellsY = ceil(prosceniumHeight / _cellSize);
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+
+ // Make sure the grid exceeds the proscenium by a small amount
+ float safetyZone = 0.1;
+ if ( _cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone) ) {
+ _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize;
+ }
+ if ( _cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone) ) {
+ _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize;
+ }
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+
+ // Find grid origin
+ _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize;
+ _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize;
+}
+
+ArbitraryGridDensityProviderFactory::ArbitraryGridDensityProviderFactory(unsigned numCells)
+ : numCells(numCells)
+{
+}
+
+ArbitraryGridDensityProviderFactory::~ArbitraryGridDensityProviderFactory () {}
+
+auto_ptr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
+{
+ return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, proscenium, numCells));
+}
+
+auto_ptr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform)
+{
+ return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, bbox, transform, numCells));
+}
+
+auto_ptr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+{
+ return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, numCells));
+}
+
diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h
new file mode 100644
index 00000000000..f863b2132a7
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h
@@ -0,0 +1,67 @@
+//
+// Filename : ArbitraryGridDensityProvider.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-5
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ARBITRARYGRIDDENSITYPROVIDER_H
+#define ARBITRARYGRIDDENSITYPROVIDER_H
+
+#include "GridDensityProvider.h"
+
+class ArbitraryGridDensityProvider : public GridDensityProvider {
+ // Disallow copying and assignment
+ ArbitraryGridDensityProvider (const ArbitraryGridDensityProvider& other);
+ ArbitraryGridDensityProvider& operator= (const ArbitraryGridDensityProvider& other);
+
+public:
+ ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numCells);
+ ArbitraryGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform, unsigned numCells);
+ ArbitraryGridDensityProvider(OccluderSource& source, unsigned numCells);
+ virtual ~ArbitraryGridDensityProvider ();
+
+protected:
+ unsigned numCells;
+
+private:
+ void initialize (const real proscenium[4]);
+};
+
+class ArbitraryGridDensityProviderFactory : public GridDensityProviderFactory {
+public:
+ ArbitraryGridDensityProviderFactory(unsigned numCells);
+ ~ArbitraryGridDensityProviderFactory ();
+
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform);
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
+protected:
+ unsigned numCells;
+};
+
+#endif // ARBITRARYGRIDDENSITYPROVIDER_H
+
diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
new file mode 100644
index 00000000000..8b4c60a7fea
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
@@ -0,0 +1,120 @@
+//
+// Filename : AverageAreaGridDensityProvider.cpp
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-9
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "AverageAreaGridDensityProvider.h"
+
+AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4], real sizeFactor)
+ : GridDensityProvider(source)
+{
+ initialize (proscenium, sizeFactor);
+}
+
+AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform, real sizeFactor)
+ : GridDensityProvider(source)
+{
+ real proscenium[4];
+ calculateQuickProscenium(transform, bbox, proscenium);
+
+ initialize (proscenium, sizeFactor);
+}
+
+AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, real sizeFactor)
+ : GridDensityProvider(source)
+{
+ real proscenium[4];
+ calculateOptimalProscenium(source, proscenium);
+
+ initialize (proscenium, sizeFactor);
+}
+
+AverageAreaGridDensityProvider::~AverageAreaGridDensityProvider () {}
+
+void AverageAreaGridDensityProvider::initialize (const real proscenium[4], real sizeFactor)
+{
+ float prosceniumWidth = (proscenium[1] - proscenium[0]);
+ float prosceniumHeight = (proscenium[3] - proscenium[2]);
+
+ real cellArea = 0.0;
+ unsigned numFaces = 0;
+ for ( source.begin(); source.isValid(); source.next() ) {
+ Polygon3r& poly(source.getGridSpacePolygon());
+ Vec3r min, max;
+ poly.getBBox(min, max);
+ cellArea += (max[0] - min[0]) * (max[1] - min[1]);
+ ++numFaces;
+ }
+ cout << "Total area: " << cellArea << ". Number of faces: " << numFaces << "." << endl;
+ cellArea /= numFaces;
+ cellArea *= sizeFactor;
+ cout << "Building grid with average area " << cellArea << endl;
+
+ _cellSize = sqrt(cellArea);
+ // Now we know how many cells make each side of our grid
+ _cellsX = ceil(prosceniumWidth / _cellSize);
+ _cellsY = ceil(prosceniumHeight / _cellSize);
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+
+ // Make sure the grid exceeds the proscenium by a small amount
+ float safetyZone = 0.1;
+ if ( _cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone) ) {
+ _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize;
+ }
+ if ( _cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone) ) {
+ _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize;
+ }
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+
+ // Find grid origin
+ _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize;
+ _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize;
+}
+
+AverageAreaGridDensityProviderFactory::AverageAreaGridDensityProviderFactory(real sizeFactor)
+ : sizeFactor(sizeFactor)
+{
+}
+
+AverageAreaGridDensityProviderFactory::~AverageAreaGridDensityProviderFactory () {}
+
+auto_ptr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
+{
+ return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
+}
+
+auto_ptr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform)
+{
+ return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor));
+}
+
+auto_ptr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+{
+ return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, sizeFactor));
+}
+
diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h
new file mode 100644
index 00000000000..73d28f006a7
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h
@@ -0,0 +1,67 @@
+//
+// Filename : AverageAreaGridDensityProvider.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-9
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef AVERAGEAREAGRIDDENSITYPROVIDER_H
+#define AVERAGEAREAGRIDDENSITYPROVIDER_H
+
+#include "GridDensityProvider.h"
+
+class AverageAreaGridDensityProvider : public GridDensityProvider {
+ // Disallow copying and assignment
+ AverageAreaGridDensityProvider (const AverageAreaGridDensityProvider& other);
+ AverageAreaGridDensityProvider& operator= (const AverageAreaGridDensityProvider& other);
+
+public:
+ AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4], real sizeFactor);
+ AverageAreaGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform, real sizeFactor);
+ AverageAreaGridDensityProvider(OccluderSource& source, real sizeFactor);
+ virtual ~AverageAreaGridDensityProvider ();
+
+protected:
+
+private:
+ void initialize (const real proscenium[4], real sizeFactor);
+};
+
+class AverageAreaGridDensityProviderFactory : public GridDensityProviderFactory {
+public:
+ AverageAreaGridDensityProviderFactory(real sizeFactor);
+ ~AverageAreaGridDensityProviderFactory ();
+
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform);
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
+
+protected:
+ real sizeFactor;
+};
+
+#endif // AVERAGEAREAGRIDDENSITYPROVIDER_H
+
diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp
new file mode 100644
index 00000000000..757cf7b6559
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp
@@ -0,0 +1,210 @@
+//
+// Filename : BoxGrid.cpp
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-1-29
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "BoxGrid.h"
+
+#include <stdexcept>
+#include <algorithm>
+
+using namespace std;
+
+// Helper Classes
+
+// OccluderData
+///////////////
+
+// Cell
+/////////
+
+BoxGrid::Cell::Cell () {}
+
+BoxGrid::Cell::~Cell () {}
+
+void BoxGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY) {
+ const real epsilon = 1.0e-06;
+ boundary[0] = x - epsilon;
+ boundary[1] = x + sizeX + epsilon;
+ boundary[2] = y - epsilon;
+ boundary[3] = y + sizeY + epsilon;
+}
+
+bool BoxGrid::Cell::compareOccludersByShallowestPoint (const BoxGrid::OccluderData* a, const BoxGrid::OccluderData* b) {
+ return a->shallowest < b->shallowest;
+}
+
+void BoxGrid::Cell::indexPolygons() {
+ // Sort occluders by their shallowest points.
+ sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint);
+}
+
+// Iterator
+//////////////////
+
+BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real epsilon)
+ : _target(grid.transform(center)),
+ _foundOccludee(false)
+{
+ // Find target cell
+ _cell = grid.findCell(_target);
+ #if boxgridlogging == 1
+ cout << "Searching for occluders of edge centered at " << _target << " in cell ["
+ << _cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2]
+ << ", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl;
+ #endif
+
+ // Set iterator
+ _current = _cell->faces.begin();
+}
+
+BoxGrid::Iterator::~Iterator () {}
+
+// BoxGrid
+/////////////////
+
+BoxGrid::BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, bool enableQI)
+ : _viewpoint(viewpoint),
+ _enableQI(enableQI)
+{
+ cout << "Generate Cell structure" << endl;
+ // Generate Cell structure
+ assignCells(source, density, viewMap);
+ cout << "Distribute occluders" << endl;
+ // Fill Cells
+ distributePolygons(source);
+ cout << "Reorganize cells" << endl;
+ // Reorganize Cells
+ reorganizeCells();
+ cout << "Ready to use BoxGrid" << endl;
+}
+
+BoxGrid::~BoxGrid () {
+}
+
+void BoxGrid::assignCells (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap) {
+ _cellSize = density.cellSize();
+ _cellsX = density.cellsX();
+ _cellsY = density.cellsY();
+ _cellOrigin[0] = density.cellOrigin(0);
+ _cellOrigin[1] = density.cellOrigin(1);
+
+ // Now allocate the cell table and fill it with default (empty) cells
+ _cells.resize(_cellsX * _cellsY);
+ for ( cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i ) {
+ (*i) = NULL;
+ }
+
+ // Identify cells that will be used, and set the dimensions for each
+ ViewMap::fedges_container& fedges = viewMap->FEdges();
+ for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f ) {
+ if ( (*f)->isInImage() ) {
+ Vec3r point = transform((*f)->center3d());
+ unsigned i, j;
+ getCellCoordinates(point, i, j);
+ if ( _cells[i * _cellsY + j] == NULL ) {
+ // This is an uninitialized cell
+
+ real x, y, width, height;
+
+ x = _cellOrigin[0] + _cellSize * i;
+ width = _cellSize;
+
+ y = _cellOrigin[1] + _cellSize * j;
+ height = _cellSize;
+
+ // Initialize cell
+ Cell* b = _cells[i * _cellsY + j] = new Cell();
+ b->setDimensions(x, y, width, height);
+ }
+ }
+ }
+}
+
+void BoxGrid::distributePolygons (OccluderSource& source) {
+ unsigned long nFaces = 0;
+ unsigned long nKeptFaces = 0;
+
+ for ( source.begin(); source.isValid(); source.next() ) {
+ OccluderData* occluder = NULL;
+
+ try {
+ if ( insertOccluder(source, occluder) ) {
+ _faces.push_back(occluder);
+ ++nKeptFaces;
+ }
+ } catch (...) {
+ // If an exception was thrown, _faces.push_back() cannot have succeeded.
+ // occluder is not owned by anyone, and must be deleted.
+ // If the exception was thrown before or during new OccluderData(), then
+ // occluder is NULL, and this delete is harmless.
+ delete occluder;
+ throw;
+ }
+ ++nFaces;
+ }
+ cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl;
+}
+
+void BoxGrid::reorganizeCells () {
+ // Sort the occluders by shallowest point
+ for ( vector<Cell*>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i ) {
+ if ( *i != NULL ) {
+ (*i)->indexPolygons();
+ }
+ }
+}
+
+void BoxGrid::getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y) {
+ x = min(_cellsX - 1, (unsigned) floor (max((double) 0.0f, point[0] - _cellOrigin[0]) / _cellSize));
+ y = min(_cellsY - 1, (unsigned) floor (max((double) 0.0f, point[1] - _cellOrigin[1]) / _cellSize));
+}
+
+BoxGrid::Cell* BoxGrid::findCell(const Vec3r& point) {
+ unsigned x, y;
+ getCellCoordinates(point, x, y);
+ return _cells[x * _cellsY + y];
+}
+
+bool BoxGrid::orthographicProjection () const {
+ return true;
+}
+
+const Vec3r& BoxGrid::viewpoint() const {
+ return _viewpoint;
+}
+
+bool BoxGrid::enableQI() const {
+ return _enableQI;
+}
+
+BoxGrid::Transform::Transform () : GridHelpers::Transform() {}
+
+Vec3r BoxGrid::Transform::operator() (const Vec3r& point) const {
+ return Vec3r(point[0], point[1], -point[2]);
+}
+
diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.h b/source/blender/freestyle/intern/view_map/BoxGrid.h
new file mode 100644
index 00000000000..43de8d713d5
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/BoxGrid.h
@@ -0,0 +1,376 @@
+//
+// Filename : BoxGrid.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-1-29
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOXGRID_H
+#define BOXGRID_H
+
+#define boxgridlogging 0
+
+// I would like to avoid using deque because including ViewMap.h and <deque> or <vector>
+// separately results in redefinitions of identifiers. ViewMap.h already includes <vector>
+// so it should be a safe fall-back.
+//#include <vector>
+//#include <deque>
+#include "ViewMap.h"
+#include "../winged_edge/WEdge.h"
+#include "../geometry/Polygon.h"
+#include "../system/PointerSequence.h"
+#include "../geometry/BBox.h"
+#include "../geometry/GridHelpers.h"
+#include "OccluderSource.h"
+#include "GridDensityProvider.h"
+
+class BoxGrid
+{
+public:
+ // Helper classes
+ struct OccluderData {
+ explicit OccluderData (OccluderSource& source, Polygon3r& p);
+ Polygon3r poly;
+ Polygon3r cameraSpacePolygon;
+ real shallowest, deepest;
+ // N.B. We could, of course, store face in poly's userdata
+ // member, like the old ViewMapBuilder code does. However,
+ // code comments make it clear that userdata is deprecated,
+ // so we avoid the temptation to save 4 or 8 bytes.
+ WFace* face;
+ };
+
+private:
+ struct Cell {
+ // Can't store Cell in a vector without copy and assign
+ //Cell(const Cell& other);
+ //Cell& operator= (const Cell& other);
+
+ explicit Cell ();
+ ~Cell ();
+
+ static bool compareOccludersByShallowestPoint (const OccluderData* a, const OccluderData* b);
+
+ void setDimensions(real x, real y, real sizeX, real sizeY);
+ void checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder);
+ void indexPolygons();
+
+ real boundary[4];
+ //deque<OccluderData*> faces;
+ vector<OccluderData*> faces;
+ };
+
+public:
+ /*****
+
+ Iterator needs to allow the user to avoid full 3D comparison in
+ two cases:
+
+ (1) Where (*current)->deepest < target[2], where the occluder is
+ unambiguously in front of the target point.
+
+ (2) Where (*current)->shallowest > target[2], where the occluder
+ is unambiguously in back of the target point.
+
+ In addition, when used by OptimizedFindOccludee, Iterator should
+ stop iterating as soon as it has an occludee candidate and
+ (*current)->shallowest > candidate[2], because at that point forward
+ no new occluder could possibly be a better occludee.
+
+ *****/
+
+ class Iterator {
+ public:
+ // epsilon is not used in this class, but other grids with the same interface may need an epsilon
+ explicit Iterator (BoxGrid& grid, Vec3r& center, real epsilon=1e-06);
+ ~Iterator ();
+ void initBeforeTarget ();
+ void initAfterTarget ();
+ void nextOccluder ();
+ void nextOccludee ();
+ bool validBeforeTarget();
+ bool validAfterTarget();
+ WFace* getWFace() const;
+ Polygon3r* getCameraSpacePolygon();
+ void reportDepth(Vec3r origin, Vec3r u, real t);
+ private:
+ bool testOccluder(bool wantOccludee);
+ void markCurrentOccludeeCandidate(real depth);
+
+ Cell* _cell;
+ Vec3r _target;
+ bool _foundOccludee;
+ real _occludeeDepth;
+ //deque<OccluderData*>::iterator _current, _occludeeCandidate;
+ vector<OccluderData*>::iterator _current, _occludeeCandidate;
+ };
+
+ class Transform : public GridHelpers::Transform {
+ public:
+ explicit Transform ();
+ explicit Transform (Transform& other);
+ Vec3r operator() (const Vec3r& point) const;
+ };
+
+private:
+ // Prevent implicit copies and assignments.
+ BoxGrid(const BoxGrid& other);
+ BoxGrid& operator= (const BoxGrid& other);
+public:
+ explicit BoxGrid (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, bool enableQI);
+ virtual ~BoxGrid();
+
+ // Generate Cell structure
+ void assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap);
+ // Fill Cells
+ void distributePolygons(OccluderSource& source);
+ // Insert one polygon into each matching cell,
+ // return true if any cell consumes the polygon
+ bool insertOccluder(OccluderSource& source, OccluderData*& occluder);
+ // Sort occluders in each cell
+ void reorganizeCells();
+
+ Cell* findCell(const Vec3r& point);
+
+ // Accessors:
+ bool orthographicProjection() const;
+ const Vec3r& viewpoint() const;
+ bool enableQI() const;
+ Transform transform;
+
+private:
+ void getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y);
+
+ typedef PointerSequence<vector<Cell*>, Cell*> cellContainer;
+ //typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer;
+ typedef PointerSequence<vector<OccluderData*>, OccluderData*> occluderContainer;
+ unsigned _cellsX, _cellsY;
+ float _cellSize;
+ float _cellOrigin[2];
+ cellContainer _cells;
+ occluderContainer _faces;
+ Vec3r _viewpoint;
+ bool _enableQI;
+};
+
+inline void BoxGrid::Iterator::initBeforeTarget () {
+ _current = _cell->faces.begin();
+ while ( _current != _cell->faces.end() && ! testOccluder(false) ) {
+ ++_current;
+ }
+}
+
+inline void BoxGrid::Iterator::initAfterTarget () {
+ if ( _foundOccludee ) {
+ #if boxgridlogging == 1
+ std::cout << "\tStarting occludee search from occludeeCandidate at depth " << _occludeeDepth << std::endl;
+ #endif
+ _current = _occludeeCandidate;
+ return;
+ }
+
+ #if boxgridlogging == 1
+ std::cout << "\tStarting occludee search from current position" << std::endl;
+ #endif
+
+ while ( _current != _cell->faces.end() && ! testOccluder(true) ) {
+ ++_current;
+ }
+}
+
+inline bool BoxGrid::Iterator::testOccluder (bool wantOccludee) {
+ // End-of-list is not even a valid iterator position
+ if ( _current == _cell->faces.end() ) {
+ // Returning true seems strange, but it will break us out of whatever loop
+ // is calling testOccluder, and _current=_cell->face.end() will make
+ // the calling routine give up.
+ return true;
+ }
+ #if boxgridlogging == 1
+ std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0];
+ for ( unsigned i = 1; i < (*_current)->poly.getVertices().size(); ++i ) {
+ std::cout << ", " << (*_current)->poly.getVertices()[i];
+ }
+ std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl;
+ #endif
+
+
+ // If we have an occluder candidate and we are unambiguously after it, abort
+ if ( _foundOccludee && (*_current)->shallowest > _occludeeDepth ) {
+ #if boxgridlogging == 1
+ std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl;
+ #endif
+ _current = _cell->faces.end();
+
+ // See note above
+ return true;
+ }
+
+ // Specific continue or stop conditions when searching for each type
+ if ( wantOccludee ) {
+ if ( (*_current)->deepest < _target[2] ) {
+ #if boxgridlogging == 1
+ std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl;
+ #endif
+ return false;
+ }
+ } else {
+ if ( (*_current)->shallowest > _target[2] ) {
+ #if boxgridlogging == 1
+ std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl;
+ #endif
+ return true;
+ }
+ }
+
+ // Depthwise, this is a valid occluder.
+
+ // Check to see if target is in the 2D bounding box
+ Vec3r bbMin, bbMax;
+ (*_current)->poly.getBBox(bbMin, bbMax);
+ if ( _target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || _target[1] > bbMax[1] ) {
+ #if boxgridlogging == 1
+ std::cout << "\t\tSkipping: bounding box violation" << std::endl;
+ #endif
+ return false;
+ }
+
+ // We've done all the corner cutting we can.
+ // Let the caller work out whether or not
+ // the geometry is correct.
+ return true;
+}
+
+inline void BoxGrid::Iterator::reportDepth (Vec3r origin, Vec3r u, real t) {
+ // The reported depth is the length of a ray in camera space
+ // We need to convert it into a Z-value in grid space
+ real depth = -(origin + (u * t))[2];
+ #if boxgridlogging == 1
+ std::cout << "\t\tReporting depth of occluder/ee: " << depth;
+ #endif
+ if ( depth > _target[2] ) {
+ #if boxgridlogging == 1
+ std::cout << " is deeper than target" << std::endl;
+ #endif
+ // If the current occluder is the best occludee so far, save it.
+ if ( ! _foundOccludee || _occludeeDepth > depth ) {
+ markCurrentOccludeeCandidate(depth);
+ }
+ } else {
+ #if boxgridlogging == 1
+ std::cout << std::endl;
+ #endif
+ }
+}
+
+inline void BoxGrid::Iterator::nextOccluder () {
+ if ( _current != _cell->faces.end() ) {
+ do {
+ ++_current;
+ } while ( _current != _cell->faces.end() && ! testOccluder(false) );
+ }
+}
+
+inline void BoxGrid::Iterator::nextOccludee () {
+ if ( _current != _cell->faces.end() ) {
+ do {
+ ++_current;
+ } while ( _current != _cell->faces.end() && ! testOccluder(true) );
+ }
+}
+
+inline bool BoxGrid::Iterator::validBeforeTarget () {
+ return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2];
+}
+
+inline bool BoxGrid::Iterator::validAfterTarget () {
+ return _current != _cell->faces.end();
+}
+
+inline void BoxGrid::Iterator::markCurrentOccludeeCandidate(real depth) {
+ #if boxgridlogging == 1
+ std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl;
+ #endif
+ _occludeeCandidate = _current;
+ _occludeeDepth = depth;
+ _foundOccludee = true;
+}
+
+inline WFace* BoxGrid::Iterator::getWFace() const {
+ return (*_current)->face;
+}
+
+inline Polygon3r* BoxGrid::Iterator::getCameraSpacePolygon() {
+ return &((*_current)->cameraSpacePolygon);
+}
+
+inline BoxGrid::OccluderData::OccluderData (OccluderSource& source, Polygon3r& p)
+ : poly(p),
+ cameraSpacePolygon(source.getCameraSpacePolygon()),
+ face(source.getWFace())
+{
+ // Set shallowest and deepest based on bbox
+ Vec3r min, max;
+ poly.getBBox(min, max);
+ shallowest = min[2];
+ deepest = max[2];
+}
+
+inline void BoxGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder) {
+ if ( GridHelpers::insideProscenium (boundary, poly) ) {
+ if ( occluder == NULL) {
+ // Disposal of occluder will be handled in BoxGrid::distributePolygons(),
+ // or automatically by BoxGrid::_faces;
+ occluder = new OccluderData(source, poly);
+ }
+ faces.push_back(occluder);
+ }
+}
+
+inline bool BoxGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder) {
+ Polygon3r& poly(source.getGridSpacePolygon());
+ occluder = NULL;
+
+ Vec3r bbMin, bbMax;
+ poly.getBBox(bbMin, bbMax);
+ // Check overlapping cells
+ unsigned startX, startY, endX, endY;
+ getCellCoordinates(bbMin, startX, startY);
+ getCellCoordinates(bbMax, endX, endY);
+
+ for ( unsigned i = startX; i <= endX; ++i ) {
+ for ( unsigned j = startY; j <= endY; ++j ) {
+ if ( _cells[i * _cellsY + j] != NULL ) {
+ _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder);
+ }
+ }
+ }
+
+ return occluder != NULL;
+}
+
+#endif // BOXGRID_H
+
diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp
new file mode 100644
index 00000000000..ea57da93347
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp
@@ -0,0 +1,277 @@
+//
+// Filename : CulledOccluderSource.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2010-12-21
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "CulledOccluderSource.h"
+#include "../geometry/GridHelpers.h"
+#include "FRS_freestyle.h"
+
+CulledOccluderSource::CulledOccluderSource (const GridHelpers::Transform& t, WingedEdge& we, ViewMap& viewMap, bool extensiveFEdgeSearch)
+ : OccluderSource(t, we),
+ rejected(0),
+ gridSpaceOccluderProsceniumInitialized(false)
+{
+ cullViewEdges(viewMap, extensiveFEdgeSearch);
+
+ // If we have not found any visible FEdges during our cull, then there is nothing
+ // to iterate over. Short-circuit everything.
+ valid = gridSpaceOccluderProsceniumInitialized;
+
+ if ( valid && ! testCurrent() ) {
+ next();
+ }
+}
+
+CulledOccluderSource::~CulledOccluderSource() {
+}
+
+bool CulledOccluderSource::testCurrent() {
+ if ( valid ) {
+ // The test for gridSpaceOccluderProsceniumInitialized should not be necessary
+ return gridSpaceOccluderProsceniumInitialized && GridHelpers::insideProscenium (gridSpaceOccluderProscenium, cachedPolygon);
+ }
+ return false;
+}
+
+bool CulledOccluderSource::next() {
+ while ( OccluderSource::next() ) {
+ if ( testCurrent() ) {
+ ++rejected;
+ return true;
+ }
+ }
+ std::cout << "Finished generating occluders. Rejected " << rejected << " faces." << std::endl;
+ return false;
+}
+
+void CulledOccluderSource::getOccluderProscenium(real proscenium[4]) {
+ for ( unsigned i = 0; i < 4; ++i ) {
+ proscenium[i] = gridSpaceOccluderProscenium[i];
+ }
+}
+
+static inline real distance2D(const Vec3r & point, const real origin[2]) {
+ return ::hypot((point[0] - origin[0]), (point[1] - origin[1]));
+}
+
+static inline bool crossesProscenium(real proscenium[4], FEdge *fe) {
+ Vec2r min(proscenium[0], proscenium[2]);
+ Vec2r max(proscenium[1], proscenium[3]);
+ Vec2r A(fe->vertexA()->getProjectedX(), fe->vertexA()->getProjectedY());
+ Vec2r B(fe->vertexB()->getProjectedX(), fe->vertexB()->getProjectedY());
+
+ return GeomUtils::intersect2dSeg2dArea (min, max, A, B);
+}
+
+static inline bool insideProscenium(real proscenium[4], const Vec3r& point) {
+ return ! ( point[0] < proscenium[0] || point[0] > proscenium[1] || point[1] < proscenium[2] || point[1] > proscenium[3] );
+}
+
+void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSearch) {
+ // Cull view edges by marking them as non-displayable.
+ // This avoids the complications of trying to delete
+ // edges from the ViewMap.
+
+ // Non-displayable view edges will be skipped over during
+ // visibility calculation.
+
+ // View edges will be culled according to their position
+ // w.r.t. the viewport proscenium (viewport + 5% border,
+ // or some such).
+
+ // Get proscenium boundary for culling
+ real viewProscenium[4];
+ GridHelpers::getDefaultViewProscenium(viewProscenium);
+ real prosceniumOrigin[2];
+ prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0;
+ prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0;
+ cout << "Proscenium culling:" << endl;
+ cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] << ", " << viewProscenium[3] << "]"<< endl;
+ cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]"<< endl;
+
+ // A separate occluder proscenium will also be maintained,
+ // starting out the same as the viewport proscenium, and
+ // expanding as necessary so that it encompasses the center
+ // point of at least one feature edge in each retained view
+ // edge.
+ // The occluder proscenium will be used later to cull occluding
+ // triangles before they are inserted into the Grid.
+ // The occluder proscenium starts out the same size as the view
+ // proscenium
+ GridHelpers::getDefaultViewProscenium(occluderProscenium);
+
+ // N.B. Freestyle is inconsistent in its use of ViewMap::viewedges_container
+ // and vector<ViewEdge*>::iterator. Probably all occurences of vector<ViewEdge*>::iterator
+ // should be replaced ViewMap::viewedges_container throughout the code.
+ // For each view edge
+ ViewMap::viewedges_container::iterator ve, veend;
+
+ for(ve=viewMap.ViewEdges().begin(), veend=viewMap.ViewEdges().end(); ve!=veend; ve++) {
+ // Overview:
+ // Search for a visible feature edge
+ // If none: mark view edge as non-displayable
+ // Otherwise:
+ // Find a feature edge with center point inside occluder proscenium.
+ // If none exists, find the feature edge with center point
+ // closest to viewport origin.
+ // Expand occluder proscenium to enclose center point.
+
+ // For each feature edge, while bestOccluderTarget not found and view edge not visibile
+ bool bestOccluderTargetFound = false;
+ FEdge *bestOccluderTarget = NULL;
+ real bestOccluderDistance = 0.0;
+ FEdge *festart = (*ve)->fedgeA();
+ FEdge *fe = festart;
+ // All ViewEdges start culled
+ (*ve)->setIsInImage(false);
+
+ // For simple visibility calculation: mark a feature edge
+ // that is known to have a center point inside the occluder proscenium.
+ // Cull all other feature edges.
+ do {
+ // All FEdges start culled
+ fe->setIsInImage(false);
+
+ // Look for the visible edge that can most easily be included
+ // in the occluder proscenium.
+ if ( ! bestOccluderTargetFound ) {
+ // If center point is inside occluder proscenium,
+ if ( insideProscenium(occluderProscenium, fe->center2d()) ) {
+ // Use this feature edge for visibility deterimination
+ fe->setIsInImage(true);
+ expandGridSpaceOccluderProscenium(fe);
+ // Mark bestOccluderTarget as found
+ bestOccluderTargetFound = true;
+ bestOccluderTarget = fe;
+ } else {
+ real d = distance2D(fe->center2d(), prosceniumOrigin);
+ // If center point is closer to viewport origin than current target
+ if ( bestOccluderTarget == NULL || d < bestOccluderDistance ) {
+ // Then store as bestOccluderTarget
+ bestOccluderDistance = d;
+ bestOccluderTarget = fe;
+ }
+ }
+ }
+
+ // If feature edge crosses the view proscenium
+ if ( ! (*ve)->isInImage() && crossesProscenium(viewProscenium, fe) ) {
+ // Then the view edge will be included in the image
+ (*ve)->setIsInImage(true);
+ }
+ fe = fe->nextEdge();
+ } while ( fe != NULL && fe != festart && ! ( bestOccluderTargetFound && (*ve)->isInImage() ) );
+
+ // Either we have run out of FEdges, or we already have the one edge we need to determine visibility
+ // Cull all remaining edges.
+ while ( fe != NULL && fe != festart ) {
+ fe->setIsInImage(false);
+ fe = fe->nextEdge();
+ }
+
+ // If bestOccluderTarget was not found inside the occluder proscenium,
+ // we need to expand the occluder proscenium to include it.
+ if ( (*ve)->isInImage() && bestOccluderTarget != NULL && ! bestOccluderTargetFound ) {
+ // Expand occluder proscenium to enclose bestOccluderTarget
+ Vec3r point = bestOccluderTarget->center2d();
+ if ( point[0] < occluderProscenium[0] ) {
+ occluderProscenium[0] = point[0];
+ } else if ( point[0] > occluderProscenium[1] ) {
+ occluderProscenium[1] = point[0];
+ }
+ if ( point[1] < occluderProscenium[2] ) {
+ occluderProscenium[2] = point[1];
+ } else if ( point[1] > occluderProscenium[3] ) {
+ occluderProscenium[3] = point[1];
+ }
+ // Use bestOccluderTarget for visibility determination
+ bestOccluderTarget->setIsInImage(true);
+ }
+ }
+
+ // We are done calculating the occluder proscenium.
+ // Expand the occluder proscenium by an epsilon to avoid rounding errors.
+ const real epsilon = 1.0e-6;
+ occluderProscenium[0] -= epsilon;
+ occluderProscenium[1] += epsilon;
+ occluderProscenium[2] -= epsilon;
+ occluderProscenium[3] += epsilon;
+
+ // For "Normal" or "Fast" style visibility computation only:
+
+ // For more detailed visibility calculation, make a second pass through
+ // the view map, marking all feature edges with center points inside
+ // the final occluder proscenium. All of these feature edges can be
+ // considered during visibility calculation.
+
+ // So far we have only found one FEdge per ViewEdge. The "Normal" and
+ // "Fast" styles of visibility computation want to consider many
+ // FEdges for each ViewEdge.
+ // Here we re-scan the view map to find any usable FEdges that we
+ // skipped on the first pass, or that have become usable because the
+ // occluder proscenium has been expanded since the edge was visited
+ // on the first pass.
+ if ( extensiveFEdgeSearch ) {
+ // For each view edge,
+ for(ve=viewMap.ViewEdges().begin(), veend=viewMap.ViewEdges().end(); ve!=veend; ve++) {
+ if ( ! (*ve)->isInImage() ) {
+ continue;
+ }
+ // For each feature edge,
+ FEdge *festart = (*ve)->fedgeA();
+ FEdge *fe = festart;
+ do {
+ // If not (already) visible and center point inside occluder proscenium,
+ if ( ! fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d()) ) {
+ // Use the feature edge for visibility determination
+ fe->setIsInImage(true);
+ expandGridSpaceOccluderProscenium(fe);
+ }
+ fe = fe->nextEdge();
+ } while ( fe != NULL && fe != festart );
+ }
+ }
+
+ // Up until now, all calculations have been done in camera space.
+ // However, the occluder source's iteration and the grid that consumes the occluders
+ // both work in gridspace, so we need a version of the occluder proscenium in gridspace.
+ // Set the gridspace occlude proscenium
+}
+
+void CulledOccluderSource::expandGridSpaceOccluderProscenium(FEdge* fe) {
+ if ( gridSpaceOccluderProsceniumInitialized ) {
+ GridHelpers::expandProscenium (gridSpaceOccluderProscenium, transform(fe->center3d()));
+ } else {
+ const Vec3r& point = transform(fe->center3d());
+ gridSpaceOccluderProscenium[0] = gridSpaceOccluderProscenium[1] = point[0];
+ gridSpaceOccluderProscenium[2] = gridSpaceOccluderProscenium[3] = point[1];
+ gridSpaceOccluderProsceniumInitialized = true;
+ }
+}
+
diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.h b/source/blender/freestyle/intern/view_map/CulledOccluderSource.h
new file mode 100644
index 00000000000..3c00d5e34ad
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.h
@@ -0,0 +1,63 @@
+//
+// Filename : CulledOccluderSource.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2010-12-21
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef CULLEDOCCLUDERSOURCE_H
+#define CULLEDOCCLUDERSOURCE_H
+
+#include "OccluderSource.h"
+#include "ViewMap.h"
+
+class CulledOccluderSource : public OccluderSource {
+ // Disallow copying and assignment
+ CulledOccluderSource (const CulledOccluderSource& other);
+ CulledOccluderSource& operator= (const CulledOccluderSource& other);
+
+public:
+ CulledOccluderSource (const GridHelpers::Transform& transform, WingedEdge& we, ViewMap& viewMap, bool extensiveFEdgeSearch = true);
+ virtual ~CulledOccluderSource();
+
+ void cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSearch);
+
+ bool next();
+
+ void getOccluderProscenium(real proscenium[4]);
+
+private:
+ bool testCurrent();
+ void expandGridSpaceOccluderProscenium(FEdge* fe);
+
+ real occluderProscenium[4];
+ real gridSpaceOccluderProscenium[4];
+
+ unsigned long rejected;
+ bool gridSpaceOccluderProsceniumInitialized;
+};
+
+#endif // CULLEDOCCLUDERSOURCE_H
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
new file mode 100755
index 00000000000..1d52f37236e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
@@ -0,0 +1,767 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "FEdgeXDetector.h"
+#include "float.h"
+#include "../geometry/GeomUtils.h"
+#include <math.h>
+#include "../geometry/normal_cycle.h"
+
+void FEdgeXDetector::processShapes(WingedEdge& we) {
+ bool progressBarDisplay = false;
+ Vec3r Min, Max;
+ vector<WShape*> wshapes = we.getWShapes();
+ WXShape * wxs;
+
+ if(_pProgressBar != NULL) {
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Detecting feature lines");
+ _pProgressBar->setTotalSteps(wshapes.size() * 3);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ for(vector<WShape*>::const_iterator it = wshapes.begin();
+ it != wshapes.end();
+ it++){
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+ wxs = dynamic_cast<WXShape*>(*it);
+ wxs->bbox(Min, Max);
+ _bbox_diagonal = (Max-Min).norm();
+ if(_changes){
+ vector<WFace*>& wfaces = wxs->GetFaceList();
+ for(vector<WFace*>::iterator wf=wfaces.begin(), wfend=wfaces.end();
+ wf!=wfend;
+ ++wf){
+ WXFace* wxf = dynamic_cast<WXFace*>(*wf);
+ wxf->Clear();
+ }
+ _computeViewIndependant = true;
+ } else if (!(wxs)->getComputeViewIndependantFlag()) {
+ wxs->Reset();
+ _computeViewIndependant = false;
+ } else {
+ _computeViewIndependant = true;
+ }
+ preProcessShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ processBorderShape(wxs);
+ if(_computeMaterialBoundaries)
+ processMaterialBoundaryShape(wxs);
+ processCreaseShape(wxs);
+ if(_computeRidgesAndValleys)
+ processRidgesAndValleysShape(wxs);
+ if(_computeSuggestiveContours)
+ processSuggestiveContourShape(wxs);
+ processSilhouetteShape(wxs);
+ processEdgeMarksShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+
+ // build smooth edges:
+ buildSmoothEdges(wxs);
+
+ // Post processing for suggestive contours
+ if(_computeSuggestiveContours)
+ postProcessSuggestiveContourShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+
+ wxs->setComputeViewIndependantFlag(false);
+ _computeViewIndependant = false;
+ _changes = false;
+
+ // reset user data
+ (*it)->ResetUserData();
+ }
+}
+
+// GENERAL STUFF
+////////////////
+void FEdgeXDetector::preProcessShape(WXShape* iWShape) {
+ _meanK1 = 0;
+ _meanKr = 0;
+ _minK1 = FLT_MAX;
+ _maxK1 = -FLT_MAX;
+ _minKr = FLT_MAX;
+ _maxKr = -FLT_MAX;
+ _nPoints = 0;
+ _meanEdgeSize = iWShape->getMeanEdgeSize();
+
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f,fend;
+ // view dependant stuff
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f){
+ preProcessFace((WXFace*)(*f));
+ }
+
+ if(_computeRidgesAndValleys || _computeSuggestiveContours ) {
+ vector<WVertex*>& wvertices = iWShape->getVertexList();
+ for(vector<WVertex*>::iterator wv=wvertices.begin(), wvend=wvertices.end();
+ wv!=wvend;
+ ++wv){
+ // Compute curvatures
+ WXVertex * wxv = dynamic_cast<WXVertex*>(*wv);
+ computeCurvatures(wxv);
+ }
+ _meanK1 /= (real)(_nPoints);
+ _meanKr /= (real)(_nPoints);
+ }
+}
+
+void FEdgeXDetector::preProcessFace(WXFace *iFace){
+ Vec3r firstPoint = iFace->GetVertex(0)->GetVertex();
+ Vec3r N = iFace->GetNormal();
+
+ // Compute the dot product between V (=_Viewpoint - firstPoint) and N:
+ Vec3r V;
+ if (_orthographicProjection) {
+ V = Vec3r(0.0, 0.0, _Viewpoint.z() - firstPoint.z());
+ } else {
+ V = Vec3r(_Viewpoint - firstPoint);
+ }
+ N.normalize();
+ V.normalize();
+ iFace->setDotP(N * V);
+
+ // compute the distance between the face center and the viewpoint:
+ if (_orthographicProjection) {
+ iFace->setZ(iFace->center().z() - _Viewpoint.z());
+ } else {
+ Vec3r dist_vec(iFace->center() - _Viewpoint);
+ iFace->setZ(dist_vec.norm());
+ }
+}
+
+void FEdgeXDetector::computeCurvatures(WXVertex *vertex){
+ // CURVATURE LAYER
+ // store all the curvature datas for each vertex
+
+ //soc unused - real K1, K2
+ real cos2theta, sin2theta;
+ Vec3r e1, n, v;
+ // one vertex curvature info :
+ CurvatureInfo *C;
+ float radius = _sphereRadius*_meanEdgeSize;
+
+ // view independant stuff
+ if(_computeViewIndependant){
+ C = new CurvatureInfo();
+ vertex->setCurvatures(C);
+ OGF::NormalCycle ncycle ;
+ ncycle.begin() ;
+ if(radius > 0) {
+ OGF::compute_curvature_tensor(vertex, radius, ncycle) ;
+ } else {
+ OGF::compute_curvature_tensor_one_ring(vertex, ncycle) ;
+ }
+ ncycle.end() ;
+ C->K1 = ncycle.kmin();
+ C->K2 = ncycle.kmax();
+ C->e1 = ncycle.Kmax(); //ncycle.kmin() * ncycle.Kmax();
+ C->e2 = ncycle.Kmin(); //ncycle.kmax() * ncycle.Kmin() ;
+
+ real absK1 = fabs(C->K1);
+ _meanK1 += absK1;
+ if(absK1 > _maxK1)
+ _maxK1 = absK1;
+ if(absK1 < _minK1)
+ _minK1 = absK1;
+ }
+ // view dependant
+ C = vertex->curvatures();
+ if(C == 0)
+ return;
+
+ // compute radial curvature :
+ n = C->e1 ^ C->e2;
+ if (_orthographicProjection) {
+ v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z());
+ } else {
+ v = Vec3r(_Viewpoint - vertex->GetVertex());
+ }
+ C->er = v - (v * n) * n;
+ C->er.normalize();
+ e1 = C->e1;
+ e1.normalize();
+ cos2theta = C->er * e1;
+ cos2theta *= cos2theta;
+ sin2theta = 1 - cos2theta;
+ C->Kr = C->K1 * cos2theta + C->K2 * sin2theta;
+ real absKr = fabs(C->Kr);
+ _meanKr += absKr;
+ if(absKr > _maxKr)
+ _maxKr = absKr;
+ if(absKr < _minKr)
+ _minKr = absKr;
+
+ ++_nPoints;
+}
+
+// SILHOUETTE
+/////////////
+void FEdgeXDetector::processSilhouetteShape(WXShape* iWShape) {
+ // Make a first pass on every polygons in order
+ // to compute all their silhouette relative values:
+ //------------------------------------------------
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f,fend;
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ ProcessSilhouetteFace((WXFace*)(*f));
+ }
+
+ // Make a pass on the edges to detect
+ // the silhouette edges that are not smooth
+ // --------------------
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->getEdgeList();
+ for(we=wedges.begin(), weend=wedges.end();
+ we!=weend;
+ ++we)
+ {
+ ProcessSilhouetteEdge((WXEdge*)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace)
+{
+
+ // SILHOUETTE LAYER
+ Vec3r normal;
+ // Compute the dot products between View direction and N at each vertex
+ // of the face:
+ Vec3r point;
+ int closestPointId = 0;
+ real dist, minDist = FLT_MAX;
+ int numVertices = iFace->numberOfVertices();
+ WXFaceLayer * faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true);
+ for(int i=0; i<numVertices; i++){
+ point = iFace->GetVertex(i)->GetVertex();
+ normal = iFace->GetVertexNormal(i);
+ normal.normalize();
+ Vec3r V;
+ if (_orthographicProjection) {
+ V = Vec3r(0.0, 0.0, _Viewpoint.z() - point.z());
+ } else {
+ V = Vec3r(_Viewpoint - point);
+ }
+ V.normalize();
+ real d = normal * V;
+ faceLayer->PushDotP(d);
+ // Find the point the closest to the viewpoint
+ if (_orthographicProjection) {
+ dist = point.z() - _Viewpoint.z();
+ } else {
+ Vec3r dist_vec(point - _Viewpoint);
+ dist = dist_vec.norm();
+ }
+ if(dist < minDist) {
+ minDist = dist;
+ closestPointId = i;
+ }
+ }
+ // Set the closest point id:
+ faceLayer->setClosestPointIndex(closestPointId);
+ // Add this layer to the face:
+ iFace->AddSmoothLayer(faceLayer);
+}
+
+void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge)
+{
+ if(iEdge->nature() & Nature::BORDER)
+ return;
+ // SILHOUETTE ?
+ //-------------
+ WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
+ WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
+
+ if((fA->front())^(fB->front())){ // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
+ // The only edges we want to set as silhouette edges in this
+ // way are the ones with 2 different normals for 1 vertex
+ // for these two faces
+ //--------------------
+ // In reality we only test the normals for 1 of the 2 vertices.
+ if(fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex()))
+ return;
+ iEdge->AddNature(Nature::SILHOUETTE);
+ if(fB->front())
+ iEdge->setOrder(1);
+ else
+ iEdge->setOrder(-1);
+ }
+}
+
+
+// BORDER
+/////////
+void FEdgeXDetector::processBorderShape(WXShape* iWShape) {
+
+ if(!_computeViewIndependant)
+ return;
+ // Make a pass on the edges to detect
+ // the BORDER
+ // --------------------
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->getEdgeList();
+ for(we=wedges.begin(), weend=wedges.end();
+ we!=weend;
+ ++we){
+ ProcessBorderEdge((WXEdge*)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessBorderEdge(WXEdge *iEdge)
+{
+ // first check whether it is a border edge:
+ // BORDER ?
+ //---------
+ if(iEdge->GetaFace() == 0){
+ // it is a border edge
+ iEdge->AddNature(Nature::BORDER);
+ }
+}
+
+
+// CREASE
+/////////
+void FEdgeXDetector::processCreaseShape(WXShape* iWShape) {
+ if(!_computeViewIndependant)
+ return;
+
+ // Make a pass on the edges to detect
+ // the CREASE
+ // --------------------
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->getEdgeList();
+ for(we=wedges.begin(), weend=wedges.end();
+ we!=weend;
+ ++we){
+ ProcessCreaseEdge((WXEdge*)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessCreaseEdge(WXEdge *iEdge)
+{
+ // CREASE ?
+ //---------
+ if(iEdge->nature() & Nature::BORDER)
+ return;
+ WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
+ WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
+
+ WVertex * aVertex = iEdge->GetaVertex();
+ if((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= _creaseAngle)
+ iEdge->AddNature(Nature::CREASE);
+}
+
+// RIDGES AND VALLEYS
+/////////////////////
+
+void FEdgeXDetector::processRidgesAndValleysShape(WXShape* iWShape) {
+ // Don't forget to add the built layer to the face at the end
+ // of the ProcessFace:
+ //iFace->AddSmoothLayer(faceLayer);
+
+ if((!_computeViewIndependant))
+ return;
+
+ // Here the curvatures must already have been computed
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ ProcessRidgeFace((WXFace*)(*f));
+ }
+}
+
+
+// RIDGES
+/////////
+
+void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
+{
+ WXFaceLayer * flayer = new WXFaceLayer(iFace, Nature::RIDGE|Nature::VALLEY, false);
+ iFace->AddSmoothLayer(flayer);
+
+ unsigned int numVertices = iFace->numberOfVertices();
+ for(unsigned int i=0; i<numVertices; ++i){
+ WVertex *wv = iFace->GetVertex(i);
+ WXVertex * wxv = dynamic_cast<WXVertex*>(wv);
+ flayer->PushDotP(wxv->curvatures()->K1);
+ }
+
+ real threshold = 0;
+ //real threshold = _maxK1 - (_maxK1-_meanK1)/20.0;
+
+ if(flayer->nPosDotP()!=numVertices){
+ if((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) && (fabs(flayer->dotP(2)) < threshold)){
+ flayer->ReplaceDotP(0, 0);
+ flayer->ReplaceDotP(1, 0);
+ flayer->ReplaceDotP(2, 0);
+ }
+ }
+}
+
+// void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
+// {
+
+// // RIDGE LAYER
+// // compute the RidgeFunction, that is the derivative of the ppal curvature
+// // along e1 at each vertex of the face
+
+// WVertex *v;
+// Vec3r v1v2;
+// real t;
+// vector<WXFaceLayer*> SmoothLayers;
+// WXFaceLayer *faceLayer;
+// Face_Curvature_Info *layer_info;
+// real K1_a(0), K1_b(0);
+// Vec3r Inter_a, Inter_b;
+
+// // find the ridge layer of the face
+// iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers);
+// if(SmoothLayers.size()!=1)
+// return;
+// faceLayer = SmoothLayers[0];
+// // retrieve the curvature info of this layer
+// layer_info = (Face_Curvature_Info *)faceLayer->userdata;
+
+// int numVertices = iFace->numberOfVertices();
+// for(int i=0; i<numVertices; i++){
+// v = iFace->GetVertex(i);
+// // vec_curvature_info[i] contains the curvature info of this vertex
+// Vec3r e2 = layer_info->vec_curvature_info[i]->K2*layer_info->vec_curvature_info[i]->e2;
+// Vec3r e1 = layer_info->vec_curvature_info[i]->K1*layer_info->vec_curvature_info[i]->e1;
+// e2.normalize();
+
+// WVertex::face_iterator fit = v->faces_begin();
+// WVertex::face_iterator fitend = v->faces_end();
+// for(; fit!=fitend; ++fit){
+// WXFace * wxf = dynamic_cast<WXFace*>(*fit);
+// WOEdge * oppositeEdge;
+// if(!(wxf->getOppositeEdge(v, oppositeEdge)))
+// continue;
+// v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex();
+// GeomUtils::intersection_test res;
+// res = GeomUtils::intersectRayPlane(oppositeEdge->GetaVertex()->GetVertex(), v1v2,
+// e2, -(v->GetVertex()*e2),
+// t,1.e-06);
+// if((res == GeomUtils::DO_INTERSECT) && (t>=0.0) && (t<=1.0)){
+// vector<WXFaceLayer*> second_ridge_layer;
+// wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer);
+// if(second_ridge_layer.size()!=1)
+// continue;
+// Face_Curvature_Info *second_layer_info = (Face_Curvature_Info*)second_ridge_layer[0]->userdata;
+
+// unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex());
+// unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex());
+// real K1_1 = second_layer_info->vec_curvature_info[index1]->K1;
+// real K1_2 = second_layer_info->vec_curvature_info[index2]->K1;
+// real K1 = (1.0-t)*K1_1 + t*K1_2;
+// Vec3r inter((1.0-t)*oppositeEdge->GetaVertex()->GetVertex() + t*oppositeEdge->GetbVertex()->GetVertex());
+// Vec3r vtmp(inter - v->GetVertex());
+// // is it K1_a or K1_b ?
+// if(vtmp*e1 > 0){
+// K1_b = K1;
+// Inter_b = inter;
+// }else{
+// K1_a = K1;
+// Inter_a = inter;
+// }
+// }
+// }
+// // Once we have K1 along the the ppal direction
+// // compute the derivative : K1b - K1a
+// // put it in DotP
+// //real d = fabs(K1_b)-fabs(K1_a);
+// real d = 0;
+// real threshold = _meanK1 + (_maxK1-_meanK1)/7.0;
+// //real threshold = _meanK1;
+// //if((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold)))
+// d = (K1_b)-(K1_a)/(Inter_b-Inter_a).norm();
+// faceLayer->PushDotP(d);
+// //faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1);
+// }
+
+// // Make the values relevant by checking whether all principal
+// // directions have the "same" direction:
+// Vec3r e0((layer_info->vec_curvature_info[0]->K1*layer_info->vec_curvature_info[0]->e1));
+// e0.normalize();
+// Vec3r e1((layer_info->vec_curvature_info[1]->K1*layer_info->vec_curvature_info[1]->e1));
+// e1.normalize();
+// Vec3r e2((layer_info->vec_curvature_info[2]->K1*layer_info->vec_curvature_info[2]->e1));
+// e2.normalize();
+// if (e0 * e1 < 0)
+// // invert dotP[1]
+// faceLayer->ReplaceDotP(1, -faceLayer->dotP(1));
+// if (e0 * e2 < 0)
+// // invert dotP[2]
+// faceLayer->ReplaceDotP(2, -faceLayer->dotP(2));
+
+// // remove the weakest values;
+// //real minDiff = (_maxK1 - _minK1)/10.0;
+// // real minDiff = _meanK1;
+// // if((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)){
+// // faceLayer->ReplaceDotP(0, 0);
+// // faceLayer->ReplaceDotP(1, 0);
+// // faceLayer->ReplaceDotP(2, 0);
+// // }
+// }
+
+// SUGGESTIVE CONTOURS
+//////////////////////
+
+void FEdgeXDetector::processSuggestiveContourShape(WXShape* iWShape) {
+
+ // Here the curvatures must already have been computed
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ ProcessSuggestiveContourFace((WXFace*)(*f));
+ }
+}
+
+void FEdgeXDetector::ProcessSuggestiveContourFace(WXFace *iFace)
+{
+ WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true);
+ iFace->AddSmoothLayer(faceLayer);
+
+ unsigned int numVertices = iFace->numberOfVertices();
+ for(unsigned int i=0; i<numVertices; ++i){
+ WVertex *wv = iFace->GetVertex(i);
+ WXVertex * wxv = dynamic_cast<WXVertex*>(wv);
+ faceLayer->PushDotP(wxv->curvatures()->Kr);
+ }
+
+ // FIXME: find a more clever way to compute the threshold
+// real threshold = _meanKr;
+// if(faceLayer->nPosDotP()!=numVertices){
+// if((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) && (fabs(faceLayer->dotP(2)) < threshold)){
+// faceLayer->ReplaceDotP(0, 0);
+// faceLayer->ReplaceDotP(1, 0);
+// faceLayer->ReplaceDotP(2, 0);
+// }
+// }
+}
+
+void FEdgeXDetector::postProcessSuggestiveContourShape(WXShape* iShape) {
+ vector<WFace*>& wfaces = iShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ postProcessSuggestiveContourFace((WXFace*)(*f));
+ }
+}
+
+void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace) {
+
+ // Compute the derivative of the radial curvature in the radial direction,
+ // at the two extremities of the smooth edge.
+ // If the derivative is smaller than a given threshold _kr_derivative_epsilon,
+ // discard the edge.
+
+ // Find the suggestive contour layer of the face (zero or one edge).
+ vector<WXFaceLayer*> sc_layers;
+ iFace->retrieveSmoothEdgesLayers(Nature::SUGGESTIVE_CONTOUR, sc_layers);
+ if(sc_layers.empty())
+ return;
+
+ WXFaceLayer *sc_layer;
+ sc_layer = sc_layers[0];
+
+ // Compute the derivative value at each vertex of the face, and add it in a vector.
+ vector<real> kr_derivatives;
+
+ unsigned vertices_nb = iFace->numberOfVertices();
+ WXVertex *v, *opposite_vertex_a, *opposite_vertex_b;
+ WXFace *wxf;
+ WOEdge *opposite_edge;
+ Vec3r normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec;
+ GeomUtils::intersection_test res;
+ real kr(0), kr1(0), kr2(0), t;
+
+ for (unsigned i = 0; i < vertices_nb; ++i) {
+ v = (WXVertex*)(iFace->GetVertex(i));
+
+ // v is a singular vertex, skip it.
+ if (v->isBoundary()) {
+ kr_derivatives.push_back(0);
+ continue;
+ }
+
+ v_vec = v->GetVertex();
+ er_vec = v->curvatures()->er;
+
+ // For each vertex, iterate on its adjacent faces.
+ for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end();
+ fit != fitend;
+ ++fit) {
+ wxf = dynamic_cast<WXFace*>(*fit);
+ if(!(wxf->getOppositeEdge(v, opposite_edge)))
+ continue;
+
+ opposite_vertex_a = (WXVertex*)opposite_edge->GetaVertex();
+ opposite_vertex_b = (WXVertex*)opposite_edge->GetbVertex();
+ normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ?
+ radial_normal_vec = er_vec ^ normal_vec;
+
+ // Test wether the radial plan intersects with the edge at the opposite of v.
+ res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(), opposite_edge->GetVec(),
+ radial_normal_vec, -(v_vec * radial_normal_vec),
+ t,
+ 1.e-06);
+
+ // If there is an intersection, compute the value of the derivative ath that point.
+ if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) {
+ kr = t * opposite_vertex_a->curvatures()->Kr + (1 - t) * opposite_vertex_b->curvatures()->Kr;
+ inter = opposite_vertex_a->GetVertex() + t * opposite_edge->GetVec();
+ tmp_vec = inter - v->GetVertex();
+ // Is it kr1 or kr2?
+ if (tmp_vec * er_vec > 0) {
+ kr2 = kr;
+ inter2 = inter;
+ } else {
+ kr1 = kr;
+ inter1 = inter;
+ }
+ }
+ }
+
+ // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace.
+ // We have to compute the derivative of kr for that vertex, equal to:
+ // (kr2 - kr1) / dist(inter1, inter2).
+ // Then we add it to the vector of derivatives.
+ v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm();
+ kr_derivatives.push_back(v->curvatures()->dKr);
+ }
+
+ // At that point, we have the derivatives for each vertex of iFace.
+ // All we have to do now is to use linear interpolation to compute the values at
+ // the extremities of the smooth edge.
+ WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge();
+ WOEdge *sc_oedge = sc_edge->woea();
+ t = sc_edge->ta();
+ if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
+ (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon) {
+ sc_layer->removeSmoothEdge();
+ return;
+ }
+ sc_oedge = sc_edge->woeb();
+ t = sc_edge->tb();
+ if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
+ (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon)
+ sc_layer->removeSmoothEdge();
+}
+
+// MATERIAL_BOUNDARY
+////////////////////
+void FEdgeXDetector::processMaterialBoundaryShape(WXShape* iWShape) {
+
+ if(!_computeViewIndependant)
+ return;
+ // Make a pass on the edges to detect material boundaries
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->getEdgeList();
+ for(we=wedges.begin(), weend=wedges.end();
+ we!=weend;
+ ++we){
+ ProcessMaterialBoundaryEdge((WXEdge*)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessMaterialBoundaryEdge(WXEdge *iEdge)
+{
+ // check whether the edge is a material boundary?
+ WFace *aFace = iEdge->GetaFace();
+ WFace *bFace = iEdge->GetbFace();
+ if(aFace && bFace && aFace->frs_materialIndex() != bFace->frs_materialIndex()){
+ iEdge->AddNature(Nature::MATERIAL_BOUNDARY);
+ }
+}
+
+// EDGE MARKS
+/////////////
+
+void FEdgeXDetector::processEdgeMarksShape(WXShape* iShape) {
+ // Make a pass on the edges to detect material boundaries
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iShape->getEdgeList();
+ for(we=wedges.begin(), weend=wedges.end();
+ we!=weend;
+ ++we){
+ ProcessEdgeMarks((WXEdge*)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessEdgeMarks(WXEdge *iEdge) {
+ if (iEdge->GetMark()) {
+ iEdge->AddNature(Nature::EDGE_MARK);
+ }
+}
+
+// Build Smooth edges
+/////////////////////
+void FEdgeXDetector::buildSmoothEdges(WXShape* iShape){
+ bool hasSmoothEdges = false;
+
+ // Make a last pass to build smooth edges from the previous stored values:
+ //--------------------------------------------------------------------------
+ vector<WFace*>& wfaces = iShape->GetFaceList();
+ for(vector<WFace*>::iterator f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ vector<WXFaceLayer*>& faceLayers = ((WXFace*)(*f))->getSmoothLayers();
+ for(vector<WXFaceLayer*>::iterator wxfl = faceLayers.begin(), wxflend=faceLayers.end();
+ wxfl!=wxflend;
+ ++wxfl){
+ if ((*wxfl)->BuildSmoothEdge())
+ hasSmoothEdges = true;
+ }
+ }
+
+ if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) {
+ vector<WVertex*>& wvertices = iShape->getVertexList();
+ for(vector<WVertex*>::iterator wv=wvertices.begin(), wvend=wvertices.end();
+ wv!=wvend;
+ ++wv){
+ // Compute curvatures
+ WXVertex * wxv = dynamic_cast<WXVertex*>(*wv);
+ computeCurvatures(wxv);
+ }
+ _meanK1 /= (real)(_nPoints);
+ _meanKr /= (real)(_nPoints);
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
new file mode 100755
index 00000000000..2fd6a4a1e8f
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
@@ -0,0 +1,203 @@
+//
+// Filename : FEdgeXDetector.h
+// Author(s) : Stephane Grabli
+// Purpose : Detects/flags/builds extended features edges on the
+// WXEdge structure
+// Date of creation : 26/10/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef FEDGEXDETECTOR_H
+# define FEDGEXDETECTOR_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../winged_edge/WXEdge.h"
+# include "../winged_edge/Curvature.h"
+# include "../system/ProgressBar.h"
+# include "../system/RenderMonitor.h"
+
+using namespace Geometry;
+
+/*! This class takes as input a WXEdge structure and fills it
+ */
+
+class LIB_VIEW_MAP_EXPORT FEdgeXDetector
+{
+public:
+
+ FEdgeXDetector() {
+ _pProgressBar = 0;
+ _pRenderMonitor = 0;
+ _computeViewIndependant = true;
+ _bbox_diagonal = 1.0;
+ _meanEdgeSize = 0;
+ _computeRidgesAndValleys = true;
+ _computeSuggestiveContours = true;
+ _computeMaterialBoundaries = true;
+ _sphereRadius = 1.0;
+ _orthographicProjection = false;
+ _faceSmoothness = false;
+ _changes = false;
+ _kr_derivative_epsilon = 0.0;
+ _creaseAngle = 0.7; // angle of 134.43 degrees
+ }
+ virtual ~FEdgeXDetector() {}
+
+ /*! Process shapes from a WingedEdge containing a list of WShapes */
+ virtual void processShapes(WingedEdge&);
+
+ // GENERAL STUFF
+ virtual void preProcessShape(WXShape* iShape);
+ virtual void preProcessFace(WXFace* iFace);
+ virtual void computeCurvatures(WXVertex *iVertex);
+
+ // SILHOUETTE
+ virtual void processSilhouetteShape(WXShape* iShape);
+ virtual void ProcessSilhouetteFace(WXFace *iFace);
+ virtual void ProcessSilhouetteEdge(WXEdge *iEdge);
+
+ // CREASE
+ virtual void processCreaseShape(WXShape* iShape);
+ virtual void ProcessCreaseEdge(WXEdge *iEdge);
+ /*! Sets the minimum angle for detecting crease edges
+ * \param angle
+ * The angular threshold in degrees (between 0 and 180) for detecting crease
+ * edges. An edge is considered a crease edge if the angle between two faces
+ * sharing the edge is smaller than the given threshold.
+ */
+ inline void setCreaseAngle(real angle) {
+ if (angle < 0.0)
+ angle = 0.0;
+ else if (angle > 180.0)
+ angle = 180.0;
+ angle = cos(M_PI * (180.0 - angle) / 180.0);
+ if (angle != _creaseAngle){
+ _creaseAngle = angle;
+ _changes = true;
+ }
+ }
+
+ // BORDER
+ virtual void processBorderShape(WXShape* iShape);
+ virtual void ProcessBorderEdge(WXEdge *iEdge);
+
+ // RIDGES AND VALLEYS
+ virtual void processRidgesAndValleysShape(WXShape* iShape);
+ virtual void ProcessRidgeFace(WXFace *iFace);
+
+ // SUGGESTIVE CONTOURS
+ virtual void processSuggestiveContourShape(WXShape* iShape);
+ virtual void ProcessSuggestiveContourFace(WXFace *iFace);
+ virtual void postProcessSuggestiveContourShape(WXShape* iShape);
+ virtual void postProcessSuggestiveContourFace(WXFace *iFace);
+ /*! Sets the minimal derivative of the radial curvature for suggestive contours
+ * \param dkr
+ * The minimal derivative of the radial curvature
+ */
+ inline void setSuggestiveContourKrDerivativeEpsilon(real dkr) {
+ if (dkr != _kr_derivative_epsilon){
+ _kr_derivative_epsilon = dkr;
+ _changes = true;
+ }
+ }
+
+ // MATERIAL BOUNDARY
+ virtual void processMaterialBoundaryShape(WXShape* iWShape);
+ virtual void ProcessMaterialBoundaryEdge(WXEdge *iEdge);
+
+ // EDGE MARKS
+ virtual void processEdgeMarksShape(WXShape* iShape);
+ virtual void ProcessEdgeMarks(WXEdge *iEdge);
+
+ // EVERYBODY
+ virtual void buildSmoothEdges(WXShape* iShape);
+
+ /*! Sets the current viewpoint */
+ inline void setViewpoint(const Vec3r& ivp) {_Viewpoint = ivp;}
+ inline void enableOrthographicProjection(bool b) {_orthographicProjection = b;}
+ inline void enableRidgesAndValleysFlag(bool b) {_computeRidgesAndValleys = b;}
+ inline void enableSuggestiveContours(bool b) {_computeSuggestiveContours = b;}
+ inline void enableMaterialBoundaries(bool b) {_computeMaterialBoundaries = b;}
+ inline void enableFaceSmoothness(bool b) {
+ if (b != _faceSmoothness) {
+ _faceSmoothness = b;
+ _changes=true;
+ }
+ }
+ inline void enableFaceMarks(bool b) {
+ if (b != _faceMarks) {
+ _faceMarks = b;
+ _changes=true;
+ }
+ }
+ /*! Sets the radius of the geodesic sphere around each vertex (for the curvature computation)
+ * \param r
+ * The radius of the sphere expressed as a ratio of the mean edge size
+ */
+ inline void setSphereRadius(real r) {
+ if(r!=_sphereRadius){
+ _sphereRadius = r;
+ _changes=true;
+ }
+ }
+
+ inline void setProgressBar(ProgressBar *iProgressBar) {_pProgressBar = iProgressBar;}
+
+ inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {_pRenderMonitor = iRenderMonitor;}
+
+protected:
+
+ Vec3r _Viewpoint;
+ real _bbox_diagonal; // diagonal of the current processed shape bbox
+ //oldtmp values
+ bool _computeViewIndependant;
+ real _meanK1;
+ real _meanKr;
+ real _minK1;
+ real _minKr;
+ real _maxK1;
+ real _maxKr;
+ unsigned _nPoints;
+ real _meanEdgeSize;
+ bool _orthographicProjection;
+
+ bool _computeRidgesAndValleys;
+ bool _computeSuggestiveContours;
+ bool _computeMaterialBoundaries;
+ bool _faceSmoothness;
+ bool _faceMarks;
+ real _sphereRadius; // expressed as a ratio of the mean edge size
+ real _creaseAngle; // [-1, 1] compared with the inner product of face normals
+ bool _changes;
+
+ real _kr_derivative_epsilon;
+
+ ProgressBar *_pProgressBar;
+ RenderMonitor *_pRenderMonitor;
+};
+
+#endif // FEDGEDXETECTOR_H
diff --git a/source/blender/freestyle/intern/view_map/Functions0D.cpp b/source/blender/freestyle/intern/view_map/Functions0D.cpp
new file mode 100755
index 00000000000..a9f997e66b0
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp
@@ -0,0 +1,357 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "Functions0D.h"
+# include "ViewMap.h"
+
+using namespace std;
+
+namespace Functions0D {
+
+ // Internal function
+ FEdge* getFEdge(Interface0D& it1, Interface0D& it2){
+ return it1.getFEdge(it2);
+ }
+
+ void getFEdges(Interface0DIterator& it,
+ FEdge*& fe1,
+ FEdge*& fe2) {
+ // count number of vertices
+ Interface0DIterator prev = it, next = it;
+ ++next;
+ int count = 1;
+ if (!it.isBegin() && !next.isEnd()) {
+ count = 3;
+ }
+ if(count < 3)
+ {
+ // if we only have 2 vertices
+ FEdge * fe = 0;
+ Interface0DIterator tmp = it;
+ if(it.isBegin())
+ {
+ ++tmp;
+ fe = it->getFEdge(*tmp);
+ }
+ else
+ {
+ --tmp;
+ fe = it->getFEdge(*tmp);
+ }
+ fe1 = fe;
+ fe2 = 0;
+ }
+ else
+ {
+ // we have more than 2 vertices
+ bool begin=false,last=false;
+ Interface0DIterator previous = it;
+ if(!previous.isBegin())
+ --previous;
+ else
+ begin=true;
+ Interface0DIterator next = it;
+ ++next;
+ if(next.isEnd())
+ last = true;
+ if(begin)
+ {
+ fe1 = it->getFEdge(*next);
+ fe2 = 0;
+ }
+ else if(last)
+ {
+ fe1 = previous->getFEdge(*it);
+ fe2 = 0;
+ }
+ else
+ {
+ fe1 = previous->getFEdge(*it);
+ fe2 = it->getFEdge(*next);
+ }
+ }
+ }
+
+ void getViewEdges(Interface0DIterator &it,
+ ViewEdge *&ve1,
+ ViewEdge *&ve2)
+ {
+ FEdge * fe1, *fe2;
+ getFEdges(it, fe1, fe2);
+ ve1 = fe1->viewedge();
+ if(fe2 != 0)
+ {
+ ve2 = fe2->viewedge();
+ if(ve2 == ve1)
+ ve2 = 0;
+ }
+ else
+ ve2 = 0;
+ }
+
+ ViewShape* getShapeF0D(Interface0DIterator& it)
+ {
+ ViewEdge *ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ return ve1->viewShape();
+ }
+
+ void getOccludersF0D(Interface0DIterator& it, set<ViewShape*>& oOccluders){
+ ViewEdge * ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ occluder_container::const_iterator oit = ve1->occluders_begin();
+ occluder_container::const_iterator oitend = ve1->occluders_end();
+
+ for(;oit!=oitend; ++oit)
+ oOccluders.insert((*oit));
+
+ if(ve2!=0){
+ oit = ve2->occluders_begin();
+ oitend = ve2->occluders_end();
+ for(;oit!=oitend; ++oit)
+ oOccluders.insert((*oit));
+ }
+ }
+
+ ViewShape * getOccludeeF0D(Interface0DIterator& it){
+ ViewEdge * ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ ViewShape *aShape = ve1->aShape();
+ return aShape;
+ }
+
+ //
+ int VertexOrientation2DF0D::operator()(Interface0DIterator& iter) {
+ Vec2f A,C;
+ Vec2f B(iter->getProjectedX(), iter->getProjectedY());
+ if(iter.isBegin())
+ A = Vec2f(iter->getProjectedX(), iter->getProjectedY());
+ else
+ {
+ Interface0DIterator previous = iter;
+ --previous ;
+ A = Vec2f(previous->getProjectedX(), previous->getProjectedY());
+ }
+ Interface0DIterator next = iter;
+ ++next ;
+ if(next.isEnd())
+ C = Vec2f(iter->getProjectedX(), iter->getProjectedY());
+ else
+ C = Vec2f(next->getProjectedX(), next->getProjectedY());
+
+ Vec2f AB(B-A);
+ if(AB.norm() != 0)
+ AB.normalize();
+ Vec2f BC(C-B);
+ if(BC.norm() != 0)
+ BC.normalize();
+ result = AB + BC;
+ if(result.norm() != 0)
+ result.normalize();
+ return 0;
+ }
+
+ int VertexOrientation3DF0D::operator()(Interface0DIterator& iter) {
+ Vec3r A,C;
+ Vec3r B(iter->getX(), iter->getY(), iter->getZ());
+ if(iter.isBegin())
+ A = Vec3r(iter->getX(), iter->getY(), iter->getZ());
+ else
+ {
+ Interface0DIterator previous = iter;
+ --previous ;
+ A = Vec3r(previous->getX(), previous->getY(), previous->getZ());
+ }
+ Interface0DIterator next = iter;
+ ++next ;
+ if(next.isEnd())
+ C = Vec3r(iter->getX(), iter->getY(), iter->getZ());
+ else
+ C = Vec3r(next->getX(), next->getY(), next->getZ());
+
+ Vec3r AB(B-A);
+ if(AB.norm() != 0)
+ AB.normalize();
+ Vec3r BC(C-B);
+ if(BC.norm() != 0)
+ BC.normalize();
+ result = AB + BC;
+ if(result.norm() != 0)
+ result.normalize();
+ return 0;
+ }
+
+ int Curvature2DAngleF0D::operator()(Interface0DIterator& iter) {
+ Interface0DIterator tmp1 = iter, tmp2 = iter;
+ ++tmp2;
+ unsigned count = 1;
+ while((!tmp1.isBegin()) && (count < 3))
+ {
+ --tmp1;
+ ++count;
+ }
+ while((!tmp2.isEnd()) && (count < 3))
+ {
+ ++tmp2;
+ ++count;
+ }
+ if(count < 3) {
+ // if we only have 2 vertices
+ result = 0;
+ return 0;
+ }
+
+ Interface0DIterator v = iter;
+ if(iter.isBegin())
+ ++v;
+ Interface0DIterator next=v;
+ ++next;
+ if(next.isEnd())
+ {
+ next = v;
+ --v;
+ }
+ Interface0DIterator prev=v;
+ --prev;
+
+ Vec2r A(prev->getProjectedX(), prev->getProjectedY());
+ Vec2r B(v->getProjectedX(), v->getProjectedY());
+ Vec2r C(next->getProjectedX(), next->getProjectedY());
+ Vec2r AB(B-A);
+ Vec2r BC(C-B);
+ Vec2r N1(-AB[1], AB[0]);
+ if(N1.norm() != 0)
+ N1.normalize();
+ Vec2r N2(-BC[1], BC[0]);
+ if(N2.norm() != 0)
+ N2.normalize();
+ if((N1.norm() == 0) && (N2.norm() == 0))
+ {
+ Exception::raiseException();
+ result = 0;
+ return -1;
+ }
+ double cosin = N1*N2;
+ if(cosin > 1)
+ cosin = 1;
+ if(cosin < -1)
+ cosin = -1;
+ result = acos(cosin);
+ return 0;
+ }
+
+ int ZDiscontinuityF0D::operator()(Interface0DIterator& iter) {
+ FEdge *fe1, *fe2;
+ getFEdges(iter, fe1, fe2);
+ result = fe1->z_discontinuity();
+ if(fe2!=0){
+ result += fe2->z_discontinuity();
+ result /= 2.f;
+ }
+ return 0;
+ }
+
+ int Normal2DF0D::operator()(Interface0DIterator& iter) {
+ FEdge *fe1, *fe2;
+ getFEdges(iter,fe1,fe2);
+ Vec3f e1(fe1->orientation2d());
+ Vec2f n1(e1[1], -e1[0]);
+ Vec2f n(n1);
+ if(fe2 != 0)
+ {
+ Vec3f e2(fe2->orientation2d());
+ Vec2f n2(e2[1], -e2[0]);
+ n += n2;
+ }
+ n.normalize();
+ result = n;
+ return 0;
+ }
+
+ int MaterialF0D::operator()(Interface0DIterator& iter) {
+ FEdge *fe1, *fe2;
+ getFEdges(iter,fe1,fe2);
+ if(fe1 == 0)
+ return -1;
+ if(fe1->isSmooth())
+ result = ((FEdgeSmooth*)fe1)->frs_material();
+ else
+ result = ((FEdgeSharp*)fe1)->bFrsMaterial();
+ // const SShape * sshape = getShapeF0D(iter);
+ // return sshape->material();
+ return 0;
+ }
+
+ int ShapeIdF0D::operator()(Interface0DIterator& iter) {
+ ViewShape * vshape = getShapeF0D(iter);
+ result = vshape->getId();
+ return 0;
+ }
+
+ int QuantitativeInvisibilityF0D::operator()(Interface0DIterator& iter) {
+ ViewEdge * ve1, *ve2;
+ getViewEdges(iter,ve1,ve2);
+ unsigned int qi1, qi2;
+ qi1 = ve1->qi();
+ if(ve2 != 0){
+ qi2 = ve2->qi();
+ if(qi2!=qi1)
+ cout << "QuantitativeInvisibilityF0D: ambiguous evaluation for point " << iter->getId() << endl;
+ }
+ result = qi1;
+ return 0;
+ }
+
+ int CurveNatureF0D::operator()(Interface0DIterator& iter) {
+ Nature::EdgeNature nat = 0;
+ ViewEdge * ve1, *ve2;
+ getViewEdges(iter, ve1, ve2);
+ nat |= ve1->getNature();
+ if(ve2!=0)
+ nat |= ve2->getNature();
+ result = nat;
+ return 0;
+ }
+
+ int GetOccludersF0D::operator()(Interface0DIterator& iter) {
+ set<ViewShape*> occluders;
+ getOccludersF0D(iter,occluders);
+ result.clear();
+ // vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end());
+ for(set<ViewShape*>::iterator it=occluders.begin(), itend=occluders.end();
+ it!=itend;
+ ++it){
+ result.push_back((*it));
+ }
+ return 0;
+ }
+
+ int GetShapeF0D::operator()(Interface0DIterator& iter) {
+ result = getShapeF0D(iter);
+ return 0;
+ }
+
+ int GetOccludeeF0D::operator()(Interface0DIterator& iter) {
+ result = getOccludeeF0D(iter);
+ return 0;
+ }
+
+} // end of namespace Functions0D
diff --git a/source/blender/freestyle/intern/view_map/Functions0D.h b/source/blender/freestyle/intern/view_map/Functions0D.h
new file mode 100755
index 00000000000..4adbc8a1bf5
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions0D.h
@@ -0,0 +1,500 @@
+//
+// Filename : Functions0D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Functions taking 0D input
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef FUNCTIONS0D_H
+# define FUNCTIONS0D_H
+
+# include "../system/Precision.h"
+# include "Interface0D.h"
+# include "../geometry/Geom.h"
+# include "../system/Exception.h"
+# include "../scene_graph/FrsMaterial.h"
+# include <set>
+# include <vector>
+class FEdge;
+class ViewEdge;
+class SShape;
+
+using namespace Geometry;
+
+#include "../python/Director.h"
+
+//
+// UnaryFunction0D (base class for functions in 0D)
+//
+///////////////////////////////////////////////////////////
+
+template <class T>
+/*! Base class for Unary Functions (functors) working
+ * on Interface0DIterator.
+ * A unary function will be used by calling
+ * its operator() on an Interface0DIterator.
+ * \attention In the scripting language, there exists
+ * several prototypes depending on the returned value type.
+ * For example, you would inherit from a UnaryFunction0DDouble
+ * if you wish to define a function that returns a double.
+ * The different existing prototypes are:
+ * - UnaryFunction0DVoid
+ * - UnaryFunction0DUnsigned
+ * - UnaryFunction0DReal
+ * - UnaryFunction0DFloat
+ * - UnaryFunction0DDouble
+ * - UnaryFunction0DVec2f
+ * - UnaryFunction0DVec3f
+ */
+class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction0D
+{
+public:
+
+ T result;
+ PyObject *py_uf0D;
+
+ /*! The type of the value
+ * returned by the functor.
+ */
+ typedef T ReturnedValueType;
+ /*! Default constructor. */
+UnaryFunction0D() { py_uf0D = 0;}
+ /*! Destructor; */
+ virtual ~UnaryFunction0D() {}
+ /*! Returns the string "UnaryFunction0D" */
+ virtual string getName() const {
+ return "UnaryFunction0D";
+ }
+ /*! The operator ().
+ * \param iter
+ * An Interface0DIterator pointing onto
+ * the point at which we wish to evaluate
+ * the function.
+ * \return the result of the function of type T.
+ */
+ virtual int operator()(Interface0DIterator& iter) {
+ return Director_BPy_UnaryFunction0D___call__( this, py_uf0D, iter );
+ }
+
+};
+
+# ifdef SWIG
+%feature("director") UnaryFunction0D<void>;
+%feature("director") UnaryFunction0D<unsigned>;
+%feature("director") UnaryFunction0D<float>;
+%feature("director") UnaryFunction0D<double>;
+%feature("director") UnaryFunction0D<Vec2f>;
+%feature("director") UnaryFunction0D<Vec3f>;
+%feature("director") UnaryFunction0D<Id>;
+
+%template(UnaryFunction0DVoid) UnaryFunction0D<void>;
+%template(UnaryFunction0DUnsigned) UnaryFunction0D<unsigned>;
+%template(UnaryFunction0DFloat) UnaryFunction0D<float>;
+%template(UnaryFunction0DDouble) UnaryFunction0D<double>;
+%template(UnaryFunction0DVec2f) UnaryFunction0D<Vec2f>;
+%template(UnaryFunction0DVec3f) UnaryFunction0D<Vec3f>;
+%template(UnaryFunction0DId) UnaryFunction0D<Id>;
+%template(UnaryFunction0DViewShape) UnaryFunction0D<ViewShape*>;
+%template(UnaryFunction0DVectorViewShape) UnaryFunction0D<std::vector<ViewShape*> >;
+# endif // SWIG
+
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+class ViewShape;
+namespace Functions0D {
+
+ // GetXF0D
+ /*! Returns the X 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetXF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetXF0D"*/
+ string getName() const {
+ return "GetXF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getX();
+ return 0;
+ }
+ };
+
+ // GetYF0D
+ /*! Returns the Y 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetYF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetYF0D"*/
+ string getName() const {
+ return "GetYF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getY();
+ return 0;
+ }
+ };
+
+ // GetZF0D
+ /*! Returns the Z 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetZF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetZF0D"*/
+ string getName() const {
+ return "GetZF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getZ();
+ return 0;
+ }
+ };
+
+ // GetProjectedXF0D
+ /*! Returns the X 3D projected coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedXF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetProjectedXF0D"*/
+ string getName() const {
+ return "GetProjectedXF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getProjectedX();
+ return 0;
+ }
+ };
+
+ // GetProjectedYF0D
+ /*! Returns the Y projected 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedYF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetProjectedYF0D"*/
+ string getName() const {
+ return "GetProjectedYF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getProjectedY();
+ return 0;
+ }
+ };
+
+ // GetProjectedZF0D
+ /*! Returns the Z projected 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedZF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetProjectedZF0D"*/
+ string getName() const {
+ return "GetProjectedZF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getProjectedZ();
+ return 0;
+ }
+ };
+
+ // GetCurvilinearAbscissaF0D
+ /*! Returns the curvilinear abscissa of an Interface0D in the context of its 1D element. */
+ class LIB_VIEW_MAP_EXPORT GetCurvilinearAbscissaF0D : public UnaryFunction0D<float>
+ {
+ public:
+ /*! Returns the string "GetCurvilinearAbscissaF0D"*/
+ string getName() const {
+ return "GetCurvilinearAbscissaF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter.t();
+ return 0;
+ }
+ };
+
+ // GetParameterF0D
+ /*! Returns the parameter of an Interface0D in the context of its 1D element. */
+ class LIB_VIEW_MAP_EXPORT GetParameterF0D : public UnaryFunction0D<float>
+ {
+ public:
+ /*! Returns the string "GetCurvilinearAbscissaF0D"*/
+ string getName() const {
+ return "GetParameterF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter.u();
+ return 0;
+ }
+ };
+
+ // VertexOrientation2DF0D
+ /*! Returns a Vec2r giving the 2D oriented tangent to the 1D element
+ * to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+ class LIB_VIEW_MAP_EXPORT VertexOrientation2DF0D : public UnaryFunction0D<Vec2f>
+ {
+ public:
+ /*! Returns the string "VertexOrientation2DF0D"*/
+ string getName() const {
+ return "VertexOrientation2DF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // VertexOrientation3DF0D
+ /*! Returns a Vec3r giving the 3D oriented tangent to the 1D element
+ * to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+ class LIB_VIEW_MAP_EXPORT VertexOrientation3DF0D : public UnaryFunction0D<Vec3f>
+ {
+ public:
+ /*! Returns the string "VertexOrientation3DF0D"*/
+ string getName() const {
+ return "VertexOrientation3DF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // Curvature2DAngleF0D
+ /*! Returns a real giving the 2D curvature (as an angle) of the 1D element
+ * to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+ class LIB_VIEW_MAP_EXPORT Curvature2DAngleF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "Curvature2DAngleF0D"*/
+ string getName() const {
+ return "Curvature2DAngleF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // ZDiscontinuity
+ /*! Returns a real giving the distance between
+ * and Interface0D and the shape that lies behind (occludee).
+ * This distance is evaluated in the camera space and normalized
+ * between 0 and 1. Therefore, if no oject is occluded by the
+ * shape to which the Interface0D belongs to, 1 is returned.
+ */
+ class LIB_VIEW_MAP_EXPORT ZDiscontinuityF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "ZDiscontinuityF0D"*/
+ string getName() const {
+ return "ZDiscontinuityF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // Normal2DF0D
+ /*! Returns a Vec2f giving the normalized 2D normal to the 1D element
+ * to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+ class LIB_VIEW_MAP_EXPORT Normal2DF0D : public UnaryFunction0D<Vec2f>
+ {
+ public:
+ /*! Returns the string "Normal2DF0D"*/
+ string getName() const {
+ return "Normal2DF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // MaterialF0D
+ /*! Returns the material of the object evaluated at the Interface0D.
+ * This evaluation can be ambiguous (in the case of a TVertex for example.
+ * This functor tries to remove this ambiguity using the context
+ * offered by the 1D element to which the Interface0DIterator& belongs
+ * to and by arbitrary chosing the material of the face
+ * that lies on its left when following the 1D element if there
+ * are two different materials on each side of the point.
+ * However, there still can be problematic cases, and the user willing
+ * to deal with this cases in a specific way should implement
+ * its own getMaterial functor.
+ */
+ class LIB_VIEW_MAP_EXPORT MaterialF0D : public UnaryFunction0D<FrsMaterial>
+ {
+ public:
+ /*! Returns the string "MaterialF0D"*/
+ string getName() const {
+ return "MaterialF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // ShapeIdF0D
+ /*! Returns the Id of the Shape the Interface0D belongs to.
+ * This evaluation can be ambiguous (in the case of a TVertex for example).
+ * This functor tries to remove this ambiguity using the context
+ * offered by the 1D element to which the Interface0DIterator& belongs
+ * to.
+ * However, there still can be problematic cases, and the user willing
+ * to deal with this cases in a specific way should implement
+ * its own getShapeIdF0D functor.
+ */
+ class LIB_VIEW_MAP_EXPORT ShapeIdF0D : public UnaryFunction0D<Id>
+ {
+ public:
+ /*! Returns the string "ShapeIdF0D"*/
+ string getName() const {
+ return "ShapeIdF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // QiF0D
+ /*! Returns the quantitative invisibility of this Interface0D.
+ * This evaluation can be ambiguous (in the case of a TVertex for example).
+ * This functor tries to remove this ambiguity using the context
+ * offered by the 1D element to which the Interface0DIterator& belongs
+ * to.
+ * However, there still can be problematic cases, and the user willing
+ * to deal with this cases in a specific way should implement
+ * its own getQIF0D functor.
+ */
+ class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF0D : public UnaryFunction0D<unsigned int>
+ {
+ public:
+ /*! Returns the string "QuantitativeInvisibilityF0D"*/
+ string getName() const {
+ return "QuantitativeInvisibilityF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // CurveNatureF0D
+ /*! Returns the Nature::EdgeNature of the 1D element the
+ * Interface0DIterator& belongs to.
+ */
+ class LIB_VIEW_MAP_EXPORT CurveNatureF0D : public UnaryFunction0D<Nature::EdgeNature>
+ {
+ public:
+ /*! Returns the string "QuantitativeInvisibilityF0D"*/
+ string getName() const {
+ return "CurveNatureF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // GetShapeF0D
+ /*! Returns the ViewShape*
+ * containing the Interface0D
+ */
+ class LIB_VIEW_MAP_EXPORT GetShapeF0D : public UnaryFunction0D< ViewShape*>
+ {
+ public:
+ /*! Returns the string "GetShapeF0D"*/
+ string getName() const {
+ return "GetShapeF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // GetOccludersF0D
+ /*! Returns a vector containing the ViewShape*
+ * occluding the Interface0D
+ */
+ class LIB_VIEW_MAP_EXPORT GetOccludersF0D : public UnaryFunction0D< std::vector<ViewShape*> >
+ {
+ public:
+ /*! Returns the string "GetOccludersF0D"*/
+ string getName() const {
+ return "GetOccludersF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // GetOccludeeF0D
+ /*! Returns the ViewShape*
+ * "occluded" by the Interface0D
+ */
+ class LIB_VIEW_MAP_EXPORT GetOccludeeF0D: public UnaryFunction0D< ViewShape*>
+ {
+ public:
+ /*! Returns the string "GetOccludeeF0D"*/
+ string getName() const {
+ return "GetOccludeeF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+
+
+ /////////////////////////// Internal ////////////////////////////
+
+ // getFEdge
+ LIB_VIEW_MAP_EXPORT
+ FEdge* getFEdge(Interface0D& it1, Interface0D& it2);
+
+ // getFEdges
+ LIB_VIEW_MAP_EXPORT
+ void getFEdges(Interface0DIterator& it,
+ FEdge*& fe1,
+ FEdge*& fe2);
+
+ // getViewEdges
+ LIB_VIEW_MAP_EXPORT
+ void getViewEdges(Interface0DIterator& it,
+ ViewEdge *&ve1,
+ ViewEdge *&ve2);
+
+ // getShapeF0D
+ LIB_VIEW_MAP_EXPORT
+ ViewShape* getShapeF0D(Interface0DIterator& it);
+
+ // getOccludersF0D
+ LIB_VIEW_MAP_EXPORT
+ void getOccludersF0D(Interface0DIterator& it, std::set<ViewShape*>& oOccluders);
+
+ // getOccludeeF0D
+ LIB_VIEW_MAP_EXPORT
+ ViewShape* getOccludeeF0D(Interface0DIterator& it);
+
+} // end of namespace Functions0D
+
+#endif // FUNCTIONS0D_H
diff --git a/source/blender/freestyle/intern/view_map/Functions1D.cpp b/source/blender/freestyle/intern/view_map/Functions1D.cpp
new file mode 100755
index 00000000000..8545c660084
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions1D.cpp
@@ -0,0 +1,231 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "Functions1D.h"
+using namespace std;
+
+namespace Functions1D {
+
+ int GetXF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetYF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetZF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetProjectedXF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetProjectedYF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetProjectedZF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int Orientation2DF1D::operator()(Interface1D& inter) {
+ FEdge * fe = dynamic_cast<FEdge*>(&inter);
+ if(fe){
+ Vec3r res = fe->orientation2d();
+ result = Vec2f(res[0], res[1]);
+ } else {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+ return 0;
+ }
+
+ int Orientation3DF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int ZDiscontinuityF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int QuantitativeInvisibilityF1D::operator()(Interface1D& inter) {
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ result = ve->qi();
+ return 0;
+ }
+ FEdge *fe = dynamic_cast<FEdge*>(&inter);
+ if (fe) {
+ result = ve->qi();
+ return 0;
+ }
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int CurveNatureF1D::operator()(Interface1D& inter) {
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve)
+ result = ve->getNature();
+ else{
+ // we return a nature that contains every
+ // natures of the viewedges spanned by the chain.
+ Nature::EdgeNature nat = Nature::NO_FEATURE;
+ Interface0DIterator it = inter.verticesBegin();
+ while(!it.isEnd()){
+ nat |= _func(it);
+ ++it;
+ }
+ result = nat;
+ }
+ return 0;
+ }
+
+ int TimeStampF1D::operator()(Interface1D& inter) {
+ TimeStamp *timestamp = TimeStamp::instance();
+ inter.setTimeStamp(timestamp->getTimeStamp());
+ return 0;
+ }
+
+ int ChainingTimeStampF1D::operator()(Interface1D& inter) {
+ TimeStamp *timestamp = TimeStamp::instance();
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if(ve)
+ ve->setChainingTimeStamp(timestamp->getTimeStamp());
+ return 0;
+ }
+
+ int IncrementChainingTimeStampF1D::operator()(Interface1D& inter) {
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if(ve)
+ ve->setChainingTimeStamp(ve->getChainingTimeStamp()+1);
+ return 0;
+ }
+
+ int GetShapeF1D::operator()(Interface1D& inter) {
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ shapesVector.push_back(ve->viewShape());
+ }else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it)
+ shapesSet.insert(Functions0D::getShapeF0D(it));
+ shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ }
+ result = shapesVector;
+ return 0;
+ }
+
+ int GetOccludersF1D::operator()(Interface1D& inter) {
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ result = ve->occluders();
+ }else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it){
+ Functions0D::getOccludersF0D(it, shapesSet);
+ }
+ shapesVector.insert(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ result = shapesVector;
+ }
+ return 0;
+ }
+
+ int GetOccludeeF1D::operator()(Interface1D& inter) {
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ ViewShape * aShape = ve->aShape();
+ shapesVector.push_back(aShape);
+ }else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it){
+ shapesSet.insert(Functions0D::getOccludeeF0D(it));
+ }
+ shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ }
+ result = shapesVector;
+ return 0;
+ }
+ // Internal
+ ////////////
+
+ void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes){
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ ViewShape * aShape = ve->aShape();
+ if(aShape == 0){
+ oShapes.insert(0);
+ return;
+ }
+ oShapes.insert(aShape);
+ }
+ else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it)
+ oShapes.insert(Functions0D::getOccludeeF0D(it));
+ }
+ }
+
+ void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes){
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ vector<ViewShape*>& occluders = ve->occluders();
+ oShapes.insert<vector<ViewShape*>::iterator>(occluders.begin(), occluders.end());
+ }
+ else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it){
+ set<ViewShape*> shapes;
+ Functions0D::getOccludersF0D(it, shapes);
+ for(set<ViewShape*>::iterator s=shapes.begin(), send=shapes.end();
+ s!=send;
+ ++s)
+ oShapes.insert(*s);
+ }
+ }
+ }
+
+ void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes){
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ oShapes.insert(ve->viewShape());
+ }else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it)
+ oShapes.insert(Functions0D::getShapeF0D(it));
+ }
+ }
+} // end of namespace Functions1D
diff --git a/source/blender/freestyle/intern/view_map/Functions1D.h b/source/blender/freestyle/intern/view_map/Functions1D.h
new file mode 100755
index 00000000000..ba42b25b47e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions1D.h
@@ -0,0 +1,555 @@
+//
+// Filename : Functions1D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Functions taking 1D input
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef FUNCTIONS1D_HPP
+# define FUNCTIONS1D_HPP
+
+# include "ViewMap.h"
+# include "Functions0D.h"
+# include "Interface1D.h"
+# include "../system/Precision.h"
+# include "../system/TimeStamp.h"
+# include "../system/FreestyleConfig.h"
+
+#include "../python/Director.h"
+
+//
+// UnaryFunction1D (base class for functions in 1D)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for Unary Functions (functors) working
+ * on Interface1D.
+ * A unary function will be used by calling
+ * its operator() on an Interface1D.
+ * \attention In the scripting language, there exists
+ * several prototypes depending on the returned value type.
+ * For example, you would inherit from a UnaryFunction1DDouble
+ * if you wish to define a function that returns a double.
+ * The different existing prototypes are:
+ * - UnaryFunction1DVoid
+ * - UnaryFunction1DUnsigned
+ * - UnaryFunction1DReal
+ * - UnaryFunction1DFloat
+ * - UnaryFunction1DDouble
+ * - UnaryFunction1DVec2f
+ * - UnaryFunction1DVec3f
+ */
+template <class T>
+class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction1D
+{
+public:
+
+ T result;
+ PyObject *py_uf1D;
+
+ /*! The type of the value
+ * returned by the functor.
+ */
+ typedef T ReturnedValueType;
+
+ /*! Default constructor */
+ UnaryFunction1D(){_integration = MEAN;}
+ /*! Builds a UnaryFunction1D from an integration type.
+ * \param iType
+ * In case the result for the Interface1D would be
+ * obtained by evaluating a 0D function over the different
+ * Interface0D of the Interface1D, \a iType tells which
+ * integration method to use.
+ * The default integration method is the MEAN.
+ */
+ UnaryFunction1D(IntegrationType iType){_integration = iType;}
+ /*! destructor. */
+ virtual ~UnaryFunction1D() {}
+
+ /*! returns the string "UnaryFunction1D". */
+ virtual string getName() const {
+ return "UnaryFunction1D";
+ }
+ /*! The operator ().
+ * \param inter
+ * The Interface1D on which we wish to evaluate
+ * the function.
+ * \return the result of the function of type T.
+ */
+ virtual int operator()(Interface1D& inter) {
+ return Director_BPy_UnaryFunction1D___call__( this, py_uf1D, inter );
+ }
+
+ /*! Sets the integration method */
+ void setIntegrationType(IntegrationType integration) {
+ _integration = integration;
+ }
+ /*! Returns the integration method. */
+ IntegrationType getIntegrationType() const {
+ return _integration;
+ }
+
+protected:
+
+ IntegrationType _integration;
+};
+
+
+class UnaryFunction1D_void
+{
+public:
+
+ PyObject *py_uf1D;
+
+ UnaryFunction1D_void(){_integration = MEAN;}
+ UnaryFunction1D_void(IntegrationType iType){_integration = iType;}
+ virtual ~UnaryFunction1D_void() {}
+
+ virtual string getName() const {
+ return "UnaryFunction1D_void";
+ }
+
+ int operator()(Interface1D& inter) {
+ return Director_BPy_UnaryFunction1D___call__( this, py_uf1D, inter );
+ }
+
+ void setIntegrationType(IntegrationType integration) { _integration = integration; }
+ IntegrationType getIntegrationType() const { return _integration; }
+
+ protected:
+ IntegrationType _integration;
+};
+
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions1D {
+
+ // GetXF1D
+ /*! Returns the X 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetXF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetXF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetXF1D(IntegrationType iType) : UnaryFunction1D<real>(iType){}
+ /*! Returns the string "GetXF1D"*/
+ string getName() const {
+ return "GetXF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) ;
+ };
+
+ // GetYF1D
+ /*! Returns the Y 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetYF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetYF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ /*! Returns the string "GetYF1D"*/
+ string getName() const {
+ return "GetYF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) ;
+ };
+
+ // GetZF1D
+ /*! Returns the Z 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetZF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetZF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ /*! Returns the string "GetZF1D"*/
+ string getName() const {
+ return "GetZF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) ;
+ };
+
+ // GetProjectedXF1D
+ /*! Returns the projected X 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedXF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetProjectedXF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetProjectedXF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ public:
+ /*! Returns the string "GetProjectedXF1D"*/
+ string getName() const {
+ return "GetProjectedXF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // GetProjectedYF1D
+ /*! Returns the projected Y 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedYF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetProjectedYF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetProjectedYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ public:
+ /*! Returns the string "GetProjectedYF1D"*/
+ string getName() const {
+ return "GetProjectedYF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // GetProjectedZF1D
+ /*! Returns the projected Z 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedZF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetProjectedZF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetProjectedZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ public:
+ /*! Returns the string "GetProjectedZF1D"*/
+ string getName() const {
+ return "GetProjectedZF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // Orientation2DF1D
+ /*! Returns the 2D orientation as a Vec2f*/
+ class LIB_VIEW_MAP_EXPORT Orientation2DF1D : public UnaryFunction1D<Vec2f>
+ {
+ private:
+ Functions0D::VertexOrientation2DF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ Orientation2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType){}
+ /*! Returns the string "Orientation2DF1D"*/
+ string getName() const {
+ return "Orientation2DF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // Orientation3DF1D
+ /*! Returns the 3D orientation as a Vec3f. */
+ class LIB_VIEW_MAP_EXPORT Orientation3DF1D : public UnaryFunction1D<Vec3f>
+ {
+ private:
+ Functions0D::VertexOrientation3DF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ Orientation3DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec3f>(iType){}
+ /*! Returns the string "Orientation3DF1D"*/
+ string getName() const {
+ return "Orientation3DF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // ZDiscontinuityF1D
+ /*! Returns a real giving the distance between
+ * and Interface1D and the shape that lies behind (occludee).
+ * This distance is evaluated in the camera space and normalized
+ * between 0 and 1. Therefore, if no oject is occluded by the
+ * shape to which the Interface1D belongs to, 1 is returned.
+ */
+ class LIB_VIEW_MAP_EXPORT ZDiscontinuityF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::ZDiscontinuityF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ ZDiscontinuityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ /*! Returns the string "ZDiscontinuityF1D"*/
+ string getName() const {
+ return "ZDiscontinuityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // QuantitativeInvisibilityF1D
+ /*! Returns the Quantitative Invisibility of an Interface1D element.
+ * If the Interface1D is a ViewEdge, then there is no ambiguity
+ * concerning the result. But, if the Interface1D results of a chaining
+ * (chain, stroke), then it might be made of several 1D elements
+ * of different Quantitative Invisibilities.
+ */
+ class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF1D : public UnaryFunction1D<unsigned>
+ {
+ private:
+ Functions0D::QuantitativeInvisibilityF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ QuantitativeInvisibilityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<unsigned int>(iType) {}
+ /*! Returns the string "QuantitativeInvisibilityF1D"*/
+ string getName() const {
+ return "QuantitativeInvisibilityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // CurveNatureF1D
+/*! Returns the nature of the Interface1D (silhouette, ridge, crease...).
+ * Except if the Interface1D is a ViewEdge, this result might be ambiguous.
+ * Indeed, the Interface1D might result from the gathering of several 1D elements,
+ * each one being of a different nature. An integration method, such as
+ * the MEAN, might give, in this case, irrelevant results.
+ */
+ class LIB_VIEW_MAP_EXPORT CurveNatureF1D : public UnaryFunction1D<Nature::EdgeNature>
+ {
+ private:
+ Functions0D::CurveNatureF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ CurveNatureF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Nature::EdgeNature>(iType) {}
+ /*! Returns the string "CurveNatureF1D"*/
+ string getName() const {
+ return "CurveNatureF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // TimeStampF1D
+/*! Returns the time stamp of the Interface1D. */
+ class LIB_VIEW_MAP_EXPORT TimeStampF1D : public UnaryFunction1D_void
+ {
+ public:
+ /*! Returns the string "TimeStampF1D"*/
+ string getName() const {
+ return "TimeStampF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // IncrementChainingTimeStampF1D
+/*! Increments the chaining time stamp of the Interface1D. */
+ class LIB_VIEW_MAP_EXPORT IncrementChainingTimeStampF1D : public UnaryFunction1D_void
+ {
+ public:
+ /*! Returns the string "IncrementChainingTimeStampF1D"*/
+ string getName() const {
+ return "IncrementChainingTimeStampF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // ChainingTimeStampF1D
+/*! Sets the chaining time stamp of the Interface1D. */
+ class LIB_VIEW_MAP_EXPORT ChainingTimeStampF1D : public UnaryFunction1D_void
+ {
+ public:
+ /*! Returns the string "ChainingTimeStampF1D"*/
+ string getName() const {
+ return "ChainingTimeStampF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+
+ // Curvature2DAngleF1D
+/*! Returns the 2D curvature as an angle for an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT Curvature2DAngleF1D : public UnaryFunction1D<real>
+ {
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ Curvature2DAngleF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+ /*! Returns the string "Curvature2DAngleF1D"*/
+ string getName() const {
+ return "Curvature2DAngleF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+ private:
+ Functions0D::Curvature2DAngleF0D _fun;
+ };
+
+ // Normal2DF1D
+ /*! Returns the 2D normal for an interface 1D. */
+ class LIB_VIEW_MAP_EXPORT Normal2DF1D : public UnaryFunction1D<Vec2f>
+ {
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ Normal2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) {}
+ /*! Returns the string "Normal2DF1D"*/
+ string getName() const {
+ return "Normal2DF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+ private:
+ Functions0D::Normal2DF0D _fun;
+ };
+
+ // GetShapeF1D
+ /*! Returns list of shapes covered by this Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetShapeF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+ {
+ public:
+ /*! Builds the functor.
+ */
+ GetShapeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+ /*! Returns the string "GetShapeF1D"*/
+ string getName() const {
+ return "GetShapeF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // GetOccludersF1D
+ /*! Returns list of occluding shapes covered by this Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetOccludersF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+ {
+ public:
+ /*! Builds the functor.
+ */
+ GetOccludersF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+ /*! Returns the string "GetOccludersF1D"*/
+ string getName() const {
+ return "GetOccludersF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // GetOccludeeF1D
+ /*! Returns list of occluded shapes covered by this Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetOccludeeF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+ {
+ public:
+ /*! Builds the functor.
+ */
+ GetOccludeeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+ /*! Returns the string "GetOccludeeF1D"*/
+ string getName() const {
+ return "GetOccludeeF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // internal
+ ////////////
+
+ // getOccludeeF1D
+ LIB_VIEW_MAP_EXPORT
+ void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+ // getOccludersF1D
+ LIB_VIEW_MAP_EXPORT
+ void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+ // getShapeF1D
+ LIB_VIEW_MAP_EXPORT
+ void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+} // end of namespace Functions1D
+
+#endif // FUNCTIONS1D_HPP
diff --git a/source/blender/freestyle/intern/view_map/GridDensityProvider.h b/source/blender/freestyle/intern/view_map/GridDensityProvider.h
new file mode 100644
index 00000000000..078fc5f2c98
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/GridDensityProvider.h
@@ -0,0 +1,131 @@
+//
+// Filename : GridDensityProvider.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-5
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GRIDDENSITYPROVIDER_H
+#define GRIDDENSITYPROVIDER_H
+
+#include <stdexcept>
+#include <memory>
+#include "OccluderSource.h"
+#include "../geometry/BBox.h"
+
+class GridDensityProvider {
+ // Disallow copying and assignment
+ GridDensityProvider (const GridDensityProvider& other);
+ GridDensityProvider& operator= (const GridDensityProvider& other);
+
+public:
+ GridDensityProvider (OccluderSource& source)
+ : source(source) {
+ }
+
+ virtual ~GridDensityProvider() {};
+
+ float cellSize() {
+ return _cellSize;
+ }
+
+ unsigned cellsX() {
+ return _cellsX;
+ }
+
+ unsigned cellsY() {
+ return _cellsY;
+ }
+
+ float cellOrigin(int index) {
+ if ( index < 2 ) {
+ return _cellOrigin[index];
+ } else {
+ throw new out_of_range("GridDensityProvider::cellOrigin can take only indexes of 0 or 1.");
+ }
+ }
+
+ static void calculateOptimalProscenium(OccluderSource& source, real proscenium[4]) {
+ source.begin();
+ if ( source.isValid() ) {
+ const Vec3r& initialPoint = source.getGridSpacePolygon().getVertices()[0];
+ proscenium[0] = proscenium[1] = initialPoint[0];
+ proscenium[2] = proscenium[3] = initialPoint[1];
+ while ( source.isValid() ) {
+ GridHelpers::expandProscenium (proscenium, source.getGridSpacePolygon());
+ source.next();
+ }
+ }
+ cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " << proscenium[3] << ")" << endl;
+ }
+
+ static void calculateQuickProscenium(const GridHelpers::Transform& transform, const BBox<Vec3r>& bbox, real proscenium[4]) {
+ real z;
+ // We want to use the z-coordinate closest to the camera to determine the proscenium face
+ if ( ::fabs(bbox.getMin()[2]) < ::fabs(bbox.getMax()[2]) ) {
+ z = bbox.getMin()[2];
+ } else {
+ z = bbox.getMax()[2];
+ }
+ // Now calculate the proscenium according to the min and max values of the x and y coordinates
+ Vec3r minPoint = transform(Vec3r(bbox.getMin()[0], bbox.getMin()[1], z));
+ Vec3r maxPoint = transform(Vec3r(bbox.getMax()[0], bbox.getMax()[1], z));
+ cout << "Bounding box: " << minPoint << " to " << maxPoint << endl;
+ proscenium[0] = std::min(minPoint[0], maxPoint[0]);
+ proscenium[1] = std::max(minPoint[0], maxPoint[0]);
+ proscenium[2] = std::min(minPoint[1], maxPoint[1]);
+ proscenium[3] = std::max(minPoint[1], maxPoint[1]);
+ cout << "Proscenium : " << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " << proscenium[3] << endl;
+ }
+
+protected:
+ OccluderSource& source;
+ unsigned _cellsX, _cellsY;
+ float _cellSize;
+ float _cellOrigin[2];
+};
+
+class GridDensityProviderFactory {
+ // Disallow copying and assignment
+ GridDensityProviderFactory (const GridDensityProviderFactory& other);
+ GridDensityProviderFactory& operator= (const GridDensityProviderFactory& other);
+
+public:
+ GridDensityProviderFactory()
+ {
+ }
+
+ virtual auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]) =0;
+
+ virtual auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform) =0;
+
+ virtual auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source) =0;
+
+ virtual ~GridDensityProviderFactory () {}
+};
+
+#endif // GRIDDENSITYPROVIDER_H
+
diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
new file mode 100644
index 00000000000..05b70af90b3
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
@@ -0,0 +1,74 @@
+//
+// Filename : HeuristicGridDensityProviderFactory.cpp
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-8
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "HeuristicGridDensityProviderFactory.h"
+
+HeuristicGridDensityProviderFactory::HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces)
+ : sizeFactor(sizeFactor), numFaces(numFaces)
+{
+}
+
+HeuristicGridDensityProviderFactory::~HeuristicGridDensityProviderFactory () {}
+
+auto_ptr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
+{
+ auto_ptr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
+ auto_ptr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, proscenium, numFaces));
+ if ( avg->cellSize() > p23->cellSize() ) {
+ return (auto_ptr<GridDensityProvider>) p23;
+ } else {
+ return (auto_ptr<GridDensityProvider>) avg;
+ }
+}
+
+auto_ptr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform)
+{
+ auto_ptr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor));
+ auto_ptr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, bbox, transform, numFaces));
+ if ( avg->cellSize() > p23->cellSize() ) {
+ return (auto_ptr<GridDensityProvider>) p23;
+ } else {
+ return (auto_ptr<GridDensityProvider>) avg;
+ }
+}
+
+auto_ptr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+{
+ real proscenium[4];
+ GridDensityProvider::calculateOptimalProscenium(source, proscenium);
+ auto_ptr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
+ auto_ptr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, proscenium, numFaces));
+ if ( avg->cellSize() > p23->cellSize() ) {
+ return (auto_ptr<GridDensityProvider>) p23;
+ } else {
+ return (auto_ptr<GridDensityProvider>) avg;
+ }
+}
+
diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h
new file mode 100644
index 00000000000..d32c4ae4407
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h
@@ -0,0 +1,54 @@
+//
+// Filename : HeuristicGridDensityProviderFactory.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-8
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef HEURISTICGRIDDENSITYPROVIDERFACTORY_H
+#define HEURISTICGRIDDENSITYPROVIDERFACTORY_H
+
+// #include <memory> // provided by GridDensityProvider.h
+// #include "GridDensityProvider.h" // provided by *GridDensityProvider.h below
+#include "Pow23GridDensityProvider.h"
+#include "AverageAreaGridDensityProvider.h"
+
+class HeuristicGridDensityProviderFactory : public GridDensityProviderFactory {
+public:
+ HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces);
+ ~HeuristicGridDensityProviderFactory ();
+
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform);
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
+
+protected:
+ real sizeFactor;
+ unsigned numFaces;
+};
+
+#endif // HEURISTICGRIDDENSITYPROVIDERFACTORY_H
+
diff --git a/source/blender/freestyle/intern/view_map/Interface0D.h b/source/blender/freestyle/intern/view_map/Interface0D.h
new file mode 100755
index 00000000000..48d956eec19
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Interface0D.h
@@ -0,0 +1,360 @@
+//
+// Filename : Interface0D.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Interface to 0D elts
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef INTERFACE0D_H
+# define INTERFACE0D_H
+
+# include <Python.h>
+# include <string>
+# include <iostream>
+# include "../system/Id.h"
+# include "../system/Precision.h"
+# include "../winged_edge/Nature.h"
+# include "../geometry/Geom.h"
+using namespace std;
+
+#include "../system/Iterator.h" //soc
+
+//
+// Interface0D
+//
+//////////////////////////////////////////////////
+
+class FEdge;
+class SVertex;
+class ViewVertex;
+class NonTVertex;
+class TVertex;
+/*! Base class for any 0D element. */
+class Interface0D
+{
+public:
+
+ /*! Default constructor */
+ Interface0D() {}
+ virtual ~Interface0D() {}; //soc
+
+ /*! Returns the string "Interface0D".*/
+ virtual string getExactTypeName() const {
+ return "Interface0D";
+ }
+
+ // Data access methods
+
+ /*! Returns the 3D x coordinate of the point. */
+ virtual real getX() const {
+ PyErr_SetString(PyExc_TypeError, "method getX() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D y coordinate of the point. */
+ virtual real getY() const {
+ PyErr_SetString(PyExc_TypeError, "method getY() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D z coordinate of the point. */
+ virtual real getZ() const {
+ PyErr_SetString(PyExc_TypeError, "method getZ() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D point. */
+ virtual Geometry::Vec3f getPoint3D() const {
+ PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D x coordinate of the point. */
+ virtual real getProjectedX() const {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedX() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D y coordinate of the point. */
+ virtual real getProjectedY() const {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedY() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D z coordinate of the point. */
+ virtual real getProjectedZ() const {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedZ() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D point. */
+ virtual Geometry::Vec2f getPoint2D() const {
+ PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the FEdge that lies between this Interface0D and the
+ * Interface0D given as argument. */
+ virtual FEdge* getFEdge(Interface0D&) {
+ PyErr_SetString(PyExc_TypeError, "method getFEdge() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the Id of the point. */
+ virtual Id getId() const {
+ PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the nature of the point. */
+ virtual Nature::VertexNature getNature() const {
+ PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden");
+ return Nature::POINT;
+ }
+
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex(){
+ PyErr_SetString(PyExc_TypeError, "method castToSVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ PyErr_SetString(PyExc_TypeError, "method castToViewVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex(){
+ PyErr_SetString(PyExc_TypeError, "method castToNonTVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex(){
+ PyErr_SetString(PyExc_TypeError, "method castToTVertex() not properly overridden");
+ return 0;
+ }
+
+};
+
+
+//
+// Interface0DIteratorNested
+//
+//////////////////////////////////////////////////
+
+class Interface0DIteratorNested : public Iterator
+{
+public:
+
+ virtual ~Interface0DIteratorNested() {}
+
+ virtual string getExactTypeName() const {
+ return "Interface0DIteratorNested";
+ }
+
+ virtual Interface0D& operator*() = 0;
+
+ virtual Interface0D* operator->() {
+ return &(operator*());
+ }
+
+ virtual int increment() = 0;
+
+ virtual int decrement() = 0;
+
+ virtual bool isBegin() const = 0;
+
+ virtual bool isEnd() const = 0;
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const = 0;
+
+ virtual bool operator!=(const Interface0DIteratorNested& it) const {
+ return !(*this == it);
+ }
+
+ /*! Returns the curvilinear abscissa */
+ virtual float t() const = 0;
+ /*! Returns the point parameter 0<u<1 */
+ virtual float u() const = 0;
+
+ virtual Interface0DIteratorNested* copy() const = 0;
+};
+
+
+//
+// Interface0DIterator
+//
+//////////////////////////////////////////////////
+
+/*! Class defining an iterator over Interface0D elements.
+ * An instance of this iterator is always obtained
+ * from a 1D element.
+ * \attention In the scripting language, you must call
+ * \code it2 = Interface0DIterator(it1) \endcode instead of \code it2 = it1 \endcode
+ * where \a it1 and \a it2 are 2 Interface0DIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+class Interface0DIterator : public Iterator
+{
+public:
+
+ Interface0DIterator(Interface0DIteratorNested* it = NULL) {
+ _iterator = it;
+ }
+
+ /*! Copy constructor */
+ Interface0DIterator(const Interface0DIterator& it) {
+ _iterator = it._iterator->copy();
+ }
+
+ /*! Destructor */
+ virtual ~Interface0DIterator() {
+ if (_iterator)
+ delete _iterator;
+ }
+
+ /*! Operator =
+ * \attention In the scripting language, you must call
+ * \code it2 = Interface0DIterator(it1) \endcode instead of \code it2 = it1 \endcode
+ * where \a it1 and \a it2 are 2 Interface0DIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+ Interface0DIterator& operator=(const Interface0DIterator& it) {
+ if(_iterator)
+ delete _iterator;
+ _iterator = it._iterator->copy();
+ return *this;
+ }
+
+ /*! Returns the string "Interface0DIterator". */
+ virtual string getExactTypeName() const {
+ if (!_iterator)
+ return "Interface0DIterator";
+ return _iterator->getExactTypeName() + "Proxy";
+ }
+
+ // FIXME test it != 0 (exceptions ?)
+
+ /*! Returns a reference to the pointed Interface0D.
+ * In the scripting language, you must call
+ * "getObject()" instead using this operator.
+ */
+ Interface0D& operator*() {
+ return _iterator->operator*();
+ }
+
+ /*! Returns a pointer to the pointed Interface0D.
+ * Can't be called in the scripting language.
+ */
+ Interface0D* operator->() {
+ return &(operator*());
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ Interface0DIterator& operator++() {
+ _iterator->increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ Interface0DIterator operator++(int) {
+ Interface0DIterator ret(*this);
+ _iterator->increment();
+ return ret;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ Interface0DIterator& operator--() {
+ _iterator->decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ Interface0DIterator operator--(int) {
+ Interface0DIterator ret(*this);
+ _iterator->decrement();
+ return ret;
+ }
+
+ /*! Increments. */
+ virtual int increment() {
+ return _iterator->increment();
+ }
+
+ /*! Decrements. */
+ virtual int decrement() {
+ return _iterator->decrement();
+ }
+
+ /*! Returns true if the pointed Interface0D is the
+ * first of the 1D element containing the points over
+ * which we're iterating.
+ */
+ virtual bool isBegin() const {
+ return _iterator->isBegin();
+ }
+
+ /*! Returns true if the pointed Interface0D is after the
+ * after the last point of the 1D element we're iterating from.
+ */
+ virtual bool isEnd() const {
+ return _iterator->isEnd();
+ }
+
+ /*! operator == . */
+ bool operator==(const Interface0DIterator& it) const {
+ return _iterator->operator==(*(it._iterator));
+ }
+
+ /*! operator != . */
+ bool operator!=(const Interface0DIterator& it) const {
+ return !(*this == it);
+ }
+
+ /*! Returns the curvilinear abscissa. */
+ inline float t() const {
+ return _iterator->t();
+ }
+ /*! Returns the point parameter in the curve 0<=u<=1. */
+ inline float u() const {
+ return _iterator->u();
+ }
+protected:
+
+ Interface0DIteratorNested* _iterator;
+};
+
+#endif // INTERFACE0D_H
diff --git a/source/blender/freestyle/intern/view_map/Interface1D.h b/source/blender/freestyle/intern/view_map/Interface1D.h
new file mode 100755
index 00000000000..60cc0ebcb7e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Interface1D.h
@@ -0,0 +1,226 @@
+//
+// Filename : Interface1D.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Interface to 1D elts
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef INTERFACE1D_H
+# define INTERFACE1D_H
+
+# include <Python.h>
+# include <string>
+# include <iostream>
+# include <float.h>
+# include "../system/Id.h"
+# include "../system/Precision.h"
+# include "../winged_edge/Nature.h"
+# include "Functions0D.h"
+
+using namespace std;
+/*! \file Interface1D.h
+ * Interface1D and related tools definitions
+ */
+// Integration method
+/*! The different integration
+ * methods that can be invoked
+ * to integrate into a single value the set of values obtained
+ * from each 0D element of a 1D element.
+ */
+typedef enum {
+ MEAN,/*!< The value computed for the 1D element is the mean of the values obtained for the 0D elements.*/
+ MIN,/*!< The value computed for the 1D element is the minimum of the values obtained for the 0D elements.*/
+ MAX,/*!< The value computed for the 1D element is the maximum of the values obtained for the 0D elements.*/
+ FIRST,/*!< The value computed for the 1D element is the first of the values obtained for the 0D elements.*/
+ LAST/*!< The value computed for the 1D element is the last of the values obtained for the 0D elements.*/
+} IntegrationType;
+
+/*! Returns a single
+ * value from a set of values evaluated at each 0D element
+ * of this 1D element.
+ * \param fun
+ * The UnaryFunction0D used to compute a value at each Interface0D.
+ * \param it
+ * The Interface0DIterator used to iterate over the 0D elements of
+ * this 1D element. The integration will occur over the 0D elements
+ * starting from the one pointed by it.
+ * \param it_end
+ * The Interface0DIterator pointing the end of the 0D elements of the
+ * 1D element.
+ * \param integration_type
+ * The integration method used to compute a single value from
+ * a set of values.
+ * \return the single value obtained for the 1D element.
+ */
+template <class T>
+T integrate(UnaryFunction0D<T>& fun,
+ Interface0DIterator it,
+ Interface0DIterator it_end,
+ IntegrationType integration_type = MEAN) {
+ T res;
+ unsigned size;
+ switch (integration_type) {
+ case MIN:
+ fun(it);
+ res = fun.result;++it;
+ for (; !it.isEnd(); ++it) {
+ fun(it);
+ if (fun.result < res)
+ res = fun.result;
+ }
+ break;
+ case MAX:
+ fun(it);
+ res = fun.result;++it;
+ for (; !it.isEnd(); ++it) {
+ fun(it);
+ if (fun.result > res)
+ res = fun.result;
+ }
+ break;
+ case FIRST:
+ fun(it);
+ res = fun.result;
+ break;
+ case LAST:
+ fun(--it_end);
+ res = fun.result;
+ break;
+ case MEAN:
+ default:
+ fun(it);
+ res = fun.result;++it;
+ for (size = 1; !it.isEnd(); ++it, ++size) {
+ fun(it);
+ res += fun.result;
+ }
+ res /= (size ? size : 1);
+ break;
+ }
+ return res;
+}
+
+//
+// Interface1D
+//
+//////////////////////////////////////////////////
+
+/*! Base class for any 1D element. */
+class Interface1D
+{
+public:
+
+ /*! Default constructor */
+ Interface1D() {_timeStamp=0;}
+ virtual ~Interface1D() {}; //soc
+
+ /*! Returns the string "Interface1D" .*/
+ virtual string getExactTypeName() const {
+ return "Interface1D";
+ }
+
+ // Iterator access
+
+ /*! Returns an iterator over the Interface1D vertices,
+ * pointing to the first vertex.
+ */
+ virtual Interface0DIterator verticesBegin() {
+ PyErr_SetString(PyExc_TypeError, "method verticesBegin() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! Returns an iterator over the Interface1D vertices,
+ * pointing after the last vertex.
+ */
+ virtual Interface0DIterator verticesEnd(){
+ PyErr_SetString(PyExc_TypeError, "method verticesEnd() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! Returns an iterator over the Interface1D points,
+ * pointing to the first point. The difference with
+ * verticesBegin() is that here we can iterate over
+ * points of the 1D element at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of
+ * this 1D element.
+ */
+ virtual Interface0DIterator pointsBegin(float t=0.f) {
+ PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! Returns an iterator over the Interface1D points,
+ * pointing after the last point. The difference with
+ * verticesEnd() is that here we can iterate over
+ * points of the 1D element at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of
+ * this 1D element.
+ */
+ virtual Interface0DIterator pointsEnd(float t=0.f) {
+ PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ // Data access methods
+
+ /*! Returns the 2D length of the 1D element. */
+ virtual real getLength2D() const {
+ PyErr_SetString(PyExc_TypeError, "method getLength2D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the Id of the 1D element .*/
+ virtual Id getId() const {
+ PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden");
+ return Id(0, 0);
+ }
+
+
+ // FIXME: ce truc n'a rien a faire la...(c une requete complexe qui doit etre ds les Function1D)
+ /*! Returns the nature of the 1D element. */
+ virtual Nature::EdgeNature getNature() const {
+ PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden");
+ return Nature::NO_FEATURE;
+ }
+
+ /*! Returns the time stamp of the 1D element. Mainly used for selection. */
+ virtual unsigned getTimeStamp() const {
+ return _timeStamp;
+ }
+
+ /*! Sets the time stamp for the 1D element. */
+ inline void setTimeStamp(unsigned iTimeStamp){
+ _timeStamp = iTimeStamp;
+ }
+
+protected:
+ unsigned _timeStamp;
+};
+
+#endif // INTERFACE1D_H
diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.cpp b/source/blender/freestyle/intern/view_map/OccluderSource.cpp
new file mode 100644
index 00000000000..356e281be4b
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/OccluderSource.cpp
@@ -0,0 +1,132 @@
+//
+// Filename : OccluderSource.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2010-12-21
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "OccluderSource.h"
+#include <algorithm>
+
+OccluderSource::OccluderSource (const GridHelpers::Transform& t, WingedEdge& we) : wingedEdge(we), valid(false), transform(t) {
+ begin();
+}
+
+OccluderSource::~OccluderSource() {
+}
+
+void OccluderSource::buildCachedPolygon() {
+ vector<Vec3r> vertices(GridHelpers::enumerateVertices((*currentFace)->getEdgeList()));
+ // This doesn't work, because our functor's polymorphism won't survive the copy:
+ // std::transform(vertices.begin(), vertices.end(), vertices.begin(), transform);
+ // so we have to do:
+ for ( vector<Vec3r>::iterator i = vertices.begin(); i != vertices.end(); ++i ) {
+ (*i) = transform(*i);
+ }
+ cachedPolygon = Polygon3r(vertices, transform((*currentFace)->GetNormal()));
+}
+
+void OccluderSource::begin() {
+ vector<WShape*>& wshapes = wingedEdge.getWShapes();
+ currentShape = wshapes.begin();
+ shapesEnd = wshapes.end();
+ valid = false;
+ if ( currentShape != shapesEnd ) {
+ vector<WFace*>& wFaces = (*currentShape)->GetFaceList();
+ currentFace = wFaces.begin();
+ facesEnd = wFaces.end();
+
+ if ( currentFace != facesEnd ) {
+ buildCachedPolygon();
+ valid = true;
+ }
+ }
+}
+
+bool OccluderSource::next() {
+ if ( valid ) {
+ ++currentFace;
+ while ( currentFace == facesEnd ) {
+ ++currentShape;
+ if ( currentShape == shapesEnd ) {
+ valid = false;
+ return false;
+ } else {
+ vector<WFace*>& wFaces = (*currentShape)->GetFaceList();
+ currentFace = wFaces.begin();
+ facesEnd = wFaces.end();
+ }
+ }
+ buildCachedPolygon();
+ return true;
+ }
+ return false;
+}
+
+bool OccluderSource::isValid() {
+ // Or:
+ // return currentShapes != shapesEnd && currentFace != facesEnd;
+ return valid;
+}
+
+WFace* OccluderSource::getWFace() {
+ return valid ? *currentFace : NULL;
+}
+
+Polygon3r OccluderSource::getCameraSpacePolygon() {
+ return Polygon3r(GridHelpers::enumerateVertices((*currentFace)->getEdgeList()), (*currentFace)->GetNormal());
+}
+
+Polygon3r& OccluderSource::getGridSpacePolygon() {
+ return cachedPolygon;
+}
+
+void OccluderSource::getOccluderProscenium(real proscenium[4]) {
+ begin();
+ const Vec3r& initialPoint = cachedPolygon.getVertices()[0];
+ proscenium[0] = proscenium[1] = initialPoint[0];
+ proscenium[2] = proscenium[3] = initialPoint[1];
+ while ( isValid() ) {
+ GridHelpers::expandProscenium (proscenium, cachedPolygon);
+ next();
+ }
+ cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " << proscenium[3] << ")" << endl;
+}
+
+real OccluderSource::averageOccluderArea() {
+ real area = 0.0;
+ unsigned numFaces = 0;
+ for ( begin(); isValid(); next() ) {
+ Vec3r min, max;
+ cachedPolygon.getBBox(min, max);
+ area += (max[0] - min[0]) * (max[1] - min[1]);
+ ++numFaces;
+ }
+ area /= numFaces;
+ return area;
+}
+
+
diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.h b/source/blender/freestyle/intern/view_map/OccluderSource.h
new file mode 100644
index 00000000000..d623cc63fed
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/OccluderSource.h
@@ -0,0 +1,70 @@
+//
+// Filename : OccluderSource.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2010-12-21
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef OCCLUDERSOURCE_H
+#define OCCLUDERSOURCE_H
+
+#include "../winged_edge/WEdge.h"
+#include "../geometry/GridHelpers.h"
+
+class OccluderSource {
+ // Disallow copying and assignment
+ OccluderSource (const OccluderSource& other);
+ OccluderSource& operator= (const OccluderSource& other);
+
+public:
+ OccluderSource (const GridHelpers::Transform& transform, WingedEdge& we);
+ virtual ~OccluderSource();
+
+ void begin();
+ virtual bool next();
+ bool isValid();
+
+ WFace* getWFace();
+ Polygon3r getCameraSpacePolygon();
+ Polygon3r& getGridSpacePolygon();
+
+ virtual void getOccluderProscenium(real proscenium[4]);
+ virtual real averageOccluderArea();
+
+protected:
+ WingedEdge& wingedEdge;
+ vector<WShape*>::const_iterator currentShape, shapesEnd;
+ vector<WFace*>::const_iterator currentFace, facesEnd;
+
+ bool valid;
+
+ Polygon3r cachedPolygon;
+ const GridHelpers::Transform& transform;
+
+ void buildCachedPolygon();
+};
+
+#endif // OCCLUDERSOURCE_H
diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
new file mode 100644
index 00000000000..2e506da9ee9
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
@@ -0,0 +1,109 @@
+//
+// Filename : Pow23GridDensityProvider.cpp
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-8
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Pow23GridDensityProvider.h"
+
+Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numFaces)
+ : GridDensityProvider(source), numFaces(numFaces)
+{
+ initialize (proscenium);
+}
+
+Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform, unsigned numFaces)
+ : GridDensityProvider(source), numFaces(numFaces)
+{
+ real proscenium[4];
+ calculateQuickProscenium(transform, bbox, proscenium);
+
+ initialize (proscenium);
+}
+
+Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, unsigned numFaces)
+ : GridDensityProvider(source), numFaces(numFaces)
+{
+ real proscenium[4];
+ calculateOptimalProscenium(source, proscenium);
+
+ initialize (proscenium);
+}
+
+Pow23GridDensityProvider::~Pow23GridDensityProvider () {}
+
+void Pow23GridDensityProvider::initialize (const real proscenium[4])
+{
+ float prosceniumWidth = (proscenium[1] - proscenium[0]);
+ float prosceniumHeight = (proscenium[3] - proscenium[2]);
+ real cellArea = prosceniumWidth * prosceniumHeight / pow(numFaces, 2.0f / 3.0f);
+ cout << prosceniumWidth << " x " << prosceniumHeight << " grid with cells of area " << cellArea << "." << endl;
+
+ _cellSize = sqrt(cellArea);
+ // Now we know how many cells make each side of our grid
+ _cellsX = ceil(prosceniumWidth / _cellSize);
+ _cellsY = ceil(prosceniumHeight / _cellSize);
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+
+ // Make sure the grid exceeds the proscenium by a small amount
+ float safetyZone = 0.1;
+ if ( _cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone) ) {
+ _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize;
+ }
+ if ( _cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone) ) {
+ _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize;
+ }
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+
+ // Find grid origin
+ _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize;
+ _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize;
+}
+
+Pow23GridDensityProviderFactory::Pow23GridDensityProviderFactory(unsigned numFaces)
+ : numFaces(numFaces)
+{
+}
+
+Pow23GridDensityProviderFactory::~Pow23GridDensityProviderFactory () {}
+
+auto_ptr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
+{
+ return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, proscenium, numFaces));
+}
+
+auto_ptr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform)
+{
+ return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, bbox, transform, numFaces));
+}
+
+auto_ptr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+{
+ return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, numFaces));
+}
+
+
diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h
new file mode 100644
index 00000000000..c398a1643a4
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h
@@ -0,0 +1,67 @@
+//
+// Filename : Pow23GridDensityProvider.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2011-2-8
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef POW23GRIDDENSITYPROVIDER_H
+#define POW23GRIDDENSITYPROVIDER_H
+
+#include "GridDensityProvider.h"
+
+class Pow23GridDensityProvider : public GridDensityProvider {
+ // Disallow copying and assignment
+ Pow23GridDensityProvider (const Pow23GridDensityProvider& other);
+ Pow23GridDensityProvider& operator= (const Pow23GridDensityProvider& other);
+
+public:
+ Pow23GridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numFaces);
+ Pow23GridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform, unsigned numFaces);
+ Pow23GridDensityProvider(OccluderSource& source, unsigned numFaces);
+ virtual ~Pow23GridDensityProvider ();
+
+protected:
+ unsigned numFaces;
+
+private:
+ void initialize (const real proscenium[4]);
+};
+
+class Pow23GridDensityProviderFactory : public GridDensityProviderFactory {
+public:
+ Pow23GridDensityProviderFactory(unsigned numFaces);
+ ~Pow23GridDensityProviderFactory ();
+
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]);
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform);
+ auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source);
+protected:
+ unsigned numFaces;
+};
+
+#endif // POW23GRIDDENSITYPROVIDER_H
+
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.cpp b/source/blender/freestyle/intern/view_map/Silhouette.cpp
new file mode 100755
index 00000000000..7a7d0a51d4b
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Silhouette.cpp
@@ -0,0 +1,370 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Silhouette.h"
+#include "ViewMap.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* SVertex */
+ /* */
+ /* */
+ /**********************************/
+
+Nature::VertexNature SVertex::getNature() const {
+ Nature::VertexNature nature = Nature::S_VERTEX;
+ if (_pViewVertex)
+ nature |= _pViewVertex->getNature();
+ return nature;
+}
+
+SVertex * SVertex::castToSVertex(){
+ return this;
+}
+
+ViewVertex * SVertex::castToViewVertex(){
+ return _pViewVertex;
+}
+
+NonTVertex * SVertex::castToNonTVertex(){
+ return dynamic_cast<NonTVertex*>(_pViewVertex);
+}
+
+TVertex * SVertex::castToTVertex(){
+ return dynamic_cast<TVertex*>(_pViewVertex);
+}
+
+float SVertex::shape_importance() const
+{
+ return shape()->importance();
+}
+
+//Material SVertex::material() const {return _Shape->material();}
+Id SVertex::shape_id() const {return _Shape->getId();}
+const SShape * SVertex::shape() const {return _Shape;}
+
+const int SVertex::qi() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->qi();
+}
+
+occluder_container::const_iterator SVertex::occluders_begin() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_begin();
+}
+
+occluder_container::const_iterator SVertex::occluders_end() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_end();
+}
+
+bool SVertex::occluders_empty() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_empty();
+}
+
+int SVertex::occluders_size() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_size();
+}
+
+const Polygon3r& SVertex::occludee() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occludee();
+}
+
+const SShape* SVertex::occluded_shape() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluded_shape();
+}
+
+const bool SVertex::occludee_empty() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occludee_empty();
+}
+
+real SVertex::z_discontinuity() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->z_discontinuity();
+}
+
+FEdge* SVertex::fedge()
+{
+ if (getNature() & Nature::T_VERTEX)
+ return 0;
+ return _FEdges[0];
+}
+
+FEdge* SVertex::getFEdge(Interface0D& inter)
+{
+ FEdge * result = 0;
+ SVertex* iVertexB = dynamic_cast<SVertex*>(&inter);
+ if (!iVertexB)
+ return result;
+ vector<FEdge*>::const_iterator fe=_FEdges.begin(), feend=_FEdges.end();
+ for(;
+ fe!=feend;
+ ++fe)
+ {
+ if( (((*fe)->vertexA() == this) && ((*fe)->vertexB() == iVertexB))
+ || (((*fe)->vertexB() == this) && ((*fe)->vertexA() == iVertexB)))
+ result = (*fe);
+ }
+ if((result == 0) && (getNature() & Nature::T_VERTEX))
+ {
+ SVertex *brother;
+ ViewVertex *vvertex = viewvertex();
+ TVertex * tvertex = dynamic_cast<TVertex*>(vvertex);
+ if(tvertex)
+ {
+ brother = tvertex->frontSVertex();
+ if(this == brother)
+ brother = tvertex->backSVertex();
+ const vector<FEdge*>& fedges = brother->fedges();
+ for(fe=fedges.begin(),feend=fedges.end();
+ fe!=feend;
+ ++fe)
+ {
+ if( (((*fe)->vertexA() == brother) && ((*fe)->vertexB() == iVertexB))
+ || (((*fe)->vertexB() == brother) && ((*fe)->vertexA() == iVertexB)))
+ result = (*fe);
+ }
+ }
+ }
+ if((result == 0) && (iVertexB->getNature() & Nature::T_VERTEX))
+ {
+ SVertex *brother;
+ ViewVertex *vvertex = iVertexB->viewvertex();
+ TVertex * tvertex = dynamic_cast<TVertex*>(vvertex);
+ if(tvertex)
+ {
+ brother = tvertex->frontSVertex();
+ if(iVertexB == brother)
+ brother = tvertex->backSVertex();
+ for(fe=_FEdges.begin(),feend=_FEdges.end();
+ fe!=feend;
+ ++fe)
+ {
+ if( (((*fe)->vertexA() == this) && ((*fe)->vertexB() == brother))
+ || (((*fe)->vertexB() == this) && ((*fe)->vertexA() == brother)))
+ result = (*fe);
+ }
+ }
+ }
+
+ return result;
+}
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdge */
+ /* */
+ /* */
+ /**********************************/
+
+
+int FEdge::viewedge_nature() const {return _ViewEdge->getNature();}
+//float FEdge::viewedge_length() const {return _ViewEdge->viewedge_length();}
+const SShape* FEdge::occluded_shape() const
+{
+ ViewShape * aShape = _ViewEdge->aShape();
+ if(aShape == 0)
+ return 0;
+ return aShape->sshape();
+}
+
+float FEdge::shape_importance() const
+{
+ return _VertexA->shape()->importance();
+}
+
+int FEdge::invisibility() const
+{
+ return _ViewEdge->qi();
+}
+
+occluder_container::const_iterator FEdge::occluders_begin() const {return _ViewEdge->occluders_begin();}
+occluder_container::const_iterator FEdge::occluders_end() const {return _ViewEdge->occluders_end();}
+bool FEdge::occluders_empty() const {return _ViewEdge->occluders_empty();}
+int FEdge::occluders_size() const {return _ViewEdge->occluders_size();}
+const bool FEdge::occludee_empty() const
+{
+ return _ViewEdge->occludee_empty();
+}
+
+
+
+Id FEdge::shape_id() const
+{
+ return _VertexA->shape()->getId();
+}
+const SShape* FEdge::shape() const
+{
+ return _VertexA->shape();
+}
+
+real FEdge::z_discontinuity() const
+{
+ if(!(getNature() & Nature::SILHOUETTE) && !(getNature() & Nature::BORDER))
+ {
+ return 0;
+ }
+
+ BBox<Vec3r> box = ViewMap::getInstance()->getScene3dBBox();
+
+ Vec3r bbox_size_vec(box.getMax() - box.getMin());
+ real bboxsize = bbox_size_vec.norm();
+ if(occludee_empty())
+
+ {
+ //return FLT_MAX;
+
+ return 1.0;
+
+ //return bboxsize;
+
+ }
+ // real result;
+ // z_discontinuity_functor<SVertex> _functor;
+
+ // Evaluate<SVertex,z_discontinuity_functor<SVertex> >(&_functor, iCombination, result )
+ Vec3r middle((_VertexB->point3d()-_VertexA->point3d()));
+
+ middle /= 2;
+ Vec3r disc_vec(middle - _occludeeIntersection);
+ real res = disc_vec.norm() / bboxsize;
+ return res;
+
+ //return fabs((middle.z()-_occludeeIntersection.z()));
+}
+
+
+//float FEdge::local_average_depth(int iCombination ) const
+//{
+//
+// float result;
+// local_average_depth_functor<SVertex> functor;
+// Evaluate(&functor, iCombination, result);
+//
+// return result;
+//}
+//float FEdge::local_depth_variance(int iCombination ) const
+//{
+// float result;
+//
+// local_depth_variance_functor<SVertex> functor;
+//
+// Evaluate(&functor, iCombination, result);
+//
+// return result;
+//}
+//
+//
+//real FEdge::local_average_density( float sigma, int iCombination) const
+//{
+// float result;
+//
+// density_functor<SVertex> functor(sigma);
+//
+// Evaluate(&functor, iCombination, result);
+//
+// return result;
+//}
+//
+////Vec3r FEdge::normal(int& oException /* = Exception::NO_EXCEPTION */)
+////{
+//// Vec3r Na = _VertexA->normal(oException);
+//// if(oException != Exception::NO_EXCEPTION)
+//// return Na;
+//// Vec3r Nb = _VertexB->normal(oException);
+//// if(oException != Exception::NO_EXCEPTION)
+//// return Nb;
+//// return (Na+Nb)/2.0;
+////}
+//
+//Vec3r FEdge::curvature2d_as_vector(int iCombination) const
+//{
+// Vec3r result;
+// curvature2d_as_vector_functor<SVertex> _functor;
+// Evaluate<Vec3r,curvature2d_as_vector_functor<SVertex> >(&_functor, iCombination, result );
+// return result;
+//}
+//
+//real FEdge::curvature2d_as_angle(int iCombination) const
+//{
+// real result;
+// curvature2d_as_angle_functor<SVertex> _functor;
+// Evaluate<real,curvature2d_as_angle_functor<SVertex> >(&_functor, iCombination, result );
+// return result;
+//}
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdgeSharp */
+ /* */
+ /* */
+ /**********************************/
+
+//Material FEdge::material() const
+//{
+// return _VertexA->shape()->material();
+//}
+const FrsMaterial& FEdgeSharp::aFrsMaterial() const {
+ return _VertexA->shape()->frs_material(_aFrsMaterialIndex);
+}
+
+const FrsMaterial& FEdgeSharp::bFrsMaterial() const {
+ return _VertexA->shape()->frs_material(_bFrsMaterialIndex);
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdgeSmooth */
+ /* */
+ /* */
+ /**********************************/
+
+const FrsMaterial& FEdgeSmooth::frs_material() const {
+ return _VertexA->shape()->frs_material(_FrsMaterialIndex);
+}
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h
new file mode 100755
index 00000000000..369267af8d9
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Silhouette.h
@@ -0,0 +1,1471 @@
+//
+// Filename : Silhouette.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define a silhouette structure
+// Date of creation : 25/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SILHOUETTE_H
+# define SILHOUETTE_H
+
+# include "Interface0D.h"
+# include "Interface1D.h"
+# include <iostream>
+# include <string>
+# include <vector>
+# include <set>
+# include <float.h>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../geometry/BBox.h"
+# include "../scene_graph/FrsMaterial.h"
+# include "../geometry/Polygon.h"
+# include "../system/Exception.h"
+# include "../winged_edge/Curvature.h"
+
+using namespace std;
+using namespace Geometry;
+
+class ViewShape;
+typedef vector<ViewShape*> occluder_container;
+
+ /**********************************/
+ /* */
+ /* */
+ /* SVertex */
+ /* */
+ /* */
+ /**********************************/
+
+class FEdge;
+class ViewVertex;
+class SShape;
+
+/*! Class to define a vertex of the embedding. */
+class LIB_VIEW_MAP_EXPORT SVertex : public Interface0D
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "SVertex" .*/
+ virtual string getExactTypeName() const {
+ return "SVertex";
+ }
+
+ // Data access methods
+
+ /*! Returns the 3D x coordinate of the vertex .*/
+ virtual real getX() const {
+ return _Point3D.x();
+ }
+
+ /*! Returns the 3D y coordinate of the vertex .*/
+ virtual real getY() const {
+ return _Point3D.y();
+ }
+
+ /*! Returns the 3D z coordinate of the vertex .*/
+ virtual real getZ() const {
+ return _Point3D.z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const {
+ return _Point3D;
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex .*/
+ virtual real getProjectedX() const {
+ return _Point2D.x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex .*/
+ virtual real getProjectedY() const {
+ return _Point2D.y();
+ }
+
+ /*! Returns the projected 3D z coordinate of the vertex .*/
+ virtual real getProjectedZ() const {
+ return _Point2D.z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const {
+ return Vec2f((float)_Point2D.x(),(float)_Point2D.y());
+ }
+
+ /*! Returns the FEdge that lies between this Svertex and the
+ * Interface0D given as argument. */
+ virtual FEdge* getFEdge(Interface0D&);
+
+ /*! Returns the Id of the vertex .*/
+ virtual Id getId() const {
+ return _Id;
+ }
+
+ /*! Returns the nature of the vertex .*/
+ virtual Nature::VertexNature getNature() const;
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex();
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex();
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex();
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex();
+
+public:
+
+ typedef vector<FEdge*> fedges_container;
+
+private:
+
+ Id _Id;
+ Vec3r _Point3D;
+ Vec3r _Point2D;
+ set<Vec3r> _Normals;
+ vector<FEdge*> _FEdges; // the edges containing this vertex
+ SShape *_Shape; // the shape to which belongs the vertex
+ ViewVertex *_pViewVertex; // The associated viewvertex, in case there is one.
+ real _curvatureFredo;
+ Vec2r _directionFredo;
+ CurvatureInfo* _curvature_info;
+
+public:
+
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+
+ /*! Default constructor.*/
+ inline SVertex() {
+ _Id = 0;
+ userdata = NULL;
+ _Shape = NULL;
+ _pViewVertex = 0;
+ _curvature_info = 0;
+ }
+
+ /*! Builds a SVertex from 3D coordinates and an Id. */
+ inline SVertex(const Vec3r &iPoint3D, const Id& id) {
+ _Point3D = iPoint3D;
+ _Id=id;
+ userdata = NULL;
+ _Shape = NULL;
+ _pViewVertex=0;
+ _curvature_info = 0;
+ }
+
+ /*! Copy constructor. */
+ inline SVertex(SVertex& iBrother) {
+ _Id = iBrother._Id;
+ _Point3D = iBrother.point3D();
+ _Point2D = iBrother.point2D();
+ _Normals = iBrother._Normals;
+ _FEdges = iBrother.fedges();
+ _Shape = iBrother.shape();
+ _pViewVertex = iBrother._pViewVertex;
+ if (!(iBrother._curvature_info))
+ _curvature_info = 0;
+ else
+ _curvature_info = new CurvatureInfo(*(iBrother._curvature_info));
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+
+ /*! Destructor. */
+ virtual ~SVertex() {
+ if (_curvature_info)
+ delete _curvature_info;
+ }
+
+ /*! Cloning method. */
+ virtual SVertex * duplicate() {
+ SVertex *clone = new SVertex(*this);
+ return clone;
+ }
+
+ /*! operator == */
+ virtual bool operator==(const SVertex& iBrother) {
+ return ((_Point2D == iBrother._Point2D) &&
+ (_Point3D == iBrother._Point3D));
+ }
+
+ /* accessors */
+ inline const Vec3r& point3D() const {return _Point3D;}
+ inline const Vec3r& point2D() const {return _Point2D;}
+ /*! Returns the set of normals for this Vertex.
+ * In a smooth surface, a vertex has exactly one normal.
+ * In a sharp surface, a vertex can have any number of normals.
+ */
+ inline set<Vec3r> normals() {return _Normals;}
+ /*! Returns the number of different normals for this vertex. */
+ inline unsigned normalsSize() const {return _Normals.size();}
+ inline const vector<FEdge*>& fedges() {return _FEdges;}
+ inline fedges_container::iterator fedges_begin() {return _FEdges.begin();}
+ inline fedges_container::iterator fedges_end() {return _FEdges.end();}
+ inline SShape * shape() {return _Shape;}
+ inline real z() const {return _Point2D[2];}
+ /*! If this SVertex is also a ViewVertex, this method
+ * returns a pointer onto this ViewVertex. 0 is returned
+ * otherwise.
+ */
+ inline ViewVertex * viewvertex() {return _pViewVertex;}
+
+ /*! modifiers */
+ /*! Sets the 3D coordinates of the SVertex. */
+ inline void setPoint3D(const Vec3r &iPoint3D) {_Point3D = iPoint3D;}
+ /*! Sets the 3D projected coordinates of the SVertex. */
+ inline void setPoint2D(const Vec3r &iPoint2D) {_Point2D = iPoint2D;}
+ /*! Adds a normal to the Svertex's set of normals. If the same
+ * normal is already in the set, nothing changes.
+ */
+ inline void AddNormal(const Vec3r& iNormal)
+ {
+ _Normals.insert(iNormal); // if iNormal in the set already exists, nothing is done
+ }
+
+ void setCurvatureInfo(CurvatureInfo* ci) {
+ if (_curvature_info) // Q. is this an error condition? (T.K. 02-May-2011)
+ delete _curvature_info;
+ _curvature_info = ci;
+ }
+
+ const CurvatureInfo* getCurvatureInfo() const {
+ return _curvature_info;
+ }
+
+ /* Fredo's normal and curvature*/
+ void setCurvatureFredo(real c) {_curvatureFredo=c;}
+ void setDirectionFredo(Vec2r d) {_directionFredo=d;}
+ real curvatureFredo () {return _curvatureFredo;}
+ const Vec2r directionFredo () {return _directionFredo;}
+
+ /*! Sets the Id */
+ inline void setId(const Id& id) {_Id = id;}
+ inline void setFEdges(const vector<FEdge*>& iFEdges) {_FEdges = iFEdges;}
+ inline void setShape(SShape *iShape) {_Shape = iShape;}
+ inline void setViewVertex(ViewVertex *iViewVertex) {_pViewVertex = iViewVertex;}
+ /*! Add an FEdge to the list of edges emanating from this SVertex. */
+ inline void AddFEdge(FEdge* iFEdge) {_FEdges.push_back(iFEdge);}
+ /* replaces edge 1 by edge 2 in the list of edges */
+ inline void Replace(FEdge *e1, FEdge *e2)
+ {
+ vector<FEdge*>::iterator insertedfe;
+ for(vector<FEdge*>::iterator fe=_FEdges.begin(),fend=_FEdges.end();
+ fe!=fend;
+ fe++)
+ {
+ if((*fe) == e1)
+ {
+ insertedfe = _FEdges.insert(fe, e2);// inserts e2 before fe.
+ // returns an iterator pointing toward e2. fe is invalidated.
+ // we want to remove e1, but we can't use fe anymore:
+ insertedfe++; // insertedfe points now to e1
+ _FEdges.erase(insertedfe);
+ return;
+ }
+ }
+ }
+
+public:
+
+ /* Information access interface */
+
+ FEdge *fedge() ; // for non T vertex
+ inline const Vec3r& point2d() const {return point2D();}
+ inline const Vec3r& point3d() const {return point3D();}
+ inline Vec3r normal() const {if(_Normals.size() == 1) return (*(_Normals.begin())); Exception::raiseException(); return *(_Normals.begin());}
+ //Material material() const ;
+ Id shape_id() const ;
+ const SShape* shape() const ;
+ float shape_importance() const ;
+
+ const int qi() const ;
+ occluder_container::const_iterator occluders_begin() const ;
+ occluder_container::const_iterator occluders_end() const ;
+ bool occluders_empty() const ;
+ int occluders_size() const ;
+ const Polygon3r& occludee() const ;
+ const SShape * occluded_shape() const ;
+ const bool occludee_empty() const ;
+ real z_discontinuity() const ;
+ //inline float local_average_depth() const ;
+ // inline float local_depth_variance() const ;
+ // inline real local_average_density(float sigma = 2.3f) const ;
+ //inline Vec3r shaded_color() const ;
+ // inline Vec3r orientation2d() const ;
+ // inline Vec3r orientation3d() const ;
+ // inline Vec3r curvature2d_as_vector() const ;
+ /*! angle in radians */
+ // inline real curvature2d_as_angle() const ;
+
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdge */
+ /* */
+ /* */
+ /**********************************/
+
+
+class ViewEdge;
+/*! Base Class for feature edges.
+ * This FEdge can represent a silhouette, a crease,
+ * a ridge/valley, a border or a suggestive contour.
+ * For silhouettes, the FEdge is oriented
+ * such as, the visible face lies on the left of the edge.
+ * For borders, the FEdge is oriented
+ * such as, the face lies on the left of the edge.
+ * An FEdge can represent an initial edge of the mesh
+ * or runs accross a face of the initial mesh depending
+ * on the smoothness or sharpness of the mesh.
+ * This class is specialized into a smooth and a sharp
+ * version since their properties slightly vary from
+ * one to the other.
+ */
+class LIB_VIEW_MAP_EXPORT FEdge : public Interface1D
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "FEdge" . */
+ virtual string getExactTypeName() const {
+ return "FEdge";
+ }
+
+ // Data access methods
+
+ /*! Returns the 2D length of the FEdge. */
+ virtual real getLength2D() const {
+ if (!_VertexA || !_VertexB)
+ return 0;
+ return (_VertexB->getPoint2D() - _VertexA->getPoint2D()).norm();
+ }
+
+ /*! Returns the Id of the FEdge. */
+ virtual Id getId() const {
+ return _Id;
+ }
+
+public:
+
+ // An edge can only be of one kind (SILHOUETTE or BORDER, etc...)
+ // For an multi-nature edge there must be several different FEdge.
+ // DEBUG:
+ // Vec3r A;
+ // Vec3r u;
+ // vector<Polygon3r> _Occludees;
+ // Vec3r intersection;
+ // vector<Vec3i> _Cells;
+
+protected:
+ SVertex *_VertexA;
+ SVertex *_VertexB;
+ Id _Id;
+ Nature::EdgeNature _Nature;
+ //vector<Polygon3r> _Occluders; // visibility // NON GERE PAR LE COPY CONSTRUCTOR!!
+
+ FEdge *_NextEdge; // next edge on the chain
+ FEdge *_PreviousEdge;
+ ViewEdge *_ViewEdge;
+ // Sometimes we need to deport the visibility computation onto another
+ // edge. For example the exact edges use edges of the mesh to
+ // compute their visibility
+
+ Polygon3r _aFace; // The occluded face which lies on the right of a silhouette edge
+ Vec3r _occludeeIntersection;
+ bool _occludeeEmpty;
+
+ bool _isSmooth;
+
+ bool _isInImage;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+ /*! Default constructor */
+ inline FEdge() {
+ userdata = NULL;
+ _VertexA = NULL;
+ _VertexB = NULL;
+ _Nature = Nature::NO_FEATURE;
+ _NextEdge = NULL;
+ _PreviousEdge = NULL;
+ _ViewEdge = NULL;
+ //_hasVisibilityPoint=false;
+ _occludeeEmpty = true;
+ _isSmooth = false;
+ _isInImage = true;
+ }
+ /*! Builds an FEdge going from vA to vB. */
+ inline FEdge(SVertex *vA, SVertex *vB) {
+ userdata = NULL;
+ _VertexA = vA;
+ _VertexB = vB;
+ _Nature = Nature::NO_FEATURE;
+ _NextEdge=NULL;
+ _PreviousEdge=NULL;
+ _ViewEdge = NULL;
+ //_hasVisibilityPoint=false;
+ _occludeeEmpty = true;
+ _isSmooth = false;
+ _isInImage = true;
+ }
+ /*! Copy constructor */
+ inline FEdge(FEdge& iBrother)
+ {
+ _VertexA = iBrother.vertexA();
+ _VertexB = iBrother.vertexB();
+ _NextEdge = iBrother.nextEdge();
+ _PreviousEdge = iBrother._PreviousEdge;
+ _Nature = iBrother.getNature();
+ _Id = iBrother._Id;
+ _ViewEdge = iBrother._ViewEdge;
+ //_hasVisibilityPoint = iBrother._hasVisibilityPoint;
+ //_VisibilityPointA = iBrother._VisibilityPointA;
+ //_VisibilityPointB = iBrother._VisibilityPointB;
+ _aFace = iBrother._aFace;
+ _occludeeEmpty = iBrother._occludeeEmpty;
+ _isSmooth = iBrother._isSmooth;
+ _isInImage = iBrother._isInImage;
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+ /*! Destructor */
+ virtual ~FEdge() {}
+ /*! Cloning method. */
+ virtual FEdge* duplicate()
+ {
+ FEdge *clone = new FEdge(*this);
+ return clone;
+ }
+ /* accessors */
+ /*! Returns the first SVertex. */
+ inline SVertex* vertexA() {return _VertexA;}
+ /*! Returns the second SVertex. */
+ inline SVertex* vertexB() {return _VertexB;}
+ /*! Returns the first SVertex if i=0, the seccond SVertex
+ * if i=1. */
+ inline SVertex* operator[](const unsigned short int& i) const{
+ return i%2==0 ? _VertexA : _VertexB;
+ }
+ /*! Returns the nature of the FEdge. */
+ inline Nature::EdgeNature getNature() const {return _Nature;}
+ /*! Returns the FEdge following this one in the ViewEdge.
+ * If this FEdge is the last of the ViewEdge, 0 is returned.
+ */
+ inline FEdge * nextEdge() {return _NextEdge;}
+ /*! Returns the Edge preceding this one in the ViewEdge.
+ * If this FEdge is the first one of the ViewEdge, 0 is returned.
+ */
+ inline FEdge * previousEdge() {return _PreviousEdge;}
+ inline SShape * shape() {return _VertexA->shape();}
+ //inline int invisibility() const {return _Occluders.size();}
+ int invisibility() const ;
+ //inline const vector<Polygon3r>& occluders() const {return _Occluders;}
+ /*! Returns a pointer to the ViewEdge to which this FEdge belongs to. */
+ inline ViewEdge * viewedge() const {return _ViewEdge;}
+ inline Vec3r center3d() {return Vec3r((_VertexA->point3D()+_VertexB->point3D())/2.0);}
+ inline Vec3r center2d() {return Vec3r((_VertexA->point2D()+_VertexB->point2D())/2.0);}
+ // inline bool hasVisibilityPoint() const {return _hasVisibilityPoint;}
+ // inline Vec3r visibilityPointA() const {return _VisibilityPointA;}
+ // inline Vec3r visibilityPointB() const {return _VisibilityPointB;}
+ inline const Polygon3r& aFace() const {return _aFace;}
+ inline const Vec3r& getOccludeeIntersection() { return _occludeeIntersection; }
+ inline bool getOccludeeEmpty() { return _occludeeEmpty; }
+ /*! Returns true if this FEdge is a smooth FEdge. */
+ inline bool isSmooth() const {return _isSmooth;}
+ inline bool isInImage () const { return _isInImage; }
+
+ /* modifiers */
+ /*! Sets the first SVertex. */
+ inline void setVertexA(SVertex *vA) {_VertexA = vA;}
+ /*! Sets the second SVertex. */
+ inline void setVertexB(SVertex *vB) {_VertexB = vB;}
+ /*! Sets the FEdge Id . */
+ inline void setId(const Id& id) {_Id = id;}
+ /*! Sets the pointer to the next FEdge. */
+ inline void setNextEdge(FEdge* iEdge) {_NextEdge = iEdge;}
+ /*! Sets the pointer to the previous FEdge. */
+ inline void setPreviousEdge(FEdge *iEdge) {_PreviousEdge = iEdge;}
+ /*! Sets the nature of this FEdge. */
+ inline void setNature(Nature::EdgeNature iNature) {_Nature = iNature;}
+ //inline void AddOccluder(Polygon3r& iPolygon) {_Occluders.push_back(iPolygon);}
+ /*! Sets the ViewEdge to which this FEdge belongs to. */
+ inline void setViewEdge(ViewEdge *iViewEdge) {_ViewEdge = iViewEdge;}
+ // inline void setHasVisibilityPoint(bool iBool) {_hasVisibilityPoint = iBool;}
+ // inline void setVisibilityPointA(const Vec3r& iPoint) {_VisibilityPointA = iPoint;}
+ // inline void setVisibilityPointB(const Vec3r& iPoint) {_VisibilityPointB = iPoint;}
+ inline void setaFace(Polygon3r& iFace) {_aFace = iFace;}
+ inline void setOccludeeIntersection(const Vec3r& iPoint) {_occludeeIntersection = iPoint;}
+ inline void setOccludeeEmpty(bool iempty) {_occludeeEmpty = iempty;}
+ /*! Sets the flag telling whether this FEdge is smooth or sharp.
+ * true for Smooth, false for Sharp.
+ */
+ inline void setSmooth(bool iFlag) {_isSmooth = iFlag;}
+ inline void setIsInImage (bool iFlag) { _isInImage = iFlag; }
+
+ /* checks whether two FEdge have a common vertex.
+ * Returns a pointer on the common vertex if it exists,
+ * NULL otherwise.
+ */
+ static inline SVertex* CommonVertex(FEdge *iEdge1, FEdge* iEdge2)
+ {
+ if((NULL == iEdge1) || (NULL == iEdge2))
+ return NULL;
+
+ SVertex *sv1 = iEdge1->vertexA();
+ SVertex *sv2 = iEdge1->vertexB();
+ SVertex *sv3 = iEdge2->vertexA();
+ SVertex *sv4 = iEdge2->vertexB();
+
+ if((sv1 == sv3) || (sv1 == sv4))
+ {
+ return sv1;
+ }
+ else if((sv2 == sv3) || (sv2 == sv4))
+ {
+ return sv2;
+ }
+
+ return NULL;
+ }
+
+ inline const SVertex* min2d() const
+ {
+ if(_VertexA->point2D() < _VertexB->point2D())
+ return _VertexA;
+ else
+ return _VertexB;
+ }
+ inline const SVertex* max2d() const
+ {
+ if(_VertexA->point2D() < _VertexB->point2D())
+ return _VertexB;
+ else
+ return _VertexA;
+ }
+
+ /* Information access interface */
+ /* Information access interface */
+
+ //Material material() const ;
+ Id shape_id() const ;
+ const SShape * shape() const ;
+ float shape_importance() const ;
+ inline const int qi() const {return invisibility();}
+ occluder_container::const_iterator occluders_begin() const ;
+ occluder_container::const_iterator occluders_end() const ;
+ bool occluders_empty() const ;
+ int occluders_size() const ;
+ inline const Polygon3r& occludee() const {return aFace();}
+ const SShape * occluded_shape() const ;
+ //inline const bool occludee_empty() const {return _occludeeEmpty;}
+ const bool occludee_empty() const ;
+ real z_discontinuity() const ;
+ // inline float local_average_depth(int iCombination = 0) const ;
+ // inline float local_depth_variance(int iCombination = 0) const ;
+ // inline real local_average_density(float sigma = 2.3f, int iCombination = 0) const ;
+ //inline Vec3r shaded_color(int iCombination = 0) const {}
+ int viewedge_nature() const ;
+ //float viewedge_length() const ;
+ inline Vec3r orientation2d() const {return Vec3r(_VertexB->point2d()-_VertexA->point2d());}
+ inline Vec3r orientation3d() const {return Vec3r(_VertexB->point3d()-_VertexA->point3d());}
+ // //inline real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);}
+ // inline Vec3r curvature2d_as_vector(int iCombination = 0) const ;
+ // /* angle in degrees*/
+ // inline real curvature2d_as_angle(int iCombination = 0) const ;
+
+
+ // Iterator access (Interface1D)
+ /*! Returns an iterator over the 2 (!) SVertex
+ * pointing to the first SVertex. */
+ virtual inline Interface0DIterator verticesBegin();
+ /*! Returns an iterator over the 2 (!) SVertex
+ * pointing after the last SVertex. */
+ virtual inline Interface0DIterator verticesEnd();
+
+ /*! Returns an iterator over the FEdge points,
+ * pointing to the first point. The difference with
+ * verticesBegin() is that here we can iterate over
+ * points of the FEdge at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of
+ * this FEdge.
+ */
+ virtual inline Interface0DIterator pointsBegin(float t=0.f);
+ /*! Returns an iterator over the FEdge points,
+ * pointing after the last point. The difference with
+ * verticesEnd() is that here we can iterate over
+ * points of the FEdge at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of
+ * this FEdge.
+ */
+ virtual inline Interface0DIterator pointsEnd(float t=0.f);
+};
+
+//
+// SVertexIterator
+//
+/////////////////////////////////////////////////
+
+namespace FEdgeInternal {
+
+ class SVertexIterator : public Interface0DIteratorNested
+ {
+ public:
+
+ SVertexIterator() {
+ _vertex = NULL;
+ _edge = NULL;
+ }
+
+ SVertexIterator(const SVertexIterator& vi) {
+ _vertex = vi._vertex;
+ _edge = vi._edge;
+ }
+
+ SVertexIterator(SVertex* v, FEdge* edge) {
+ _vertex = v;
+ _edge = edge;
+ }
+
+ SVertexIterator& operator=(const SVertexIterator& vi) {
+ _vertex = vi._vertex;
+ _edge = vi._edge;
+ return *this;
+ }
+
+ virtual string getExactTypeName() const {
+ return "SVertexIterator";
+ }
+
+ virtual SVertex& operator*() {
+ return *_vertex;
+ }
+
+ virtual SVertex* operator->() {
+ return &(operator*());
+ }
+
+ virtual SVertexIterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ virtual SVertexIterator operator++(int) {
+ SVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ virtual SVertexIterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ virtual SVertexIterator operator--(int) {
+ SVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ virtual int increment() {
+ if (_vertex == _edge->vertexB()) {
+ _vertex = 0;
+ return 0;
+ }
+
+ _vertex = _edge->vertexB();
+ return 0;
+ }
+
+ virtual int decrement() {
+ if (_vertex == _edge->vertexA()) {
+ _vertex = 0;
+ return 0;
+ }
+ _vertex = _edge->vertexA();
+ return 0;
+ }
+
+ virtual bool isBegin() const {
+ return _vertex == _edge->vertexA();
+ }
+
+ virtual bool isEnd() const {
+ return _vertex == _edge->vertexB();
+ }
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const {
+ const SVertexIterator* it_exact = dynamic_cast<const SVertexIterator*>(&it);
+ if (!it_exact)
+ return false;
+ return ((_vertex == it_exact->_vertex) &&
+ (_edge == it_exact->_edge));
+ }
+
+ virtual float t() const{
+ if(_vertex == _edge->vertexA()){
+ return 0;
+ }
+ return ((float)_edge->getLength2D());
+ }
+ virtual float u() const{
+ if(_vertex == _edge->vertexA()){
+ return 0;
+ }
+ return 1.0;
+ }
+ virtual SVertexIterator* copy() const {
+ return new SVertexIterator(*this);
+ }
+
+ private:
+
+ SVertex* _vertex;
+ FEdge* _edge;
+ };
+
+} // end of namespace FEdgeInternal
+
+// Iterator access (implementation)
+
+Interface0DIterator FEdge::verticesBegin() {
+ Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this));
+ return ret;
+}
+
+Interface0DIterator FEdge::verticesEnd() {
+ Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this));
+ return ret;
+}
+
+Interface0DIterator FEdge::pointsBegin(float t) {
+ return verticesBegin();
+}
+
+Interface0DIterator FEdge::pointsEnd(float t) {
+ return verticesEnd();
+}
+
+/*! Class defining a sharp FEdge. A Sharp FEdge
+ * corresponds to an initial edge of the input mesh.
+ * It can be a silhouette, a crease or a border.
+ * If it is a crease edge, then it is borded
+ * by two faces of the mesh. Face a lies on its right
+ * whereas Face b lies on its left.
+ * If it is a border edge, then it doesn't have any
+ * face on its right, and thus Face a = 0.
+ */
+class LIB_VIEW_MAP_EXPORT FEdgeSharp : public FEdge
+{
+protected:
+ Vec3r _aNormal; // When following the edge, normal of the right face
+ Vec3r _bNormal; // When following the edge, normal of the left face
+ unsigned _aFrsMaterialIndex;
+ unsigned _bFrsMaterialIndex;
+ bool _aFaceMark;
+ bool _bFaceMark;
+
+public:
+ /*! Returns the string "FEdgeSharp" . */
+ virtual string getExactTypeName() const {
+ return "FEdgeSharp";
+ }
+ /*! Default constructor. */
+ inline FEdgeSharp() : FEdge(){
+ _aFrsMaterialIndex = _bFrsMaterialIndex = 0;
+ _aFaceMark = _bFaceMark = false;
+ }
+ /*! Builds an FEdgeSharp going from vA to vB. */
+ inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB){
+ _aFrsMaterialIndex = _bFrsMaterialIndex = 0;
+ _aFaceMark = _bFaceMark = false;
+ }
+ /*! Copy constructor. */
+ inline FEdgeSharp(FEdgeSharp& iBrother) : FEdge(iBrother){
+ _aNormal = iBrother._aNormal;
+ _bNormal = iBrother._bNormal;
+ _aFrsMaterialIndex = iBrother._aFrsMaterialIndex;
+ _bFrsMaterialIndex = iBrother._bFrsMaterialIndex;
+ _aFaceMark = iBrother._aFaceMark;
+ _bFaceMark = iBrother._bFaceMark;
+
+ }
+ /*! Destructor. */
+ virtual ~FEdgeSharp() {}
+ /*! Cloning method. */
+ virtual FEdge* duplicate(){
+ FEdge *clone = new FEdgeSharp(*this);
+ return clone;
+ }
+ /*! Returns the normal to the face lying on the
+ * right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no normal.
+ */
+ inline const Vec3r& normalA() {return _aNormal;}
+ /*! Returns the normal to the face lying on the
+ * left of the FEdge.
+ */
+ inline const Vec3r& normalB() {return _bNormal;}
+ /*! Returns the index of the material of the face lying on the
+ * right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no material.
+ */
+ inline unsigned aFrsMaterialIndex() const {return _aFrsMaterialIndex;}
+ /*! Returns the material of the face lying on the
+ * right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no material.
+ */
+ const FrsMaterial& aFrsMaterial() const ;
+ /*! Returns the index of the material of the face lying on the
+ * left of the FEdge.
+ */
+ inline unsigned bFrsMaterialIndex() const {return _bFrsMaterialIndex;}
+ /*! Returns the material of the face lying on the
+ * left of the FEdge.
+ */
+ const FrsMaterial& bFrsMaterial() const ;
+ /*! Returns the face mark of the face lying on the right of the FEdge.
+ * If this FEdge is a border, it has no Face on its right and thus
+ * false is returned. */
+ inline bool aFaceMark() const {return _aFaceMark;}
+ /*! Returns the face mark of the face lying on the left of the FEdge. */
+ inline bool bFaceMark() const {return _bFaceMark;}
+
+ /*! Sets the normal to the face lying on the right of the FEdge. */
+ inline void setNormalA(const Vec3r& iNormal) {_aNormal = iNormal;}
+ /*! Sets the normal to the face lying on the left of the FEdge. */
+ inline void setNormalB(const Vec3r& iNormal) {_bNormal = iNormal;}
+ /*! Sets the index of the material lying on the right of the FEdge.*/
+ inline void setaFrsMaterialIndex(unsigned i) {_aFrsMaterialIndex = i;}
+ /*! Sets the index of the material lying on the left of the FEdge.*/
+ inline void setbFrsMaterialIndex(unsigned i) {_bFrsMaterialIndex = i;}
+ /*! Sets the face mark of the face lying on the right of the FEdge. */
+ inline void setaFaceMark(bool iFaceMark) {_aFaceMark = iFaceMark;}
+ /*! Sets the face mark of the face lying on the left of the FEdge. */
+ inline void setbFaceMark(bool iFaceMark) {_bFaceMark = iFaceMark;}
+
+};
+
+/*! Class defining a smooth edge. This kind of edge typically
+ * runs across a face of the input mesh. It can be
+ * a silhouette, a ridge or valley, a suggestive contour.
+ */
+class LIB_VIEW_MAP_EXPORT FEdgeSmooth : public FEdge
+{
+protected:
+ Vec3r _Normal;
+ unsigned _FrsMaterialIndex;
+ // bool _hasVisibilityPoint;
+ // Vec3r _VisibilityPointA; // The edge on which the visibility will be computed represented
+ // Vec3r _VisibilityPointB; // using its 2 extremity points A and B
+ void * _Face; // In case of exact silhouette, Face is the WFace crossed by Fedge
+ // NON GERE PAR LE COPY CONSTRUCTEUR
+ bool _FaceMark;
+public:
+ /*! Returns the string "FEdgeSmooth" . */
+ virtual string getExactTypeName() const {
+ return "FEdgeSmooth";
+ }
+ /*! Default constructor. */
+ inline FEdgeSmooth() : FEdge(){
+ _Face=0;
+ _FaceMark = false;
+ _FrsMaterialIndex = 0;
+ _isSmooth = true;
+ }
+ /*! Builds an FEdgeSmooth going from vA to vB. */
+ inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB){
+ _Face=0;
+ _FaceMark = false;
+ _FrsMaterialIndex = 0;
+ _isSmooth = true;
+
+ }
+ /*! Copy constructor. */
+ inline FEdgeSmooth(FEdgeSmooth& iBrother) : FEdge(iBrother){
+ _Normal = iBrother._Normal;
+ _Face = iBrother._Face;
+ _FaceMark = iBrother._FaceMark;
+ _FrsMaterialIndex = iBrother._FrsMaterialIndex;
+ _isSmooth = true;
+ }
+ /*! Destructor. */
+ virtual ~FEdgeSmooth() {}
+ /*! Cloning method. */
+ virtual FEdge* duplicate(){
+ FEdge *clone = new FEdgeSmooth(*this);
+ return clone;
+ }
+
+ inline void * face() const {return _Face;}
+ /*! Returns the face mark of the face it is running across. */
+ inline bool faceMark() const {return _FaceMark;}
+ /*! Returns the normal to the Face it is running accross. */
+ inline const Vec3r& normal() {return _Normal;}
+ /*! Returns the index of the material of the face it is running accross. */
+ inline unsigned frs_materialIndex() const {return _FrsMaterialIndex;}
+ /*! Returns the material of the face it is running accross. */
+ const FrsMaterial& frs_material() const ;
+
+ inline void setFace(void * iFace) {_Face = iFace;}
+ /*! Sets the face mark of the face it is running across. */
+ inline void setFaceMark(bool iFaceMark) {_FaceMark = iFaceMark;}
+ /*! Sets the normal to the Face it is running accross. */
+ inline void setNormal(const Vec3r& iNormal) {_Normal = iNormal;}
+ /*! Sets the index of the material of the face it is running accross. */
+ inline void setFrsMaterialIndex(unsigned i) {_FrsMaterialIndex = i;}
+};
+ /**********************************/
+ /* */
+ /* */
+ /* SShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+/*! Class to define a feature shape. It is the gathering
+ * of feature elements from an identified input shape
+ */
+class LIB_VIEW_MAP_EXPORT SShape
+{
+private:
+ vector<FEdge*> _chains; // list of fedges that are chains starting points.
+ vector<SVertex*> _verticesList; // list of all vertices
+ vector<FEdge*> _edgesList; // list of all edges
+ Id _Id;
+ string _Name;
+ BBox<Vec3r> _BBox;
+ vector<FrsMaterial> _FrsMaterials;
+
+ float _importance;
+
+ ViewShape *_ViewShape;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void* userdata; // added by E.T.
+ /*! Default constructor */
+ inline SShape()
+ {
+ userdata = 0;
+
+ _importance = 0.f;
+ _ViewShape = 0;
+ }
+ /*! Copy constructor */
+ inline SShape(SShape& iBrother)
+ {
+ userdata = 0;
+ _Id = iBrother._Id;
+ _Name = iBrother._Name;
+ _BBox = iBrother.bbox();
+ _FrsMaterials = iBrother._FrsMaterials;
+
+ _importance = iBrother._importance;
+
+ _ViewShape = iBrother._ViewShape;
+
+
+ //---------
+ // vertices
+ //---------
+ vector<SVertex*>::iterator sv,svend;
+ vector<SVertex*>& verticesList = iBrother.getVertexList();
+ for(sv=verticesList.begin(), svend=verticesList.end();
+ sv!=svend;
+ sv++)
+ {
+ SVertex *newv = new SVertex(*(*sv));
+ newv->setShape(this);
+ _verticesList.push_back(newv);
+ }
+
+ //------
+ // edges
+ //------
+ vector<FEdge*>::iterator e,eend;
+ vector<FEdge*>& edgesList = iBrother.getEdgeList();
+ for(e=edgesList.begin(),eend=edgesList.end();
+ e!=eend;
+ e++)
+ {
+ FEdge *newe = (*e)->duplicate();
+ _edgesList.push_back(newe);
+ }
+
+ //-------------------------
+ // starting chain edges
+ //-------------------------
+ vector<FEdge*>::iterator fe,fend;
+ vector<FEdge*>& fedges = iBrother.getChains();
+ for(fe=fedges.begin(),fend=fedges.end();
+ fe!=fend;
+ fe++)
+ {
+ _chains.push_back((FEdge*)((*fe)->userdata));
+ }
+
+
+ //-------------------------
+ // remap edges in vertices:
+ //-------------------------
+ for(sv=_verticesList.begin(),svend=_verticesList.end();
+ sv!=svend;
+ sv++)
+ {
+ const vector<FEdge*>& fedgeList = (*sv)->fedges();
+ vector<FEdge*> newfedgelist;
+ for(vector<FEdge*>::const_iterator fed=fedgeList.begin(),fedend=fedgeList.end();
+ fed!=fedend;
+ fed++)
+ {
+ FEdge *current = *fed;
+ newfedgelist.push_back((FEdge*)current->userdata);
+ }
+ (*sv)->setFEdges(newfedgelist);
+ }
+
+ //-------------------------------------
+ // remap vertices and nextedge in edges:
+ //-------------------------------------
+ for(e=_edgesList.begin(),eend=_edgesList.end();
+ e!=eend;
+ e++)
+ {
+ (*e)->setVertexA((SVertex*)((*e)->vertexA()->userdata));
+ (*e)->setVertexB((SVertex*)((*e)->vertexB()->userdata));
+ (*e)->setNextEdge((FEdge*)((*e)->nextEdge()->userdata));
+ (*e)->setPreviousEdge((FEdge*)((*e)->previousEdge()->userdata));
+ }
+
+
+ // reset all brothers userdata to NULL:
+ //-------------------------------------
+ //---------
+ // vertices
+ //---------
+ for(sv=_verticesList.begin(),svend=_verticesList.end();
+ sv!=svend;
+ sv++)
+ {
+ (*sv)->userdata = NULL;
+ }
+
+ //------
+ // edges
+ //------
+ for(e=_edgesList.begin(),eend=_edgesList.end();
+ e!=eend;
+ e++)
+ {
+ (*e)->userdata = NULL;
+ }
+ }
+ /*! Cloning method. */
+ virtual SShape * duplicate()
+ {
+ SShape *clone = new SShape(*this);
+ return clone;
+ }
+ /*! Destructor. */
+ virtual inline ~SShape()
+ {
+ vector<SVertex*>::iterator sv,svend;
+ vector<FEdge*>::iterator e,eend;
+ if(0 != _verticesList.size())
+ {
+ for(sv=_verticesList.begin(),svend=_verticesList.end();
+ sv!=svend;
+ sv++)
+ {
+ delete (*sv);
+ }
+ _verticesList.clear();
+ }
+
+ if(0 != _edgesList.size())
+ {
+ for(e=_edgesList.begin(),eend=_edgesList.end();
+ e!=eend;
+ e++)
+ {
+ delete (*e);
+ }
+ _edgesList.clear();
+ }
+
+ //! Clear the chains list
+ //-----------------------
+ if(0 != _chains.size())
+ {
+ _chains.clear();
+ }
+ }
+
+ /*! Adds a FEdge to the list of FEdges. */
+ inline void AddEdge(FEdge *iEdge)
+ {
+ _edgesList.push_back(iEdge);
+ }
+
+ /*! Adds a SVertex to the list of SVertex of this Shape.
+ * The SShape attribute of the SVertex is also set to 'this'.
+ */
+ inline void AddNewVertex(SVertex* iv) {iv->setShape(this);_verticesList.push_back(iv);}
+ inline void AddChain(FEdge *iEdge){
+ _chains.push_back(iEdge);
+ }
+
+ inline SVertex * CreateSVertex(const Vec3r& P3D, const Vec3r& P2D, const Id& id)
+ {
+ SVertex *Ia = new SVertex(P3D, id);
+ Ia->setPoint2D(P2D);
+ AddNewVertex(Ia);
+ return Ia;
+ }
+ /* splits an edge into several edges.
+ * The edge's vertices are passed rather than
+ * the edge itself. This way, all feature edges (SILHOUETTE,
+ * CREASE, BORDER) are splitted in the same time.
+ * The processed edges are flagged as done (using the userdata
+ * flag).One single new vertex is created whereas
+ * several splitted edges might created for the different
+ * kinds of edges. These new elements are added to the lists
+ * maintained by the shape.
+ * new chains are also created.
+ * ioA
+ * The first vertex for the edge that gets splitted
+ * ioB
+ * The second vertex for the edge that gets splitted
+ * iParameters
+ * A vector containing 2D real vectors indicating the parameters
+ * giving the intersections coordinates in 3D and in 2D.
+ * These intersections points must be sorted from B to A.
+ * Each parameter defines the intersection point I as I=A+T*AB.
+ * T<0 and T>1 are then incorrect insofar as they give intersections
+ * points that lie outside the segment.
+ * ioNewEdges
+ * The edges that are newly created (the initial edges are not
+ * included) are added to this list.
+ */
+ inline void SplitEdge(FEdge *fe, const vector<Vec2r>& iParameters, vector<FEdge*>& ioNewEdges)
+ {
+
+ SVertex *ioA = fe->vertexA();
+ SVertex *ioB = fe->vertexB();
+ Vec3r A = ioA->point3D();
+ Vec3r B = ioB->point3D();
+ Vec3r a = ioA->point2D();
+ Vec3r b = ioB->point2D();
+
+ Vec3r newpoint3d,newpoint2d;
+ vector<SVertex*> intersections;
+ real t,T;
+ for(vector<Vec2r>::const_iterator p=iParameters.begin(),pend=iParameters.end();
+ p!=pend;
+ p++)
+ {
+ T=(*p)[0];
+ t=(*p)[1];
+
+ if((t < 0) || (t > 1))
+ cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - " << ioB->getId() << endl;
+
+ // compute the 3D and 2D coordinates for the intersections points:
+ newpoint3d = Vec3r(A + T*(B-A));
+ newpoint2d = Vec3r(a + t*(b-a));
+
+ // create new SVertex:
+ // (we keep B's id)
+ SVertex* newVertex = new SVertex(newpoint3d, ioB->getId());
+ newVertex->setPoint2D(newpoint2d);
+
+ // Add this vertex to the intersections list:
+ intersections.push_back(newVertex);
+
+ // Add this vertex to this sshape:
+ AddNewVertex(newVertex);
+ }
+
+ for(vector<SVertex*>::iterator sv=intersections.begin(),svend=intersections.end();
+ sv!=svend;
+ sv++)
+ {
+ //SVertex *svA = fe->vertexA();
+ SVertex *svB = fe->vertexB();
+
+ // We split edge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+ // The edge AB becomes edge AA'.
+ (fe)->setVertexB((*sv));
+ // a new edge, A'B is created.
+ FEdge *newEdge;
+ if(fe->isSmooth()){
+ newEdge = new FEdgeSmooth((*sv), svB);
+ FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge);
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ se->setFrsMaterialIndex(fes->frs_materialIndex());
+ }else{
+ newEdge = new FEdgeSharp((*sv), svB);
+ FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge);
+ FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(fe);
+ se->setaFrsMaterialIndex(fes->aFrsMaterialIndex());
+ se->setbFrsMaterialIndex(fes->bFrsMaterialIndex());
+ }
+
+ newEdge->setNature((fe)->getNature());
+
+
+ // to build a new chain:
+ AddChain(newEdge);
+ // add the new edge to the sshape edges list.
+ AddEdge(newEdge);
+ // add new edge to the list of new edges passed as argument:
+ ioNewEdges.push_back(newEdge);
+
+ // update edge A'B for the next pointing edge
+ newEdge->setNextEdge((fe)->nextEdge());
+ fe->nextEdge()->setPreviousEdge(newEdge);
+ Id id(fe->getId().getFirst(), fe->getId().getSecond()+1);
+ newEdge->setId(fe->getId());
+ fe->setId(id);
+
+ // update edge AA' for the next pointing edge
+ //ioEdge->setNextEdge(newEdge);
+ (fe)->setNextEdge(NULL);
+
+ // update vertex pointing edges list:
+ // -- vertex B --
+ svB->Replace((fe), newEdge);
+ // -- vertex A' --
+ (*sv)->AddFEdge((fe));
+ (*sv)->AddFEdge(newEdge);
+ }
+
+ }
+
+ /* splits an edge into 2 edges. The new vertex and edge are added
+ * to the sshape list of vertices and edges
+ * a new chain is also created.
+ * returns the new edge.
+ * ioEdge
+ * The edge that gets splitted
+ * newpoint
+ * x,y,z coordinates of the new point.
+ */
+ inline FEdge* SplitEdgeIn2(FEdge* ioEdge, SVertex * ioNewVertex)
+ {
+ //soc unused - SVertex *A = ioEdge->vertexA();
+ SVertex *B = ioEdge->vertexB();
+
+
+ // We split edge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+
+ // a new edge, A'B is created.
+ FEdge *newEdge;
+ if(ioEdge->isSmooth()){
+ newEdge = new FEdgeSmooth(ioNewVertex, B);
+ FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge);
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(ioEdge);
+ se->setNormal(fes->normal());
+ se->setFrsMaterialIndex(fes->frs_materialIndex());
+ }else{
+ newEdge = new FEdgeSharp(ioNewVertex, B);
+ FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge);
+ FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(ioEdge);
+ se->setNormalA(fes->normalA());
+ se->setNormalB(fes->normalB());
+ se->setaFrsMaterialIndex(fes->aFrsMaterialIndex());
+ se->setbFrsMaterialIndex(fes->bFrsMaterialIndex());
+ }
+ newEdge->setNature(ioEdge->getNature());
+
+
+ if(ioEdge->nextEdge() != 0)
+ ioEdge->nextEdge()->setPreviousEdge(newEdge);
+
+ // update edge A'B for the next pointing edge
+ newEdge->setNextEdge(ioEdge->nextEdge());
+ // update edge A'B for the previous pointing edge
+ newEdge->setPreviousEdge(0); // because it is now a TVertex
+ Id id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond()+1);
+ newEdge->setId(ioEdge->getId());
+ ioEdge->setId(id);
+
+ // update edge AA' for the next pointing edge
+ ioEdge->setNextEdge(0); // because it is now a TVertex
+
+ // update vertex pointing edges list:
+ // -- vertex B --
+ B->Replace(ioEdge, newEdge);
+ // -- vertex A' --
+ ioNewVertex->AddFEdge(ioEdge);
+ ioNewVertex->AddFEdge(newEdge);
+
+ // to build a new chain:
+ AddChain(newEdge);
+ AddEdge(newEdge); // FIXME ??
+
+ // The edge AB becomes edge AA'.
+ ioEdge->setVertexB(ioNewVertex);
+
+ if(ioEdge->isSmooth()){
+ ((FEdgeSmooth*)newEdge)->setFace(((FEdgeSmooth*)ioEdge)->face());
+ }
+
+ return newEdge;
+ }
+
+ /*! Sets the Bounding Box of the Shape */
+ inline void setBBox(const BBox<Vec3r>& iBBox) {_BBox = iBBox;}
+
+ /*! Compute the bbox of the sshape */
+ inline void ComputeBBox()
+ {
+ if(0 == _verticesList.size())
+ return;
+
+ Vec3r firstVertex = _verticesList[0]->point3D();
+ real XMax = firstVertex[0];
+ real YMax = firstVertex[1];
+ real ZMax = firstVertex[2];
+
+ real XMin = firstVertex[0];
+ real YMin = firstVertex[1];
+ real ZMin = firstVertex[2];
+
+ vector<SVertex*>::iterator v,vend;
+ // parse all the coordinates to find
+ // the Xmax, YMax, ZMax
+ for(v=_verticesList.begin(),vend=_verticesList.end();
+ v!=vend;
+ v++)
+ {
+ Vec3r vertex = (*v)->point3D();
+ // X
+ real x = vertex[0];
+ if(x > XMax)
+ XMax = x;
+ if(x < XMin)
+ XMin = x;
+
+ // Y
+ real y = vertex[1];
+ if(y > YMax)
+ YMax = y;
+ if(y < YMin)
+ YMin = y;
+
+ // Z
+ real z = vertex[2];
+ if(z > ZMax)
+ ZMax = z;
+ if(z < ZMin)
+ ZMin = z;
+ }
+
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+ }
+
+ inline void RemoveEdgeFromChain(FEdge *iEdge)
+ {
+ for(vector<FEdge*>::iterator fe=_chains.begin(), feend=_chains.end();
+ fe!=feend;
+ fe++)
+ {
+ if(iEdge == (*fe))
+ {
+ _chains.erase(fe);
+ break;
+ }
+ }
+ }
+
+ inline void RemoveEdge(FEdge *iEdge)
+ {
+ for(vector<FEdge*>::iterator fe=_edgesList.begin(), feend=_edgesList.end();
+ fe!=feend;
+ fe++)
+ {
+ if(iEdge == (*fe))
+ {
+ _edgesList.erase(fe);
+ break;
+ }
+ }
+ }
+
+ /* accessors */
+ /*! Returns the list of SVertex of the Shape. */
+ inline vector<SVertex*>& getVertexList() {return _verticesList;} // Get vertices list
+ /*! Returns the list of FEdges of the Shape. */
+ inline vector<FEdge*>& getEdgeList() {return _edgesList;} // Get edges list
+ inline vector<FEdge*>& getChains() {return _chains;}
+ /*! Returns the bounding box of the shape. */
+ inline const BBox<Vec3r>& bbox() {return _BBox;}
+ /*! Returns the ith material of the shape. */
+ inline const FrsMaterial& frs_material(unsigned i) const {return _FrsMaterials[i];}
+ /*! Returns the list of materials of the Shape. */
+ inline const vector<FrsMaterial>& frs_materials() const {return _FrsMaterials;}
+ inline ViewShape * viewShape() {return _ViewShape;}
+ inline float importance() const {return _importance;}
+ /*! Returns the Id of the Shape. */
+ inline Id getId() const { return _Id; }
+ /*! Returns the name of the Shape. */
+ inline const string& getName() const { return _Name; }
+
+ /* Modififers */
+ /*! Sets the Id of the shape.*/
+ inline void setId(Id id) {_Id = id;}
+ /*! Sets the name of the shape.*/
+ inline void setName(const string& name) {_Name = name;}
+ /*! Sets the list of materials for the shape */
+ inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials) {_FrsMaterials = iMaterials;}
+ inline void setViewShape(ViewShape *iShape) {_ViewShape = iShape;}
+ inline void setImportance(float importance){_importance = importance;}
+};
+
+#endif // SILHOUETTE_H
diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
new file mode 100755
index 00000000000..6327956ca80
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
@@ -0,0 +1,272 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Silhouette.h"
+#include "SilhouetteGeomEngine.h"
+#include "../geometry/GeomUtils.h"
+
+using namespace std;
+
+Vec3r SilhouetteGeomEngine::_Viewpoint = Vec3r(0,0,0);
+real SilhouetteGeomEngine::_translation[3] = {0,0,0};
+real SilhouetteGeomEngine::_modelViewMatrix[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+real SilhouetteGeomEngine::_projectionMatrix[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+real SilhouetteGeomEngine::_transform[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+int SilhouetteGeomEngine::_viewport[4] = {1,1,1,1}; // the viewport
+real SilhouetteGeomEngine::_Focal = 0.0;
+
+real SilhouetteGeomEngine::_glProjectionMatrix[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+real SilhouetteGeomEngine::_glModelViewMatrix[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+real SilhouetteGeomEngine::_znear = 0.0;
+real SilhouetteGeomEngine::_zfar = 100.0;
+bool SilhouetteGeomEngine::_isOrthographicProjection = false;
+
+SilhouetteGeomEngine * SilhouetteGeomEngine::_pInstance = 0;
+
+void SilhouetteGeomEngine::setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], const int iViewport[4], real iFocal)
+{
+ unsigned int i,j;
+ _translation[0] = iModelViewMatrix[3][0];
+ _translation[1] = iModelViewMatrix[3][1];
+ _translation[2] = iModelViewMatrix[3][2];
+
+ for(i=0; i<4; i++){
+ for(j=0; j<4; j++)
+ {
+ _modelViewMatrix[i][j] = iModelViewMatrix[j][i];
+ _glModelViewMatrix[i][j] = iModelViewMatrix[i][j];
+ }
+ }
+
+ for(i=0; i<4; i++){
+ for(j=0; j<4; j++)
+ {
+ _projectionMatrix[i][j] = iProjectionMatrix[j][i];
+ _glProjectionMatrix[i][j] = iProjectionMatrix[i][j];
+ }
+ }
+
+ for(i=0; i<4; i++){
+ for(j=0; j<4; j++)
+ {
+ _transform[i][j] = 0;
+ for(unsigned int k=0; k<4; k++)
+ _transform[i][j] += _projectionMatrix[i][k] * _modelViewMatrix[k][j];
+ }
+ }
+
+ for(i=0; i<4; i++){
+ _viewport[i] = iViewport[i];
+ }
+ _Focal = iFocal;
+
+ _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0);
+}
+
+void SilhouetteGeomEngine::setFrustum(real iZNear, real iZFar)
+{
+ _znear = iZNear;
+ _zfar = iZFar;
+}
+
+void SilhouetteGeomEngine::retrieveViewport(int viewport[4]){
+ memcpy(viewport, _viewport, 4*sizeof(int));
+}
+//#define HUGE 1e9
+
+void SilhouetteGeomEngine::ProjectSilhouette(vector<SVertex*>& ioVertices)
+{
+ Vec3r newPoint;
+ // real min=HUGE;
+ // real max=-HUGE;
+ vector<SVertex*>::iterator sv, svend;
+ const real depth = _zfar - _znear;
+ const real fac = (depth < 1e-6) ? 1.0 : 1.0 / depth;
+
+ for(sv=ioVertices.begin(), svend=ioVertices.end();
+ sv!=svend;
+ sv++)
+ {
+ GeomUtils::fromWorldToImage((*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport);
+ newPoint[2] = (-newPoint[2]-_znear) * fac; // normalize Z between 0 and 1
+ (*sv)->setPoint2D(newPoint);
+ //cerr << (*sv)->point2d().z() << " ";
+ // real d=(*sv)->point2d()[2];
+ // if (d>max) max =d;
+ // if (d<min) min =d;
+ }
+ // for(sv=ioVertices.begin(), svend=ioVertices.end();
+ // sv!=svend;
+ // sv++)
+ // {
+ // Vec3r P((*sv)->point2d());
+ // (*sv)->setPoint2D(Vec3r(P[0], P[1], 1.0-(P[2]-min)/(max-min)));
+ // //cerr<<(*sv)->point2d()[2]<<" ";
+ // }
+}
+
+void SilhouetteGeomEngine::ProjectSilhouette(SVertex* ioVertex)
+{
+ Vec3r newPoint;
+ // real min=HUGE;
+ // real max=-HUGE;
+ vector<SVertex*>::iterator sv, svend;
+ const real depth = _zfar - _znear;
+ const real fac = (depth < 1e-6) ? 1.0 : 1.0 / depth;
+ GeomUtils::fromWorldToImage(ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport);
+ newPoint[2] = (-newPoint[2]-_znear) * fac; // normalize Z between 0 and 1
+ ioVertex->setPoint2D(newPoint);
+}
+
+real SilhouetteGeomEngine::ImageToWorldParameter(FEdge *fe, real t)
+{
+ if( _isOrthographicProjection )
+ return t;
+
+ // we need to compute for each parameter t the corresponding
+ // parameter T which gives the intersection in 3D.
+ real T;
+
+ // suffix w for world, c for camera, r for retina, i for image
+ Vec3r Aw = (fe)->vertexA()->point3D();
+ Vec3r Bw = (fe)->vertexB()->point3D();
+ Vec3r Ac, Bc;
+ GeomUtils::fromWorldToCamera(Aw, Ac, _modelViewMatrix);
+ GeomUtils::fromWorldToCamera(Bw, Bc, _modelViewMatrix);
+ Vec3r ABc = Bc - Ac;
+#if 0
+ cout << "Ac " << Ac << endl;
+ cout << "Bc " << Bc << endl;
+ cout << "ABc " << ABc << endl;
+#endif
+ Vec3r Ai = (fe)->vertexA()->point2D();
+ Vec3r Bi = (fe)->vertexB()->point2D();
+ Vec3r Ii = Ai + t * (Bi - Ai); // the intersection point in the 2D image space
+ Vec3r Ir, Ic;
+ GeomUtils::fromImageToRetina(Ii, Ir, _viewport);
+
+ real alpha, beta, denom;
+ real m11 = _projectionMatrix[0][0];
+ real m13 = _projectionMatrix[0][2];
+ real m22 = _projectionMatrix[1][1];
+ real m23 = _projectionMatrix[1][2];
+
+ if (fabs(ABc[0]) > 1e-6) {
+
+ alpha = ABc[2] / ABc[0];
+ beta = Ac[2] - alpha * Ac[0];
+ denom = alpha * (Ir[0] + m13) + m11;
+ if (fabs(denom) < 1e-6)
+ goto iter;
+ Ic[0] = -beta * (Ir[0] + m13) / denom;
+// Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22;
+// Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2];
+ T = (Ic[0] - Ac[0]) / ABc[0];
+
+ } else if (fabs(ABc[1]) > 1e-6) {
+
+ alpha = ABc[2] / ABc[1];
+ beta = Ac[2] - alpha * Ac[1];
+ denom = alpha * (Ir[1] + m23) + m22;
+ if (fabs(denom) < 1e-6)
+ goto iter;
+ Ic[1] = -beta * (Ir[1] + m23) / denom;
+// Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11;
+// Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2];
+ T = (Ic[1] - Ac[1]) / ABc[1];
+
+ } else {
+
+iter: bool x_coords, less_than;
+ if (fabs(Bi[0] - Ai[0]) > 1e-6) {
+ x_coords = true;
+ less_than = Ai[0] < Bi[0];
+ } else {
+ x_coords = false;
+ less_than = Ai[1] < Bi[1];
+ }
+ Vec3r Pc, Pr, Pi;
+ real T_sta = 0.0;
+ real T_end = 1.0;
+ real delta_x, delta_y, dist, dist_threshold = 1e-6;
+ int i, max_iters = 100;
+ for (i = 0; i < max_iters; i++) {
+ T = T_sta + 0.5 * (T_end - T_sta);
+ Pc = Ac + T * ABc;
+ GeomUtils::fromCameraToRetina(Pc, Pr, _projectionMatrix);
+ GeomUtils::fromRetinaToImage(Pr, Pi, _viewport);
+ delta_x = Ii[0] - Pi[0];
+ delta_y = Ii[1] - Pi[1];
+ dist = sqrt(delta_x * delta_x + delta_y * delta_y);
+ if (dist < dist_threshold)
+ break;
+ if (x_coords) {
+ if (less_than) {
+ if (Pi[0] < Ii[0]) { T_sta = T; } else { T_end = T; }
+ } else {
+ if (Pi[0] > Ii[0]) { T_sta = T; } else { T_end = T; }
+ }
+ } else {
+ if (less_than) {
+ if (Pi[1] < Ii[1]) { T_sta = T; } else { T_end = T; }
+ } else {
+ if (Pi[1] > Ii[1]) { T_sta = T; } else { T_end = T; }
+ }
+ }
+ }
+#if 0
+ printf("SilhouetteGeomEngine::ImageToWorldParameter(): #iters = %d, dist = %e\n", i, dist);
+#endif
+ if (i == max_iters)
+ printf("SilhouetteGeomEngine::ImageToWorldParameter(): reached to max_iters (dist = %e)\n", dist);
+ }
+
+ return T;
+}
+
+Vec3r SilhouetteGeomEngine::WorldToImage(const Vec3r& M)
+
+{
+
+ const real depth = _zfar - _znear;
+ const real fac = (depth < 1e-6) ? 1.0 : 1.0 / depth;
+ Vec3r newPoint;
+ GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport);
+ newPoint[2] = (-newPoint[2]-_znear) * fac; // normalize Z between 0 and 1
+ return newPoint;
+
+}
+
diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h
new file mode 100755
index 00000000000..5bd89f8a162
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h
@@ -0,0 +1,123 @@
+//
+// Filename : SilhouetteGeomEngine.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to perform all geometric operations dedicated
+// to silhouette. That, for example, implies that
+// this geom engine has as member data the viewpoint,
+// transformations, projections...
+// Date of creation : 03/09/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SILHOUETTEGEOMENGINE_H
+# define SILHOUETTEGEOMENGINE_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+
+using namespace Geometry;
+
+class SVertex;
+class FEdge;
+
+class LIB_VIEW_MAP_EXPORT SilhouetteGeomEngine
+{
+private:
+ static Vec3r _Viewpoint; // The viewpoint under which the silhouette has to be computed
+ static real _translation[3];
+ static real _modelViewMatrix[4][4]; // the model view matrix (_modelViewMatrix[i][j] means element of line i and column j)
+ static real _projectionMatrix[4][4]; // the projection matrix (_projectionMatrix[i][j] means element of line i and column j)
+ static real _transform[4][4]; // the global transformation from world to screen (projection included) (_transform[i][j] means element of line i and column j)
+ static int _viewport[4]; // the viewport
+ static real _Focal;
+
+ static real _znear;
+ static real _zfar;
+
+ static real _glProjectionMatrix[4][4]; // GL style (column major) projection matrix
+ static real _glModelViewMatrix[4][4]; // GL style (column major) model view matrix
+
+static bool _isOrthographicProjection;
+
+
+ static SilhouetteGeomEngine *_pInstance;
+public:
+
+ /*! retrieves an instance on the singleton */
+ static SilhouetteGeomEngine * getInstance()
+ {
+ if(0 == _pInstance)
+ {
+ _pInstance = new SilhouetteGeomEngine;
+ }
+ return _pInstance;
+ }
+
+ /*! Sets the current viewpoint */
+ static inline void setViewpoint(const Vec3r& ivp) {_Viewpoint = ivp;}
+
+ /*! Sets the current transformation
+ * iModelViewMatrix
+ * The 4x4 model view matrix, in column major order (openGL like).
+ * iProjection matrix
+ * The 4x4 projection matrix, in column major order (openGL like).
+ * iViewport
+ * The viewport. 4 real array: origin.x, origin.y, width, length
+ * iFocal
+ * The focal length
+ */
+ static void setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], const int iViewport[4], real iFocal) ;
+
+ /*! Sets the current znear and zfar
+ */
+ static void setFrustum(real iZNear, real iZFar) ;
+
+ /* accessors */
+ static void retrieveViewport(int viewport[4]);
+
+ /*! Projects the silhouette in camera coordinates
+ * This method modifies the ioEdges passed as argument.
+ * ioVertices
+ * The vertices to project. It is modified during the
+ * operation.
+ */
+ static void ProjectSilhouette(std::vector<SVertex*>& ioVertices);
+ static void ProjectSilhouette(SVertex* ioVertex);
+
+ /*! transforms the parameter t defining a 2D intersection for edge fe in order to obtain
+ * the parameter giving the corresponding 3D intersection.
+ * Returns the 3D parameter
+ * fe
+ * The edge
+ * t
+ * The parameter for the 2D intersection.
+ */
+ static real ImageToWorldParameter(FEdge *fe, real t);
+
+ /*! From world to image */
+ static Vec3r WorldToImage(const Vec3r& M);
+};
+
+#endif // SILHOUETTEGEOMENGINE_H
diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
new file mode 100644
index 00000000000..c1647050d0d
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
@@ -0,0 +1,221 @@
+//
+// Filename : SphericalGrid.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2010-12-19
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SphericalGrid.h"
+
+#include <stdexcept>
+#include <algorithm>
+
+using namespace std;
+
+// Helper Classes
+
+// OccluderData
+///////////////
+
+// Cell
+/////////
+
+SphericalGrid::Cell::Cell () {}
+
+SphericalGrid::Cell::~Cell () {}
+
+void SphericalGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY) {
+ const real epsilon = 1.0e-06;
+ boundary[0] = x - epsilon;
+ boundary[1] = x + sizeX + epsilon;
+ boundary[2] = y - epsilon;
+ boundary[3] = y + sizeY + epsilon;
+}
+
+bool SphericalGrid::Cell::compareOccludersByShallowestPoint (const SphericalGrid::OccluderData* a, const SphericalGrid::OccluderData* b) {
+ return a->shallowest < b->shallowest;
+}
+
+void SphericalGrid::Cell::indexPolygons() {
+ // Sort occluders by their shallowest points.
+ sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint);
+}
+
+// Iterator
+//////////////////
+
+SphericalGrid::Iterator::Iterator (SphericalGrid& grid, Vec3r& center, real epsilon)
+ : _target(SphericalGrid::Transform::sphericalProjection(center)),
+ _foundOccludee(false)
+{
+ // Find target cell
+ _cell = grid.findCell(_target);
+ #if sphericalgridlogging == 1
+ cout << "Searching for occluders of edge centered at " << _target << " in cell ["
+ << _cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2]
+ << ", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl;
+ #endif
+
+ // Set iterator
+ _current = _cell->faces.begin();
+}
+
+SphericalGrid::Iterator::~Iterator () {}
+
+// SphericalGrid
+/////////////////
+
+SphericalGrid::SphericalGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, bool enableQI)
+ : _viewpoint(viewpoint),
+ _enableQI(enableQI)
+{
+ cout << "Generate Cell structure" << endl;
+ // Generate Cell structure
+ assignCells(source, density, viewMap);
+ cout << "Distribute occluders" << endl;
+ // Fill Cells
+ distributePolygons(source);
+ cout << "Reorganize cells" << endl;
+ // Reorganize Cells
+ reorganizeCells();
+ cout << "Ready to use SphericalGrid" << endl;
+}
+
+SphericalGrid::~SphericalGrid () {
+}
+
+void SphericalGrid::assignCells (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap) {
+ _cellSize = density.cellSize();
+ _cellsX = density.cellsX();
+ _cellsY = density.cellsY();
+ _cellOrigin[0] = density.cellOrigin(0);
+ _cellOrigin[1] = density.cellOrigin(1);
+
+ // Now allocate the cell table and fill it with default (empty) cells
+ _cells.resize(_cellsX * _cellsY);
+ for ( cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i ) {
+ (*i) = NULL;
+ }
+
+ // Identify cells that will be used, and set the dimensions for each
+ ViewMap::fedges_container& fedges = viewMap->FEdges();
+ for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f ) {
+ if ( (*f)->isInImage() ) {
+ Vec3r point = SphericalGrid::Transform::sphericalProjection((*f)->center3d());
+ unsigned i, j;
+ getCellCoordinates(point, i, j);
+ if ( _cells[i * _cellsY + j] == NULL ) {
+ // This is an uninitialized cell
+
+ real x, y, width, height;
+
+ x = _cellOrigin[0] + _cellSize * i;
+ width = _cellSize;
+
+ y = _cellOrigin[1] + _cellSize * j;
+ height = _cellSize;
+
+ // Initialize cell
+ Cell* b = _cells[i * _cellsY + j] = new Cell();
+ b->setDimensions(x, y, width, height);
+ }
+ }
+ }
+}
+
+void SphericalGrid::distributePolygons (OccluderSource& source) {
+ unsigned long nFaces = 0;
+ unsigned long nKeptFaces = 0;
+
+ for ( source.begin(); source.isValid(); source.next() ) {
+ OccluderData* occluder = NULL;
+
+ try {
+ if ( insertOccluder(source, occluder) ) {
+ _faces.push_back(occluder);
+ ++nKeptFaces;
+ }
+ } catch (...) {
+ // If an exception was thrown, _faces.push_back() cannot have succeeded.
+ // occluder is not owned by anyone, and must be deleted.
+ // If the exception was thrown before or during new OccluderData(), then
+ // occluder is NULL, and this delete is harmless.
+ delete occluder;
+ throw;
+ }
+ ++nFaces;
+ }
+ cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl;
+}
+
+void SphericalGrid::reorganizeCells () {
+ // Sort the occluders by shallowest point
+ for ( vector<Cell*>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i ) {
+ if ( *i != NULL ) {
+ (*i)->indexPolygons();
+ }
+ }
+}
+
+void SphericalGrid::getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y) {
+ x = min(_cellsX - 1, (unsigned) floor (max((double) 0.0f, point[0] - _cellOrigin[0]) / _cellSize));
+ y = min(_cellsY - 1, (unsigned) floor (max((double) 0.0f, point[1] - _cellOrigin[1]) / _cellSize));
+}
+
+SphericalGrid::Cell* SphericalGrid::findCell(const Vec3r& point) {
+ unsigned x, y;
+ getCellCoordinates(point, x, y);
+ return _cells[x * _cellsY + y];
+}
+
+bool SphericalGrid::orthographicProjection () const {
+ return false;
+}
+
+const Vec3r& SphericalGrid::viewpoint() const {
+ return _viewpoint;
+}
+
+bool SphericalGrid::enableQI() const {
+ return _enableQI;
+}
+
+SphericalGrid::Transform::Transform () : GridHelpers::Transform() {
+}
+
+Vec3r SphericalGrid::Transform::operator() (const Vec3r& point) const {
+ return sphericalProjection(point);
+}
+
+Vec3r SphericalGrid::Transform::sphericalProjection(const Vec3r& M) {
+ Vec3r newPoint;
+
+ newPoint[0] = ::atan(M[0] / M[2]);
+ newPoint[1] = ::atan(M[1] / M[2]);
+ newPoint[2] = ::sqrt(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]);
+
+ return newPoint;
+}
+
diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.h b/source/blender/freestyle/intern/view_map/SphericalGrid.h
new file mode 100644
index 00000000000..55cdee19a80
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SphericalGrid.h
@@ -0,0 +1,388 @@
+//
+// Filename : SphericalGrid.h
+// Author(s) : Alexander Beels
+// Purpose : Class to define a cell grid surrounding
+// the projected image of a scene
+// Date of creation : 2010-12-19
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SPHERICALGRID_H
+#define SPHERICALGRID_H
+
+#define sphericalgridlogging 0
+
+// I would like to avoid using deque because including ViewMap.h and <deque> or <vector>
+// separately results in redefinitions of identifiers. ViewMap.h already includes <vector>
+// so it should be a safe fall-back.
+//#include <vector>
+//#include <deque>
+#include "ViewMap.h"
+#include "../winged_edge/WEdge.h"
+#include "../geometry/Polygon.h"
+#include "../system/PointerSequence.h"
+#include "../geometry/BBox.h"
+#include "../geometry/GridHelpers.h"
+#include "OccluderSource.h"
+#include "GridDensityProvider.h"
+
+class SphericalGrid
+{
+public:
+ // Helper classes
+ struct OccluderData {
+ explicit OccluderData (OccluderSource& source, Polygon3r& p);
+ Polygon3r poly;
+ Polygon3r cameraSpacePolygon;
+ real shallowest, deepest;
+ // N.B. We could, of course, store face in poly's userdata
+ // member, like the old ViewMapBuilder code does. However,
+ // code comments make it clear that userdata is deprecated,
+ // so we avoid the temptation to save 4 or 8 bytes.
+ WFace* face;
+ };
+
+private:
+ struct Cell {
+ // Can't store Cell in a vector without copy and assign
+ //Cell(const Cell& other);
+ //Cell& operator= (const Cell& other);
+
+ explicit Cell ();
+ ~Cell ();
+
+ static bool compareOccludersByShallowestPoint (const OccluderData* a, const OccluderData* b);
+
+ void setDimensions(real x, real y, real sizeX, real sizeY);
+ void checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder);
+ void indexPolygons();
+
+ real boundary[4];
+ //deque<OccluderData*> faces;
+ vector<OccluderData*> faces;
+ };
+
+public:
+ /*****
+
+ Iterator needs to allow the user to avoid full 3D comparison in
+ two cases:
+
+ (1) Where (*current)->deepest < target[2], where the occluder is
+ unambiguously in front of the target point.
+
+ (2) Where (*current)->shallowest > target[2], where the occluder
+ is unambiguously in back of the target point.
+
+ In addition, when used by OptimizedFindOccludee, Iterator should
+ stop iterating as soon as it has an occludee candidate and
+ (*current)->shallowest > candidate[2], because at that point forward
+ no new occluder could possibly be a better occludee.
+
+ *****/
+
+ class Iterator {
+ public:
+ // epsilon is not used in this class, but other grids with the same interface may need an epsilon
+ explicit Iterator (SphericalGrid& grid, Vec3r& center, real epsilon=1e-06);
+ ~Iterator ();
+ void initBeforeTarget ();
+ void initAfterTarget ();
+ void nextOccluder ();
+ void nextOccludee ();
+ bool validBeforeTarget();
+ bool validAfterTarget();
+ WFace* getWFace() const;
+ Polygon3r* getCameraSpacePolygon();
+ void reportDepth(Vec3r origin, Vec3r u, real t);
+ private:
+ bool testOccluder(bool wantOccludee);
+ void markCurrentOccludeeCandidate(real depth);
+
+ Cell* _cell;
+ Vec3r _target;
+ bool _foundOccludee;
+ real _occludeeDepth;
+ //deque<OccluderData*>::iterator _current, _occludeeCandidate;
+ vector<OccluderData*>::iterator _current, _occludeeCandidate;
+ };
+
+ class Transform : public GridHelpers::Transform {
+ public:
+ explicit Transform ();
+ explicit Transform (Transform& other);
+ Vec3r operator() (const Vec3r& point) const;
+ static Vec3r sphericalProjection(const Vec3r& M);
+ };
+
+private:
+ // Prevent implicit copies and assignments.
+ SphericalGrid(const SphericalGrid& other);
+ SphericalGrid& operator= (const SphericalGrid& other);
+public:
+ explicit SphericalGrid (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, bool enableQI);
+ virtual ~SphericalGrid();
+
+ // Generate Cell structure
+ void assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap);
+ // Fill Cells
+ void distributePolygons(OccluderSource& source);
+ // Insert one polygon into each matching cell,
+ // return true if any cell consumes the polygon
+ bool insertOccluder(OccluderSource& source, OccluderData*& occluder);
+ // Sort occluders in each cell
+ void reorganizeCells();
+
+ Cell* findCell(const Vec3r& point);
+
+ // Accessors:
+ bool orthographicProjection() const;
+ const Vec3r& viewpoint() const;
+ bool enableQI() const;
+
+private:
+ void getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y);
+
+ typedef PointerSequence<vector<Cell*>, Cell*> cellContainer;
+ //typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer;
+ typedef PointerSequence<vector<OccluderData*>, OccluderData*> occluderContainer;
+ unsigned _cellsX, _cellsY;
+ float _cellSize;
+ float _cellOrigin[2];
+ cellContainer _cells;
+ occluderContainer _faces;
+ Vec3r _viewpoint;
+ bool _enableQI;
+};
+
+inline void SphericalGrid::Iterator::initBeforeTarget () {
+ _current = _cell->faces.begin();
+ while ( _current != _cell->faces.end() && ! testOccluder(false) ) {
+ ++_current;
+ }
+}
+
+inline void SphericalGrid::Iterator::initAfterTarget () {
+ if ( _foundOccludee ) {
+ #if sphericalgridlogging == 1
+ std::cout << "\tStarting occludee search from occludeeCandidate at depth " << _occludeeDepth << std::endl;
+ #endif
+ _current = _occludeeCandidate;
+ return;
+ }
+
+ #if sphericalgridlogging == 1
+ std::cout << "\tStarting occludee search from current position" << std::endl;
+ #endif
+
+ while ( _current != _cell->faces.end() && ! testOccluder(true) ) {
+ ++_current;
+ }
+}
+
+inline bool SphericalGrid::Iterator::testOccluder (bool wantOccludee) {
+ // End-of-list is not even a valid iterator position
+ if ( _current == _cell->faces.end() ) {
+ // Returning true seems strange, but it will break us out of whatever loop
+ // is calling testOccluder, and _current=_cell->face.end() will make
+ // the calling routine give up.
+ return true;
+ }
+ #if sphericalgridlogging == 1
+ std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0];
+ for ( unsigned i = 1; i < (*_current)->poly.getVertices().size(); ++i ) {
+ std::cout << ", " << (*_current)->poly.getVertices()[i];
+ }
+ std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl;
+ #endif
+
+
+ // If we have an occluder candidate and we are unambiguously after it, abort
+ if ( _foundOccludee && (*_current)->shallowest > _occludeeDepth ) {
+ #if sphericalgridlogging == 1
+ std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl;
+ #endif
+ _current = _cell->faces.end();
+
+ // See note above
+ return true;
+ }
+
+ // Specific continue or stop conditions when searching for each type
+ if ( wantOccludee ) {
+ if ( (*_current)->deepest < _target[2] ) {
+ #if sphericalgridlogging == 1
+ std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl;
+ #endif
+ return false;
+ }
+ } else {
+ if ( (*_current)->shallowest > _target[2] ) {
+ #if sphericalgridlogging == 1
+ std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl;
+ #endif
+ return true;
+ }
+ }
+
+ // Depthwise, this is a valid occluder.
+
+ // Check to see if target is in the 2D bounding box
+ Vec3r bbMin, bbMax;
+ (*_current)->poly.getBBox(bbMin, bbMax);
+ if ( _target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || _target[1] > bbMax[1] ) {
+ #if sphericalgridlogging == 1
+ std::cout << "\t\tSkipping: bounding box violation" << std::endl;
+ #endif
+ return false;
+ }
+
+ // We've done all the corner cutting we can.
+ // Let the caller work out whether or not
+ // the geometry is correct.
+ return true;
+}
+
+inline void SphericalGrid::Iterator::reportDepth (Vec3r origin, Vec3r u, real t) {
+ // The reported depth is the length of a ray in camera space
+ // We need to convert it into the distance from viewpoint
+ // If origin is the viewpoint, depth == t
+ // A future optimization could allow the caller to tell us if origin is viewponit or target,
+ // at the cost of changing the OptimizedGrid API.
+ real depth = (origin + u * t).norm();
+ #if sphericalgridlogging == 1
+ std::cout << "\t\tReporting depth of occluder/ee: " << depth;
+ #endif
+ if ( depth > _target[2] ) {
+ #if sphericalgridlogging == 1
+ std::cout << " is deeper than target" << std::endl;
+ #endif
+ // If the current occluder is the best occludee so far, save it.
+ if ( ! _foundOccludee || _occludeeDepth > depth ) {
+ markCurrentOccludeeCandidate(depth);
+ }
+ } else {
+ #if sphericalgridlogging == 1
+ std::cout << std::endl;
+ #endif
+ }
+}
+
+inline void SphericalGrid::Iterator::nextOccluder () {
+ if ( _current != _cell->faces.end() ) {
+ do {
+ ++_current;
+ } while ( _current != _cell->faces.end() && ! testOccluder(false) );
+ }
+}
+
+inline void SphericalGrid::Iterator::nextOccludee () {
+ if ( _current != _cell->faces.end() ) {
+ do {
+ ++_current;
+ } while ( _current != _cell->faces.end() && ! testOccluder(true) );
+ }
+}
+
+inline bool SphericalGrid::Iterator::validBeforeTarget () {
+ return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2];
+}
+
+inline bool SphericalGrid::Iterator::validAfterTarget () {
+ return _current != _cell->faces.end();
+}
+
+inline void SphericalGrid::Iterator::markCurrentOccludeeCandidate(real depth) {
+ #if sphericalgridlogging == 1
+ std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl;
+ #endif
+ _occludeeCandidate = _current;
+ _occludeeDepth = depth;
+ _foundOccludee = true;
+}
+
+inline WFace* SphericalGrid::Iterator::getWFace() const {
+ return (*_current)->face;
+}
+
+inline Polygon3r* SphericalGrid::Iterator::getCameraSpacePolygon() {
+ return &((*_current)->cameraSpacePolygon);
+}
+
+inline SphericalGrid::OccluderData::OccluderData (OccluderSource& source, Polygon3r& p)
+ : poly(p),
+ cameraSpacePolygon(source.getCameraSpacePolygon()),
+ face(source.getWFace())
+{
+ const Vec3r viewpoint(0, 0, 0);
+ // Get the point on the camera-space polygon that is closest to the viewpoint
+ // shallowest is the distance from the viewpoint to that point
+ shallowest = GridHelpers::distancePointToPolygon(viewpoint, cameraSpacePolygon);
+
+ // Get the point on the camera-space polygon that is furthest from the viewpoint
+ // deepest is the distance from the viewpoint to that point
+ deepest = cameraSpacePolygon.getVertices()[2].norm();
+ for ( unsigned i = 0; i < 2; ++i ) {
+ real t = cameraSpacePolygon.getVertices()[i].norm();
+ if ( t > deepest ) {
+ deepest = t;
+ }
+ }
+}
+
+inline void SphericalGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder) {
+ if ( GridHelpers::insideProscenium (boundary, poly) ) {
+ if ( occluder == NULL) {
+ // Disposal of occluder will be handled in SphericalGrid::distributePolygons(),
+ // or automatically by SphericalGrid::_faces;
+ occluder = new OccluderData(source, poly);
+ }
+ faces.push_back(occluder);
+ }
+}
+
+inline bool SphericalGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder) {
+ Polygon3r& poly(source.getGridSpacePolygon());
+ occluder = NULL;
+
+ Vec3r bbMin, bbMax;
+ poly.getBBox(bbMin, bbMax);
+ // Check overlapping cells
+ unsigned startX, startY, endX, endY;
+ getCellCoordinates(bbMin, startX, startY);
+ getCellCoordinates(bbMax, endX, endY);
+
+ for ( unsigned i = startX; i <= endX; ++i ) {
+ for ( unsigned j = startY; j <= endY; ++j ) {
+ if ( _cells[i * _cellsY + j] != NULL ) {
+ _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder);
+ }
+ }
+ }
+
+ return occluder != NULL;
+}
+
+#endif // SPHERICALGRID_H
+
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
new file mode 100755
index 00000000000..6b76c2512f0
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
@@ -0,0 +1,267 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Silhouette.h"
+#include "SteerableViewMap.h"
+#include "../image/ImagePyramid.h"
+#include "../image/Image.h"
+#include <math.h>
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+//soc #include <qstring.h>
+//soc #include <qimage.h>
+#include <sstream>
+
+extern "C" {
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+}
+
+SteerableViewMap::SteerableViewMap(unsigned int nbOrientations){
+ _nbOrientations = nbOrientations;
+ _bound = cos(M_PI/(float)_nbOrientations);
+ for(unsigned i=0; i<_nbOrientations; ++i){
+ _directions.push_back(Vec2d(cos((float)i*M_PI/(float)_nbOrientations), sin((float)i*M_PI/(float)_nbOrientations)));
+ }
+ Build();
+}
+
+void SteerableViewMap::Build(){
+ _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM
+ memset((_imagesPyramids),0,(_nbOrientations+1)*sizeof(ImagePyramid*));
+}
+
+SteerableViewMap::SteerableViewMap(const SteerableViewMap& iBrother){
+ _nbOrientations = iBrother._nbOrientations;
+ unsigned i;
+ _bound = iBrother._bound;
+ _directions = iBrother._directions;
+ _mapping = iBrother._mapping;
+ _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM
+ for(i=0;i<_nbOrientations+1;++i)
+ _imagesPyramids[i] = new GaussianPyramid(*(dynamic_cast<GaussianPyramid*>(iBrother._imagesPyramids[i])));
+}
+
+SteerableViewMap::~SteerableViewMap(){
+ Clear();
+}
+
+void SteerableViewMap::Clear(){
+ unsigned i;
+ if(_imagesPyramids){
+ for(i=0; i<=_nbOrientations; ++i){
+ if(_imagesPyramids[i])
+ delete (_imagesPyramids)[i];
+ }
+ delete [] _imagesPyramids;
+ _imagesPyramids = 0;
+ }
+ if(!_mapping.empty()){
+ for(map<unsigned int, double*>::iterator m=_mapping.begin(), mend=_mapping.end();
+ m!=mend;
+ ++m){
+ delete [] (*m).second;
+ }
+ _mapping.clear();
+ }
+}
+
+void SteerableViewMap::Reset(){
+ Clear();
+ Build();
+}
+
+double SteerableViewMap::ComputeWeight(const Vec2d& dir, unsigned i){
+ double dotp = fabs(dir*_directions[i]);
+ if(dotp < _bound)
+ return 0;
+ if(dotp>1)
+ dotp = 1;
+
+ return cos((float)_nbOrientations/2.0*acos(dotp));
+}
+
+double * SteerableViewMap::AddFEdge(FEdge *iFEdge){
+ unsigned i;
+ unsigned id = iFEdge->getId().getFirst();
+ map<unsigned int, double* >::iterator o = _mapping.find(id);
+ if(o!=_mapping.end()){
+ return (*o).second;
+ }
+ double * res = new double[_nbOrientations];
+ for(i=0; i<_nbOrientations; ++i){
+ res[i] = 0;
+ }
+ Vec3r o2d3 = iFEdge->orientation2d();
+ Vec2r o2d2(o2d3.x(), o2d3.y());
+ real norm = o2d2.norm();
+ if(norm < 1e-6){
+ return res;
+ }
+ o2d2/=norm;
+
+ for(i=0; i<_nbOrientations; ++i){
+ res[i] = ComputeWeight(o2d2, i);
+ }
+ _mapping[id] = res;
+ return res;
+}
+
+unsigned SteerableViewMap::getSVMNumber(const Vec2f& orient){
+ Vec2f dir(orient);
+ //soc unsigned res = 0;
+ real norm = dir.norm();
+ if(norm < 1e-6){
+ return _nbOrientations+1;
+ }
+ dir/=norm;
+ double maxw = 0.f;
+ unsigned winner = _nbOrientations+1;
+ for(unsigned i=0; i<_nbOrientations; ++i){
+ double w = ComputeWeight(dir, i);
+ if(w>maxw){
+ maxw = w;
+ winner = i;
+ }
+ }
+ return winner;
+}
+
+
+unsigned SteerableViewMap::getSVMNumber(unsigned id){
+ map<unsigned int, double* >::iterator o = _mapping.find(id);
+ if(o!=_mapping.end()){
+ double* wvalues= (*o).second;
+ double maxw = 0.f;
+ unsigned winner = _nbOrientations+1;
+ for(unsigned i=0; i<_nbOrientations; ++i){
+ double w = wvalues[i];
+ if(w>maxw){
+ maxw = w;
+ winner = i;
+ }
+ }
+ return winner;
+ }
+ return _nbOrientations+1;
+}
+
+void SteerableViewMap::buildImagesPyramids(GrayImage **steerableBases, bool copy, unsigned iNbLevels, float iSigma){
+ for(unsigned i=0; i<=_nbOrientations; ++i){
+ ImagePyramid * svm = (_imagesPyramids)[i];
+ if(svm)
+ delete svm;
+ if(copy)
+ svm = new GaussianPyramid(*(steerableBases[i]), iNbLevels, iSigma);
+ else
+ svm = new GaussianPyramid(steerableBases[i], iNbLevels, iSigma);
+ _imagesPyramids[i] = svm;
+ }
+}
+
+float SteerableViewMap::readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y){
+ ImagePyramid *pyramid = _imagesPyramids[iOrientation];
+ if(pyramid==0){
+ cout << "Warning: this steerable ViewMap level doesn't exist" << endl;
+ return 0;
+ }
+ if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height()))
+ return 0;
+ //float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)*255.f;
+ float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)/32.f; // we encode both the directionality and the lines counting on 8 bits
+ // (because of frame buffer). Thus, we allow until 8 lines to pass through
+ // the same pixel, so that we can discretize the Pi/_nbOrientations angle into
+ // 32 slices. Therefore, for example, in the vertical direction, a vertical line
+ // will have the value 32 on each pixel it passes through.
+ return v;
+}
+
+float SteerableViewMap::readCompleteViewMapPixel(int iLevel, int x, int y){
+ return readSteerableViewMapPixel(_nbOrientations,iLevel,x,y);
+}
+
+unsigned int SteerableViewMap::getNumberOfPyramidLevels() const{
+ if(_imagesPyramids[0])
+ return _imagesPyramids[0]->getNumberOfLevels();
+ return 0;
+}
+
+void SteerableViewMap::saveSteerableViewMap() const {
+ for(unsigned i=0; i<=_nbOrientations; ++i){
+ if(_imagesPyramids[i] == 0){
+ cerr << "SteerableViewMap warning: orientation " << i <<" of steerable View Map whas not been computed yet" << endl;
+ continue;
+ }
+ int ow = _imagesPyramids[i]->width(0);
+ int oh = _imagesPyramids[i]->height(0);
+
+ //soc QString base("SteerableViewMap");
+ string base("SteerableViewMap");
+ stringstream filename;
+
+ for(int j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){ //soc
+ float coeff = 1;//1/255.f; //100*255;//*pow(2,j);
+ //soc QImage qtmp(ow, oh, QImage::Format_RGB32);
+ ImBuf *ibuf = IMB_allocImBuf(ow, oh, 32, IB_rect);
+ int rowbytes = ow*4;
+ char *pix;
+
+ for(int y=0;y<oh;++y){ //soc
+ for(int x=0;x<ow;++x){ //soc
+ int c = (int)(coeff*_imagesPyramids[i]->pixel(x,y,j));
+ if(c>255)
+ c=255;
+ //int c = (int)(_imagesPyramids[i]->pixel(x,y,j));
+
+ //soc qtmp.setPixel(x,y,qRgb(c,c,c));
+ pix = (char*)ibuf->rect + y*rowbytes + x*4;
+ pix[0] = pix [1] = pix[2] = c;
+ }
+ }
+
+ //soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG");
+ filename << base;
+ filename << i << "-" << j << ".png";
+ ibuf->ftype= PNG;
+ IMB_saveiff(ibuf, const_cast<char *>(filename.str().c_str()), 0);
+
+ }
+ // QString base("SteerableViewMap");
+ // for(unsigned j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){
+ // GrayImage * img = _imagesPyramids[i]->getLevel(j);
+ // int ow = img->width();
+ // int oh = img->height();
+ // float coeff = 1; //100*255;//*pow(2,j);
+ // QImage qtmp(ow, oh, 32);
+ // for(unsigned y=0;y<oh;++y){
+ // for(unsigned x=0;x<ow;++x){
+ // int c = (int)(coeff*img->pixel(x,y));
+ // if(c>255)
+ // c=255;
+ // //int c = (int)(_imagesPyramids[i]->pixel(x,y,j));
+ // qtmp.setPixel(x,y,qRgb(c,c,c));
+ // }
+ // }
+ // qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG");
+ // }
+ //
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
new file mode 100755
index 00000000000..fe7c2493752
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
@@ -0,0 +1,153 @@
+//
+// Filename : SteerbaleViewMap.h
+// Author(s) : Stephane Grabli
+// Purpose : Convenient access to the steerable ViewMap
+// to which any element of the ViewMap belongs to.
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+#ifndef STEERABLEVIEWMAP_H
+# define STEERABLEVIEWMAP_H
+
+#include <map>
+#include "../system/FreestyleConfig.h"
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+using namespace std;
+
+class FEdge;
+class ImagePyramid;
+class GrayImage;
+/*! This class checks for every FEdge in which steerable
+ * it belongs and stores the mapping allowing to retrieve
+ * this information from the FEdge Id
+ */
+class LIB_VIEW_MAP_EXPORT SteerableViewMap{
+protected:
+ map<unsigned int, double* > _mapping; // for each vector the list of nbOrientations weigths corresponding to its contributions to the nbOrientations directional maps
+ unsigned _nbOrientations;
+ ImagePyramid **_imagesPyramids; // the pyramids of images storing the different SVM
+
+ // internal
+ double _bound; // cos(Pi/N)
+ vector<Vec2d> _directions;
+
+public:
+ SteerableViewMap(unsigned int nbOrientations = 4);
+ SteerableViewMap(const SteerableViewMap& iBrother);
+ virtual ~SteerableViewMap();
+
+ /*! Resets everything */
+ virtual void Reset();
+
+ /*! Adds a FEdge to steerable VM.
+ * Returns the nbOrientations weigths corresponding to
+ * the FEdge contributions to the nbOrientations directional maps.
+ */
+ double* AddFEdge(FEdge *iFEdge);
+
+ /*! Compute the weight of direction dir for orientation iNOrientation */
+ double ComputeWeight(const Vec2d& dir, unsigned iNOrientation);
+
+ /*! Returns the number of the SVM to which a direction belongs
+ * to.
+ * \param dir
+ * The direction
+ */
+ unsigned getSVMNumber(const Vec2f& dir);
+
+ /*! Returns the number of the SVM to which a FEdge belongs
+ * most.
+ * \param id
+ * The First element of the Id struct of the FEdge
+ * we're intersted in.
+ */
+ unsigned getSVMNumber(unsigned id);
+
+ /*! Builds _nbOrientations+1 pyramids of images from the _nbOrientations+1 base images
+ * of the steerable viewmap.
+ * \param steerableBases
+ * The _nbOrientations+1 images constituing the basis for the steerable
+ * pyramid.
+ * \param copy
+ * If false, the data is not duplicated, and Canvas deals
+ * with the memory management of these _nbOrientations+1 images. If true, data
+ * is copied, and it's up to the caller to delete the images.
+ * \params iNbLevels
+ * The number of levels desired for each pyramid.
+ * If iNbLevels == 0, the complete pyramid is built.
+ * \param iSigma
+ * The sigma that will be used for the gaussian blur
+ */
+ void buildImagesPyramids(GrayImage **steerableBases, bool copy = false, unsigned iNbLevels=4, float iSigma = 1.f);
+
+ /*! Reads a pixel value in one of the VewMap density steerable pyramids.
+ * Returns a value between 0 and 1.
+ * \param iOrientation
+ * the number telling which orientation we need to check.
+ * There are _nbOrientations+1 oriented ViewMaps:
+ * 0 -> the ViewMap containing every horizontal lines
+ * 1 -> the ViewMap containing every lines whose orientation is around PI/4
+ * 2 -> the ViewMap containing every vertical lines
+ * 3 -> the ViewMap containing every lines whose orientation is around 3PI/4
+ * 4 -> the complete ViewMap
+ * \param iLevel
+ * The level of the pyramid we want to read
+ * \param x
+ * The abscissa of the desired pixel specified in level0 coordinate
+ * system. The origin is the lower left corner.
+ * \param y
+ * The ordinate of the desired pixel specified in level0 coordinate
+ * system. The origin is the lower left corner.
+ */
+ float readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y);
+
+ /*! Reads a pixel in the one of the level of the
+ * pyramid containing the images of the complete
+ * ViewMap.
+ * Returns a value between 0 and 1.
+ * Equivalent to : readSteerableViewMapPixel(nbOrientations, x,y)
+ */
+ float readCompleteViewMapPixel(int iLevel, int x, int y);
+
+ /*! Returns the number of levels in the pyramids */
+ unsigned int getNumberOfPyramidLevels() const;
+
+ /*! Returns the number of orientations */
+ unsigned int getNumberOfOrientations() const{
+ return _nbOrientations;
+ }
+
+ /*! for debug purposes */
+ void saveSteerableViewMap() const ;
+
+protected:
+ void Clear();
+ void Build();
+
+
+};
+
+#endif // STEERABLEVIEWMAP_H
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
new file mode 100755
index 00000000000..4cb48d6613e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
@@ -0,0 +1,736 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewMap.h"
+#include "ViewEdgeXBuilder.h"
+#include "../winged_edge/WXEdge.h"
+#include "SilhouetteGeomEngine.h"
+#include <list>
+
+using namespace std;
+
+void ViewEdgeXBuilder::Init(ViewShape *oVShape){
+ if(0 == oVShape)
+ return;
+
+ // for design conveniance, we store the current SShape.
+ _pCurrentSShape = oVShape->sshape();
+ if(0 == _pCurrentSShape)
+ return;
+
+ _pCurrentVShape = oVShape;
+
+ // Reset previous data
+ //--------------------
+ if(!_SVertexMap.empty())
+ _SVertexMap.clear();
+}
+
+void ViewEdgeXBuilder::BuildViewEdges( WXShape *iWShape, ViewShape *oVShape,
+ vector<ViewEdge*>& ioVEdges,
+ vector<ViewVertex*>& ioVVertices,
+ vector<FEdge*>& ioFEdges,
+ vector<SVertex*>& ioSVertices){
+ // Reinit structures
+ Init(oVShape);
+
+ ViewEdge *vedge ;
+ // Let us build the smooth stuff
+ //----------------------------------------
+ // We parse all faces to find the ones
+ // that contain smooth edges
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator wf, wfend;
+ WXFace *wxf;
+ for(wf=wfaces.begin(), wfend=wfaces.end();
+ wf!=wfend;
+ wf++){
+ wxf = dynamic_cast<WXFace*>(*wf);
+ if(false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ?
+ continue;
+ // parse all smooth layers:
+ vector<WXFaceLayer*>& smoothLayers = wxf->getSmoothLayers();
+ for(vector<WXFaceLayer*>::iterator sl = smoothLayers.begin(), slend=smoothLayers.end();
+ sl!=slend;
+ ++sl){
+ if(!(*sl)->hasSmoothEdge())
+ continue;
+ if(stopSmoothViewEdge((*sl))) // has it been parsed already ?
+ continue;
+ // here we know that we're dealing with a face layer that has not been
+ // processed yet and that contains a smooth edge.
+ vedge = BuildSmoothViewEdge(OWXFaceLayer(*sl, true));
+ }
+ }
+
+ // Now let's build sharp view edges:
+ //----------------------------------
+ // Reset all userdata for WXEdge structure
+ //----------------------------------------
+ //iWShape->ResetUserData();
+
+ WXEdge * wxe;
+ vector<WEdge*>& wedges = iWShape->getEdgeList();
+ //
+ //------------------------------
+ for(vector<WEdge*>::iterator we=wedges.begin(),weend=wedges.end();
+ we!=weend;
+ we++){
+ wxe = dynamic_cast<WXEdge*>(*we);
+ if(Nature::NO_FEATURE == wxe->nature())
+ continue;
+
+ if(!stopSharpViewEdge(wxe)){
+ bool b=true;
+ if(wxe->order() == -1)
+ b = false;
+ BuildSharpViewEdge(OWXEdge(wxe,b));
+ }
+ }
+
+ // Reset all userdata for WXEdge structure
+ //----------------------------------------
+ iWShape->ResetUserData();
+
+ // Add all these new edges to the scene's feature edges list:
+ //-----------------------------------------------------------
+ vector<FEdge*>& newedges = _pCurrentSShape->getEdgeList();
+ vector<SVertex*>& newVertices = _pCurrentSShape->getVertexList();
+ vector<ViewVertex*>& newVVertices = _pCurrentVShape->vertices();
+ vector<ViewEdge*>& newVEdges = _pCurrentVShape->edges();
+
+ // inserts in ioFEdges, at its end, all the edges of newedges
+ ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end());
+ ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end());
+ ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end());
+ ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end());
+
+}
+
+ViewEdge * ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer){
+ // Find first edge:
+ OWXFaceLayer first = iFaceLayer;
+ OWXFaceLayer currentFace = first;
+
+ // bidirectional chaining.
+ // first direction
+ list<OWXFaceLayer> facesChain;
+ unsigned size = 0;
+ while(!stopSmoothViewEdge(currentFace.fl)){
+ facesChain.push_back(currentFace);
+ ++size;
+ currentFace.fl->userdata = (void*)1; // processed
+ // Find the next edge!
+ currentFace = FindNextFaceLayer(currentFace);
+ }
+ OWXFaceLayer end = facesChain.back();
+ // second direction
+ currentFace = FindPreviousFaceLayer(first);
+ while(!stopSmoothViewEdge(currentFace.fl)){
+ facesChain.push_front(currentFace);
+ ++size;
+ currentFace.fl->userdata = (void*)1; // processed
+ // Find the previous edge!
+ currentFace = FindPreviousFaceLayer(currentFace);
+ }
+ first = facesChain.front();
+
+ if(iFaceLayer.fl->nature() & Nature::RIDGE){
+ if(size<4){
+ return 0;
+ }
+ }
+
+ // Start a new chain edges
+ ViewEdge * newVEdge = new ViewEdge;
+ newVEdge->setId(_currentViewId);
+ ++_currentViewId;
+
+ _pCurrentVShape->AddEdge(newVEdge);
+
+
+ // build FEdges
+ FEdge * feprevious = 0;
+ FEdge * fefirst = 0;
+ FEdge * fe = 0;
+ for(list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend=facesChain.end();
+ fl!=flend;
+ ++fl){
+ fe = BuildSmoothFEdge(feprevious, (*fl));
+ if (feprevious && fe == feprevious)
+ continue;
+ fe->setViewEdge(newVEdge);
+ if(!fefirst)
+ fefirst = fe;
+ feprevious = fe;
+ }
+ // Store the chain starting edge:
+ _pCurrentSShape->AddChain(fefirst);
+ newVEdge->setNature(iFaceLayer.fl->nature());
+ newVEdge->setFEdgeA(fefirst);
+ newVEdge->setFEdgeB(fe);
+
+ // is it a closed loop ?
+ if((first == end) && (size != 1)){
+ fefirst->setPreviousEdge(fe);
+ fe->setNextEdge(fefirst);
+ newVEdge->setA(0);
+ newVEdge->setB(0);
+ }else{
+ ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
+ ViewVertex *vvb = MakeViewVertex(fe->vertexB());
+
+ ((NonTVertex*)vva)->AddOutgoingViewEdge(newVEdge);
+ ((NonTVertex*)vvb)->AddIncomingViewEdge(newVEdge);
+
+ newVEdge->setA(vva);
+ newVEdge->setB(vvb);
+ }
+
+ return newVEdge;
+}
+
+ViewEdge * ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge& iWEdge) {
+ // Start a new sharp chain edges
+ ViewEdge * newVEdge = new ViewEdge;
+ newVEdge->setId(_currentViewId);
+ ++_currentViewId;
+ unsigned size=0;
+
+ _pCurrentVShape->AddEdge(newVEdge);
+
+ // Find first edge:
+ OWXEdge firstWEdge = iWEdge;
+ OWXEdge previousWEdge = firstWEdge;
+ OWXEdge currentWEdge = firstWEdge;
+ list<OWXEdge> edgesChain;
+#if 0 /* TK 02-Sep-2012 Experimental fix for incorrect view edge visibility. */
+ // bidirectional chaining
+ // first direction:
+ while(!stopSharpViewEdge(currentWEdge.e)){
+ edgesChain.push_back(currentWEdge);
+ ++size;
+ currentWEdge.e->userdata = (void*)1; // processed
+ // Find the next edge!
+ currentWEdge = FindNextWEdge(currentWEdge);
+ }
+ OWXEdge endWEdge = edgesChain.back();
+ // second direction
+ currentWEdge = FindPreviousWEdge(firstWEdge);
+ while(!stopSharpViewEdge(currentWEdge.e)){
+ edgesChain.push_front(currentWEdge);
+ ++size;
+ currentWEdge.e->userdata = (void*)1; // processed
+ // Find the previous edge!
+ currentWEdge = FindPreviousWEdge(currentWEdge);
+ }
+#else
+ edgesChain.push_back(currentWEdge);
+ ++size;
+ currentWEdge.e->userdata = (void*)1; // processed
+ OWXEdge endWEdge = edgesChain.back();
+#endif
+ firstWEdge = edgesChain.front();
+
+ // build FEdges
+ FEdge * feprevious = 0;
+ FEdge * fefirst = 0;
+ FEdge * fe = 0;
+ for(list<OWXEdge>::iterator we = edgesChain.begin(), weend=edgesChain.end();
+ we!=weend;
+ ++we){
+ fe = BuildSharpFEdge(feprevious, (*we));
+ fe->setViewEdge(newVEdge);
+ if(!fefirst)
+ fefirst = fe;
+ feprevious = fe;
+ }
+ // Store the chain starting edge:
+ _pCurrentSShape->AddChain(fefirst);
+ newVEdge->setNature(iWEdge.e->nature());
+ newVEdge->setFEdgeA(fefirst);
+ newVEdge->setFEdgeB(fe);
+
+ // is it a closed loop ?
+ if((firstWEdge == endWEdge) && (size!=1)){
+ fefirst->setPreviousEdge(fe);
+ fe->setNextEdge(fefirst);
+ newVEdge->setA(0);
+ newVEdge->setB(0);
+ }else{
+ ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
+ ViewVertex *vvb = MakeViewVertex(fe->vertexB());
+
+ ((NonTVertex*)vva)->AddOutgoingViewEdge(newVEdge);
+ ((NonTVertex*)vvb)->AddIncomingViewEdge(newVEdge);
+
+ newVEdge->setA(vva);
+ newVEdge->setB(vvb);
+ }
+
+ return newVEdge;
+}
+
+OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer& iFaceLayer){
+ WXFace *nextFace = 0;
+ WOEdge * woeend;
+ real tend;
+ if(iFaceLayer.order){
+ woeend = iFaceLayer.fl->getSmoothEdge()->woeb();
+ tend = iFaceLayer.fl->getSmoothEdge()->tb();
+ }else{
+ woeend = iFaceLayer.fl->getSmoothEdge()->woea();
+ tend = iFaceLayer.fl->getSmoothEdge()->ta();
+ }
+ // special case of EDGE_VERTEX config:
+ if((tend == 0.0) || (tend == 1.0)){
+ WVertex *nextVertex;
+ if(tend == 0.0)
+ nextVertex = woeend->GetaVertex();
+ else
+ nextVertex = woeend->GetbVertex();
+ if(nextVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
+ return OWXFaceLayer(0,true);
+ bool found = false;
+ WVertex::face_iterator f=nextVertex->faces_begin();
+ WVertex::face_iterator fend=nextVertex->faces_end();
+ while((!found) && (f!=fend)){
+ nextFace = dynamic_cast<WXFace*>(*f);
+ if((0 != nextFace) && (nextFace!=iFaceLayer.fl->getFace())){
+ vector<WXFaceLayer*> sameNatureLayers;
+ nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ if(sameNatureLayers.size() == 1) {// don't know
+ // maybe should test whether this face has
+ // also a vertex_edge configuration
+ WXFaceLayer * winner = sameNatureLayers[0];
+ // check face mark continuity
+ if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
+ return OWXFaceLayer(0,true);
+ if(woeend == winner->getSmoothEdge()->woea()->twin())
+ return OWXFaceLayer(winner,true);
+ else
+ return OWXFaceLayer(winner,false);
+ }
+ }
+ ++f;
+ }
+ }else{
+ nextFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woeend));
+ if(0 == nextFace)
+ return OWXFaceLayer(0,true);
+ // if the next face layer has either no smooth edge or
+ // no smooth edge of same nature, no next face
+ if(!nextFace->hasSmoothEdges())
+ return OWXFaceLayer(0,true);
+ vector<WXFaceLayer*> sameNatureLayers;
+ nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face
+ return OWXFaceLayer(0,true);
+ else{
+ WXFaceLayer * winner = sameNatureLayers[0];
+ // check face mark continuity
+ if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
+ return OWXFaceLayer(0,true);
+ if(woeend == winner->getSmoothEdge()->woea()->twin())
+ return OWXFaceLayer(winner,true);
+ else
+ return OWXFaceLayer(winner,false);
+ }
+ }
+ return OWXFaceLayer(0,true);
+}
+
+OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer) {
+ WXFace *previousFace = 0;
+ WOEdge * woebegin;
+ real tend;
+ if(iFaceLayer.order){
+ woebegin = iFaceLayer.fl->getSmoothEdge()->woea();
+ tend = iFaceLayer.fl->getSmoothEdge()->ta();
+ }else{
+ woebegin = iFaceLayer.fl->getSmoothEdge()->woeb();
+ tend = iFaceLayer.fl->getSmoothEdge()->tb();
+ }
+
+ // special case of EDGE_VERTEX config:
+ if((tend == 0.0) || (tend == 1.0)){
+ WVertex *previousVertex;
+ if(tend == 0.0)
+ previousVertex = woebegin->GetaVertex();
+ else
+ previousVertex = woebegin->GetbVertex();
+ if(previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
+ return OWXFaceLayer(0,true);
+ bool found = false;
+ WVertex::face_iterator f=previousVertex->faces_begin();
+ WVertex::face_iterator fend=previousVertex->faces_end();
+ while((!found) && (f!=fend)){
+ previousFace = dynamic_cast<WXFace*>(*f);
+ if((0 != previousFace) && (previousFace!=iFaceLayer.fl->getFace())){
+ vector<WXFaceLayer*> sameNatureLayers;
+ previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ if(sameNatureLayers.size() == 1) {// don't know
+ // maybe should test whether this face has
+ // also a vertex_edge configuration
+ WXFaceLayer * winner = sameNatureLayers[0];
+ // check face mark continuity
+ if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
+ return OWXFaceLayer(0,true);
+ if(woebegin == winner->getSmoothEdge()->woeb()->twin())
+ return OWXFaceLayer(winner,true);
+ else
+ return OWXFaceLayer(winner,false);
+ }
+ }
+ ++f;
+ }
+ }else{
+ previousFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin));
+ if(0 == previousFace)
+ return OWXFaceLayer(0,true);
+
+ // if the next face layer has either no smooth edge or
+ // no smooth edge of same nature, no next face
+ if(!previousFace->hasSmoothEdges())
+ return OWXFaceLayer(0,true);
+ vector<WXFaceLayer*> sameNatureLayers;
+ previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face
+ return OWXFaceLayer(0,true);
+ else{
+ WXFaceLayer * winner = sameNatureLayers[0];
+ // check face mark continuity
+ if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
+ return OWXFaceLayer(0,true);
+ if(woebegin == winner->getSmoothEdge()->woeb()->twin())
+ return OWXFaceLayer(winner,true);
+ else
+ return OWXFaceLayer(winner,false);
+ }
+ }
+ return OWXFaceLayer(0,true);
+}
+
+FEdge * ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl){
+ WOEdge *woea, *woeb;
+ real ta, tb;
+ SVertex *va, *vb;
+ FEdgeSmooth *fe;
+ // retrieve exact silhouette data
+ WXSmoothEdge *se = ifl.fl->getSmoothEdge();
+
+ if (ifl.order) {
+ woea = se->woea();
+ woeb = se->woeb();
+ ta = se->ta();
+ tb = se->tb();
+ } else {
+ woea = se->woeb();
+ woeb = se->woea();
+ ta = se->tb();
+ tb = se->ta();
+ }
+
+ Vec3r normal;
+ // Make the 2 Svertices
+ if(feprevious == 0){ // that means that we don't have any vertex already built for that face
+ Vec3r A1(woea->GetaVertex()->GetVertex());
+ Vec3r A2(woea->GetbVertex()->GetVertex());
+ Vec3r A(A1+ta*(A2-A1));
+
+ va = MakeSVertex(A, false);
+ // Set normal:
+ Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(woea->GetaVertex()));
+ Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(woea->GetbVertex()));
+ Vec3r na((1 - ta) * NA1 + ta * NA2);
+ na.normalize();
+ va->AddNormal(na);
+ normal = na;
+
+ // Set CurvatureInfo
+ CurvatureInfo* curvature_info_a = new CurvatureInfo(
+ *(dynamic_cast<WXVertex*>(woea->GetaVertex())->curvatures()),
+ *(dynamic_cast<WXVertex*>(woea->GetbVertex())->curvatures()),
+ ta);
+ va->setCurvatureInfo(curvature_info_a);
+ }
+ else
+ va = feprevious->vertexB();
+
+ Vec3r B1(woeb->GetaVertex()->GetVertex());
+ Vec3r B2(woeb->GetbVertex()->GetVertex());
+ Vec3r B(B1+tb*(B2-B1));
+
+ if (feprevious && (B - va->point3D()).norm() < 1e-6)
+ return feprevious;
+
+ vb = MakeSVertex(B, false);
+ // Set normal:
+ Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(woeb->GetaVertex()));
+ Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(woeb->GetbVertex()));
+ Vec3r nb((1 - tb) * NB1 + tb * NB2);
+ nb.normalize();
+ normal += nb;
+ vb->AddNormal(nb);
+
+ // Set CurvatureInfo
+ CurvatureInfo* curvature_info_b = new CurvatureInfo(
+ *(dynamic_cast<WXVertex*>(woeb->GetaVertex())->curvatures()),
+ *(dynamic_cast<WXVertex*>(woeb->GetbVertex())->curvatures()),
+ tb);
+ vb->setCurvatureInfo(curvature_info_b);
+
+ // Creates the corresponding feature edge
+ fe = new FEdgeSmooth(va, vb);
+ fe->setNature(ifl.fl->nature());
+ fe->setId(_currentFId);
+ fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex());
+ fe->setFace(ifl.fl->getFace());
+ fe->setFaceMark(ifl.fl->getFace()->GetMark());
+ if(feprevious == 0)
+ normal.normalize();
+ fe->setNormal(normal);
+ fe->setPreviousEdge(feprevious);
+ if(feprevious)
+ feprevious->setNextEdge(fe);
+ _pCurrentSShape->AddEdge(fe);
+ va->AddFEdge(fe);
+ vb->AddFEdge(fe);
+
+ ++_currentFId;
+ ifl.fl->userdata = fe;
+ return fe;
+}
+
+bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer){
+ if(0 == iFaceLayer)
+ return true;
+ if(iFaceLayer->userdata == 0)
+ return false;
+ return true;
+}
+
+int ViewEdgeXBuilder::retrieveFaceMarks(WXEdge *iEdge)
+{
+ WFace *aFace = iEdge->GetaFace();
+ WFace *bFace = iEdge->GetbFace();
+ int result = 0;
+ if (aFace && aFace->GetMark())
+ result += 1;
+ if (bFace && bFace->GetMark())
+ result += 2;
+ return result;
+}
+
+OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge& iEdge){
+ if(Nature::NO_FEATURE == iEdge.e->nature())
+ return OWXEdge(0, true);
+
+ WVertex *v;
+ if(true == iEdge.order)
+ v = iEdge.e->GetbVertex();
+ else
+ v = iEdge.e->GetaVertex();
+
+ if(((WXVertex*)v)->isFeature())
+ return 0;
+
+
+ int faceMarks = retrieveFaceMarks(iEdge.e);
+ vector<WEdge*>& vEdges = (v)->GetEdges();
+ for(vector<WEdge*>::iterator ve=vEdges.begin(),veend=vEdges.end();
+ ve!=veend;
+ ve++){
+ WXEdge *wxe = dynamic_cast<WXEdge*>(*ve);
+ if(wxe == iEdge.e)
+ continue; // same edge as the one processed
+
+ if(wxe->nature() != iEdge.e->nature())
+ continue;
+
+ // check face mark continuity
+ if(retrieveFaceMarks(wxe) != faceMarks)
+ continue;
+
+ if(wxe->GetaVertex() == v){
+ // That means that the face necesarily lies on the edge left.
+ // So the vertex order is OK.
+ return OWXEdge(wxe, true);
+ }else{
+ // That means that the face necesarily lies on the edge left.
+ // So the vertex order is OK.
+ return OWXEdge(wxe, false);
+ }
+ }
+ // we did not find:
+ return OWXEdge(0, true);
+}
+
+OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge& iEdge){
+ if(Nature::NO_FEATURE == iEdge.e->nature())
+ return OWXEdge(0, true);
+
+ WVertex *v;
+ if(true == iEdge.order)
+ v = iEdge.e->GetaVertex();
+ else
+ v = iEdge.e->GetbVertex();
+
+ if(((WXVertex*)v)->isFeature())
+ return 0;
+
+
+ int faceMarks = retrieveFaceMarks(iEdge.e);
+ vector<WEdge*>& vEdges = (v)->GetEdges();
+ for(vector<WEdge*>::iterator ve=vEdges.begin(),veend=vEdges.end();
+ ve!=veend;
+ ve++){
+ WXEdge *wxe = dynamic_cast<WXEdge*>(*ve);
+ if(wxe == iEdge.e)
+ continue; // same edge as the one processed
+
+ if(wxe->nature() != iEdge.e->nature())
+ continue;
+
+ // check face mark continuity
+ if(retrieveFaceMarks(wxe) != faceMarks)
+ continue;
+
+ if(wxe->GetbVertex() == v){
+ return OWXEdge(wxe, true);
+ }else{
+ return OWXEdge(wxe, false);
+ }
+ }
+ // we did not find:
+ return OWXEdge(0, true);
+}
+
+FEdge * ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe){
+ SVertex *va, *vb;
+ FEdgeSharp *fe;
+ WXVertex *wxVA, *wxVB;
+ if(iwe.order){
+ wxVA = (WXVertex*)iwe.e->GetaVertex();
+ wxVB = (WXVertex*)iwe.e->GetbVertex();
+ }else{
+ wxVA = (WXVertex*)iwe.e->GetbVertex();
+ wxVB = (WXVertex*)iwe.e->GetaVertex();
+ }
+ // Make the 2 SVertex
+ va = MakeSVertex(wxVA->GetVertex(), true);
+ vb = MakeSVertex(wxVB->GetVertex(), true);
+
+ // get the faces normals and the material indices
+ Vec3r normalA, normalB;
+ unsigned matA(0), matB(0);
+ bool faceMarkA = false, faceMarkB = false;
+ if(iwe.order){
+ normalB = (iwe.e->GetbFace()->GetNormal());
+ matB = (iwe.e->GetbFace()->frs_materialIndex());
+ faceMarkB = (iwe.e->GetbFace()->GetMark());
+ if(!(iwe.e->nature() & Nature::BORDER)) {
+ normalA = (iwe.e->GetaFace()->GetNormal());
+ matA = (iwe.e->GetaFace()->frs_materialIndex());
+ faceMarkA = (iwe.e->GetaFace()->GetMark());
+ }
+ }else{
+ normalA = (iwe.e->GetbFace()->GetNormal());
+ matA = (iwe.e->GetbFace()->frs_materialIndex());
+ faceMarkA = (iwe.e->GetbFace()->GetMark());
+ if(!(iwe.e->nature() & Nature::BORDER)) {
+ normalB = (iwe.e->GetaFace()->GetNormal());
+ matB = (iwe.e->GetaFace()->frs_materialIndex());
+ faceMarkB = (iwe.e->GetaFace()->GetMark());
+ }
+ }
+ // Creates the corresponding feature edge
+ // Creates the corresponding feature edge
+ fe = new FEdgeSharp(va, vb);
+ fe->setNature(iwe.e->nature());
+ fe->setId(_currentFId);
+ fe->setaFrsMaterialIndex(matA);
+ fe->setbFrsMaterialIndex(matB);
+ fe->setaFaceMark(faceMarkA);
+ fe->setbFaceMark(faceMarkB);
+ fe->setNormalA(normalA);
+ fe->setNormalB(normalB);
+ fe->setPreviousEdge(feprevious);
+ if(feprevious)
+ feprevious->setNextEdge(fe);
+ _pCurrentSShape->AddEdge(fe);
+ va->AddFEdge(fe);
+ vb->AddFEdge(fe);
+ //Add normals:
+ va->AddNormal(normalA);
+ va->AddNormal(normalB);
+ vb->AddNormal(normalA);
+ vb->AddNormal(normalB);
+
+ ++_currentFId;
+ iwe.e->userdata = fe;
+ return fe;
+}
+
+bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge){
+ if(0 == iEdge)
+ return true;
+ if(iEdge->userdata == 0)
+ return false;
+ return true;
+}
+
+SVertex * ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint){
+ SVertex *va = new SVertex(iPoint, _currentSVertexId);
+ SilhouetteGeomEngine::ProjectSilhouette(va);
+ ++_currentSVertexId;
+ // Add the svertex to the SShape svertex list:
+ _pCurrentSShape->AddNewVertex(va);
+ return va;
+}
+
+SVertex * ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint, bool shared){
+ SVertex *va;
+ if (!shared) {
+ va = MakeSVertex(iPoint);
+ } else {
+ // Check whether the iPoint is already in the table
+ SVertexMap::const_iterator found = _SVertexMap.find(iPoint);
+ if (shared && found != _SVertexMap.end()) {
+ va = (*found).second;
+ }else{
+ va = MakeSVertex(iPoint);
+ // Add the svertex into the table using iPoint as the key
+ _SVertexMap[iPoint] = va;
+ }
+ }
+ return va;
+}
+
+ViewVertex * ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex){
+ ViewVertex *vva = iSVertex->viewvertex();
+ if(vva != 0)
+ return vva;
+ vva = new NonTVertex(iSVertex);
+ // Add the view vertex to the ViewShape svertex list:
+ _pCurrentVShape->AddVertex(vva);
+ return vva;
+}
+
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h
new file mode 100755
index 00000000000..744cc520b2b
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h
@@ -0,0 +1,218 @@
+//
+// Filename : ViewEdgeXBuilder.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build view edges and the underlying chains
+// of feature edges...
+// Date of creation : 27/10/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWEDGEXBUILDER_H
+# define VIEWEDGEXBUILDER_H
+
+# include <map>
+# include <utility>
+# include <vector>
+
+// soc
+// # if defined(__GNUC__) && (__GNUC__ >= 3)
+// //hash_map is not part of the C++ standard anymore; hash_map.h has been kept though for backward compatibility
+// # include <hash_map.h>
+// # else
+// # include <hash_map>
+// # endif
+
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "Interface1D.h"
+
+using namespace Geometry;
+using namespace std;
+
+class SVertex;
+/*! Defines a hash table used for searching the SVertex */
+struct SVertexHasher {
+#define _MUL 950706376UL
+#define _MOD 2147483647UL
+ inline size_t operator() (const Vec3r& p) const {
+ size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
+ }
+};
+
+// Key_compare predicate for hash_map. In particular, return false if equal.
+struct epsilonEquals{
+ bool operator()(const Vec3r& v1, const Vec3r& v2) const{
+ real norm = (v1-v2).norm();
+ return (norm<1e-06);
+ }
+};
+
+
+// typedef hash_map<Vec3r, SVertex*, SVertexHasher, epsilonEquals> SVertexMap;
+typedef map<Vec3r , SVertex*> SVertexMap;
+
+class WXFaceLayer;
+/*! class to describe an oriented smooth edge */
+class OWXFaceLayer{
+public:
+ WXFaceLayer * fl;
+ bool order;
+
+ OWXFaceLayer() {fl=0;order=true;}
+ OWXFaceLayer(WXFaceLayer *ifl, bool iOrder=true){fl = ifl;order=iOrder;}
+ OWXFaceLayer& operator=(const OWXFaceLayer& iBrother){
+ fl = iBrother.fl;
+ order = iBrother.order;
+ return *this;
+ }
+ bool operator==(const OWXFaceLayer& b){
+ return ((fl == b.fl) && (order == b.order));
+ }
+ bool operator!=(const OWXFaceLayer& b){
+ return !(*this==b);
+ }
+};
+
+class WXEdge;
+/*! class to describe an oriented sharp edge */
+class OWXEdge{
+public:
+ WXEdge * e;
+ bool order;
+
+ OWXEdge() {e=0;order=true;}
+ OWXEdge(WXEdge *ie, bool iOrder=true){e = ie;order=iOrder;}
+ OWXEdge& operator=(const OWXEdge& iBrother){
+ e = iBrother.e;
+ order = iBrother.order;
+ return *this;
+ }
+ bool operator==(const OWXEdge& b){
+ return ((e == b.e) && (order == b.order));
+ }
+ bool operator!=(const OWXEdge& b){
+ return !(*this==b);
+ }
+};
+
+class WOEdge;
+class WXEdge;
+class WXShape;
+class SVertex;
+class FEdge;
+class ViewVertex;
+class ViewEdge;
+class ViewShape;
+class LIB_VIEW_MAP_EXPORT ViewEdgeXBuilder
+{
+protected:
+ int _currentViewId; // Id for view edges
+ int _currentFId; // Id for FEdges
+ int _currentSVertexId; // Id for SVertex
+public:
+
+ inline ViewEdgeXBuilder()
+ {_currentViewId = 1;_currentFId=0;_currentSVertexId=0;}
+ virtual ~ViewEdgeXBuilder(){}
+
+ /*! Builds a view shape from a WXShape in which the feature edges
+ * are flagged
+ * Builds chains of feature edges (so ViewEdges) from a WXShape
+ * iWShape
+ * The Winged Edge structure in which all silhouette edges
+ * and vertices are flagged.
+ * oViewShape
+ * The Silhouette Shape in which the chains must be added.
+ * ioVEdges
+ * The list of new ViewEdges.
+ * ioVVertices
+ * THe new ViewVertices
+ * ioFEdges
+ * A list in which all new FEdges are added
+ * ioSVertices
+ * A list of SVertex where all created SVertex are added.
+ */
+ virtual void BuildViewEdges(WXShape *iWShape, ViewShape *oVShape,
+ std::vector<ViewEdge*>& ioVEdges,
+ std::vector<ViewVertex*>& ioVVertices,
+ std::vector<FEdge*>& ioFEdges,
+ std::vector<SVertex*>& ioSVertices) ;
+
+ /*! Builds a smooth view edge, starting the face iFace.*/
+ ViewEdge * BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer);
+
+ /*! Makes a sharp viewedge
+ */
+ ViewEdge * BuildSharpViewEdge(const OWXEdge& iWEdge) ;
+
+
+public:
+ /*! accessors */
+ inline int currentViewId() const { return _currentViewId; }
+ inline int currentFId() const { return _currentFId; }
+ inline int currentSVertexId() const { return _currentSVertexId; }
+ /*! modifiers */
+ inline void setCurrentViewId(int id) { _currentViewId = id; }
+ inline void setCurrentFId(int id) { _currentFId = id; }
+ inline void setCurrentSVertexId(int id) { _currentSVertexId = id; }
+
+protected:
+ /*! Init the view edges building */
+ virtual void Init(ViewShape *oVShape) ;
+
+ // SMOOTH //
+ /*! checks whether a face has already been processed or not */
+ bool stopSmoothViewEdge(WXFaceLayer *iFaceLayer);
+ OWXFaceLayer FindNextFaceLayer(const OWXFaceLayer& iFaceLayer);
+ OWXFaceLayer FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer);
+ FEdge * BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl);
+
+ // SHARP //
+ /*! checks whether a WEdge has already been processed or not */
+ bool stopSharpViewEdge(WXEdge *iFace);
+ int retrieveFaceMarks(WXEdge *iEdge);
+ OWXEdge FindNextWEdge(const OWXEdge& iEdge);
+ OWXEdge FindPreviousWEdge(const OWXEdge& iEdge);
+ FEdge * BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe);
+
+ // GENERAL //
+ /*! Instanciate a SVertex */
+ SVertex * MakeSVertex(Vec3r& iPoint);
+ /*! Instanciate a SVertex if it hasn't been already created */
+ SVertex * MakeSVertex(Vec3r& iPoint, bool shared);
+ /*! instanciate a ViewVertex from a SVertex, if it doesn't exist yet */
+ ViewVertex * MakeViewVertex(SVertex *iSVertex);
+
+ //oldtmp values
+ // IdHashTable _hashtable;
+ // VVIdHashTable _multivertexHashTable;
+ SVertexMap _SVertexMap;
+ SShape *_pCurrentSShape;
+ ViewShape * _pCurrentVShape;
+};
+
+#endif
+
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp
new file mode 100755
index 00000000000..87624669204
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp
@@ -0,0 +1,703 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewMap.h"
+#include "../geometry/GeomUtils.h"
+#include <float.h>
+#include "ViewMapIterators.h"
+#include "ViewMapAdvancedIterators.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewMap */
+ /* */
+ /* */
+ /**********************************/
+
+ViewMap * ViewMap::_pInstance = 0;
+
+ViewMap::~ViewMap()
+{
+ // The view vertices must be deleted here as some of them
+ // are shared between two shapes:
+ for(vector<ViewVertex*>::iterator vv=_VVertices.begin(), vvend=_VVertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ delete (*vv);
+ }
+ _VVertices.clear();
+
+ for(vector<ViewShape*>::iterator vs=_VShapes.begin(),vsend=_VShapes.end();
+ vs!=vsend;
+ vs++)
+ {
+ delete (*vs);
+ }
+ _VShapes.clear();
+
+ _FEdges.clear();
+ _SVertices.clear();
+ _VEdges.clear();
+}
+
+ViewShape * ViewMap::viewShape(unsigned id)
+{
+ int index = _shapeIdToIndex[id];
+ return _VShapes[ index ];
+}
+void ViewMap::AddViewShape(ViewShape *iVShape) {
+ _shapeIdToIndex[iVShape->getId().getFirst()] = _VShapes.size();
+ _VShapes.push_back(iVShape);
+}
+const FEdge * ViewMap::getClosestFEdge(real x, real y) const
+{
+ // find the closest of this candidates:
+ real minDist = DBL_MAX;
+ FEdge * winner = 0;
+ for(fedges_container::const_iterator fe=_FEdges.begin(),feend=_FEdges.end();
+ fe!=feend;
+ fe++)
+ {
+ Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]);
+ Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]);
+ real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x,y),A, B);
+ if(dist < minDist)
+ {
+ minDist = dist;
+ winner = (*fe);
+ }
+
+ }
+ if(winner==0)
+ return 0;
+
+ return winner;
+}
+
+const ViewEdge * ViewMap::getClosestViewEdge(real x, real y) const
+{
+ // find the closest of this candidates:
+ real minDist = DBL_MAX;
+ FEdge * winner = 0;
+ for(fedges_container::const_iterator fe=_FEdges.begin(),feend=_FEdges.end();
+ fe!=feend;
+ fe++)
+ {
+ Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]);
+ Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]);
+ real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x,y),A, B);
+ if(dist < minDist)
+ {
+ minDist = dist;
+ winner = (*fe);
+ }
+
+ }
+ if(winner==0)
+ return 0;
+
+ return winner->viewedge();
+}
+
+
+TVertex* ViewMap::CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA,
+ const Vec3r& iB3D, const Vec3r& iB2D, FEdge *iFEdgeB,
+ const Id& id)
+{
+ ViewShape *vshapeA = iFEdgeA->viewedge()->viewShape();
+ SShape *shapeA = iFEdgeA->shape();
+ ViewShape *vshapeB = iFEdgeB->viewedge()->viewShape();
+ SShape *shapeB = iFEdgeB->shape();
+
+ SVertex * Ia = shapeA->CreateSVertex(iA3D, iA2D, iFEdgeA->vertexA()->getId());
+ SVertex * Ib = shapeB->CreateSVertex(iB3D, iB2D, iFEdgeB->vertexA()->getId());
+
+ // depending on which of these 2 svertices is the nearest from the
+ // viewpoint, we're going to build the TVertex by giving them in
+ // an order or another (the first one must be the nearest)
+ real dista = Ia->point2D()[2];
+ real distb = Ib->point2D()[2];
+
+ TVertex * tvertex;
+ if(dista < distb)
+ tvertex = new TVertex(Ia, Ib);
+ else
+ tvertex = new TVertex(Ib,Ia);
+
+ tvertex->setId(id);
+
+ // add these vertices to the view map
+ AddViewVertex(tvertex);
+ AddSVertex(Ia);
+ AddSVertex(Ib);
+
+ // and this T Vertex to the view shapes:
+ vshapeA->AddVertex(tvertex);
+ vshapeB->AddVertex(tvertex);
+
+ return tvertex;
+}
+
+ViewVertex * ViewMap::InsertViewVertex(SVertex *iVertex,
+ vector<ViewEdge*>& newViewEdges){
+ NonTVertex *vva = dynamic_cast<NonTVertex*>(iVertex->viewvertex());
+ if(vva != 0)
+ return vva;
+ // beacuse it is not already a ViewVertex, this SVertex must have only
+ // 2 FEdges. The incoming one still belongs to ioEdge, the outgoing one
+ // now belongs to newVEdge
+ const vector<FEdge*>& fedges = iVertex->fedges();
+ if(fedges.size()!=2){
+ cerr << "ViewMap warning: Can't split the ViewEdge" << endl;
+ return 0;
+ }
+ FEdge * fend(0), * fbegin(0);
+ for(vector<FEdge*>::const_iterator fe=fedges.begin(), feend=fedges.end();
+ fe!=feend;
+ ++fe){
+ if((*fe)->vertexB() == iVertex){
+ fend = (*fe);
+ }
+ if((*fe)->vertexA() == iVertex){
+ fbegin = (*fe);
+ }
+ if((fbegin!=0) && (fend!=0))
+ break;
+ }
+ ViewEdge *ioEdge = fbegin->viewedge();
+ ViewShape * vshape = ioEdge->viewShape();
+ vva = new NonTVertex(iVertex);
+ // if the ViewEdge is a closed loop, we don't create
+ // a new VEdge
+ if(ioEdge->A() == 0){
+ // closed loop
+ ioEdge->setA(vva);
+ ioEdge->setB(vva);
+ // update sshape
+ vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeA());
+ vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeB());
+
+ ioEdge->setFEdgeA(fbegin);
+ ioEdge->setFEdgeB(fend);
+
+ // Update FEdges
+ fend->setNextEdge(0);
+ fbegin->setPreviousEdge(0);
+
+ // update new View Vertex:
+ vva->AddOutgoingViewEdge(ioEdge);
+ vva->AddIncomingViewEdge(ioEdge);
+
+ vshape->sshape()->AddChain(ioEdge->fedgeA());
+ vshape->sshape()->AddChain(ioEdge->fedgeB());
+ }else{
+ // Create new ViewEdge
+ ViewEdge * newVEdge = new ViewEdge(vva, ioEdge->B(), fbegin, ioEdge->fedgeB(), vshape);
+ newVEdge->setId(Id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond()+1));
+ newVEdge->setNature(ioEdge->getNature());
+ //newVEdge->UpdateFEdges(); // done in the ViewEdge constructor
+ // Update old ViewEdge
+ ioEdge->setB(vva);
+ ioEdge->setFEdgeB(fend);
+
+ // Update FEdges
+ fend->setNextEdge(0);
+ fbegin->setPreviousEdge(0);
+
+ // update new View Vertex:
+ vva->AddOutgoingViewEdge(newVEdge);
+ vva->AddIncomingViewEdge(ioEdge);
+ // update ViewShape
+ //vshape->AddEdge(newVEdge);
+ // update SShape
+ vshape->sshape()->AddChain(fbegin);
+ // update ViewMap
+ //_VEdges.push_back(newVEdge);
+ newViewEdges.push_back(newVEdge);
+ }
+
+ // update ViewShape
+ vshape->AddVertex(vva);
+
+ // update ViewMap
+ _VVertices.push_back(vva);
+
+ return vva;
+}
+
+//FEdge * ViewMap::Connect(FEdge *ioEdge, SVertex *ioVertex, vector<ViewEdge*>& oNewVEdges){
+// SShape * sshape = ioEdge->shape();
+// FEdge *newFEdge = sshape->SplitEdgeIn2(ioEdge, ioVertex);
+// AddFEdge(newFEdge);
+// InsertViewVertex(ioVertex, oNewVEdges);
+// return newFEdge;
+//}
+
+ /**********************************/
+ /* */
+ /* */
+ /* TVertex */
+ /* */
+ /* */
+ /**********************************/
+
+// is dve1 before dve2 ? (does it have a smaller angle ?)
+bool ViewEdgeComp(ViewVertex::directedViewEdge& dve1, ViewVertex::directedViewEdge& dve2){
+ FEdge *fe1;
+ if(dve1.second)
+ fe1 = dve1.first->fedgeB();
+ else
+ fe1 = dve1.first->fedgeA();
+ FEdge *fe2;
+ if(dve2.second)
+ fe2 = dve2.first->fedgeB();
+ else
+ fe2 = dve2.first->fedgeA();
+
+ Vec3r V1 = fe1->orientation2d();
+ Vec2r v1(V1.x(), V1.y());v1.normalize();
+ Vec3r V2 = fe2->orientation2d();
+ Vec2r v2(V2.x(), V2.y());v2.normalize();
+ if(v1.y() > 0){
+ if(v2.y() < 0)
+ return true;
+ else
+ return (v1.x() > v2.x());
+ }else{
+ if(v2.y() > 0)
+ return false;
+ else
+ return (v1.x() < v2.x());
+ }
+ return false;
+}
+void TVertex::setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming) {
+ if (!iFrontEdgeA) {
+ cerr << "Warning: null pointer passed as argument of TVertex::setFrontEdgeA()" << endl;
+ return;
+ }
+ _FrontEdgeA = directedViewEdge(iFrontEdgeA, incoming);
+ if(!_sortedEdges.empty()){
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(**dve, _FrontEdgeA)){
+ ++dve;
+ }
+ _sortedEdges.insert( dve, &_FrontEdgeA);
+ }
+ else
+ _sortedEdges.push_back(&_FrontEdgeA);
+}
+void TVertex::setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming) {
+ if (!iFrontEdgeB) {
+ cerr << "Warning: null pointer passed as argument of TVertex::setFrontEdgeB()" << endl;
+ return;
+ }
+ _FrontEdgeB = directedViewEdge(iFrontEdgeB, incoming);
+ if(!_sortedEdges.empty()){
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(**dve, _FrontEdgeB)){
+ ++dve;
+ }
+ _sortedEdges.insert(dve, &_FrontEdgeB);
+ }
+ else
+ _sortedEdges.push_back(&_FrontEdgeB);
+}
+void TVertex::setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming) {
+ if (!iBackEdgeA) {
+ cerr << "Warning: null pointer passed as argument of TVertex::setBackEdgeA()" << endl;
+ return;
+ }
+ _BackEdgeA = directedViewEdge(iBackEdgeA, incoming);
+ if(!_sortedEdges.empty()){
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(**dve, _BackEdgeA)){
+ ++dve;
+ }
+ _sortedEdges.insert(dve, &_BackEdgeA);
+ }
+ else
+ _sortedEdges.push_back(&_BackEdgeA);
+}
+void TVertex::setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming) {
+ if (!iBackEdgeB) {
+ cerr << "Warning: null pointer passed as argument of TVertex::setBackEdgeB()" << endl;
+ return;
+ }
+ _BackEdgeB = directedViewEdge(iBackEdgeB, incoming);
+ if(!_sortedEdges.empty()){
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(**dve, _BackEdgeB)){
+ ++dve;
+ }
+ _sortedEdges.insert(dve, &_BackEdgeB);
+ }
+ else
+ _sortedEdges.push_back(&_BackEdgeB);
+}
+void TVertex::Replace(ViewEdge *iOld, ViewEdge *iNew)
+{
+ // theoritically, we only replace edges for which this
+ // view vertex is the B vertex
+ if((iOld == _FrontEdgeA.first) && (_FrontEdgeA.first->B() == this))
+ {
+ _FrontEdgeA.first = iNew;
+ return;
+ }
+ if((iOld == _FrontEdgeB.first) && (_FrontEdgeB.first->B() == this))
+ {
+ _FrontEdgeB.first = iNew;
+ return;
+ }
+ if((iOld == _BackEdgeA.first) && (_BackEdgeA.first->B() == this))
+ {
+ _BackEdgeA.first = iNew;
+ return;
+ }
+ if((iOld == _BackEdgeB.first) && (_BackEdgeB.first->B() == this))
+ {
+ _BackEdgeB.first = iNew;
+ return;
+ }
+}
+
+/*! iterators access */
+ViewVertex::edge_iterator TVertex::edges_begin()
+{
+ //return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA);
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+ViewVertex::const_edge_iterator TVertex::edges_begin() const
+{
+ //return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA);
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+ViewVertex::edge_iterator TVertex::edges_end()
+{
+ //return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, directedViewEdge(0,true));
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+ViewVertex::const_edge_iterator TVertex::edges_end() const
+{
+ //return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, directedViewEdge(0, true));
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+ViewVertex::edge_iterator TVertex::edges_iterator(ViewEdge *iEdge)
+{
+ for(edge_pointers_container::iterator it=_sortedEdges.begin(), itend=_sortedEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((*it)->first == iEdge)
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+
+ // directedViewEdge dEdge;
+ // if(_FrontEdgeA.first == iEdge)
+ // dEdge = _FrontEdgeA;
+ // else if(_FrontEdgeB.first == iEdge)
+ // dEdge = _FrontEdgeB;
+ // else if(_BackEdgeA.first == iEdge)
+ // dEdge = _BackEdgeA;
+ // else if(_BackEdgeB.first == iEdge)
+ // dEdge = _BackEdgeB;
+ // return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge);
+}
+ViewVertex::const_edge_iterator TVertex::edges_iterator(ViewEdge *iEdge) const
+{
+ for(edge_pointers_container::const_iterator it=_sortedEdges.begin(), itend=_sortedEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((*it)->first == iEdge)
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+
+ // directedViewEdge dEdge;
+ // if(_FrontEdgeA.first == iEdge)
+ // dEdge = _FrontEdgeA;
+ // else if(_FrontEdgeB.first == iEdge)
+ // dEdge = _FrontEdgeB;
+ // else if(_BackEdgeA.first == iEdge)
+ // dEdge = _BackEdgeA;
+ // else if(_BackEdgeB.first == iEdge)
+ // dEdge = _BackEdgeB;
+ // return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge);
+}
+
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesBegin() {
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesEnd() {
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesIterator(ViewEdge *iEdge) {
+ for(edge_pointers_container::iterator it=_sortedEdges.begin(), itend=_sortedEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((*it)->first == iEdge)
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+ /**********************************/
+ /* */
+ /* */
+ /* NonTVertex */
+ /* */
+ /* */
+ /**********************************/
+
+void NonTVertex::AddOutgoingViewEdge(ViewEdge * iVEdge){
+ // let's keep the viewedges ordered in CCW order
+ // in the 2D image plan
+ directedViewEdge idve(iVEdge, false);
+ if(!_ViewEdges.empty()){
+ edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(*dve, idve)){
+ ++dve;
+ }
+ _ViewEdges.insert(dve, idve);
+ }
+ else
+ _ViewEdges.push_back(idve);
+}
+
+void NonTVertex::AddIncomingViewEdge(ViewEdge * iVEdge){
+ // let's keep the viewedges ordered in CCW order
+ // in the 2D image plan
+ directedViewEdge idve(iVEdge, true);
+ if(!_ViewEdges.empty()){
+ edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(*dve, idve)){
+ ++dve;
+ }
+ _ViewEdges.insert(dve, idve);
+ }
+ else
+ _ViewEdges.push_back(idve);
+}
+
+/*! iterators access */
+ViewVertex::edge_iterator NonTVertex::edges_begin()
+{
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ViewVertex::const_edge_iterator NonTVertex::edges_begin() const
+{
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ViewVertex::edge_iterator NonTVertex::edges_end()
+{
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+ViewVertex::const_edge_iterator NonTVertex::edges_end() const
+{
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+ViewVertex::edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge)
+{
+ for(edges_container::iterator it=_ViewEdges.begin(), itend=_ViewEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((it)->first == iEdge)
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ViewVertex::const_edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge) const
+{
+ for(edges_container::const_iterator it=_ViewEdges.begin(), itend=_ViewEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((it)->first == iEdge)
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesBegin() {
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesEnd() {
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesIterator(ViewEdge *iEdge) {
+ for(edges_container::iterator it=_ViewEdges.begin(), itend=_ViewEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((it)->first == iEdge)
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+real ViewEdge::getLength2D() const
+{
+ float length = 0.f;
+ ViewEdge::const_fedge_iterator itlast = fedge_iterator_last();
+ ViewEdge::const_fedge_iterator it = fedge_iterator_begin(), itend=fedge_iterator_end();
+ Vec2r seg;
+ do{
+ seg = Vec2r((*it)->orientation2d()[0], (*it)->orientation2d()[1]);
+ length += seg.norm();
+ ++it;
+ }while((it!=itend) && (it!=itlast));
+ return length;
+}
+
+
+//! view edge iterator
+ViewEdge::edge_iterator ViewEdge::ViewEdge_iterator() {return edge_iterator(this);}
+ViewEdge::const_edge_iterator ViewEdge::ViewEdge_iterator() const {return const_edge_iterator((ViewEdge*)this);}
+//! feature edge iterator
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_begin() {return fedge_iterator(this->_FEdgeA, this->_FEdgeB);}
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_begin() const {return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB);}
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_last() {return fedge_iterator(this->_FEdgeB, this->_FEdgeB);}
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_last() const {return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB);}
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_end() {return fedge_iterator(0, this->_FEdgeB);}
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_end() const {return const_fedge_iterator(0, this->_FEdgeB);}
+//! embedding vertex iterator
+ViewEdge::const_vertex_iterator ViewEdge::vertices_begin() const {return const_vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA);}
+ViewEdge::vertex_iterator ViewEdge::vertices_begin() {return vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA);}
+ViewEdge::const_vertex_iterator ViewEdge::vertices_last() const {return const_vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);}
+ViewEdge::vertex_iterator ViewEdge::vertices_last() {return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);}
+ViewEdge::const_vertex_iterator ViewEdge::vertices_end() const {return const_vertex_iterator(0, _FEdgeB, 0);}
+ViewEdge::vertex_iterator ViewEdge::vertices_end() {return vertex_iterator(0, _FEdgeB, 0);}
+
+
+Interface0DIterator ViewEdge::verticesBegin() {
+ Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(this->_FEdgeA->vertexA(), this->_FEdgeA->vertexA(), 0, _FEdgeA, 0.f));
+ return ret;
+}
+
+Interface0DIterator ViewEdge::verticesEnd() {
+ Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(0, this->_FEdgeA->vertexA(), _FEdgeB, 0, getLength2D()));
+ return ret;
+}
+
+Interface0DIterator ViewEdge::pointsBegin(float t) {
+ return verticesBegin();
+}
+
+Interface0DIterator ViewEdge::pointsEnd(float t) {
+ return verticesEnd();
+}
+
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+ViewShape::~ViewShape()
+{
+ _Vertices.clear();
+
+ if(!(_Edges.empty()))
+ {
+ for(vector<ViewEdge*>::iterator e=_Edges.begin(), eend=_Edges.end();
+ e!=eend;
+ e++)
+ {
+ delete (*e);
+ }
+ _Edges.clear();
+ }
+
+ if(0 != _SShape)
+ {
+ delete _SShape;
+ _SShape = 0;
+ }
+}
+
+void ViewShape::RemoveEdge(ViewEdge * iViewEdge)
+{
+ FEdge * fedge = iViewEdge->fedgeA();
+ for(vector<ViewEdge*>::iterator ve=_Edges.begin(),veend=_Edges.end();
+ ve!=veend;
+ ve++)
+ {
+ if(iViewEdge == (*ve))
+ {
+ _Edges.erase(ve);
+ _SShape->RemoveEdge(fedge);
+ break;
+ }
+ }
+}
+
+void ViewShape::RemoveVertex(ViewVertex * iViewVertex)
+{
+ for(vector<ViewVertex*>::iterator vv=_Vertices.begin(), vvend=_Vertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ if(iViewVertex == (*vv))
+ {
+ _Vertices.erase(vv);
+ break;
+ }
+ }
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+
+void ViewEdge::UpdateFEdges()
+{
+ FEdge *currentEdge = _FEdgeA;
+ do
+ {
+ currentEdge->setViewEdge(this);
+ currentEdge = currentEdge->nextEdge();
+ }while((currentEdge != NULL) && (currentEdge!= _FEdgeB));
+ // last one
+ _FEdgeB->setViewEdge(this);
+
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h
new file mode 100755
index 00000000000..d2d7a9a5341
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMap.h
@@ -0,0 +1,1506 @@
+//
+// Filename : ViewMap.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define a View Map (ViewVertex, ViewEdge, etc.)
+// Date of creation : 03/09/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAP_H
+# define VIEWMAP_H
+
+# include "Interface0D.h"
+# include "Interface1D.h"
+# include "Silhouette.h" // defines the embedding
+# include "../system/BaseIterator.h"
+# include "../system/FreestyleConfig.h"
+# include "../geometry/GeomUtils.h"
+# include <map>
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewMap */
+ /* */
+ /* */
+ /**********************************/
+
+
+/* Density
+ Mean area depth value
+ distance to a point
+ */
+
+class ViewVertex;
+class ViewEdge;
+class ViewShape;
+class TVertex;
+
+/*! Class defining the ViewMap.*/
+class LIB_VIEW_MAP_EXPORT ViewMap
+{
+public:
+
+ typedef vector<ViewEdge*> viewedges_container;
+ typedef vector<ViewVertex*> viewvertices_container;
+ typedef vector<ViewShape*> viewshapes_container;
+ typedef vector<SVertex*> svertices_container;
+ typedef vector<FEdge*> fedges_container;
+ typedef map<int,int> id_to_index_map;
+
+private:
+
+ static ViewMap *_pInstance;
+ viewshapes_container _VShapes; // view shapes
+ viewedges_container _VEdges; // view edges
+ viewvertices_container _VVertices; // view vertices
+ fedges_container _FEdges; // feature edges (embedded edges)
+ svertices_container _SVertices; // embedded vertices
+ BBox<Vec3r> _scene3DBBox;
+ id_to_index_map _shapeIdToIndex; // Mapping between the WShape or VShape id to the VShape index in the
+ // _VShapes vector. Used in the method viewShape(int id) to access a shape from its id.
+
+public:
+
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void* userdata;
+
+ /*! Default constructor. */
+ ViewMap() {
+ _pInstance = this;
+ userdata = 0;
+ }
+ /*! Destructor. */
+ virtual ~ViewMap();
+
+ /*! Gets the viewedge the nearest to the
+ * 2D position specified as argument
+ */
+ const ViewEdge * getClosestViewEdge(real x, real y) const ;
+
+ /*! Gets the Fedge the nearest to the
+ * 2D position specified as argument
+ */
+ const FEdge * getClosestFEdge(real x, real y) const ;
+
+ /* accessors */
+ /*! The ViewMap is a singleton class. This static method
+ * returns the instance of the ViewMap.
+ */
+ static inline ViewMap * getInstance() {return _pInstance;}
+ /* Returns the list of ViewShapes of the scene. */
+ inline viewshapes_container& ViewShapes() {return _VShapes;}
+ /* Returns the list of ViewEdges of the scene. */
+ inline viewedges_container& ViewEdges() {return _VEdges;}
+ /* Returns the list of ViewVertices of the scene. */
+ inline viewvertices_container& ViewVertices() {return _VVertices;}
+ /* Returns the list of FEdges of the scene. */
+ inline fedges_container& FEdges() {return _FEdges;}
+ /* Returns the list of SVertices of the scene. */
+ inline svertices_container& SVertices() {return _SVertices;}
+ /* Returns an iterator pointing onto the first ViewEdge of the list. */
+ inline viewedges_container::iterator viewedges_begin() {return _VEdges.begin();}
+ inline viewedges_container::iterator viewedges_end() {return _VEdges.end();}
+ inline int viewedges_size() {return _VEdges.size();}
+ ViewShape * viewShape(unsigned index);
+ id_to_index_map& shapeIdToIndexMap() {return _shapeIdToIndex;}
+
+ /*! Returns the scene 3D bounding box. */
+ inline BBox<Vec3r> getScene3dBBox() const {return _scene3DBBox;}
+
+ /* modifiers */
+ void AddViewShape(ViewShape *iVShape);
+ inline void AddViewEdge(ViewEdge *iVEdge) {_VEdges.push_back(iVEdge);}
+ inline void AddViewVertex(ViewVertex *iVVertex) {_VVertices.push_back(iVVertex);}
+ inline void AddFEdge(FEdge *iFEdge) {_FEdges.push_back(iFEdge);}
+ inline void AddSVertex(SVertex *iSVertex) {_SVertices.push_back(iSVertex);}
+ /*! Sets the scene 3D bounding box. */
+ inline void setScene3dBBox(const BBox<Vec3r>& bbox) {_scene3DBBox=bbox;}
+
+ /* Creates a T vertex in the view map.
+ * A T vertex is the intersection between 2
+ * FEdges (before these ones are splitted).
+ * The TVertex is a 2D intersection but it
+ * corresponds to a 3D point on each of the 2 FEdges.
+ * iA3D
+ * The 3D coordinates of the point corresponding
+ * to the intersection on the first edge.
+ * iA2D
+ * The x,y,z 2D coordinates of the projection
+ * of iA3D
+ * iFEdgeA
+ * The first FEdge
+ * iB3D
+ * The 3D coordinates of the point corresponding
+ * to the intersection on the second edge.
+ * iB2D
+ * The x,y,z 2D coordinates of the projection
+ * of iB3D
+ * iFEdgeB
+ * The second FEdge
+ * id
+ * The id that must be given to that TVertex
+ */
+ TVertex* CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA,
+ const Vec3r& iB3D, const Vec3r& iB2D, FEdge *iFEdgeB,
+ const Id& id);
+
+ /* Updates the structures to take into account the fact
+ * that a SVertex must now be considered as a ViewVertex
+ * iVertex
+ * The SVertex on top of which the ViewVertex is built (it is necessarily
+ * a NonTVertex because it is a SVertex)
+ * newViewEdges
+ * The new ViewEdges that must be add to the ViewMap
+ */
+ ViewVertex * InsertViewVertex(SVertex *iVertex, vector<ViewEdge*>& newViewEdges);
+
+ /* connects a FEdge to the graph trough a SVertex */
+ //FEdge * Connect(FEdge *ioEdge, SVertex *ioVertex);
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewVertex */
+ /* */
+ /* */
+ /**********************************/
+
+class ViewEdge;
+class SShape;
+
+namespace ViewVertexInternal {
+ class edge_const_traits;
+ class edge_nonconst_traits;
+ template<class Traits> class edge_iterator_base ;
+ class orientedViewEdgeIterator;
+} // end of namespace ViewEdgeInternal
+/*! Class to define a view vertex
+ * A view vertex is a feature vertex corresponding
+ * to a point of the image graph, where the characteristics of an
+ * edge might change (nature, visibility, ...).
+ * A ViewVertex can be of two kinds: a TVertex when
+ * it corresponds to the intersection between two
+ * ViewEdges or a NonTVertex when it corresponds to a
+ * vertex of the initial input mesh (it is the case
+ * for vertices such as corners for example).
+ * Thus, this class can be specialized into two classes,
+ * the TVertex class and the NonTVertex class.
+ */
+class LIB_VIEW_MAP_EXPORT ViewVertex : public Interface0D
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "ViewVertex" .*/
+ virtual string getExactTypeName() const {
+ return "ViewVertex";
+ }
+
+public:
+ friend class ViewShape;
+ typedef pair<ViewEdge*, bool> directedViewEdge; // if bool = true, the ViewEdge is incoming
+
+ typedef vector<directedViewEdge> edges_container;
+
+ typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_nonconst_traits> edge_iterator;
+ typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_const_traits> const_edge_iterator;
+
+private:
+
+ Nature::VertexNature _Nature;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void * userdata;
+ /*! Default constructor.*/
+ inline ViewVertex() {userdata = 0;_Nature = Nature::VIEW_VERTEX; }
+ inline ViewVertex(Nature::VertexNature nature) {
+ userdata = 0;
+ _Nature = Nature::VIEW_VERTEX | nature;
+ }
+
+protected:
+ /*! Copy constructor. */
+ inline ViewVertex(ViewVertex& iBrother)
+ {
+ _Nature = iBrother._Nature;
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+ /*! Cloning method. */
+ virtual ViewVertex * duplicate() = 0;
+
+public:
+ /*! Destructor. */
+ virtual ~ViewVertex() {}
+
+ /* accessors */
+ /*! Returns the nature of the vertex .*/
+ virtual Nature::VertexNature getNature() const {
+ return _Nature;
+ }
+
+ /* modifiers */
+ /*! Sets the nature of the vertex. */
+ inline void setNature(Nature::VertexNature iNature) {_Nature = iNature;}
+
+ /* Replaces old edge by new edge */
+ virtual void Replace(ViewEdge *, ViewEdge *) {}
+
+public:
+
+ /* iterators access */
+ // allows iteration on the edges that comes from/goes to
+ // this vertex in CCW order (order defined in 2D in the image plan)
+ virtual edge_iterator edges_begin() = 0;
+ virtual const_edge_iterator edges_begin() const = 0;
+ virtual edge_iterator edges_end() = 0;
+ virtual const_edge_iterator edges_end() const = 0;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge) = 0;
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const = 0;
+
+
+ // Iterator access
+ /*! Returns an iterator over the ViewEdges that goes to or comes from
+ * this ViewVertex pointing to the first ViewEdge of the list.
+ * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() = 0;
+
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex,
+ * pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() = 0;
+
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge
+ * given as argument.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) = 0;
+
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* TVertex */
+ /* */
+ /* */
+ /**********************************/
+
+/*! class to define a T vertex, i.e. an intersection between
+ * two edges.
+ * It points towards 2 SVertex and 4 View edges.
+ * Among these ViewEdges, 2 are front and 2 are back.
+ * Basically the front edge hides part of the back edge.
+ * So, among the back edges, 1 is of invisibility n
+ * and the other of visibility n+1
+ */
+class LIB_VIEW_MAP_EXPORT TVertex : public ViewVertex
+{
+public:
+ typedef vector<directedViewEdge*> edge_pointers_container;
+public: // Implementation of Interface0D
+
+ /*! Returns the string "TVertex" .*/
+ virtual string getExactTypeName() const {
+ return "TVertex";
+ }
+
+ // Data access methods
+ /* Returns the 3D x coordinate of the vertex .
+ * Ambiguous in this case.
+ */
+ virtual real getX() const {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().x();
+ }
+
+ virtual real getY() const {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().y();
+ }
+
+ virtual real getZ() const {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const {
+ cerr << "Warning: getPoint3D() undefined for this point" << endl;
+ return _FrontSVertex->getPoint3D();
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex .*/
+ virtual real getProjectedX() const {
+ return _FrontSVertex->point2D().x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex .*/
+ virtual real getProjectedY() const {
+ return _FrontSVertex->point2D().y();
+ }
+
+ virtual real getProjectedZ() const {
+ return _FrontSVertex->point2D().z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const {
+ return _FrontSVertex->getPoint2D();
+ }
+
+ /*! Returns the Id of the TVertex .*/
+ virtual Id getId() const {
+ return _Id;
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ // it can't
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ return this;
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex(){
+ return this;
+ }
+
+private:
+ SVertex *_FrontSVertex;
+ SVertex *_BackSVertex;
+ directedViewEdge _FrontEdgeA;
+ directedViewEdge _FrontEdgeB;
+ directedViewEdge _BackEdgeA;
+ directedViewEdge _BackEdgeB;
+ Id _Id; // id to identify t vertices . these id will be negative in order not to be mixed with NonTVertex ids.
+ edge_pointers_container _sortedEdges; // the list of the four ViewEdges, ordered in CCW order (in the image plan)
+
+
+public:
+ /*! Default constructor.*/
+ inline TVertex() : ViewVertex(Nature::T_VERTEX)
+ {
+ _FrontSVertex = 0;
+ _BackSVertex = 0;
+ _FrontEdgeA.first = 0;
+ _FrontEdgeB.first = 0;
+ _BackEdgeA.first = 0;
+ _BackEdgeB.first = 0;
+
+ }
+
+ inline TVertex(SVertex *svFront, SVertex *svBack)
+ : ViewVertex(Nature::T_VERTEX)
+ {
+ _FrontSVertex = svFront;
+ _BackSVertex = svBack;
+ _FrontEdgeA.first = 0;
+ _FrontEdgeB.first = 0;
+ _BackEdgeA.first = 0;
+ _BackEdgeB.first = 0;
+ svFront->setViewVertex(this);
+ svBack->setViewVertex(this);
+ }
+
+protected:
+ /*! Copy constructor. */
+ inline TVertex(TVertex& iBrother)
+ : ViewVertex(iBrother)
+ {
+ _FrontSVertex = iBrother._FrontSVertex;
+ _BackSVertex = iBrother._BackSVertex;
+ _FrontEdgeA = iBrother._FrontEdgeA;
+ _FrontEdgeB = iBrother._FrontEdgeB;
+ _BackEdgeA = iBrother._BackEdgeA;
+ _BackEdgeB = iBrother._BackEdgeB;
+ _sortedEdges = iBrother._sortedEdges;
+ }
+
+ /*! Cloning method. */
+ virtual ViewVertex * duplicate()
+ {
+ TVertex *clone = new TVertex(*this);
+ return clone;
+ }
+
+public:
+ /* accessors */
+ /*! Returns the SVertex that is closer to the viewpoint. */
+ inline SVertex *frontSVertex() {return _FrontSVertex;}
+ /*! Returns the SVertex that is further away from the viewpoint. */
+ inline SVertex *backSVertex() {return _BackSVertex;}
+ inline directedViewEdge& frontEdgeA() {return _FrontEdgeA;}
+ inline directedViewEdge& frontEdgeB() {return _FrontEdgeB;}
+ inline directedViewEdge& backEdgeA() {return _BackEdgeA;}
+ inline directedViewEdge& backEdgeB() {return _BackEdgeB;}
+
+ /* modifiers */
+ /*! Sets the SVertex that is closer to the viewpoint. */
+ inline void setFrontSVertex(SVertex *iFrontSVertex) {_FrontSVertex = iFrontSVertex;_FrontSVertex->setViewVertex(this);}
+ /*! Sets the SVertex that is further away from the viewpoint. */
+ inline void setBackSVertex(SVertex *iBackSVertex) {_BackSVertex = iBackSVertex;_BackSVertex->setViewVertex(this);}
+ void setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming=true);
+ void setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming=true) ;
+ void setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming=true);
+ void setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming=true) ;
+ /*! Sets the Id. */
+ inline void setId(const Id& iId) {_Id = iId;}
+
+ /*! Returns the SVertex (among the 2) belonging to the FEdge iFEdge */
+ inline SVertex * getSVertex(FEdge *iFEdge)
+ {
+ const vector<FEdge*>& vfEdges = _FrontSVertex->fedges();
+ vector<FEdge*>::const_iterator fe,fend;
+ for(fe=vfEdges.begin(),fend=vfEdges.end();
+ fe!=fend;
+ fe++)
+ {
+ if((*fe) == iFEdge)
+ return _FrontSVertex;
+ }
+
+ const vector<FEdge*>& vbEdges = _BackSVertex->fedges();
+ for(fe=vbEdges.begin(),fend=vbEdges.end();
+ fe!=fend;
+ fe++)
+ {
+ if((*fe) == iFEdge)
+ return _BackSVertex;
+ }
+ return 0;
+ }
+
+ virtual void Replace(ViewEdge *iOld, ViewEdge *iNew);
+
+ /*! returns the mate edge of iEdgeA.
+ * For example, if iEdgeA is frontEdgeA,
+ * then frontEdgeB is returned. If iEdgeA is
+ * frontEdgeB then frontEdgeA is returned.
+ * Same for back edges
+ */
+ virtual ViewEdge * mate(ViewEdge* iEdgeA)
+ {
+ if(iEdgeA == _FrontEdgeA.first)
+ return _FrontEdgeB.first;
+ if(iEdgeA == _FrontEdgeB.first)
+ return _FrontEdgeA.first;
+ if(iEdgeA == _BackEdgeA.first)
+ return _BackEdgeB.first;
+ if(iEdgeA == _BackEdgeB.first)
+ return _BackEdgeA.first;
+ return 0;
+ }
+
+ /* iterators access */
+ virtual edge_iterator edges_begin();
+ virtual const_edge_iterator edges_begin() const;
+ virtual edge_iterator edges_end();
+ virtual const_edge_iterator edges_end() const;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge);
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const;
+
+ /*! Returns an iterator over the ViewEdges that goes to or comes from
+ * this ViewVertex pointing to the first ViewEdge of the list.
+ * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() ;
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex,
+ * pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() ;
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge
+ * given as argument.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) ;
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* NonTVertex */
+ /* */
+ /* */
+ /**********************************/
+
+
+// (non T vertex)
+/*! View vertex for corners, cusps, etc...
+ * Associated to a single SVertex.
+ * Can be associated to 2 or several view edges
+ */
+class LIB_VIEW_MAP_EXPORT NonTVertex : public ViewVertex
+{
+public:
+ typedef vector<directedViewEdge> edges_container;
+
+public: // Implementation of Interface0D
+
+ /*! Returns the string "ViewVertex" .*/
+ virtual string getExactTypeName() const {
+ return "NonTVertex";
+ }
+
+ // Data access methods
+ /*! Returns the 3D x coordinate of the vertex .*/
+ virtual real getX() const {
+ return _SVertex->point3D().x();
+ }
+ /*! Returns the 3D y coordinate of the vertex .*/
+ virtual real getY() const {
+ return _SVertex->point3D().y();
+ }
+
+ /*! Returns the 3D z coordinate of the vertex .*/
+ virtual real getZ() const {
+ return _SVertex->point3D().z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const {
+ return _SVertex->getPoint3D();
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex .*/
+ virtual real getProjectedX() const {
+ return _SVertex->point2D().x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex .*/
+ virtual real getProjectedY() const {
+ return _SVertex->point2D().y();
+ }
+
+ /*! Returns the projected 3D z coordinate of the vertex .*/
+ virtual real getProjectedZ() const {
+ return _SVertex->point2D().z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const {
+ return _SVertex->getPoint2D();
+ }
+
+ /*! Returns the Id of the vertex .*/
+ virtual Id getId() const {
+ return _SVertex->getId();
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex(){
+ return _SVertex;
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ return this;
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex(){
+ return this;
+ }
+
+private:
+ SVertex *_SVertex;
+ edges_container _ViewEdges;
+public:
+ /*! Default constructor.*/
+ inline NonTVertex() : ViewVertex(Nature::NON_T_VERTEX) { _SVertex = 0; }
+ /*! Builds a NonTVertex from a SVertex. */
+ inline NonTVertex(SVertex* iSVertex) : ViewVertex(Nature::NON_T_VERTEX)
+ {
+ _SVertex = iSVertex;
+ _SVertex->setViewVertex(this);
+ }
+protected:
+ /*! Copy constructor. */
+ inline NonTVertex(NonTVertex& iBrother)
+ : ViewVertex(iBrother)
+ {
+ _SVertex = iBrother._SVertex;
+ _SVertex->setViewVertex(this);
+ _ViewEdges = iBrother._ViewEdges;
+ }
+ /*! Cloning method. */
+ virtual ViewVertex * duplicate()
+ {
+ NonTVertex *clone = new NonTVertex(*this);
+ return clone;
+ }
+public:
+ /*! destructor. */
+ virtual ~NonTVertex() {}
+
+ /* accessors */
+ /*! Returns the SVertex on top of which this NonTVertex is built. */
+ inline SVertex * svertex() {return _SVertex;}
+ inline edges_container& viewedges() {return _ViewEdges;}
+
+ /* modifiers */
+ /*! Sets the SVertex on top of which this NonTVertex is built. */
+ inline void setSVertex(SVertex *iSVertex) {_SVertex = iSVertex;_SVertex->setViewVertex(this);}
+ inline void setViewEdges(const vector<directedViewEdge>& iViewEdges) {_ViewEdges = iViewEdges;}
+ void AddIncomingViewEdge(ViewEdge * iVEdge) ;
+ void AddOutgoingViewEdge(ViewEdge * iVEdge) ;
+ inline void AddViewEdge(ViewEdge * iVEdge, bool incoming=true) {
+ if(incoming)
+ AddIncomingViewEdge(iVEdge);
+ else
+ AddOutgoingViewEdge(iVEdge);
+ }
+ /* Replaces old edge by new edge */
+ virtual void Replace(ViewEdge *iOld, ViewEdge *iNew)
+ {
+
+ edges_container::iterator insertedve;
+ for(edges_container::iterator ve=_ViewEdges.begin(),vend=_ViewEdges.end();
+ ve!=vend;
+ ve++)
+ {
+ if((ve)->first == iOld)
+ {
+ insertedve = _ViewEdges.insert(ve, directedViewEdge(iNew, ve->second));// inserts e2 before ve.
+ // returns an iterator pointing toward e2. ve is invalidated.
+ // we want to remove e1, but we can't use ve anymore:
+ insertedve++; // insertedve points now to e1
+ _ViewEdges.erase(insertedve);
+ return;
+ }
+ }
+ }
+
+
+ /* iterators access */
+ virtual edge_iterator edges_begin();
+ virtual const_edge_iterator edges_begin() const;
+ virtual edge_iterator edges_end();
+ virtual const_edge_iterator edges_end() const;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge);
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const;
+
+ /*! Returns an iterator over the ViewEdges that goes to or comes from
+ * this ViewVertex pointing to the first ViewEdge of the list.
+ * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() ;
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex,
+ * pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() ;
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge
+ * given as argument.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) ;
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+/* Geometry(normals...)
+ Nature of edges
+ 2D spaces (1or2, material, z...)
+ Parent Shape
+ 3D Shading, material
+ Importance
+ Occluders
+ */
+class ViewShape;
+
+namespace ViewEdgeInternal {
+ template<class Traits> class edge_iterator_base ;
+ template<class Traits> class fedge_iterator_base ;
+ template<class Traits> class vertex_iterator_base ;
+} // end of namespace ViewEdgeInternal
+
+/*! Class defining a ViewEdge. A ViewEdge in an edge
+ * of the image graph. it connnects two ViewVertex.
+ * It is made by connecting a set of FEdges.
+ */
+class LIB_VIEW_MAP_EXPORT ViewEdge : public Interface1D
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "ViewEdge" .*/
+ virtual string getExactTypeName() const {
+ return "ViewEdge";
+ }
+
+ // Data access methods
+ /*! Returns the Id of the vertex .*/
+ virtual Id getId() const {
+ return _Id;
+ }
+
+ /*! Returns the nature of the ViewEdge. */
+ virtual Nature::EdgeNature getNature() const {
+ return _Nature;
+ }
+
+public:
+
+ typedef SVertex vertex_type;
+ friend class ViewShape;
+ // for ViewEdge iterator
+ typedef ViewEdgeInternal::edge_iterator_base<Nonconst_traits<ViewEdge*> > edge_iterator;
+ typedef ViewEdgeInternal::edge_iterator_base<Const_traits<ViewEdge*> > const_edge_iterator;
+ // for fedge iterator
+ typedef ViewEdgeInternal::fedge_iterator_base<Nonconst_traits<FEdge*> > fedge_iterator;
+ typedef ViewEdgeInternal::fedge_iterator_base<Const_traits<FEdge*> > const_fedge_iterator;
+ // for svertex iterator
+ typedef ViewEdgeInternal::vertex_iterator_base<Nonconst_traits<SVertex*> > vertex_iterator;
+ typedef ViewEdgeInternal::vertex_iterator_base<Const_traits<SVertex*> > const_vertex_iterator;
+private:
+
+ ViewVertex * __A; // edge starting vertex
+ ViewVertex * __B; // edge ending vertex
+ Nature::EdgeNature _Nature; // nature of view edge
+ ViewShape *_Shape; // shape to which the view edge belongs
+ FEdge * _FEdgeA; // first edge of the embedded fedges chain
+ FEdge * _FEdgeB; // last edge of the embedded fedges chain
+ Id _Id;
+ unsigned _ChainingTimeStamp;
+ ViewShape *_aShape; // The silhouette view edge separates 2 2D spaces. The one on the left is
+ // necessarly the Shape _Shape (the one to which this edge belongs to)
+ // and _aShape is the one on its right // NON GERE PAR LE COPY CONSTRUCTEUR
+ int _qi;
+ vector<ViewShape*> _Occluders;
+ bool _isInImage;
+
+ // tmp
+ Id * _splittingId;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void * userdata;
+ /*! Default constructor.*/
+ inline ViewEdge() {
+ __A=0;
+ __B=0;
+ _FEdgeA = 0;
+ _FEdgeB = 0;
+ _ChainingTimeStamp = 0;
+ _qi = 0;
+ _aShape=0;
+ userdata = 0;
+ _splittingId = 0;
+ _isInImage = true;
+ }
+ inline ViewEdge(ViewVertex* iA, ViewVertex *iB)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = 0;
+ _FEdgeB = 0;
+ _Shape = 0;
+ _ChainingTimeStamp = 0;
+ _aShape = 0;
+ _qi = 0;
+ userdata = 0;
+ _splittingId = 0;
+ _isInImage = true;
+ }
+ inline ViewEdge(ViewVertex* iA, ViewVertex *iB, FEdge *iFEdgeA)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = iFEdgeA;
+ _FEdgeB = 0;
+ _Shape = 0;
+ _ChainingTimeStamp = 0;
+ _aShape = 0;
+ _qi = 0;
+ userdata = 0;
+ _splittingId = 0;
+ _isInImage = true;
+ }
+ inline ViewEdge(ViewVertex* iA, ViewVertex *iB, FEdge *iFEdgeA, FEdge *iFEdgeB, ViewShape *iShape)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = iFEdgeA;
+ _FEdgeB = iFEdgeB;
+ _Shape = iShape;
+ _ChainingTimeStamp = 0;
+ _aShape = 0;
+ _qi = 0;
+ userdata = 0;
+ _splittingId = 0;
+ _isInImage = true;
+ UpdateFEdges(); // tells every FEdge between iFEdgeA and iFEdgeB that this is theit ViewEdge
+ }
+
+//soc protected:
+
+ /*! Copy constructor. */
+ inline ViewEdge(ViewEdge& iBrother)
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _FEdgeA = iBrother._FEdgeA;
+ _FEdgeB = iBrother._FEdgeB;
+ _Nature = iBrother._Nature;
+ _Shape = 0;
+ _Id = iBrother._Id;
+ _ChainingTimeStamp = iBrother._ChainingTimeStamp;
+ _aShape = iBrother._aShape;
+ _qi = iBrother._qi;
+ _splittingId = 0;
+ _isInImage = iBrother._isInImage;
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+ /*! Cloning method. */
+ virtual ViewEdge * duplicate()
+ {
+ ViewEdge *clone = new ViewEdge(*this);
+ return clone;
+ }
+
+public:
+ /*! Destructor. */
+ virtual ~ViewEdge()
+ {
+ // if(0 != _aFace)
+ // {
+ // delete _aFace;
+ // _aFace = 0;
+ // }
+ // only the last splitted deletes this id
+ if(_splittingId){
+ if(*_splittingId == _Id)
+ delete _splittingId;
+ }
+ }
+
+ /* accessors */
+ /*! Returns the first ViewVertex. */
+ inline ViewVertex* A() {return __A;}
+ /*! Returns the second ViewVertex. */
+ inline ViewVertex* B() {return __B;}
+ /*! Returns the first FEdge that constitues this ViewEdge. */
+ inline FEdge* fedgeA() {return _FEdgeA;}
+ /*! Returns the last FEdge that constitues this ViewEdge. */
+ inline FEdge* fedgeB() {return _FEdgeB;}
+ /*! Returns the ViewShape to which this ViewEdge belongs to .*/
+ inline ViewShape * viewShape() {return _Shape;}
+ /*! Returns the shape that is occluded by the ViewShape
+ * to which this ViewEdge belongs to. If no object is occluded,
+ * 0 is returned.
+ * \return The occluded ViewShape.
+ */
+ inline ViewShape * aShape() {return _aShape;}
+ /*! Tells whether this ViewEdge forms a closed loop
+ * or not.
+ */
+ inline bool isClosed()
+ {
+ if(__B == 0)
+ return true;
+ return false;
+ }
+ /*! Returns the time stamp of this ViewEdge. */
+ inline unsigned getChainingTimeStamp() {return _ChainingTimeStamp;}
+ inline const ViewShape * aShape() const {return _aShape;}
+ inline const ViewShape * bShape() const {return _Shape;}
+ inline vector<ViewShape*>& occluders() {return _Occluders;}
+ inline Id * splittingId() {return _splittingId;}
+ inline bool isInImage() const { return _isInImage; }
+
+ /* modifiers */
+ /*! Sets the first ViewVertex of the ViewEdge. */
+ inline void setA(ViewVertex* iA) { __A = iA; }
+ /*! Sets the last ViewVertex of the ViewEdge. */
+ inline void setB(ViewVertex* iB) { __B = iB; }
+ /*! Sets the nature of the ViewEdge. */
+ inline void setNature(Nature::EdgeNature iNature) { _Nature = iNature; }
+ /*! Sets the first FEdge of the ViewEdge. */
+ inline void setFEdgeA(FEdge* iFEdge) { _FEdgeA = iFEdge; }
+ /*! Sets the last FEdge of the ViewEdge. */
+ inline void setFEdgeB(FEdge* iFEdge) { _FEdgeB = iFEdge; }
+ /*! Sets the ViewShape to which this ViewEdge belongs to.*/
+ inline void setShape(ViewShape *iVShape)
+ {
+ _Shape = iVShape;
+ }
+ /*! Sets the ViewEdge id. */
+ inline void setId(const Id& id) {_Id = id;}
+ /*! Sets Viewedge to this for all embedded fedges */
+ void UpdateFEdges();
+ /*! Sets the occluded ViewShape */
+ inline void setaShape(ViewShape * iShape) {_aShape = iShape;}
+ /*! Sets the quantitative invisibility value. */
+ inline void setQI(int qi) {_qi = qi;}
+ /*! Sets the time stamp value. */
+ inline void setChainingTimeStamp(unsigned ts) {_ChainingTimeStamp = ts;}
+ inline void AddOccluder(ViewShape *iShape) {_Occluders.push_back(iShape);}
+ inline void setSplittingId(Id * id) {_splittingId = id;}
+ inline void setIsInImage(bool iFlag) { _isInImage = iFlag; }
+
+ /* stroke interface definition */
+ inline bool intersect_2d_area(const Vec2r& iMin, const Vec2r& iMax) const
+ {
+ // parse edges to check if one of them is intersection the region:
+ FEdge * current = _FEdgeA;
+ do
+ {
+ if(GeomUtils::intersect2dSeg2dArea(iMin,iMax,
+ Vec2r(current->vertexA()->point2D()[0],current->vertexA()->point2D()[1]),
+ Vec2r(current->vertexB()->point2D()[0],current->vertexB()->point2D()[1])))
+
+ return true;
+ current = current->nextEdge();
+ }while((current != 0) && (current != _FEdgeA));
+
+ return false;
+ }
+ inline bool include_in_2d_area(const Vec2r& iMin, const Vec2r& iMax) const
+ {
+ // parse edges to check if all of them are intersection the region:
+ FEdge * current = _FEdgeA;
+
+ do
+ {
+ if(!GeomUtils::include2dSeg2dArea(iMin,iMax,
+ Vec2r(current->vertexA()->point2D()[0],current->vertexA()->point2D()[1]),
+ Vec2r(current->vertexB()->point2D()[0],current->vertexB()->point2D()[1])))
+ return false;
+ current = current->nextEdge();
+ }while((current != 0) && (current != _FEdgeA));
+
+ return true;
+ }
+
+ /* Information access interface */
+
+ //inline Nature::EdgeNature viewedge_nature() const {return getNature();}
+ //float viewedge_length() const ;
+ /*! Returns the 2D length of the Viewedge. */
+ real getLength2D() const;
+ //inline Material material() const {return _FEdgeA->vertexA()->shape()->material();}
+ inline int qi() const {return _qi;}
+ inline occluder_container::const_iterator occluders_begin() const {return _Occluders.begin();}
+ inline occluder_container::const_iterator occluders_end() const {return _Occluders.end();}
+ inline int occluders_size() const {return _Occluders.size();}
+ inline bool occluders_empty() const {return _Occluders.empty();}
+ inline const Polygon3r& occludee() const {return (_FEdgeA->aFace());}
+ inline const SShape * occluded_shape() const ;
+ inline const bool occludee_empty() const {if(_aShape == 0) return true; return false;}
+ //inline real z_discontinuity(int iCombination = 0) const ;
+ inline Id shape_id() const {return _FEdgeA->vertexA()->shape()->getId();}
+ inline const SShape * shape() const {return _FEdgeA->vertexA()->shape();}
+ inline float shape_importance() const {return _FEdgeA->shape_importance();}
+
+ /* iterators access */
+ // view edge iterator
+ edge_iterator ViewEdge_iterator();
+ const_edge_iterator ViewEdge_iterator() const;
+ // feature edge iterator
+ fedge_iterator fedge_iterator_begin();
+ const_fedge_iterator fedge_iterator_begin() const;
+ fedge_iterator fedge_iterator_last();
+ const_fedge_iterator fedge_iterator_last() const;
+ fedge_iterator fedge_iterator_end();
+ const_fedge_iterator fedge_iterator_end() const;
+ // embedding vertex iterator
+ const_vertex_iterator vertices_begin() const;
+ vertex_iterator vertices_begin();
+ const_vertex_iterator vertices_last() const;
+ vertex_iterator vertices_last();
+ const_vertex_iterator vertices_end() const;
+ vertex_iterator vertices_end();
+
+ // Iterator access (Interface1D)
+ /*! Returns an Interface0DIterator to iterate over
+ * the SVertex constituing the embedding of this ViewEdge.
+ * The returned Interface0DIterator points to the first
+ * SVertex of the ViewEdge.
+ */
+ virtual Interface0DIterator verticesBegin();
+ /*! Returns an Interface0DIterator to iterate over
+ * the SVertex constituing the embedding of this ViewEdge.
+ * The returned Interface0DIterator points after the last
+ * SVertex of the ViewEdge.
+ */
+ virtual Interface0DIterator verticesEnd();
+
+ /*! Returns an Interface0DIterator to iterate over
+ * the points of this ViewEdge at a given resolution.
+ * The returned Interface0DIterator points on the first
+ * Point of the ViewEdge.
+ * \param t
+ * the sampling value.
+ */
+ virtual Interface0DIterator pointsBegin(float t=0.f);
+ /*! Returns an Interface0DIterator to iterate over
+ * the points of this ViewEdge at a given resolution.
+ * The returned Interface0DIterator points after the last
+ * Point of the ViewEdge.
+ * \param t
+ * the sampling value.
+ */
+ virtual Interface0DIterator pointsEnd(float t=0.f);
+};
+
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewShape */
+ /* */
+ /* */
+ /**********************************/
+
+/*! Class gathering the elements of the ViewMap (ViewVertex, ViewEdge)
+ * that are issued from the same input shape.
+ */
+class LIB_VIEW_MAP_EXPORT ViewShape
+{
+private:
+ vector<ViewVertex*> _Vertices;
+ vector<ViewEdge*> _Edges;
+ SShape * _SShape;
+
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void* userdata;
+ /*! Default constructor.*/
+ inline ViewShape() { userdata = 0; _SShape = 0;}
+ /*! Builds a ViewShape from a SShape. */
+ inline ViewShape(SShape *iSShape) {userdata = 0; _SShape = iSShape;}//_SShape->setViewShape(this);}
+ /*! Copy constructor. */
+ inline ViewShape(ViewShape& iBrother)
+ {
+ userdata = 0;
+ vector<ViewVertex*>::iterator vv,vvend;
+ vector<ViewEdge*>::iterator ve, veend;
+
+ _SShape = iBrother._SShape;
+
+ vector<ViewVertex*>& vvertices = iBrother.vertices();
+ // duplicate vertices
+ for(vv=vvertices.begin(), vvend=vvertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ ViewVertex * newVertex = (*vv)->duplicate();
+ AddVertex(newVertex);
+ }
+
+ vector<ViewEdge*>& vvedges = iBrother.edges();
+ // duplicate edges
+ for(ve=vvedges.begin(), veend=vvedges.end();
+ ve!=veend;
+ ve++)
+ {
+ ViewEdge * newEdge = (*ve)->duplicate();
+ AddEdge(newEdge); // here the shape is set as the edge's shape
+ }
+
+ //-------------------------
+ // remap edges in vertices:
+ //-------------------------
+ for(vv=_Vertices.begin(), vvend=_Vertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ switch((*vv)->getNature())
+ {
+ case Nature::T_VERTEX:
+ {
+ TVertex *v = (TVertex*)(*vv);
+ ViewEdge *veFrontA = (ViewEdge*)(v)->frontEdgeA().first->userdata;
+ ViewEdge *veFrontB = (ViewEdge*)(v)->frontEdgeB().first->userdata;
+ ViewEdge *veBackA = (ViewEdge*)(v)->backEdgeA().first->userdata;
+ ViewEdge *veBackB = (ViewEdge*)(v)->backEdgeB().first->userdata;
+
+ v->setFrontEdgeA(veFrontA, v->frontEdgeA().second);
+ v->setFrontEdgeB(veFrontB, v->frontEdgeB().second);
+ v->setBackEdgeA(veBackA, v->backEdgeA().second);
+ v->setBackEdgeB(veBackB, v->backEdgeB().second);
+ }
+ break;
+ case Nature::NON_T_VERTEX:
+ {
+ NonTVertex * v = (NonTVertex*)(*vv);
+ vector<ViewVertex::directedViewEdge>& vedges = (v)->viewedges();
+ vector<ViewVertex::directedViewEdge> newEdges;
+ for(vector<ViewVertex::directedViewEdge>::iterator ve=vedges.begin(), veend=vedges.end();
+ ve!=veend;
+ ve++)
+ {
+ ViewEdge *current = (ViewEdge*)((ve)->first)->userdata;
+ newEdges.push_back(ViewVertex::directedViewEdge(current, ve->second));
+ }
+ (v)->setViewEdges(newEdges);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+ //-------------------------------------
+ // remap vertices in edges:
+ //-------------------------------------
+ for(ve=_Edges.begin(),veend=_Edges.end();
+ ve!=veend;
+ ve++)
+ {
+ (*ve)->setA((ViewVertex*)((*ve)->A()->userdata));
+ (*ve)->setB((ViewVertex*)((*ve)->B()->userdata));
+ //---------------------------------------
+ // Update all embedded FEdges
+ //---------------------------------------
+ (*ve)->UpdateFEdges();
+ }
+
+
+ // reset all brothers userdata to NULL:
+ //-------------------------------------
+ //---------
+ // vertices
+ //---------
+ for(vv=vvertices.begin(),vvend=vvertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ (*vv)->userdata = NULL;
+ }
+
+ //------
+ // edges
+ //------
+ for(ve=vvedges.begin(),veend=vvedges.end();
+ ve!=veend;
+ ve++)
+ {
+ (*ve)->userdata = NULL;
+ }
+ }
+
+ /*! Cloning method. */
+ virtual ViewShape * duplicate()
+ {
+ ViewShape *clone = new ViewShape(*this);
+ return clone;
+ }
+
+ /*! Destructor. */
+ virtual ~ViewShape();
+
+ /* splits a view edge into several view edges.
+ * fe
+ * The FEdge that gets splitted
+ * iViewVertices
+ * The view vertices corresponding to the different intersections for the edge fe.
+ * This list need to be sorted such as the first view vertex is the
+ * farther away from fe->vertexA.
+ * ioNewEdges
+ * The feature edges that are newly created (the initial edges are not
+ * included) are added to this list.
+ * ioNewViewEdges
+ * The view edges that are newly created (the initial edges are not
+ * included) are added to this list.
+ */
+ inline void SplitEdge(FEdge *fe,
+ const vector<TVertex*>& iViewVertices,
+ vector<FEdge*>& ioNewEdges,
+ vector<ViewEdge*>& ioNewViewEdges);
+ /* accessors */
+ /*! Returns the SShape on top of which this ViewShape is built. */
+ inline SShape * sshape() {return _SShape;}
+ /*! Returns the SShape on top of which this ViewShape is built. */
+ inline const SShape * sshape() const {return _SShape;}
+ /*! Returns the list of ViewVertex contained in this ViewShape. */
+ inline vector<ViewVertex*>& vertices() {return _Vertices;}
+ /*! Returns the list of ViewEdge contained in this ViewShape. */
+ inline vector<ViewEdge*>& edges() {return _Edges;}
+ /*! Returns the ViewShape id. */
+ inline Id getId() const {return _SShape->getId();}
+ /*! Returns the ViewShape id. */
+ inline const string& getName() const {return _SShape->getName();}
+
+ /* modifiers */
+ /*! Sets the SShape on top of which the ViewShape is built. */
+ inline void setSShape(SShape* iSShape) {_SShape = iSShape;}
+ /*! Sets the list of ViewVertex contained in this ViewShape. */
+ inline void setVertices(const vector<ViewVertex*>& iVertices) {_Vertices = iVertices;}
+ /*! Sets the list of ViewEdge contained in this ViewShape. */
+ inline void setEdges(const vector<ViewEdge*>& iEdges) {_Edges = iEdges;}
+ /*! Adds a ViewVertex to the list. */
+ inline void AddVertex(ViewVertex *iVertex)
+ {
+ _Vertices.push_back(iVertex);
+ //_SShape->AddNewVertex(iVertex->svertex());
+ }
+ /*! Adds a ViewEdge to the list */
+ inline void AddEdge(ViewEdge *iEdge)
+ {
+ _Edges.push_back(iEdge);
+ iEdge->setShape(this);
+ //_SShape->AddNewEdge(iEdge->fedge());
+ }
+
+ /* removes the view edge iViewEdge in the
+ * View Shape and the associated FEdge chain entry
+ * in the underlying SShape
+ */
+ void RemoveEdge(ViewEdge * iViewEdge);
+
+ /* removes the view vertex iViewVertex in the
+ * View Shape.
+ */
+ void RemoveVertex(ViewVertex * iViewVertex);
+};
+
+
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+/* for inline functions */
+
+void ViewShape::SplitEdge(FEdge *fe,
+ const vector<TVertex*>& iViewVertices,
+ vector<FEdge*>& ioNewEdges,
+ vector<ViewEdge*>& ioNewViewEdges)
+{
+ ViewEdge *vEdge = fe->viewedge();
+
+
+ // We first need to sort the view vertices from farther to closer to fe->vertexA
+
+ SVertex *sv, *sv2;
+ ViewVertex *vva, *vvb;
+ vector<TVertex*>::const_iterator vv, vvend;
+ for(vv=iViewVertices.begin(), vvend = iViewVertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ // Add the viewvertices to the ViewShape
+ AddVertex((*vv));
+
+ // retrieve the correct SVertex from the view vertex
+ //--------------------------------------------------
+ sv = (*vv)->frontSVertex();
+ sv2 = (*vv)->backSVertex();
+
+ if(sv->shape() != sv2->shape())
+ {
+ if(sv->shape() != _SShape)
+ sv = sv2;
+ }
+ else
+ {
+ // if the shape is the same we can safely differ
+ // the two vertices using their ids:
+ if(sv->getId() != fe->vertexA()->getId())
+ sv = sv2;
+ }
+
+ vva = vEdge->A();
+ vvb = vEdge->B();
+
+ // We split Fedge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+ SShape * shape = fe->shape();
+
+ // a new edge, A'B is created.
+ FEdge *newEdge = shape->SplitEdgeIn2(fe, sv);
+ /*
+ * One of the two FEdges (fe and newEdge) may have a 2D length less than M_EPSILON.
+ * (22 Feb 2011, T.K.)
+ */
+
+ ioNewEdges.push_back(newEdge);
+ ViewEdge *newVEdge;
+
+ if((vva == 0) || (vvb == 0)) // that means we're dealing with a closed viewedge (loop)
+ {
+ // remove the chain that was starting by the fedge A of vEdge (which is different from fe !!!!)
+ shape->RemoveEdgeFromChain(vEdge->fedgeA());
+ // we set
+ vEdge->setA(*vv);
+ vEdge->setB(*vv);
+ vEdge->setFEdgeA(newEdge);
+ //FEdge *previousEdge = newEdge->previousEdge();
+ vEdge->setFEdgeB(fe);
+ newVEdge = vEdge;
+ vEdge->fedgeA()->setViewEdge(newVEdge);
+ }
+ else
+ {
+
+ // while we create the view edge, it updates the "ViewEdge" pointer
+ // of every underlying FEdges to this.
+ newVEdge = new ViewEdge((*vv),vvb);//, newEdge, vEdge->fedgeB());
+ newVEdge->setNature((fe)->getNature());
+ newVEdge->setFEdgeA(newEdge);
+ //newVEdge->setFEdgeB(fe);
+ // If our original viewedge is made of one FEdge,
+ // then
+ if((vEdge->fedgeA() == vEdge->fedgeB()) || (fe == vEdge->fedgeB()))
+ newVEdge->setFEdgeB(newEdge);
+ else
+ newVEdge->setFEdgeB(vEdge->fedgeB()); //MODIF
+
+ Id * newId = vEdge->splittingId();
+ if(newId == 0){
+ newId = new Id(vEdge->getId());
+ vEdge->setSplittingId(newId);
+ }
+ newId->setSecond(newId->getSecond()+1);
+ newVEdge->setId(*newId);
+ newVEdge->setSplittingId(newId);
+ // Id id(vEdge->getId().getFirst(), vEdge->getId().getSecond()+1);
+ // newVEdge->setId(vEdge->getId());
+ // vEdge->setId(id);
+
+ AddEdge(newVEdge); // here this shape is set as the edge's shape
+
+ // add new edge to the list of new edges passed as argument:
+ ioNewViewEdges.push_back(newVEdge);
+
+
+
+ if(0 != vvb)
+ vvb->Replace((vEdge), newVEdge);
+
+ // we split the view edge:
+ vEdge->setB((*vv));
+ vEdge->setFEdgeB(fe); //MODIF
+
+ // Update fedges so that they point to the new viewedge:
+ newVEdge->UpdateFEdges();
+
+ }
+ // check whether this vertex is a front vertex or a back
+ // one
+
+ if(sv == (*vv)->frontSVertex())
+ {
+ // -- View Vertex A' --
+ (*vv)->setFrontEdgeA(vEdge, true);
+ (*vv)->setFrontEdgeB(newVEdge, false);
+ }
+ else
+ {
+ // -- View Vertex A' --
+ (*vv)->setBackEdgeA(vEdge, true);
+ (*vv)->setBackEdgeB(newVEdge, false);
+ }
+ }
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+
+// inline Vec3r ViewEdge::orientation2d(int iCombination) const
+// {
+// return edge_orientation2d_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline Vec3r ViewEdge::orientation3d(int iCombination) const
+// {
+// return edge_orientation3d_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline real ViewEdge::z_discontinuity(int iCombination) const
+// {
+// return z_discontinuity_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline float ViewEdge::local_average_depth(int iCombination ) const
+// {
+// return local_average_depth_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline float ViewEdge::local_depth_variance(int iCombination) const
+// {
+// return local_depth_variance_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline real ViewEdge::local_average_density(float sigma, int iCombination) const
+// {
+// return density_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+inline const SShape * ViewEdge::occluded_shape() const
+{
+ if(0 == _aShape)
+ return 0;
+ return _aShape->sshape();
+}
+
+// inline Vec3r ViewEdge::curvature2d_as_vector(int iCombination) const
+// {
+// return curvature2d_as_vector_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline real ViewEdge::curvature2d_as_angle(int iCombination) const
+// {
+// return curvature2d_as_angle_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+
+#endif // VIEWMAP_H
diff --git a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
new file mode 100755
index 00000000000..31abefbfb97
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
@@ -0,0 +1,691 @@
+//
+// Filename : ViewMapAdvancedIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the various elements of the ViewMap
+// These iterators can't be exported to python.
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPADVANCEDITERATORS_H
+# define VIEWMAPADVANCEDITERATORS_H
+
+#include "ViewMap.h"
+#include "../system/Iterator.h" //soc
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewMap */
+ /* */
+ /* */
+ /**********************************/
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewVertex */
+ /* */
+ /* */
+ /**********************************/
+
+namespace ViewVertexInternal{
+
+ class edge_const_traits : public Const_traits< ::ViewVertex::directedViewEdge> {
+ public:
+ typedef vector< ::ViewVertex::directedViewEdge> edges_container;
+ typedef edges_container::const_iterator edges_container_iterator ;
+ typedef vector< ::ViewVertex::directedViewEdge*> edge_pointers_container;
+ typedef edge_pointers_container::const_iterator edge_pointers_container_iterator ;
+ };
+ class edge_nonconst_traits : public Nonconst_traits< ::ViewVertex::directedViewEdge> {
+ public:
+ typedef vector< ::ViewVertex::directedViewEdge> edges_container;
+ typedef edges_container::iterator edges_container_iterator ;
+ typedef vector< ::ViewVertex::directedViewEdge*> edge_pointers_container;
+ typedef edge_pointers_container::iterator edge_pointers_container_iterator ;
+ };
+
+template<class Traits>
+ class edge_iterator_base : public IteratorBase<Traits,InputIteratorTag_Traits>
+ {
+ public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef edge_iterator_base<Traits> Self;
+ typedef typename Traits::edges_container_iterator edges_container_iterator;
+ typedef typename Traits::edge_pointers_container_iterator edge_pointers_container_iterator;
+ typedef edge_iterator_base<edge_nonconst_traits> iterator;
+ typedef edge_iterator_base<edge_const_traits> const_iterator;
+ public:
+ friend class ViewVertex;
+ friend class TVertex;
+ friend class NonTVertex;
+ friend class ViewEdge;
+ friend class edge_iterator;
+ protected:
+ Nature::VertexNature _Nature; // the nature of the underlying vertex
+ // T vertex attributes
+ edge_pointers_container_iterator _tbegin;
+ edge_pointers_container_iterator _tend;
+ edge_pointers_container_iterator _tvertex_iter;
+
+ // mutable value_type _tvertex_iter;
+ // value_type _feA;
+ // value_type _feB;
+ // value_type _beA;
+ // value_type _beB;
+
+ // Non TVertex attributes
+ edges_container_iterator _begin;
+ edges_container_iterator _end;
+ edges_container_iterator _nontvertex_iter;
+
+ typedef IteratorBase<Traits,InputIteratorTag_Traits> parent_class;
+
+ public:
+ inline edge_iterator_base() : parent_class() {}
+ inline edge_iterator_base(Nature::VertexNature iNature)
+ : parent_class()
+ {_Nature = iNature;}
+ edge_iterator_base(const edge_iterator_base<edge_nonconst_traits>& iBrother)
+ : parent_class(iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if(_Nature & Nature::T_VERTEX)
+ {
+ // _feA = iBrother._feA;
+ // _feB = iBrother._feB;
+ // _beA = iBrother._beA;
+ // _beB = iBrother._beB;
+ // _tvertex_iter = iBrother._tvertex_iter;
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else
+ {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+ edge_iterator_base(const edge_iterator_base<edge_const_traits>& iBrother)
+ : parent_class(iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if(_Nature & Nature::T_VERTEX)
+ {
+ // _feA = iBrother._feA;
+ // _feB = iBrother._feB;
+ // _beA = iBrother._beA;
+ // _beB = iBrother._beB;
+ // _tvertex_iter = iBrother._tvertex_iter;
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else
+ {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+ virtual ~edge_iterator_base() {}
+ //protected://FIXME
+ public:
+ // inline edge_iterator_base(value_type ifeA,
+ // value_type ifeB,
+ // value_type ibeA,
+ // value_type ibeB,
+ // value_type iter)
+ // : parent_class()
+ // {
+ // _Nature = Nature::T_VERTEX;
+ // _feA = ifeA;
+ // _feB = ifeB;
+ // _beA = ibeA;
+ // _beB = ibeB;
+ // _tvertex_iter = iter;
+ // }
+ inline edge_iterator_base(edge_pointers_container_iterator begin,
+ edge_pointers_container_iterator end,
+ edge_pointers_container_iterator iter)
+ : parent_class()
+ {
+ _Nature = Nature::T_VERTEX;
+ _tbegin = begin;
+ _tend = end;
+ _tvertex_iter = iter;
+ }
+ inline edge_iterator_base(edges_container_iterator begin,
+ edges_container_iterator end,
+ edges_container_iterator iter)
+ : parent_class()
+ {
+ _Nature = Nature::NON_T_VERTEX;
+ _begin = begin;
+ _end = end;
+ _nontvertex_iter = iter;
+ }
+
+ public:
+
+
+ virtual bool begin() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tbegin);
+ //return (_tvertex_iter == _feA);
+ else
+ return (_nontvertex_iter == _begin);
+ }
+ virtual bool end() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ //return (_tvertex_iter.first == 0);
+ return (_tvertex_iter == _tend);
+ else
+ return (_nontvertex_iter == _end);
+ }
+
+ // operators
+ virtual Self& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ virtual Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter != b._tvertex_iter);
+ else
+ return (_nontvertex_iter != b._nontvertex_iter);
+ }
+
+ virtual bool operator==(const Self& b) const
+ {return !(*this != b);}
+
+ // dereferencing
+ virtual reference operator*() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ //return _tvertex_iter;
+ return **_tvertex_iter;
+ else
+ return (*_nontvertex_iter);
+ }
+ virtual pointer operator->() const { return &(operator*());}
+
+ protected:
+ inline void increment()
+ {
+ if(_Nature & Nature::T_VERTEX)
+ {
+ value_type tmp = (**_tvertex_iter);
+ ++_tvertex_iter;
+ value_type tmp2 = (**_tvertex_iter);
+ if(tmp2.first == tmp.first)
+ ++_tvertex_iter;
+ // // Hack to deal with cusp. the result of a cusp
+ // // is a TVertex having two identical viewedges.
+ // // In order to iterate properly, we chose to
+ // // to skip these last ones.
+ // if(_feB.first == _beA.first)
+ // {
+ // if(_feA.first == _beB.first)
+ // {
+ // _tvertex_iter.first = 0;
+ // return;
+ // }
+ //
+ // if(_tvertex_iter.first == _feA.first)
+ // _tvertex_iter.first = _beB.first;
+ // else if(_tvertex_iter.first == _beB.first)
+ // _tvertex_iter.first = 0;
+ // else
+ // _tvertex_iter.first = _feA.first;
+ // return;
+ // }
+ // if(_feA.first == _beB.first)
+ // {
+ // if(_feB.first == _beA.first)
+ // {
+ // _tvertex_iter.first = 0;
+ // return;
+ // }
+ //
+ // if(_tvertex_iter.first == _feB.first)
+ // _tvertex_iter.first = _beA.first;
+ // else if(_tvertex_iter.first == _beA.first)
+ // _tvertex_iter.first = 0;
+ // else
+ // _tvertex_iter.first = _feB.first;
+ // return;
+ // }
+ // // End of hack
+ //
+ // if(_tvertex_iter.first == _feA.first){
+ // // we return bea or beb
+ //
+ //
+ // // choose one of them
+ //
+ // _tvertex_iter.first = _feB.first;
+ // return;
+ // }
+ // if(_tvertex_iter.first == _feB.first)
+ // {
+ // _tvertex_iter.first = _beA.first;
+ // return;
+ // }
+ // if(_tvertex_iter.first == _beA.first)
+ // {
+ // _tvertex_iter.first = _beB.first;
+ // return;
+ // }
+ // if(_tvertex_iter.first == _beB.first)
+ // {
+ // _tvertex_iter.first = 0;
+ // return;
+ // }
+ }
+ else
+ ++_nontvertex_iter;
+ }
+ };
+
+ }
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+namespace ViewEdgeInternal {
+
+ /*!----------------------*/
+ /*! Iterators definition */
+ /*!----------------------*/
+ template<class Traits>
+ class edge_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef edge_iterator_base<Traits> Self;
+ public:
+ mutable value_type _ViewEdge;
+ //friend class edge_iterator_base<Nonconst_traits<ViewEdge*> >;
+ //friend class edge_iterator_base<Const_traits<ViewEdge*> >;
+ value_type _first;
+ bool _orientation;
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+
+ public:
+ friend class ViewEdge;
+ inline edge_iterator_base()
+ : parent_class()
+ {_orientation=true;_first=0;}
+
+ inline edge_iterator_base(const edge_iterator_base<Nonconst_traits< ::ViewEdge*> >& iBrother)
+ : parent_class()
+ {
+ _ViewEdge = iBrother._ViewEdge;
+ _first = iBrother._first;
+ _orientation = iBrother._orientation;
+ }
+
+ inline edge_iterator_base(const edge_iterator_base<Const_traits< ::ViewEdge*> >& iBrother)
+ : parent_class()
+ {
+ _ViewEdge = iBrother._ViewEdge;
+ _first = iBrother._first;
+ _orientation = iBrother._orientation;
+ }
+
+ //protected://FIXME
+ public:
+ inline edge_iterator_base(value_type iEdge, bool orientation = true)
+ : parent_class()
+ {
+ _ViewEdge = iEdge;
+ _first = iEdge;
+ _orientation = orientation;
+ }
+
+
+ public:
+ virtual Self* clone() const
+ {
+ return new edge_iterator_base(*this);
+ }
+ virtual ~edge_iterator_base() {}
+
+ public:
+
+ virtual bool orientation() {return _orientation;}
+ virtual void set_edge(value_type iVE) {_ViewEdge=iVE;}
+ virtual void set_orientation(bool iOrientation) {_orientation = iOrientation;}
+ virtual void change_orientation() {_orientation = !_orientation;}
+
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ //++_ViewEdge->getTimeStamp();
+ increment();
+ return *this;
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ //++_ViewEdge->getTimeStamp();
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ //++_ViewEdge->getTimeStamp();
+ decrement();
+ return *this;
+ }
+ inline Self operator--(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ //++_ViewEdge->getTimeStamp();
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ decrement(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_ViewEdge != b._ViewEdge);
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const {return (_ViewEdge);}
+ virtual pointer operator->() const { return &(operator*());}
+
+ public:
+ virtual bool begin() const {return _ViewEdge==_first ? true : false;}
+ virtual bool end() const {return _ViewEdge==0 ? true : false;}
+
+ protected:
+ virtual void increment() {}
+ virtual void decrement() {}
+ };
+
+ template<class Traits>
+ class fedge_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef fedge_iterator_base<Traits> Self;
+ public:
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+ mutable value_type _FEdge;
+ value_type _first;
+ value_type _FEdgeB; // last fedge of the view edge
+
+ public:
+ friend class ::ViewEdge;
+ friend class fedge_iterator;
+ inline fedge_iterator_base()
+ : parent_class()
+ {}
+ inline fedge_iterator_base(const fedge_iterator_base<Nonconst_traits<FEdge*> >& iBrother)
+ : parent_class()
+ {
+ _FEdge = iBrother._FEdge;
+ _first = iBrother._first;
+ _FEdgeB = iBrother._FEdgeB;
+ }
+ inline fedge_iterator_base(const fedge_iterator_base<Const_traits<FEdge*> >& iBrother)
+ : parent_class()
+ {
+ _FEdge = iBrother._FEdge;
+ _first = iBrother._first;
+ _FEdgeB = iBrother._FEdgeB;
+ }
+ //protected://FIXME
+ public:
+ inline fedge_iterator_base(value_type iEdge, value_type iFEdgeB)
+ : parent_class()
+ {
+ _FEdge = iEdge;
+ _first = iEdge;
+ _FEdgeB = iFEdgeB;
+ }
+
+ public:
+ virtual ~fedge_iterator_base() {}
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ decrement();
+ return *this;
+ }
+ inline Self operator--(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ decrement(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_FEdge != b._FEdge);
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const {return (_FEdge);}
+ virtual pointer operator->() const { return &(operator*());}
+
+
+ public:
+ virtual bool begin() const {return _FEdge==_first ? true : false;}
+ virtual bool end() const {return _FEdge==0 ? true : false;}
+ protected:
+ virtual void increment()
+ {
+ _FEdge = _FEdge->nextEdge(); // we don't change or
+ }
+
+ virtual void decrement()
+ {
+ if(0 == _FEdge)
+ {
+ _FEdge = _FEdgeB;
+ return;
+ }
+ _FEdge = _FEdge->previousEdge(); // we don't change or
+ }
+ };
+
+ template<class Traits>
+ class vertex_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef vertex_iterator_base<Traits> Self;
+ protected:
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+ public:
+ mutable value_type _SVertex;
+ FEdge *_NextFEdge;
+ FEdge *_PreviousFEdge;
+ public:
+ friend class ViewEdge;
+ friend class vertex_iterator;
+ inline vertex_iterator_base()
+ : parent_class()
+ {}
+ inline vertex_iterator_base(const vertex_iterator_base<Const_traits<SVertex*> >& iBrother)
+ : parent_class()
+ {
+ _SVertex = iBrother._SVertex;
+ _NextFEdge = iBrother._NextFEdge;
+ _PreviousFEdge = iBrother._PreviousFEdge;
+ }
+ inline vertex_iterator_base(const vertex_iterator_base<Nonconst_traits<SVertex*> >& iBrother)
+ : parent_class()
+ {
+ _SVertex = iBrother._SVertex;
+ _NextFEdge = iBrother._NextFEdge;
+ _PreviousFEdge = iBrother._PreviousFEdge;
+ }
+
+ //protected://FIXME
+ public:
+
+ inline vertex_iterator_base(value_type iVertex, FEdge *iPreviousFEdge, FEdge *iNextFEdge)
+ : parent_class()
+ {
+ _SVertex = iVertex;
+ _NextFEdge = iNextFEdge;
+ _PreviousFEdge = iPreviousFEdge;
+ }
+
+ public:
+ virtual ~vertex_iterator_base() {}
+
+ virtual bool begin() const {return _PreviousFEdge==0? true : false;}
+ virtual bool end() const {return _SVertex==0 ? true : false;}
+
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ decrement();
+ return *this;
+ }
+ inline Self operator--(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ decrement(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_SVertex != b._SVertex);
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const {return (_SVertex);}
+ virtual pointer operator->() const { return &(operator*());}
+
+ protected:
+ virtual void increment()
+ {
+ if(0 == _NextFEdge)
+ {
+ _SVertex = 0;
+ return;
+ }
+
+ _SVertex = _NextFEdge->vertexB();
+ _PreviousFEdge = _NextFEdge;
+ _NextFEdge = _NextFEdge->nextEdge();
+
+ }
+ virtual void decrement()
+ {
+ // if(0 == _SVertex)
+ // {
+ // _SVertex = _PreviousFEdge->vertexB();
+ // return;
+ // }
+ if(0 == _PreviousFEdge)
+ {
+ _SVertex = 0;
+ return;
+ }
+ _SVertex = _PreviousFEdge->vertexA();
+ _NextFEdge = _PreviousFEdge;
+ _PreviousFEdge = _PreviousFEdge->previousEdge();
+ }
+ };
+
+
+} // end of namespace ViewEdgeInternal
+
+#endif // VIEWMAPADVANCEDITERATORS_H
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
new file mode 100755
index 00000000000..d503daa3696
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
@@ -0,0 +1,2333 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewMapBuilder.h"
+#include <algorithm>
+#include <stdexcept>
+#include <memory>
+#include "../winged_edge/WFillGrid.h"
+#include "../../FRS_freestyle.h"
+#include "../geometry/GeomUtils.h"
+#include "../geometry/GridHelpers.h"
+#include "BoxGrid.h"
+#include "SphericalGrid.h"
+#include "OccluderSource.h"
+#include "CulledOccluderSource.h"
+#include "HeuristicGridDensityProviderFactory.h"
+
+#define logging 0
+
+using namespace std;
+
+template <typename G, typename I>
+static void findOccludee(FEdge *fe, G& grid, I& occluders, real epsilon, WFace** oaWFace,
+ Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices)
+{
+ WFace *face = 0;
+ if(fe->isSmooth()){
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+ WFace * oface;
+ bool skipFace;
+
+ WVertex::incoming_edge_iterator ie;
+
+ *oaWFace = 0;
+ if(((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER))
+ {
+ // we cast a ray from A in the same direction but looking behind
+ Vec3r v(-u[0],-u[1],-u[2]);
+ bool noIntersection = true;
+ real mint=FLT_MAX;
+
+ for( occluders.initAfterTarget(); occluders.validAfterTarget(); occluders.nextOccludee() )
+ {
+#if logging > 0
+ cout << "\t\tEvaluating intersection for occludee " << occluders.getWFace() << " and ray " << A << " * " << u << endl;
+#endif
+ oface = occluders.getWFace();
+ Polygon3r* p = occluders.getCameraSpacePolygon();
+ real d = -((p->getVertices())[0] * p->getNormal());
+ real t,t_u,t_v;
+
+ if(0 != face)
+ {
+ skipFace = false;
+
+ if(face == oface)
+ continue;
+
+ if(faceVertices.empty())
+ continue;
+
+ for(vector<WVertex*>::iterator fv=faceVertices.begin(), fvend=faceVertices.end();
+ fv!=fvend;
+ ++fv)
+ {
+ if((*fv)->isBoundary())
+ continue;
+ WVertex::incoming_edge_iterator iebegin=(*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend=(*fv)->incoming_edges_end();
+ for(ie=iebegin;ie!=ieend; ++ie)
+ {
+ if((*ie) == 0)
+ continue;
+
+ WFace * sface = (*ie)->GetbFace();
+ if(sface == oface)
+ {
+ skipFace = true;
+ break;
+ }
+ }
+ if(skipFace)
+ break;
+ }
+ if(skipFace)
+ continue;
+ }
+ else
+ {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, p->getNormal(), d, t, epsilon)) {
+#if logging > 0
+cout << "\t\tRejecting occluder for target coincidence." << endl;
+#endif
+ continue;
+ }
+ }
+
+ if(p->rayIntersect(A, v, t, t_u, t_v))
+ {
+#if logging > 0
+cout << "\t\tRay " << A << " * " << v << " intersects at time " << t << endl;
+#endif
+#if logging > 0
+cout << "\t\t(v * normal) == " << (v * p->getNormal()) << " for normal " << p->getNormal() << endl;
+#endif
+ if (fabs(v * p->getNormal()) > 0.0001)
+ if ((t>0.0)) // && (t<1.0))
+ {
+ if (t<mint)
+ {
+ *oaWFace = oface;
+ mint = t;
+ noIntersection = false;
+ fe->setOccludeeIntersection(Vec3r(A+t*v));
+#if logging > 0
+cout << "\t\tIs occludee" << endl;
+#endif
+ }
+ }
+
+ occluders.reportDepth(A, v, t);
+ }
+
+ }
+
+ if(noIntersection)
+ *oaWFace = 0;
+ }
+}
+
+template <typename G, typename I>
+static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge* ve, WFace** oaFace)
+{
+ Vec3r A;
+ Vec3r edge;
+ Vec3r origin;
+ A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0);
+ edge = Vec3r((fe)->vertexB()->point3D()-(fe)->vertexA()->point3D());
+ origin = Vec3r((fe)->vertexA()->point3D());
+ Vec3r u;
+ if (grid.orthographicProjection()) {
+ u = Vec3r(0.0, 0.0, grid.viewpoint().z()-A.z());
+ } else {
+ u = Vec3r(grid.viewpoint()-A);
+ }
+ u.normalize();
+
+ vector<WVertex*> faceVertices;
+
+ WFace *face = 0;
+ if(fe->isSmooth()) {
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+
+ if(0 != face) {
+ face->RetrieveVertexList(faceVertices);
+ }
+
+ I occluders(grid, A, epsilon);
+ findOccludee<G, I>(fe, grid, occluders, epsilon, oaFace, u, A, origin, edge, faceVertices);
+}
+
+// computeVisibility takes a pointer to foundOccluders, instead of using a reference,
+// so that computeVeryFastVisibility can skip the AddOccluders step with minimal overhead.
+template <typename G, typename I>
+static int computeVisibility(ViewMap* viewMap, FEdge *fe, G& grid, real epsilon, ViewEdge* ve, WFace** oaWFace, set<ViewShape*>* foundOccluders)
+{
+ int qi = 0;
+
+ Vec3r center;
+ Vec3r edge;
+ Vec3r origin;
+
+ center = fe->center3d();
+ edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
+ origin = Vec3r(fe->vertexA()->point3D());
+
+ Vec3r vp;
+ if (grid.orthographicProjection()) {
+ vp = Vec3r(center.x(), center.y(), grid.viewpoint().z());
+ } else {
+ vp = Vec3r(grid.viewpoint());
+ }
+ Vec3r u(vp - center);
+ real raylength = u.norm();
+ u.normalize();
+
+ WFace *face = 0;
+ if(fe->isSmooth()){
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+ vector<WVertex*> faceVertices;
+ WVertex::incoming_edge_iterator ie;
+
+ WFace * oface;
+ bool skipFace;
+
+ if(face)
+ face->RetrieveVertexList(faceVertices);
+
+ I occluders(grid, center, epsilon);
+
+ for(occluders.initBeforeTarget(); occluders.validBeforeTarget(); occluders.nextOccluder())
+ {
+ // If we're dealing with an exact silhouette, check whether
+ // we must take care of this occluder of not.
+ // (Indeed, we don't consider the occluders that
+ // share at least one vertex with the face containing
+ // this edge).
+ //-----------
+ oface = occluders.getWFace();
+ Polygon3r* p = occluders.getCameraSpacePolygon();
+ real t, t_u, t_v;
+#if logging > 0
+ cout << "\t\tEvaluating intersection for occluder " << (p->getVertices())[0] << (p->getVertices())[1] << (p->getVertices())[2] << endl << "\t\t\tand ray " << vp << " * " << u << " (center " << center << ")" << endl;
+#endif
+
+#if logging > 0
+ Vec3r v(vp - center);
+ real rl = v.norm();
+ v.normalize();
+ vector<Vec3r> points;
+ // Iterate over vertices, storing projections in points
+ for(vector<WOEdge*>::const_iterator woe=oface->getEdgeList().begin(), woend=oface->getEdgeList().end(); woe!=woend; woe++) {
+ points.push_back(Vec3r((*woe)->GetaVertex()->GetVertex()));
+ }
+ Polygon3r p1(points, oface->GetNormal());
+ Vec3r v1((p1.getVertices())[0]);
+ real d = -(v1 * p->getNormal());
+ cout << "\t\tp: " << (p->getVertices())[0] << (p->getVertices())[1] << (p->getVertices())[2] << ", norm: " << p->getNormal() << endl;
+ cout << "\t\tp1: " << (p1.getVertices())[0] << (p1.getVertices())[1] << (p1.getVertices())[2] << ", norm: " << p1.getNormal() << endl;
+#else
+ real d = -((p->getVertices())[0] * p->getNormal());
+#endif
+
+ if(0 != face)
+ {
+#if logging > 0
+cout << "\t\tDetermining face adjacency...";
+#endif
+ skipFace = false;
+
+ if(face == oface) {
+#if logging > 0
+cout << " Rejecting occluder for face concurrency." << endl;
+#endif
+ continue;
+ }
+
+
+ for(vector<WVertex*>::iterator fv=faceVertices.begin(), fvend=faceVertices.end();
+ fv!=fvend;
+ ++fv)
+ {
+ if((*fv)->isBoundary())
+ continue;
+
+ WVertex::incoming_edge_iterator iebegin=(*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend=(*fv)->incoming_edges_end();
+ for(ie=iebegin;ie!=ieend; ++ie)
+ {
+ if((*ie) == 0)
+ continue;
+
+ WFace * sface = (*ie)->GetbFace();
+ //WFace * sfacea = (*ie)->GetaFace();
+ //if((sface == oface) || (sfacea == oface))
+ if(sface == oface)
+ {
+ skipFace = true;
+ break;
+ }
+ }
+ if(skipFace)
+ break;
+ }
+ if(skipFace) {
+#if logging > 0
+cout << " Rejecting occluder for face adjacency." << endl;
+#endif
+ continue;
+ }
+ }
+ else
+ {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+
+ if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, p->getNormal(), d, t, epsilon)) {
+#if logging > 0
+cout << "\t\tRejecting occluder for target coincidence." << endl;
+#endif
+ continue;
+ }
+ }
+
+#if logging > 0
+
+ real x;
+ if ( p1.rayIntersect(center, v, x, t_u, t_v) ) {
+ cout << "\t\tRay should intersect at time " << (rl - x) << ". Center: " << center << ", V: " << v << ", RL: " << rl << ", T:" << x << endl;
+ } else {
+ cout << "\t\tRay should not intersect. Center: " << center << ", V: " << v << ", RL: " << rl << endl;
+ }
+
+#endif
+
+ if(p->rayIntersect(center, u, t, t_u, t_v))
+ {
+#if logging > 0
+cout << "\t\tRay " << center << " * " << u << " intersects at time " << t << " (raylength is " << raylength << ")" << endl;
+#endif
+#if logging > 0
+cout << "\t\t(u * normal) == " << (u * p->getNormal()) << " for normal " << p->getNormal() << endl;
+#endif
+ if (fabs(u * p->getNormal()) > 0.0001)
+ if ((t>0.0) && (t<raylength))
+ {
+#if logging > 0
+cout << "\t\tIs occluder" << endl;
+#endif
+ if ( foundOccluders != NULL ) {
+ ViewShape *vshape = viewMap->viewShape(oface->GetVertex(0)->shape()->GetId());
+ foundOccluders->insert(vshape);
+ }
+
+ ++qi;
+
+ if(! grid.enableQI())
+ break;
+ }
+
+ occluders.reportDepth(center, u, t);
+ }
+ }
+
+ // Find occludee
+ findOccludee<G, I>(fe, grid, occluders, epsilon, oaWFace, u, center, origin, edge, faceVertices);
+
+ return qi;
+}
+
+// computeCumulativeVisibility returns the lowest x such that the majority
+// of FEdges have QI <= x
+//
+// This was probably the original intention of the "normal" algorithm
+// on which computeDetailedVisibility is based. But because the "normal"
+// algorithm chooses the most popular QI, without considering any other
+// values, a ViewEdge with FEdges having QIs of 0, 21, 22, 23, 24 and 25
+// will end up having a total QI of 0, even though most of the FEdges are
+// heavily occluded. computeCumulativeVisibility will treat this case as
+// a QI of 22 because 3 out of 6 occluders have QI <= 22.
+
+template <typename G, typename I>
+static void computeCumulativeVisibility(ViewMap *ioViewMap, G& grid, real epsilon, RenderMonitor *iRenderMonitor)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+
+ FEdge * fe, *festart;
+ int nSamples = 0;
+ vector<WFace*> wFaces;
+ WFace *wFace = 0;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end(); ve!=veend; ve++) {
+ if (iRenderMonitor && iRenderMonitor->testBreak())
+ break;
+#if logging > 0
+cout << "Processing ViewEdge " << (*ve)->getId() << endl;
+#endif
+ // Find an edge to test
+ if ( ! (*ve)->isInImage() ) {
+ // This view edge has been proscenium culled
+ (*ve)->setQI(255);
+ (*ve)->setaShape(0);
+#if logging > 0
+cout << "\tCulled." << endl;
+#endif
+ continue;
+ }
+
+ // Test edge
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 0;
+ do {
+ if ( fe != NULL && fe->isInImage() ) {
+ qiMajority++;
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+
+ if ( qiMajority == 0 ) {
+ // There are no occludable FEdges on this ViewEdge
+ // This should be impossible.
+ cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl;
+ // We can recover from this error:
+ // Treat this edge as fully visible with no occludee
+ (*ve)->setQI(0);
+ (*ve)->setaShape(0);
+ continue;
+ } else {
+ ++qiMajority;
+ qiMajority >>= 1;
+ }
+#if logging > 0
+cout << "\tqiMajority: " << qiMajority << endl;
+#endif
+
+ tmpQI = 0;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> foundOccluders;
+
+ fe = (*ve)->fedgeA();
+ do
+ {
+ if ( fe == NULL || ! fe->isInImage() ) {
+ fe = fe->nextEdge();
+ continue;
+ }
+ if((maxCard < qiMajority)) {
+ tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); //ARB: change &wFace to wFace and use reference in called function
+#if logging > 0
+cout << "\tFEdge: visibility " << tmpQI << endl;
+#endif
+
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if(tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ } else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); //ARB: change &wFace to wFace and use reference in called function
+#if logging > 0
+cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl;
+#endif
+ }
+
+ // Store test results
+ if(wFace) {
+ vector<Vec3r> vertices;
+ for ( int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i ) {
+ vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex()));
+ }
+ Polygon3r poly(vertices, wFace->GetNormal());
+ poly.userdata = (void *) wFace;
+ fe->setaFace(poly);
+ wFaces.push_back(wFace);
+ fe->setOccludeeEmpty(false);
+#if logging > 0
+cout << "\tFound occludee" << endl;
+#endif
+ } else {
+ fe->setOccludeeEmpty(true);
+ }
+
+ ++nSamples;
+ fe = fe->nextEdge();
+ }
+ while((maxCard < qiMajority) && (0!=fe) && (fe!=festart));
+#if logging > 0
+cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl;
+#endif
+
+ // ViewEdge
+ // qi --
+ // Find the minimum value that is >= the majority of the QI
+ for ( unsigned count = 0, i = 0; i < 256; ++i ) {
+ count += qiClasses[i];
+ if ( count >= qiMajority ) {
+ (*ve)->setQI(i);
+ break;
+ }
+ }
+ // occluders --
+ // I would rather not have to go through the effort of creating this
+ // this set and then copying out its contents. Is there a reason why
+ // ViewEdge::_Occluders cannot be converted to a set<>?
+ for(set<ViewShape*>::iterator o=foundOccluders.begin(), oend=foundOccluders.end(); o!=oend; ++o) {
+ (*ve)->AddOccluder((*o));
+ }
+#if logging > 0
+cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl;
+#endif
+ // occludee --
+ if(!wFaces.empty())
+ {
+ if(wFaces.size() <= (float)nSamples/2.f)
+ {
+ (*ve)->setaShape(0);
+ }
+ else
+ {
+ ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ wFaces.clear();
+ }
+}
+
+template <typename G, typename I>
+static void computeDetailedVisibility(ViewMap *ioViewMap, G& grid, real epsilon, RenderMonitor *iRenderMonitor)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+
+ FEdge * fe, *festart;
+ int nSamples = 0;
+ vector<WFace*> wFaces;
+ WFace *wFace = 0;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end(); ve!=veend; ve++) {
+ if (iRenderMonitor && iRenderMonitor->testBreak())
+ break;
+#if logging > 0
+cout << "Processing ViewEdge " << (*ve)->getId() << endl;
+#endif
+ // Find an edge to test
+ if ( ! (*ve)->isInImage() ) {
+ // This view edge has been proscenium culled
+ (*ve)->setQI(255);
+ (*ve)->setaShape(0);
+#if logging > 0
+cout << "\tCulled." << endl;
+#endif
+ continue;
+ }
+
+ // Test edge
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 0;
+ do {
+ if ( fe != NULL && fe->isInImage() ) {
+ qiMajority++;
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+
+ if ( qiMajority == 0 ) {
+ // There are no occludable FEdges on this ViewEdge
+ // This should be impossible.
+ cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl;
+ // We can recover from this error:
+ // Treat this edge as fully visible with no occludee
+ (*ve)->setQI(0);
+ (*ve)->setaShape(0);
+ continue;
+ } else {
+ ++qiMajority;
+ qiMajority >>= 1;
+ }
+#if logging > 0
+cout << "\tqiMajority: " << qiMajority << endl;
+#endif
+
+ tmpQI = 0;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> foundOccluders;
+
+ fe = (*ve)->fedgeA();
+ do
+ {
+ if ( fe == NULL || ! fe->isInImage() ) {
+ fe = fe->nextEdge();
+ continue;
+ }
+ if((maxCard < qiMajority)) {
+ tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); //ARB: change &wFace to wFace and use reference in called function
+#if logging > 0
+cout << "\tFEdge: visibility " << tmpQI << endl;
+#endif
+
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if(tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ } else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); //ARB: change &wFace to wFace and use reference in called function
+#if logging > 0
+cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl;
+#endif
+ }
+
+ // Store test results
+ if(wFace) {
+ vector<Vec3r> vertices;
+ for ( int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i ) {
+ vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex()));
+ }
+ Polygon3r poly(vertices, wFace->GetNormal());
+ poly.userdata = (void *) wFace;
+ fe->setaFace(poly);
+ wFaces.push_back(wFace);
+ fe->setOccludeeEmpty(false);
+#if logging > 0
+cout << "\tFound occludee" << endl;
+#endif
+ } else {
+ fe->setOccludeeEmpty(true);
+ }
+
+ ++nSamples;
+ fe = fe->nextEdge();
+ }
+ while((maxCard < qiMajority) && (0!=fe) && (fe!=festart));
+#if logging > 0
+cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl;
+#endif
+
+ // ViewEdge
+ // qi --
+ (*ve)->setQI(maxIndex);
+ // occluders --
+ // I would rather not have to go through the effort of creating this
+ // this set and then copying out its contents. Is there a reason why
+ // ViewEdge::_Occluders cannot be converted to a set<>?
+ for(set<ViewShape*>::iterator o=foundOccluders.begin(), oend=foundOccluders.end(); o!=oend; ++o) {
+ (*ve)->AddOccluder((*o));
+ }
+#if logging > 0
+cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl;
+#endif
+ // occludee --
+ if(!wFaces.empty())
+ {
+ if(wFaces.size() <= (float)nSamples/2.f)
+ {
+ (*ve)->setaShape(0);
+ }
+ else
+ {
+ ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ wFaces.clear();
+ }
+}
+
+template <typename G, typename I>
+static void computeFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+
+ FEdge * fe, *festart;
+ unsigned nSamples = 0;
+ vector<WFace*> wFaces;
+ WFace *wFace = 0;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ bool even_test;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end(); ve!=veend; ve++) {
+ // Find an edge to test
+ if ( ! (*ve)->isInImage() ) {
+ // This view edge has been proscenium culled
+ (*ve)->setQI(255);
+ (*ve)->setaShape(0);
+ continue;
+ }
+
+ // Test edge
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+
+ even_test = true;
+ qiMajority = 0;
+ do {
+ if ( even_test && fe != NULL && fe->isInImage() ) {
+ qiMajority++;
+ even_test = ! even_test;
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+
+ if (qiMajority == 0 ) {
+ // There are no occludable FEdges on this ViewEdge
+ // This should be impossible.
+ cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl;
+ // We can recover from this error:
+ // Treat this edge as fully visible with no occludee
+ (*ve)->setQI(0);
+ (*ve)->setaShape(0);
+ continue;
+ } else {
+ ++qiMajority;
+ qiMajority >>= 1;
+ }
+
+ even_test = true;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> foundOccluders;
+
+ fe = (*ve)->fedgeA();
+ do
+ {
+ if ( fe == NULL || ! fe->isInImage() ) {
+ fe = fe->nextEdge();
+ continue;
+ }
+ if (even_test)
+ {
+ if((maxCard < qiMajority)) {
+ tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); //ARB: change &wFace to wFace and use reference in called function
+
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if(tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ } else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); //ARB: change &wFace to wFace and use reference in called function
+ }
+
+ if(wFace)
+ {
+ vector<Vec3r> vertices;
+ for ( int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i ) {
+ vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex()));
+ }
+ Polygon3r poly(vertices, wFace->GetNormal());
+ poly.userdata = (void *) wFace;
+ fe->setaFace(poly);
+ wFaces.push_back(wFace);
+ }
+ ++nSamples;
+ }
+
+ even_test = ! even_test;
+ fe = fe->nextEdge();
+ } while ((maxCard < qiMajority) && (0!=fe) && (fe!=festart));
+
+ // qi --
+ (*ve)->setQI(maxIndex);
+
+ // occluders --
+ for(set<ViewShape*>::iterator o=foundOccluders.begin(), oend=foundOccluders.end(); o!=oend; ++o) {
+ (*ve)->AddOccluder((*o));
+ }
+
+ // occludee --
+ if(!wFaces.empty())
+ {
+ if(wFaces.size() < nSamples / 2)
+ {
+ (*ve)->setaShape(0);
+ }
+ else
+ {
+ ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ wFaces.clear();
+ }
+}
+
+template <typename G, typename I>
+static void computeVeryFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+
+ FEdge* fe;
+ unsigned qi = 0;
+ WFace* wFace = 0;
+
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end(); ve!=veend; ve++)
+ {
+ // Find an edge to test
+ if ( ! (*ve)->isInImage() ) {
+ // This view edge has been proscenium culled
+ (*ve)->setQI(255);
+ (*ve)->setaShape(0);
+ continue;
+ }
+ fe = (*ve)->fedgeA();
+ // Find a FEdge inside the occluder proscenium to test for visibility
+ FEdge* festart = fe;
+ while ( fe != NULL && ! fe->isInImage() ) {
+ fe = fe->nextEdge();
+ if ( fe == festart ) {
+ break;
+ }
+ }
+
+ // Test edge
+ if ( fe == NULL || ! fe->isInImage() ) {
+ // There are no occludable FEdges on this ViewEdge
+ // This should be impossible.
+ cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl;
+ // We can recover from this error:
+ // Treat this edge as fully visible with no occludee
+ qi = 0;
+ wFace = NULL;
+ } else {
+ qi = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, NULL);
+ }
+
+ // Store test results
+ if(wFace)
+ {
+ vector<Vec3r> vertices;
+ for ( int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i ) {
+ vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex()));
+ }
+ Polygon3r poly(vertices, wFace->GetNormal());
+ poly.userdata = (void *) wFace;
+ fe->setaFace(poly); // This works because setaFace *copies* the polygon
+ ViewShape *vshape = ioViewMap->viewShape(wFace->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ else
+ {
+ (*ve)->setaShape(0);
+ }
+ (*ve)->setQI(qi);
+ }
+
+}
+
+void ViewMapBuilder::BuildGrid(WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces) {
+ _Grid->clear();
+ Vec3r size;
+ for(unsigned int i=0; i<3; i++)
+ {
+ size[i] = fabs(bbox.getMax()[i] - bbox.getMin()[i]);
+ size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections
+ if(size[i]==0){
+ cout << "Warning: the bbox size is 0 in dimension "<<i<<endl;
+ }
+ }
+ _Grid->configure(Vec3r(bbox.getMin() - size / 20.0), size, sceneNumFaces);
+
+ // Fill in the grid:
+ WFillGrid fillGridRenderer(_Grid, &we);
+ fillGridRenderer.fillGrid();
+
+ // DEBUG
+ _Grid->displayDebug();
+}
+
+ViewMap* ViewMapBuilder::BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon,
+ const BBox<Vec3r>& bbox, unsigned int sceneNumFaces) {
+ _ViewMap = new ViewMap;
+ _currentId = 1;
+ _currentFId = 0;
+ _currentSVertexId = 0;
+
+ // Builds initial view edges
+ computeInitialViewEdges(we);
+
+ // Detects cusps
+ computeCusps(_ViewMap);
+
+ // Compute intersections
+ ComputeIntersections(_ViewMap, sweep_line, epsilon);
+
+ // Compute visibility
+ ComputeEdgesVisibility(_ViewMap, we, bbox, sceneNumFaces, iAlgo, epsilon);
+
+ return _ViewMap;
+}
+
+static inline real distance2D(const Vec3r & point, const real origin[2]) {
+ return ::hypot((point[0] - origin[0]), (point[1] - origin[1]));
+}
+
+static inline bool crossesProscenium(real proscenium[4], FEdge *fe) {
+ Vec2r min(proscenium[0], proscenium[2]);
+ Vec2r max(proscenium[1], proscenium[3]);
+ Vec2r A(fe->vertexA()->getProjectedX(), fe->vertexA()->getProjectedY());
+ Vec2r B(fe->vertexB()->getProjectedX(), fe->vertexB()->getProjectedY());
+
+ return GeomUtils::intersect2dSeg2dArea (min, max, A, B);
+}
+
+static inline bool insideProscenium(real proscenium[4], const Vec3r& point) {
+ return ! ( point[0] < proscenium[0] || point[0] > proscenium[1] || point[1] < proscenium[2] || point[1] > proscenium[3] );
+}
+
+void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], real occluderProscenium[4], bool extensiveFEdgeSearch) {
+ // Cull view edges by marking them as non-displayable.
+ // This avoids the complications of trying to delete
+ // edges from the ViewMap.
+
+ // Non-displayable view edges will be skipped over during
+ // visibility calculation.
+
+ // View edges will be culled according to their position
+ // w.r.t. the viewport proscenium (viewport + 5% border,
+ // or some such).
+
+ // Get proscenium boundary for culling
+ GridHelpers::getDefaultViewProscenium(viewProscenium);
+ real prosceniumOrigin[2];
+ prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0;
+ prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0;
+ cout << "Proscenium culling:" << endl;
+ cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] << ", " << viewProscenium[3] << "]"<< endl;
+ cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]"<< endl;
+
+ // A separate occluder proscenium will also be maintained,
+ // starting out the same as the viewport proscenium, and
+ // expanding as necessary so that it encompasses the center
+ // point of at least one feature edge in each retained view
+ // edge.
+ // The occluder proscenium will be used later to cull occluding
+ // triangles before they are inserted into the Grid.
+ // The occluder proscenium starts out the same size as the view
+ // proscenium
+ GridHelpers::getDefaultViewProscenium(occluderProscenium);
+
+ // N.B. Freestyle is inconsistent in its use of ViewMap::viewedges_container
+ // and vector<ViewEdge*>::iterator. Probably all occurences of vector<ViewEdge*>::iterator
+ // should be replaced ViewMap::viewedges_container throughout the code.
+ // For each view edge
+ ViewMap::viewedges_container::iterator ve, veend;
+
+ for(ve=ioViewMap->ViewEdges().begin(), veend=ioViewMap->ViewEdges().end(); ve!=veend; ve++) {
+ // Overview:
+ // Search for a visible feature edge
+ // If none: mark view edge as non-displayable
+ // Otherwise:
+ // Find a feature edge with center point inside occluder proscenium.
+ // If none exists, find the feature edge with center point
+ // closest to viewport origin.
+ // Expand occluder proscenium to enclose center point.
+
+ // For each feature edge, while bestOccluderTarget not found and view edge not visibile
+ bool bestOccluderTargetFound = false;
+ FEdge *bestOccluderTarget = NULL;
+ real bestOccluderDistance = 0.0;
+ FEdge *festart = (*ve)->fedgeA();
+ FEdge *fe = festart;
+ // All ViewEdges start culled
+ (*ve)->setIsInImage(false);
+
+ // For simple visibility calculation: mark a feature edge
+ // that is known to have a center point inside the occluder proscenium.
+ // Cull all other feature edges.
+ do {
+ // All FEdges start culled
+ fe->setIsInImage(false);
+
+ // Look for the visible edge that can most easily be included
+ // in the occluder proscenium.
+ if ( ! bestOccluderTargetFound ) {
+ // If center point is inside occluder proscenium,
+ if ( insideProscenium(occluderProscenium, fe->center2d()) ) {
+ // Use this feature edge for visibility deterimination
+ fe->setIsInImage(true);
+ // Mark bestOccluderTarget as found
+ bestOccluderTargetFound = true;
+ bestOccluderTarget = fe;
+ } else {
+ real d = distance2D(fe->center2d(), prosceniumOrigin);
+ // If center point is closer to viewport origin than current target
+ if ( bestOccluderTarget == NULL || d < bestOccluderDistance ) {
+ // Then store as bestOccluderTarget
+ bestOccluderDistance = d;
+ bestOccluderTarget = fe;
+ }
+ }
+ }
+
+ // If feature edge crosses the view proscenium
+ if ( ! (*ve)->isInImage() && crossesProscenium(viewProscenium, fe) ) {
+ // Then the view edge will be included in the image
+ (*ve)->setIsInImage(true);
+ }
+ fe = fe->nextEdge();
+ } while ( fe != NULL && fe != festart && ! ( bestOccluderTargetFound && (*ve)->isInImage() ) );
+
+ // Either we have run out of FEdges, or we already have the one edge we need to determine visibility
+ // Cull all remaining edges.
+ while ( fe != NULL && fe != festart ) {
+ fe->setIsInImage(false);
+ fe = fe->nextEdge();
+ }
+
+ // If bestOccluderTarget was not found inside the occluder proscenium,
+ // we need to expand the occluder proscenium to include it.
+ if ( (*ve)->isInImage() && bestOccluderTarget != NULL && ! bestOccluderTargetFound ) {
+ // Expand occluder proscenium to enclose bestOccluderTarget
+ Vec3r point = bestOccluderTarget->center2d();
+ if ( point[0] < occluderProscenium[0] ) {
+ occluderProscenium[0] = point[0];
+ } else if ( point[0] > occluderProscenium[1] ) {
+ occluderProscenium[1] = point[0];
+ }
+ if ( point[1] < occluderProscenium[2] ) {
+ occluderProscenium[2] = point[1];
+ } else if ( point[1] > occluderProscenium[3] ) {
+ occluderProscenium[3] = point[1];
+ }
+ // Use bestOccluderTarget for visibility determination
+ bestOccluderTarget->setIsInImage(true);
+ }
+ }
+
+ // We are done calculating the occluder proscenium.
+ // Expand the occluder proscenium by an epsilon to avoid rounding errors.
+ const real epsilon = 1.0e-6;
+ occluderProscenium[0] -= epsilon;
+ occluderProscenium[1] += epsilon;
+ occluderProscenium[2] -= epsilon;
+ occluderProscenium[3] += epsilon;
+
+ // For "Normal" or "Fast" style visibility computation only:
+
+ // For more detailed visibility calculation, make a second pass through
+ // the view map, marking all feature edges with center points inside
+ // the final occluder proscenium. All of these feature edges can be
+ // considered during visibility calculation.
+
+ // So far we have only found one FEdge per ViewEdge. The "Normal" and
+ // "Fast" styles of visibility computation want to consider many
+ // FEdges for each ViewEdge.
+ // Here we re-scan the view map to find any usable FEdges that we
+ // skipped on the first pass, or that have become usable because the
+ // occluder proscenium has been expanded since the edge was visited
+ // on the first pass.
+ if ( extensiveFEdgeSearch ) {
+ // For each view edge,
+ for(ve=ioViewMap->ViewEdges().begin(), veend=ioViewMap->ViewEdges().end(); ve!=veend; ve++) {
+ if ( ! (*ve)->isInImage() ) {
+ continue;
+ }
+ // For each feature edge,
+ FEdge *festart = (*ve)->fedgeA();
+ FEdge *fe = festart;
+ do {
+ // If not (already) visible and center point inside occluder proscenium,
+ if ( ! fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d()) ) {
+ // Use the feature edge for visibility determination
+ fe->setIsInImage(true);
+ }
+ fe = fe->nextEdge();
+ } while ( fe != NULL && fe != festart );
+ }
+ }
+}
+
+void ViewMapBuilder::computeInitialViewEdges(WingedEdge& we)
+{
+ vector<WShape*> wshapes = we.getWShapes();
+ SShape* psShape;
+
+ for (vector<WShape*>::const_iterator it = wshapes.begin();
+ it != wshapes.end();
+ it++) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+
+ // create the embedding
+ psShape = new SShape;
+ psShape->setId((*it)->GetId());
+ psShape->setName((*it)->getName());
+ psShape->setFrsMaterials((*it)->frs_materials()); // FIXME
+
+ // create the view shape
+ ViewShape * vshape = new ViewShape(psShape);
+ // add this view shape to the view map:
+ _ViewMap->AddViewShape(vshape);
+
+ _pViewEdgeBuilder->setCurrentViewId(_currentId); // we want to number the view edges in a unique way for the while scene.
+ _pViewEdgeBuilder->setCurrentFId(_currentFId); // we want to number the feature edges in a unique way for the while scene.
+ _pViewEdgeBuilder->setCurrentSVertexId(_currentFId); // we want to number the SVertex in a unique way for the while scene.
+ _pViewEdgeBuilder->BuildViewEdges(dynamic_cast<WXShape*>(*it), vshape,
+ _ViewMap->ViewEdges(),
+ _ViewMap->ViewVertices(),
+ _ViewMap->FEdges(),
+ _ViewMap->SVertices());
+
+ _currentId = _pViewEdgeBuilder->currentViewId()+1;
+ _currentFId = _pViewEdgeBuilder->currentFId()+1;
+ _currentSVertexId = _pViewEdgeBuilder->currentSVertexId()+1;
+
+ psShape->ComputeBBox();
+ }
+}
+
+void ViewMapBuilder::computeCusps(ViewMap *ioViewMap){
+ vector<ViewVertex*> newVVertices;
+ vector<ViewEdge*> newVEdges;
+ ViewMap::viewedges_container& vedges = ioViewMap->ViewEdges();
+ ViewMap::viewedges_container::iterator ve=vedges.begin(), veend=vedges.end();
+ for(;
+ ve!=veend;
+ ++ve){
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+ if((!((*ve)->getNature() & Nature::SILHOUETTE)) || (!((*ve)->fedgeA()->isSmooth())))
+ continue;
+ FEdge *fe = (*ve)->fedgeA();
+ FEdge * fefirst = fe;
+ bool first = true;
+ bool positive = true;
+ do{
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ Vec3r A((fes)->vertexA()->point3d());
+ Vec3r B((fes)->vertexB()->point3d());
+ Vec3r AB(B-A);
+ AB.normalize();
+ Vec3r m((A+B)/2.0);
+ Vec3r crossP(AB^(fes)->normal());
+ crossP.normalize();
+ Vec3r viewvector;
+ if (_orthographicProjection) {
+ viewvector = Vec3r(0.0, 0.0, m.z()-_viewpoint.z());
+ } else {
+ viewvector = Vec3r(m-_viewpoint);
+ }
+ viewvector.normalize();
+ if(first){
+ if(((crossP)*(viewvector)) > 0)
+ positive = true;
+ else
+ positive = false;
+ first = false;
+ }
+ // If we're in a positive part, we need
+ // a stronger negative value to change
+ NonTVertex *cusp = 0;
+ if(positive){
+ if(((crossP)*(viewvector)) < -0.1){
+ // state changes
+ positive = false;
+ // creates and insert cusp
+ cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges));
+ if(cusp!=0)
+ cusp->setNature(cusp->getNature()|Nature::CUSP);
+ }
+
+ }else{
+ // If we're in a negative part, we need
+ // a stronger negative value to change
+ if(((crossP)*(viewvector)) > 0.1){
+ positive = true;
+ cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges));
+ if(cusp!=0)
+ cusp->setNature(cusp->getNature()|Nature::CUSP);
+ }
+ }
+ fe = fe->nextEdge();
+ }while((fe!=0) && (fe!=fefirst));
+ }
+ for(ve=newVEdges.begin(), veend=newVEdges.end();
+ ve!=veend;
+ ++ve){
+ (*ve)->viewShape()->AddEdge(*ve);
+ vedges.push_back(*ve);
+ }
+}
+
+void ViewMapBuilder::ComputeCumulativeVisibility(ViewMap *ioViewMap,
+ WingedEdge& we, const BBox<Vec3r>& bbox, real epsilon, bool cull, GridDensityProviderFactory& factory)
+{
+ auto_ptr<GridHelpers::Transform> transform;
+ auto_ptr<OccluderSource> source;
+
+ if ( _orthographicProjection ) {
+ transform.reset(new BoxGrid::Transform);
+ } else {
+ transform.reset(new SphericalGrid::Transform);
+ }
+
+ if ( cull ) {
+ source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true));
+ } else {
+ source.reset(new OccluderSource(*transform, we));
+ }
+
+ auto_ptr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform));
+
+ if ( _orthographicProjection ) {
+ BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
+ computeCumulativeVisibility<BoxGrid, BoxGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor);
+ } else {
+ SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
+ computeCumulativeVisibility<SphericalGrid, SphericalGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor);
+ }
+}
+
+void ViewMapBuilder::ComputeDetailedVisibility(ViewMap *ioViewMap,
+ WingedEdge& we, const BBox<Vec3r>& bbox, real epsilon, bool cull, GridDensityProviderFactory& factory)
+{
+ auto_ptr<GridHelpers::Transform> transform;
+ auto_ptr<OccluderSource> source;
+
+ if ( _orthographicProjection ) {
+ transform.reset(new BoxGrid::Transform);
+ } else {
+ transform.reset(new SphericalGrid::Transform);
+ }
+
+ if ( cull ) {
+ source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true));
+ } else {
+ source.reset(new OccluderSource(*transform, we));
+ }
+
+ auto_ptr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform));
+
+ if ( _orthographicProjection ) {
+ BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
+ computeDetailedVisibility<BoxGrid, BoxGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor);
+ } else {
+ SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
+ computeDetailedVisibility<SphericalGrid, SphericalGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor);
+ }
+}
+
+void ViewMapBuilder::ComputeEdgesVisibility(ViewMap *ioViewMap,
+ WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces, visibility_algo iAlgo, real epsilon)
+{
+ switch(iAlgo)
+ {
+ case ray_casting:
+ cout << "Using ordinary ray casting" << endl;
+ BuildGrid(we, bbox, sceneNumFaces);
+ ComputeRayCastingVisibility(ioViewMap, epsilon);
+ break;
+ case ray_casting_fast:
+ cout << "Using fast ray casting" << endl;
+ BuildGrid(we, bbox, sceneNumFaces);
+ ComputeFastRayCastingVisibility(ioViewMap, epsilon);
+ break;
+ case ray_casting_very_fast:
+ cout << "Using very fast ray casting" << endl;
+ BuildGrid(we, bbox, sceneNumFaces);
+ ComputeVeryFastRayCastingVisibility(ioViewMap, epsilon);
+ break;
+ case ray_casting_culled_adaptive_traditional:
+ cout << "Using culled adaptive grid with heuristic density and traditional QI calculation" << endl;
+ try {
+ HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces);
+ ComputeDetailedVisibility(ioViewMap, we, bbox, epsilon, true, factory);
+ } catch (...) {
+ // Last resort catch to make sure RAII semantics hold for OptimizedGrid
+ // Can be replaced with try...catch block around main() if the program
+ // as a whole is converted to RAII
+
+ // This is the little-mentioned caveat of RAII: RAII does not work unless
+ // destructors are always called, but destructors are only called if all
+ // exceptions are caught (or std::terminate() is replaced).
+
+ // We don't actually handle the exception here, so re-throw it
+ // now that our destructors have had a chance to run.
+ throw;
+ }
+ break;
+ case ray_casting_adaptive_traditional:
+ cout << "Using unculled adaptive grid with heuristic density and traditional QI calculation" << endl;
+ try {
+ HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces);
+ ComputeDetailedVisibility(ioViewMap, we, bbox, epsilon, false, factory);
+ } catch (...) {
+ throw;
+ }
+ break;
+ case ray_casting_culled_adaptive_cumulative:
+ cout << "Using culled adaptive grid with heuristic density and cumulative QI calculation" << endl;
+ try {
+ HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces);
+ ComputeCumulativeVisibility(ioViewMap, we, bbox, epsilon, true, factory);
+ } catch (...) {
+ throw;
+ }
+ break;
+ case ray_casting_adaptive_cumulative:
+ cout << "Using unculled adaptive grid with heuristic density and cumulative QI calculation" << endl;
+ try {
+ HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces);
+ ComputeCumulativeVisibility(ioViewMap, we, bbox, epsilon, false, factory);
+ } catch (...) {
+ throw;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static const unsigned gProgressBarMaxSteps = 10;
+static const unsigned gProgressBarMinSize = 2000;
+
+void ViewMapBuilder::ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge * fe, *festart;
+ int nSamples = 0;
+ vector<Polygon3r*> aFaces;
+ Polygon3r *aFace = 0;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ static unsigned timestamp = 1;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end();
+ ve!=veend;
+ ve++)
+ {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+#if logging > 0
+cout << "Processing ViewEdge " << (*ve)->getId() << endl;
+#endif
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 1;
+ do {
+ qiMajority++;
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+ qiMajority >>= 1;
+#if logging > 0
+cout << "\tqiMajority: " << qiMajority << endl;
+#endif
+
+ tmpQI = 0;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ fe = (*ve)->fedgeA();
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> occluders;
+ do
+ {
+ if((maxCard < qiMajority)) {
+ tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++);
+
+#if logging > 0
+cout << "\tFEdge: visibility " << tmpQI << endl;
+#endif
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if(tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ } else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ FindOccludee(fe, _Grid, epsilon, &aFace, timestamp++);
+#if logging > 0
+cout << "\tFEdge: occludee only (" << (aFace != NULL ? "found" : "not found") << ")" << endl;
+#endif
+ }
+
+ if(aFace) {
+ fe->setaFace(*aFace);
+ aFaces.push_back(aFace);
+ fe->setOccludeeEmpty(false);
+#if logging > 0
+cout << "\tFound occludee" << endl;
+#endif
+ }
+ else
+ {
+ //ARB: We are arbitrarily using the last observed value for occludee
+ // (almost always the value observed for the edge before festart).
+ // Is that meaningful?
+ // ...in fact, _occludeeEmpty seems to be unused.
+ fe->setOccludeeEmpty(true);
+ }
+
+ ++nSamples;
+ fe = fe->nextEdge();
+ }
+ while((maxCard < qiMajority) && (0!=fe) && (fe!=festart));
+#if logging > 0
+cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl;
+#endif
+
+ // ViewEdge
+ // qi --
+ (*ve)->setQI(maxIndex);
+ // occluders --
+ for(set<ViewShape*>::iterator o=occluders.begin(), oend=occluders.end();
+ o!=oend;
+ ++o)
+ (*ve)->AddOccluder((*o));
+#if logging > 0
+cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl;
+#endif
+ // occludee --
+ if(!aFaces.empty())
+ {
+ if(aFaces.size() <= (float)nSamples/2.f)
+ {
+ (*ve)->setaShape(0);
+ }
+ else
+ {
+ vector<Polygon3r*>::iterator p = aFaces.begin();
+ WFace * wface = (WFace*)((*p)->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ ++p;
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ aFaces.clear();
+ }
+}
+
+void ViewMapBuilder::ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge * fe, *festart;
+ unsigned nSamples = 0;
+ vector<Polygon3r*> aFaces;
+ Polygon3r *aFace = 0;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ static unsigned timestamp = 1;
+ bool even_test;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end();
+ ve!=veend;
+ ve++)
+ {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 1;
+ do {
+ qiMajority++;
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+ if (qiMajority >= 4)
+ qiMajority >>= 2;
+ else
+ qiMajority = 1;
+
+ set<ViewShape*> occluders;
+
+ even_test = true;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ fe = (*ve)->fedgeA();
+ do
+ {
+ if (even_test)
+ {
+ if((maxCard < qiMajority)) {
+ tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++);
+
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if(tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ } else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ FindOccludee(fe, _Grid, epsilon, &aFace, timestamp++);
+ }
+
+ if(aFace)
+ {
+ fe->setaFace(*aFace);
+ aFaces.push_back(aFace);
+ }
+ ++nSamples;
+ even_test = false;
+ }
+ else
+ even_test = true;
+ fe = fe->nextEdge();
+ } while ((maxCard < qiMajority) && (0!=fe) && (fe!=festart));
+
+ (*ve)->setQI(maxIndex);
+
+ if(!aFaces.empty())
+ {
+ if(aFaces.size() < nSamples / 2)
+ {
+ (*ve)->setaShape(0);
+ }
+ else
+ {
+ vector<Polygon3r*>::iterator p = aFaces.begin();
+ WFace * wface = (WFace*)((*p)->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ ++p;
+ // for(;
+ // p!=pend;
+ // ++p)
+ // {
+ // WFace *f = (WFace*)((*p)->userdata);
+ // ViewShape *vs = ioViewMap->viewShape(f->GetVertex(0)->shape()->GetId());
+ // if(vs != vshape)
+ // {
+ // sameShape = false;
+ // break;
+ // }
+ // }
+ // if(sameShape)
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ //(*ve)->setaFace(aFace);
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ aFaces.clear();
+ }
+}
+
+void ViewMapBuilder::ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge* fe;
+ unsigned qi = 0;
+ Polygon3r *aFace = 0;
+ static unsigned timestamp = 1;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end();
+ ve!=veend;
+ ve++)
+ {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+
+ set<ViewShape*> occluders;
+
+ fe = (*ve)->fedgeA();
+ qi = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++);
+ if(aFace)
+ {
+ fe->setaFace(*aFace);
+ WFace * wface = (WFace*)(aFace->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ else
+ {
+ (*ve)->setaShape(0);
+ }
+
+ (*ve)->setQI(qi);
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ }
+}
+
+void ViewMapBuilder::FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp,
+ Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices)
+{
+ WFace *face = 0;
+ if(fe->isSmooth()){
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+ OccludersSet occluders;
+ WFace * oface;
+ bool skipFace;
+
+ WVertex::incoming_edge_iterator ie;
+ OccludersSet::iterator p, pend;
+
+ *oaPolygon = 0;
+ if(((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER))
+ {
+ occluders.clear();
+ // we cast a ray from A in the same direction but looking behind
+ Vec3r v(-u[0],-u[1],-u[2]);
+ iGrid->castInfiniteRay(A, v, occluders, timestamp);
+
+ bool noIntersection = true;
+ real mint=FLT_MAX;
+ // we met some occluders, let us fill the aShape field
+ // with the first intersected occluder
+ for(p=occluders.begin(),pend=occluders.end();
+ p!=pend;
+ p++)
+ {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ oface = (WFace*)(*p)->userdata;
+ Vec3r v1(((*p)->getVertices())[0]);
+ Vec3r normal((*p)->getNormal());
+ real d = -(v1 * normal);
+ real t,t_u,t_v;
+
+ if(0 != face)
+ {
+ skipFace = false;
+
+ if(face == oface)
+ continue;
+
+ if(faceVertices.empty())
+ continue;
+
+ for(vector<WVertex*>::iterator fv=faceVertices.begin(), fvend=faceVertices.end();
+ fv!=fvend;
+ ++fv)
+ {
+ if((*fv)->isBoundary())
+ continue;
+ WVertex::incoming_edge_iterator iebegin=(*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend=(*fv)->incoming_edges_end();
+ for(ie=iebegin;ie!=ieend; ++ie)
+ {
+ if((*ie) == 0)
+ continue;
+
+ WFace * sface = (*ie)->GetbFace();
+ if(sface == oface)
+ {
+ skipFace = true;
+ break;
+ }
+ }
+ if(skipFace)
+ break;
+ }
+ if(skipFace)
+ continue;
+ }
+ else
+ {
+ if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon))
+ continue;
+ }
+ if((*p)->rayIntersect(A, v, t,t_u,t_v))
+ {
+ if (fabs(v * normal) > 0.0001)
+ if ((t>0.0)) // && (t<1.0))
+ {
+ if (t<mint)
+ {
+ *oaPolygon = (*p);
+ mint = t;
+ noIntersection = false;
+ fe->setOccludeeIntersection(Vec3r(A+t*v));
+ }
+ }
+ }
+ }
+
+ if(noIntersection)
+ *oaPolygon = 0;
+ }
+}
+
+void ViewMapBuilder::FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp)
+{
+ OccludersSet occluders;
+
+ Vec3r A;
+ Vec3r edge;
+ Vec3r origin;
+ A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D())/2.0);
+ edge = Vec3r((fe)->vertexB()->point3D()-(fe)->vertexA()->point3D());
+ origin = Vec3r((fe)->vertexA()->point3D());
+ Vec3r u;
+ if (_orthographicProjection) {
+ u = Vec3r(0.0, 0.0, _viewpoint.z()-A.z());
+ } else {
+ u = Vec3r(_viewpoint-A);
+ }
+ u.normalize();
+ if(A < iGrid->getOrigin())
+ cerr << "Warning: point is out of the grid for fedge " << fe->getId().getFirst() << "-" << fe->getId().getSecond() << endl;
+
+ vector<WVertex*> faceVertices;
+
+ WFace *face = 0;
+ if(fe->isSmooth()){
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+ if(0 != face)
+ face->RetrieveVertexList(faceVertices);
+
+ return FindOccludee(fe,iGrid, epsilon, oaPolygon, timestamp,
+ u, A, origin, edge, faceVertices);
+}
+
+int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid* iGrid, real epsilon, set<ViewShape*>& oOccluders,
+ Polygon3r** oaPolygon, unsigned timestamp)
+{
+ OccludersSet occluders;
+ int qi = 0;
+
+ Vec3r center;
+ Vec3r edge;
+ Vec3r origin;
+
+ center = fe->center3d();
+ edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
+ origin = Vec3r(fe->vertexA()->point3D());
+ //
+ // // Is the edge outside the view frustum ?
+ Vec3r gridOrigin(iGrid->getOrigin());
+ Vec3r gridExtremity(iGrid->getOrigin()+iGrid->gridSize());
+
+ if( (center.x() < gridOrigin.x()) || (center.y() < gridOrigin.y()) || (center.z() < gridOrigin.z())
+ ||(center.x() > gridExtremity.x()) || (center.y() > gridExtremity.y()) || (center.z() > gridExtremity.z())){
+ cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl;
+ //return 0;
+ }
+
+
+ // Vec3r A(fe->vertexA()->point2d());
+ // Vec3r B(fe->vertexB()->point2d());
+ // int viewport[4];
+ // SilhouetteGeomEngine::retrieveViewport(viewport);
+ // if( (A.x() < viewport[0]) || (A.x() > viewport[2]) || (A.y() < viewport[1]) || (A.y() > viewport[3])
+ // ||(B.x() < viewport[0]) || (B.x() > viewport[2]) || (B.y() < viewport[1]) || (B.y() > viewport[3])){
+ // cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl;
+ // //return 0;
+ // }
+
+ Vec3r vp;
+ if (_orthographicProjection) {
+ vp = Vec3r(center.x(), center.y(), _viewpoint.z());
+ } else {
+ vp = Vec3r(_viewpoint);
+ }
+ Vec3r u(vp - center);
+ real raylength = u.norm();
+ u.normalize();
+ //cout << "grid origin " << iGrid->getOrigin().x() << "," << iGrid->getOrigin().y() << "," << iGrid->getOrigin().z() << endl;
+ //cout << "center " << center.x() << "," << center.y() << "," << center.z() << endl;
+
+ iGrid->castRay(center, vp, occluders, timestamp);
+
+ WFace *face = 0;
+ if(fe->isSmooth()){
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+ vector<WVertex*> faceVertices;
+ WVertex::incoming_edge_iterator ie;
+
+ WFace * oface;
+ bool skipFace;
+ OccludersSet::iterator p, pend;
+ if(face)
+ face->RetrieveVertexList(faceVertices);
+
+ for(p=occluders.begin(),pend=occluders.end();
+ p!=pend;
+ p++)
+ {
+ // If we're dealing with an exact silhouette, check whether
+ // we must take care of this occluder of not.
+ // (Indeed, we don't consider the occluders that
+ // share at least one vertex with the face containing
+ // this edge).
+ //-----------
+ oface = (WFace*)(*p)->userdata;
+#if logging > 1
+cout << "\t\tEvaluating intersection for occluder " << ((*p)->getVertices())[0] << ((*p)->getVertices())[1] << ((*p)->getVertices())[2] << endl << "\t\t\tand ray " << vp << " * " << u << " (center " << center << ")" << endl;
+#endif
+ Vec3r v1(((*p)->getVertices())[0]);
+ Vec3r normal((*p)->getNormal());
+ real d = -(v1 * normal);
+ real t, t_u, t_v;
+
+#if logging > 1
+cout << "\t\tp: " << ((*p)->getVertices())[0] << ((*p)->getVertices())[1] << ((*p)->getVertices())[2] << ", norm: " << (*p)->getNormal() << endl;
+#endif
+
+ if(0 != face)
+ {
+#if logging > 1
+cout << "\t\tDetermining face adjacency...";
+#endif
+ skipFace = false;
+
+ if(face == oface) {
+#if logging > 1
+cout << " Rejecting occluder for face concurrency." << endl;
+#endif
+ continue;
+ }
+
+
+ for(vector<WVertex*>::iterator fv=faceVertices.begin(), fvend=faceVertices.end();
+ fv!=fvend;
+ ++fv)
+ {
+ if((*fv)->isBoundary())
+ continue;
+
+ WVertex::incoming_edge_iterator iebegin=(*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend=(*fv)->incoming_edges_end();
+ for(ie=iebegin;ie!=ieend; ++ie)
+ {
+ if((*ie) == 0)
+ continue;
+
+ WFace * sface = (*ie)->GetbFace();
+ //WFace * sfacea = (*ie)->GetaFace();
+ //if((sface == oface) || (sfacea == oface))
+ if(sface == oface)
+ {
+ skipFace = true;
+ break;
+ }
+ }
+ if(skipFace)
+ break;
+ }
+ if(skipFace) {
+#if logging > 1
+cout << " Rejecting occluder for face adjacency." << endl;
+#endif
+ continue;
+ }
+ }
+ else
+ {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+
+ if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon)) {
+#if logging > 1
+cout << "\t\tRejecting occluder for target coincidence." << endl;
+#endif
+ continue;
+ }
+ }
+
+ if((*p)->rayIntersect(center, u, t, t_u, t_v))
+ {
+#if logging > 1
+cout << "\t\tRay " << vp << " * " << u << " intersects at time " << t << " (raylength is " << raylength << ")" << endl;
+#endif
+#if logging > 1
+cout << "\t\t(u * normal) == " << (u * normal) << " for normal " << normal << endl;
+#endif
+ if (fabs(u * normal) > 0.0001)
+ if ((t>0.0) && (t<raylength))
+ {
+#if logging > 1
+cout << "\t\tIs occluder" << endl;
+#endif
+ WFace *f = (WFace*)((*p)->userdata);
+ ViewShape *vshape = _ViewMap->viewShape(f->GetVertex(0)->shape()->GetId());
+ oOccluders.insert(vshape);
+ ++qi;
+ if(!_EnableQI)
+ break;
+ }
+ }
+ }
+
+ // Find occludee
+ FindOccludee(fe,iGrid, epsilon, oaPolygon, timestamp,
+ u, center, edge, origin, faceVertices);
+
+ return qi;
+}
+
+void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo, real epsilon)
+{
+ switch(iAlgo)
+ {
+ case sweep_line:
+ ComputeSweepLineIntersections(ioViewMap, epsilon);
+ break;
+ default:
+ break;
+ }
+ ViewMap::viewvertices_container& vvertices = ioViewMap->ViewVertices();
+ for(ViewMap::viewvertices_container::iterator vv=vvertices.begin(), vvend=vvertices.end();
+ vv!=vvend;
+ ++vv)
+ {
+ if((*vv)->getNature() == Nature::T_VERTEX)
+ {
+ TVertex *tvertex = (TVertex*)(*vv);
+ cout << "TVertex " << tvertex->getId() << " has :" << endl;
+ cout << "FrontEdgeA: " << tvertex->frontEdgeA().first << endl;
+ cout << "FrontEdgeB: " << tvertex->frontEdgeB().first << endl;
+ cout << "BackEdgeA: " << tvertex->backEdgeA().first << endl;
+ cout << "BackEdgeB: " << tvertex->backEdgeB().first << endl << endl;
+ }
+ }
+}
+
+struct less_SVertex2D : public binary_function<SVertex*, SVertex*, bool>
+{
+ real epsilon;
+ less_SVertex2D(real eps)
+ : binary_function<SVertex*,SVertex*,bool>()
+ {
+ epsilon = eps;
+ }
+ bool operator()(SVertex* x, SVertex* y)
+ {
+ Vec3r A = x->point2D();
+ Vec3r B = y->point2D();
+ for(unsigned int i=0; i<3; i++)
+ {
+ if((fabs(A[i] - B[i])) < epsilon)
+ continue;
+ if(A[i] < B[i])
+ return true;
+ if(A[i] > B[i])
+ return false;
+ }
+
+ return false;
+ }
+};
+
+typedef Segment<FEdge*,Vec3r > segment;
+typedef Intersection<segment> intersection;
+
+struct less_Intersection : public binary_function<intersection*, intersection*, bool>
+{
+ segment *edge;
+ less_Intersection(segment *iEdge)
+ : binary_function<intersection*,intersection*,bool>()
+ {
+ edge = iEdge;
+ }
+ bool operator()(intersection* x, intersection* y)
+ {
+ real tx = x->getParameter(edge);
+ real ty = y->getParameter(edge);
+ if(tx > ty)
+ return true;
+ return false;
+ }
+};
+
+struct silhouette_binary_rule : public binary_rule<segment,segment>
+{
+ silhouette_binary_rule() : binary_rule<segment,segment>() {}
+ virtual bool operator() (segment& s1, segment& s2)
+ {
+ FEdge * f1 = s1.edge();
+ FEdge * f2 = s2.edge();
+
+ if((!(((f1)->getNature() & Nature::SILHOUETTE) || ((f1)->getNature() & Nature::BORDER))) && (!(((f2)->getNature() & Nature::SILHOUETTE) || ((f2)->getNature() & Nature::BORDER))))
+ return false;
+
+ return true;
+ }
+};
+
+void ViewMapBuilder::ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon)
+{
+ vector<SVertex*>& svertices = ioViewMap->SVertices();
+ bool progressBarDisplay = false;
+ unsigned sVerticesSize = svertices.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+ // ViewMap::fedges_container& fedges = ioViewMap->FEdges();
+ // for(ViewMap::fedges_container::const_iterator f=fedges.begin(), end=fedges.end();
+ // f!=end;
+ // ++f){
+ // cout << (*f)->aMaterialIndex() << "-" << (*f)->bMaterialIndex() << endl;
+ // }
+
+ unsigned progressBarStep = 0;
+
+ if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, sVerticesSize);
+ progressBarStep = sVerticesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Sweep Line Intersections");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+
+ sort(svertices.begin(), svertices.end(), less_SVertex2D(epsilon));
+
+ SweepLine<FEdge*,Vec3r> SL;
+
+ vector<FEdge*>& ioEdges = ioViewMap->FEdges();
+
+ vector<segment* > segments;
+
+ vector<FEdge*>::iterator fe,fend;
+
+ for(fe=ioEdges.begin(), fend=ioEdges.end();
+ fe!=fend;
+ fe++)
+ {
+ segment * s = new segment((*fe), (*fe)->vertexA()->point2D(), (*fe)->vertexB()->point2D());
+ (*fe)->userdata = s;
+ segments.push_back(s);
+ }
+
+ vector<segment*> vsegments;
+ for(vector<SVertex*>::iterator sv=svertices.begin(),svend=svertices.end();
+ sv!=svend;
+ sv++)
+ {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+
+ const vector<FEdge*>& vedges = (*sv)->fedges();
+
+ for(vector<FEdge*>::const_iterator sve=vedges.begin(), sveend=vedges.end();
+ sve!=sveend;
+ sve++)
+ {
+ vsegments.push_back((segment*)((*sve)->userdata));
+ }
+
+ Vec3r evt((*sv)->point2D());
+ silhouette_binary_rule sbr;
+ SL.process(evt, vsegments, sbr, epsilon);
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ vsegments.clear();
+ }
+
+ if (_pRenderMonitor && _pRenderMonitor->testBreak()) {
+ // delete segments
+ if(!segments.empty()){
+ vector<segment* >::iterator s, send;
+ for(s=segments.begin(),send=segments.end();
+ s!=send;
+ s++){
+ delete *s;
+ }
+ }
+ return;
+ }
+
+ // reset userdata:
+ for(fe=ioEdges.begin(), fend=ioEdges.end();
+ fe!=fend;
+ fe++)
+ (*fe)->userdata = NULL;
+
+ // list containing the new edges resulting from splitting operations.
+ vector<FEdge*> newEdges;
+
+ // retrieve the intersected edges:
+ vector<segment* >& iedges = SL.intersectedEdges();
+ // retrieve the intersections:
+ vector<intersection*>& intersections = SL.intersections();
+
+ int id=0;
+ // create a view vertex for each intersection and linked this one
+ // with the intersection object
+ vector<intersection*>::iterator i, iend;
+ for(i=intersections.begin(),iend=intersections.end();
+ i!=iend;
+ i++)
+ {
+ FEdge *fA = (*i)->EdgeA->edge();
+ FEdge *fB = (*i)->EdgeB->edge();
+
+ Vec3r A1 = fA->vertexA()->point3D();
+ Vec3r A2 = fA->vertexB()->point3D();
+ Vec3r B1 = fB->vertexA()->point3D();
+ Vec3r B2 = fB->vertexB()->point3D();
+
+ Vec3r a1 = fA->vertexA()->point2D();
+ Vec3r a2 = fA->vertexB()->point2D();
+ Vec3r b1 = fB->vertexA()->point2D();
+ Vec3r b2 = fB->vertexB()->point2D();
+
+ real ta = (*i)->tA;
+ real tb = (*i)->tB;
+
+ if((ta < -epsilon) || (ta > 1+epsilon))
+ cerr << "Warning: 2D intersection out of range for edge " << fA->vertexA()->getId() << " - " << fA->vertexB()->getId() << endl;
+
+ if((tb < -epsilon) || (tb > 1+epsilon))
+ cerr << "Warning: 2D intersection out of range for edge " << fB->vertexA()->getId() << " - " << fB->vertexB()->getId() << endl;
+
+ real Ta = SilhouetteGeomEngine::ImageToWorldParameter(fA, ta);
+ real Tb = SilhouetteGeomEngine::ImageToWorldParameter(fB, tb);
+
+ if((Ta < -epsilon) || (Ta > 1+epsilon))
+ cerr << "Warning: 3D intersection out of range for edge " << fA->vertexA()->getId() << " - " << fA->vertexB()->getId() << endl;
+
+ if((Tb < -epsilon) || (Tb > 1+epsilon))
+ cerr << "Warning: 3D intersection out of range for edge " << fB->vertexA()->getId() << " - " << fB->vertexB()->getId() << endl;
+
+#if 0
+ if((Ta < -epsilon) || (Ta > 1+epsilon) || (Tb < -epsilon) || (Tb > 1+epsilon)) {
+ printf("ta %.12e\n", ta);
+ printf("tb %.12e\n", tb);
+ printf("a1 %e, %e -- b1 %e, %e\n", a1[0], a1[1], b1[0], b1[1]);
+ printf("a2 %e, %e -- b2 %e, %e\n", a2[0], a2[1], b2[0], b2[1]);
+ if((Ta < -epsilon) || (Ta > 1+epsilon))
+ printf("Ta %.12e\n", Ta);
+ if((Tb < -epsilon) || (Tb > 1+epsilon))
+ printf("Tb %.12e\n", Tb);
+ printf("A1 %e, %e, %e -- B1 %e, %e, %e\n", A1[0], A1[1], A1[2], B1[0], B1[1], B1[2]);
+ printf("A2 %e, %e, %e -- B2 %e, %e, %e\n", A2[0], A2[1], A2[2], B2[0], B2[1], B2[2]);
+ }
+#endif
+
+ TVertex * tvertex = ioViewMap->CreateTVertex(Vec3r(A1 + Ta*(A2-A1)), Vec3r(a1 + ta*(a2-a1)), fA,
+ Vec3r(B1 + Tb*(B2-B1)), Vec3r(b1 + tb*(b2-b1)), fB, id);
+
+ (*i)->userdata = tvertex;
+ ++id;
+ }
+
+ progressBarStep = 0;
+
+ if(progressBarDisplay) {
+ unsigned iEdgesSize = iedges.size();
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, iEdgesSize);
+ progressBarStep = iEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Splitting intersected edges");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ }
+
+ counter = progressBarStep;
+
+ vector<TVertex*> edgeVVertices;
+ vector<ViewEdge*> newVEdges;
+ vector<segment* >::iterator s, send;
+ for(s=iedges.begin(),send=iedges.end();
+ s!=send;
+ s++)
+ {
+ edgeVVertices.clear();
+ newEdges.clear();
+ newVEdges.clear();
+
+ FEdge* fedge = (*s)->edge();
+ ViewEdge *vEdge = fedge->viewedge();
+ ViewShape *shape = vEdge->viewShape();
+
+ vector<intersection*>& eIntersections = (*s)->intersections();
+ // we first need to sort these intersections from farther to closer to A
+ sort(eIntersections.begin(), eIntersections.end(), less_Intersection(*s));
+ for(i=eIntersections.begin(),iend=eIntersections.end();
+ i!=iend;
+ i++)
+ edgeVVertices.push_back((TVertex*)(*i)->userdata);
+
+ shape->SplitEdge(fedge, edgeVVertices, ioViewMap->FEdges(), ioViewMap->ViewEdges());
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ }
+
+ // reset userdata:
+ for(fe=ioEdges.begin(), fend=ioEdges.end();
+ fe!=fend;
+ fe++)
+ (*fe)->userdata = NULL;
+
+ // delete segments
+ if(!segments.empty()){
+ for(s=segments.begin(),send=segments.end();
+ s!=send;
+ s++){
+ delete *s;
+ }
+ }
+}
+
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
new file mode 100755
index 00000000000..a41df92062e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
@@ -0,0 +1,248 @@
+//
+// Filename : ViewMapBuilder.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build silhouette edges from a
+// Winged-Edge structure
+// Date of creation : 25/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPBUILDER_H
+# define VIEWMAPBUILDER_H
+
+# include "Silhouette.h"
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../scene_graph/NodeGroup.h"
+# include "../winged_edge/WXEdge.h"
+# include "../geometry/GeomUtils.h"
+# include "../geometry/Grid.h"
+# include "../system/ProgressBar.h"
+# include "../system/RenderMonitor.h"
+# include "../geometry/SweepLine.h"
+# include "ViewMap.h"
+# include "SilhouetteGeomEngine.h"
+# include "../scene_graph/TriangleRep.h"
+# include "../winged_edge/WEdge.h"
+# include "ViewEdgeXBuilder.h"
+# include "../system/TimeUtils.h"
+# include "GridDensityProvider.h"
+
+using namespace Geometry;
+
+class LIB_VIEW_MAP_EXPORT ViewMapBuilder
+{
+private:
+
+ ViewMap * _ViewMap; // result
+ //SilhouetteGeomEngine _GeomEngine;
+ ProgressBar *_pProgressBar;
+ RenderMonitor *_pRenderMonitor;
+ Vec3r _viewpoint;
+ bool _orthographicProjection;
+ Grid* _Grid;
+ ViewEdgeXBuilder *_pViewEdgeBuilder;
+ bool _EnableQI;
+ double _epsilon;
+
+
+ // tmp values:
+ int _currentId;
+ int _currentFId;
+ int _currentSVertexId;
+
+
+public:
+
+ typedef enum {
+ sweep_line
+ } intersection_algo;
+
+ typedef enum {
+ ray_casting,
+ ray_casting_fast,
+ ray_casting_very_fast,
+ ray_casting_culled_adaptive_traditional,
+ ray_casting_adaptive_traditional,
+ ray_casting_culled_adaptive_cumulative,
+ ray_casting_adaptive_cumulative
+ } visibility_algo;
+
+ inline ViewMapBuilder()
+ {
+ _pProgressBar = 0;
+ _pRenderMonitor = 0;
+ _Grid = 0;
+ _currentId = 1;
+ _currentFId = 0;
+ _currentSVertexId = 0;
+ _pViewEdgeBuilder = new ViewEdgeXBuilder;
+ _EnableQI = true;
+ }
+
+ inline ~ViewMapBuilder()
+ {
+ if(_pViewEdgeBuilder){
+ delete _pViewEdgeBuilder;
+ _pViewEdgeBuilder = 0;
+ }
+ }
+
+ /* Build Grid for ray casting */
+ /*! Build non-culled Grid in camera space for ray casting */
+ void BuildGrid(WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces);
+
+ /*! Compute Shapes from a WingedEdge containing a list of WShapes */
+ void computeInitialViewEdges(WingedEdge&);
+
+ /*! Compute Cusps */
+ void computeCusps(ViewMap *ioViewMap);
+ /*! Detects cusps (for a single ViewEdge) among SVertices and builds a ViewVertex on top of
+ * each cusp SVertex
+ * We use a hysteresis approach to avoid noise.
+ */
+ void DetectCusps(ViewEdge *ioEdge);
+
+
+ /*! Sets the current viewpoint */
+ inline void setViewpoint(const Vec3r& ivp) {_viewpoint = ivp; SilhouetteGeomEngine::setViewpoint(ivp);}
+
+ /*! Sets the current transformation
+ * iModelViewMatrix
+ * The 4x4 model view matrix, in column major order (openGL like).
+ * iProjection matrix
+ * The 4x4 projection matrix, in column major order (openGL like).
+ * iViewport
+ * The viewport. 4 real array: origin.x, origin.y, width, length
+ */
+ inline void setTransform(const real iModelViewMatrix[4][4],
+ const real iProjectionMatrix[4][4],
+ const int iViewport[4],
+ real iFocalLength,
+ real iAspect,
+ real iFovy) {
+ _orthographicProjection = (iProjectionMatrix[3][3] != 0.0);
+ SilhouetteGeomEngine::setTransform(iModelViewMatrix, iProjectionMatrix, iViewport, iFocalLength);
+ }
+
+ inline void setFrustum(real iZnear, real iZfar) {
+ SilhouetteGeomEngine::setFrustum(iZnear, iZfar);
+ }
+
+ /*! Builds the scene view map
+ * returns the list the view map
+ * it is up to the caller to delete this ViewMap
+ * iWRoot
+ * The root group node containing the WEdge structured scene
+ */
+
+ ViewMap* BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon,
+ const BBox<Vec3r>& bbox, unsigned int sceneNumFaces);
+ void CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], real occluderProscenium[4], bool extensiveFEdgeSearch = true);
+ /*! computes the intersection between all 2D
+ * feature edges of the scene.
+ * ioViewMap
+ * The view map. It is modified by the method.
+ * The list of all features edges of the scene.
+ * Each time an intersection is found, the 2 intersecting
+ * edges are splitted (creating 2 new vertices)
+ * At the end, this list is updated with the adding
+ * of all new created edges (resulting from splitting).
+ * iAlgo
+ * The algo to use for computing the intersections
+ */
+ void ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo = sweep_line, real epsilon=1e-06);
+
+ /*! Computes the 2D scene silhouette edges visibility
+ * iGrid
+ * For the Ray Casting algorithm.
+ */
+ void ComputeEdgesVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces,
+ visibility_algo iAlgo= ray_casting, real epsilon=1e-6);
+
+ void setGrid(Grid *iGrid) {_Grid = iGrid;}
+
+ /*! accessors */
+
+ /*! Modifiers */
+ inline void setProgressBar(ProgressBar *iProgressBar) {_pProgressBar = iProgressBar;}
+ inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {_pRenderMonitor = iRenderMonitor;}
+ inline void setEnableQI(bool iBool) {_EnableQI = iBool;}
+
+protected:
+
+ /*! Computes intersections on all edges of the scene using a sweep line
+ * algorithm*/
+ void ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon = 1e-6);
+
+ /*! Computes the 2D scene silhouette edges visibility
+ * using a ray casting. On each edge, a ray is cast
+ * to check its quantitative invisibility. The list
+ * of occluders are each time stored in the tested edge.
+ * ioViewMap
+ * The view map.
+ * The 2D scene silhouette edges as FEdges.
+ * These edges have already been splitted at their intersections points.
+ * Thus, these edges do not intersect anymore.
+ * The visibility corresponding to each edge of ioScene is set is this
+ * edge.
+ */
+ void ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilon=1e-6);
+ void ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon=1e-6);
+ void ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon=1e-6);
+
+void ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge& we,
+ const BBox<Vec3r>& bbox, real epsilon, bool cull, GridDensityProviderFactory& factory);
+void ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& we,
+ const BBox<Vec3r>& bbox, real epsilon, bool cull, GridDensityProviderFactory& factory);
+
+ /*! Compute the visibility for the FEdge fe.
+ * The occluders are added to fe occluders list.
+ * fe
+ * The FEdge
+ * iGrid
+ * The grid used to compute the ray casting visibility
+ * epsilon
+ * The epsilon used for computation
+ * oShapeId
+ * fe is the border (in 2D) between 2 2D spaces.
+ * if fe is a silhouette,
+ * One of these 2D spaces is occupied by the shape
+ * to which fe belongs (on its left) and the other one is either occupied
+ * by another shape or empty or occupied by the same shape.
+ * We use this ray csating operation to determine which shape
+ * lies on fe's right.
+ * The result is the shape id stored in oShapeId
+ */
+ int ComputeRayCastingVisibility(FEdge *fe, Grid* iGrid, real epsilon, set<ViewShape*>& oOccluders,
+ Polygon3r** oaPolygon, unsigned timestamp);
+ // FIXME
+ void FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp);
+ void FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp,
+ Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices);
+
+};
+
+#endif // VIEWMAPBUILDER_H
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
new file mode 100755
index 00000000000..f99a574766b
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
@@ -0,0 +1,1245 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewMapIO.h"
+
+#ifdef IRIX
+# define WRITE(n) Internal::write<sizeof((n))>(out, (const char*)(&(n)))
+# define READ(n) Internal::read<sizeof((n))>(in, (char*)(&(n)))
+#else
+# define WRITE(n) out.write((const char*)(&(n)), sizeof((n)))
+# define READ(n) in.read((char*)(&(n)), sizeof((n)))
+#endif
+
+#define WRITE_IF_NON_NULL(ptr) if ((ptr) == NULL) { WRITE(ZERO); } else { WRITE((ptr)->userdata); }
+#define READ_IF_NON_NULL(ptr, array) READ(tmp); if (tmp == ZERO) { (ptr) = NULL; } else { (ptr) = (array)[tmp]; }
+
+namespace ViewMapIO {
+
+ namespace Internal {
+
+ ViewMap* g_vm;
+
+ //////////////////// 'load' Functions ////////////////////
+
+ inline
+ int load(istream& in, Vec3r& v) {
+
+ if (Options::getFlags() & Options::FLOAT_VECTORS) {
+ float tmp;
+ READ(tmp);
+ v[0] = tmp;
+ READ(tmp);
+ v[1] = tmp;
+ READ(tmp);
+ v[2] = tmp;
+ } else {
+ Vec3r::value_type tmp;
+ READ(tmp);
+ v[0] = tmp;
+ READ(tmp);
+ v[1] = tmp;
+ READ(tmp);
+ v[2] = tmp;
+ }
+ return 0;
+ }
+
+
+ inline
+ int load(istream& in, Polygon3r& p) {
+
+ unsigned tmp;
+
+ // Id
+ READ(tmp);
+ p.setId(tmp);
+
+ // vertices (List)
+ vector<Vec3r> tmp_vec;
+ Vec3r v;
+ READ(tmp);
+ for (unsigned i = 0; i < tmp; i++) {
+ load(in, v);
+ tmp_vec.push_back(v);
+ }
+ p.setVertices(tmp_vec);
+
+ // min & max
+ // Already computed (in the SetVertices() method)
+
+ return 0;
+ }
+
+
+ inline
+ int load(istream& in, FrsMaterial& m) {
+
+ float tmp_array[4];
+ int i;
+
+ // Diffuse
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.setDiffuse(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Specular
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.setSpecular(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Ambient
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.setAmbient(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Emission
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.setEmission(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Shininess
+ READ(tmp_array[0]);
+ m.setShininess(tmp_array[0]);
+
+ return 0;
+ }
+
+
+ int load(istream& in, ViewShape* vs) {
+
+ if (!vs || !vs->sshape())
+ return 1;
+
+ // SShape
+
+ // -> Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ vs->sshape()->setId(Id(id1, id2));
+
+ // -> Importance
+ float importance;
+ READ(importance);
+ vs->sshape()->setImportance(importance);
+
+ // -> BBox
+ // Not necessary (only used during view map computatiom)
+
+ unsigned i, size, tmp;
+
+ // -> Material
+ READ(size);
+ vector<FrsMaterial> frs_materials;
+ FrsMaterial m;
+ for(i=0; i<size; ++i){
+ load(in, m);
+ frs_materials.push_back(m);
+ }
+ vs->sshape()->setFrsMaterials(frs_materials);
+
+
+
+ // -> VerticesList (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ SVertex* sv;
+ READ_IF_NON_NULL(sv, g_vm->SVertices());
+ vs->sshape()->AddNewVertex(sv);
+ }
+
+ // -> Chains (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ FEdge* fe;
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ vs->sshape()->AddChain(fe);
+ }
+
+ // -> EdgesList (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ FEdge* fe;
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ vs->sshape()->AddEdge(fe);
+ }
+
+ // ViewEdges (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ ViewEdge* ve;
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ vs->AddEdge(ve);
+ }
+
+ // ViewVertices (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ ViewVertex* vv;
+ READ_IF_NON_NULL(vv, g_vm->ViewVertices());
+ vs->AddVertex(vv);
+ }
+
+ return 0;
+ }
+
+
+ int load(istream& in, FEdge* fe) {
+
+ if (!fe)
+ return 1;
+
+ bool b;
+
+ FEdgeSmooth *fesmooth = 0;
+ FEdgeSharp * fesharp = 0;
+ if(fe->isSmooth()){
+ fesmooth = dynamic_cast<FEdgeSmooth*>(fe);
+ }else{
+ fesharp = dynamic_cast<FEdgeSharp*>(fe);
+ }
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ fe->setId(Id(id1, id2));
+
+ // Nature
+ Nature::EdgeNature nature;
+ READ(nature);
+ fe->setNature(nature);
+
+ // hasVisibilityPoint
+ // bool b;
+ // READ(b);
+ // fe->setHasVisibilityPoint(b);
+
+ Vec3r v;
+ unsigned int matindex;
+
+ // VisibilityPointA
+ // load(in, v);
+ // fe->setVisibilityPointA(v);
+
+ // VisibilityPointB
+ // load(in, v);
+ // fe->setVisibilityPointB(v);
+
+ if(fe->isSmooth()){
+ // Normal
+ load(in, v);
+ fesmooth->setNormal(v);
+
+ // Material
+ READ(matindex);
+ fesmooth->setFrsMaterialIndex(matindex);
+ }else{
+ // aNormal
+ load(in, v);
+ fesharp->setNormalA(v);
+
+ // bNormal
+ load(in, v);
+ fesharp->setNormalB(v);
+
+ // Materials
+ READ(matindex);
+ fesharp->setaFrsMaterialIndex(matindex);
+ READ(matindex);
+ fesharp->setbFrsMaterialIndex(matindex);
+ }
+
+ unsigned tmp;
+
+ // VertexA
+ SVertex* sva;
+ READ_IF_NON_NULL(sva, g_vm->SVertices());
+ fe->setVertexA(sva);
+
+ // VertexB
+ SVertex* svb;
+ READ_IF_NON_NULL(svb, g_vm->SVertices());
+ fe->setVertexB(svb);
+
+ // NextEdge
+ FEdge* nfe;
+ READ_IF_NON_NULL(nfe, g_vm->FEdges());
+ fe->setNextEdge(nfe);
+
+ // PreviousEdge
+ FEdge* pfe;
+ READ_IF_NON_NULL(pfe, g_vm->FEdges());
+ fe->setPreviousEdge(pfe);
+
+ // ViewEdge
+ ViewEdge* ve;
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ fe->setViewEdge(ve);
+
+ // Face
+ // Not necessary (only used during view map computatiom)
+
+ Polygon3r p;
+
+ // aFace
+ load(in, p);
+ fe->setaFace(p);
+
+ // occludeeEmpty
+ READ(b);
+ fe->setOccludeeEmpty(b);
+
+ // occludeeIntersection
+ load(in, v);
+ fe->setOccludeeIntersection(v);
+
+ return 0;
+ }
+
+
+ int load(istream& in, SVertex* sv) {
+
+ if (!sv)
+ return 1;
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ sv->setId(Id(id1, id2));
+
+ Vec3r v;
+
+ // Point3D
+ load(in, v);
+ sv->setPoint3D(v);
+
+ // Point2D
+ load(in, v);
+ sv->setPoint2D(v);
+
+ unsigned tmp;
+
+ // Shape
+ ViewShape* vs;
+ READ_IF_NON_NULL(vs, g_vm->ViewShapes());
+ sv->setShape(vs->sshape());
+
+ // pViewVertex
+ ViewVertex* vv;
+ READ_IF_NON_NULL(vv, g_vm->ViewVertices());
+ sv->setViewVertex(vv);
+
+ unsigned i, size;
+
+ // Normals (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ load(in, v);
+ sv->AddNormal(v);
+ }
+
+ // FEdges (List)
+ READ(size);
+ FEdge* fe;
+ for (i = 0; i < size; i++) {
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ sv->AddFEdge(fe);
+ }
+
+ return 0;
+ }
+
+
+ int load(istream& in, ViewEdge* ve) {
+
+ if (!ve)
+ return 1;
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ ve->setId(Id(id1, id2));
+
+ // Nature
+ Nature::EdgeNature nature;
+ READ(nature);
+ ve->setNature(nature);
+
+ // QI
+ READ(tmp);
+ ve->setQI(tmp);
+
+ // Shape
+ ViewShape* vs;
+ READ_IF_NON_NULL(vs, g_vm->ViewShapes());
+ ve->setShape(vs);
+
+ // aShape
+ ViewShape* avs;
+ READ_IF_NON_NULL(avs, g_vm->ViewShapes());
+ ve->setaShape(avs);
+
+ // FEdgeA
+ FEdge* fea;
+ READ_IF_NON_NULL(fea, g_vm->FEdges());
+ ve->setFEdgeA(fea);
+
+ // FEdgeB
+ FEdge* feb;
+ READ_IF_NON_NULL(feb, g_vm->FEdges());
+ ve->setFEdgeB(feb);
+
+ // A
+ ViewVertex* vva;
+ READ_IF_NON_NULL(vva, g_vm->ViewVertices());
+ ve->setA(vva);
+
+ // B
+ ViewVertex* vvb;
+ READ_IF_NON_NULL(vvb, g_vm->ViewVertices());
+ ve->setB(vvb);
+
+ // Occluders (List)
+ if (!(Options::getFlags() & Options::NO_OCCLUDERS)) {
+ unsigned size;
+ READ(size);
+ ViewShape* vso;
+ for (unsigned i = 0; i < size; i++) {
+ READ_IF_NON_NULL(vso, g_vm->ViewShapes());
+ ve->AddOccluder(vso);
+ }
+ }
+
+ return 0;
+ }
+
+
+ int load(istream& in, ViewVertex* vv) {
+
+ if (!vv)
+ return 1;
+
+ unsigned tmp;
+ bool b;
+
+ // Nature
+ Nature::VertexNature nature;
+ READ(nature);
+ vv->setNature(nature);
+
+ if (vv->getNature() & Nature::T_VERTEX) {
+ TVertex* tv = dynamic_cast<TVertex*>(vv);
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ tv->setId(Id(id1, id2));
+
+ // FrontSVertex
+ SVertex* fsv;
+ READ_IF_NON_NULL(fsv, g_vm->SVertices());
+ tv->setFrontSVertex(fsv);
+
+ // BackSVertex
+ SVertex* bsv;
+ READ_IF_NON_NULL(bsv, g_vm->SVertices());
+ tv->setBackSVertex(bsv);
+
+ // FrontEdgeA
+ ViewEdge* fea;
+ READ_IF_NON_NULL(fea, g_vm->ViewEdges());
+ READ(b);
+ tv->setFrontEdgeA(fea, b);
+
+ // FrontEdgeB
+ ViewEdge* feb;
+ READ_IF_NON_NULL(feb, g_vm->ViewEdges());
+ READ(b);
+ tv->setFrontEdgeB(feb, b);
+
+ // BackEdgeA
+ ViewEdge* bea;
+ READ_IF_NON_NULL(bea, g_vm->ViewEdges());
+ READ(b);
+ tv->setBackEdgeA(bea, b);
+
+ // BackEdgeB
+ ViewEdge* beb;
+ READ_IF_NON_NULL(beb, g_vm->ViewEdges());
+ READ(b);
+ tv->setBackEdgeB(beb, b);
+ }
+ else if (vv->getNature() & Nature::NON_T_VERTEX) {
+ NonTVertex* ntv = dynamic_cast<NonTVertex*>(vv);
+
+ // SVertex
+ SVertex* sv;
+ READ_IF_NON_NULL(sv, g_vm->SVertices());
+ ntv->setSVertex(sv);
+
+ // ViewEdges (List)
+ unsigned size;
+ READ(size);
+ ViewEdge* ve;
+ for (unsigned i = 0; i < size; i++) {
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ READ(b);
+ ntv->AddViewEdge(ve, b);
+ }
+ }
+
+ return 0;
+ }
+
+ //////////////////// 'save' Functions ////////////////////
+
+ inline
+ int save(ostream& out, const Vec3r& v) {
+
+ if (Options::getFlags() & Options::FLOAT_VECTORS) {
+ float tmp;
+
+ tmp = v[0];
+ WRITE(tmp);
+ tmp = v[1];
+ WRITE(tmp);
+ tmp = v[2];
+ WRITE(tmp);
+ } else {
+ Vec3r::value_type tmp;
+
+ tmp = v[0];
+ WRITE(tmp);
+ tmp = v[1];
+ WRITE(tmp);
+ tmp = v[2];
+ WRITE(tmp);
+ }
+ return 0;
+ }
+
+
+ inline
+ int save(ostream& out, const Polygon3r& p) {
+
+ unsigned tmp;
+
+ // Id
+ tmp = p.getId();
+ WRITE(tmp);
+
+ // vertices (List)
+ tmp = p.getVertices().size();
+ WRITE(tmp);
+ for (vector<Vec3r>::const_iterator i = p.getVertices().begin();
+ i != p.getVertices().end(); i++) {
+ save(out, *i);
+ }
+
+ // min & max
+ // Do not need to be saved
+
+ return 0;
+ }
+
+
+ inline
+ int save(ostream& out, const FrsMaterial& m) {
+
+ unsigned i;
+
+ // Diffuse
+ for (i = 0; i < 4; i++)
+ WRITE(m.diffuse()[i]);
+
+ // Specular
+ for (i = 0; i < 4; i++)
+ WRITE(m.specular()[i]);
+
+ // Ambient
+ for (i = 0; i < 4; i++)
+ WRITE(m.ambient()[i]);
+
+ // Emission
+ for (i = 0; i < 4; i++)
+ WRITE(m.emission()[i]);
+
+ // Shininess
+ float shininess = m.shininess();
+ WRITE(shininess);
+
+ return 0;
+ }
+
+
+ int save(ostream& out, ViewShape* vs) {
+
+ if (!vs || !vs->sshape()) {
+ cerr << "Warning: null ViewShape" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // SShape
+
+ // -> Id
+ Id::id_type id = vs->sshape()->getId().getFirst();
+ WRITE(id);
+ id = vs->sshape()->getId().getSecond();
+ WRITE(id);
+
+ // -> Importance
+ float importance = vs->sshape()->importance();
+ WRITE(importance);
+
+ // -> BBox
+ // Not necessary (only used during view map computatiom)
+
+ // -> Material
+ unsigned size = vs->sshape()->frs_materials().size();
+ WRITE(size);
+ for(unsigned i=0; i<size; ++i)
+ save(out, vs->sshape()->frs_material(i));
+
+ // -> VerticesList (List)
+ tmp = vs->sshape()->getVertexList().size();
+ WRITE(tmp);
+ for (vector<SVertex*>::const_iterator i1 = vs->sshape()->getVertexList().begin();
+ i1 != vs->sshape()->getVertexList().end(); i1++)
+ WRITE_IF_NON_NULL(*i1);
+
+ // -> Chains (List)
+ tmp = vs->sshape()->getChains().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator i2 = vs->sshape()->getChains().begin();
+ i2 != vs->sshape()->getChains().end(); i2++)
+ WRITE_IF_NON_NULL(*i2);
+
+ // -> EdgesList (List)
+ tmp = vs->sshape()->getEdgeList().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator i3 = vs->sshape()->getEdgeList().begin();
+ i3 != vs->sshape()->getEdgeList().end(); i3++)
+ WRITE_IF_NON_NULL(*i3);
+
+ // ViewEdges (List)
+ tmp = vs->edges().size();
+ WRITE(tmp);
+ for (vector<ViewEdge*>::const_iterator i4 = vs->edges().begin();
+ i4 != vs->edges().end(); i4++)
+ WRITE_IF_NON_NULL(*i4);
+
+ // ViewVertices (List)
+ tmp = vs->vertices().size();
+ WRITE(tmp);
+ for (vector<ViewVertex*>::const_iterator i5 = vs->vertices().begin();
+ i5 != vs->vertices().end(); i5++)
+ WRITE_IF_NON_NULL(*i5);
+
+
+ return 0;
+ }
+
+
+ int save(ostream& out, FEdge* fe) {
+
+ if (!fe) {
+ cerr << "Warning: null FEdge" << endl;
+ return 1;
+ }
+
+ FEdgeSmooth * fesmooth = dynamic_cast<FEdgeSmooth*>(fe);
+ FEdgeSharp * fesharp = dynamic_cast<FEdgeSharp*>(fe);
+
+ // Id
+ Id::id_type id = fe->getId().getFirst();
+ WRITE(id);
+ id = fe->getId().getSecond();
+ WRITE(id);
+
+ // Nature
+ Nature::EdgeNature nature = fe->getNature();
+ WRITE(nature);
+
+ bool b;
+
+ // hasVisibilityPoint
+ // b = fe->hasVisibilityPoint();
+ // WRITE(b);
+
+ // VisibilityPointA
+ // save(out, fe->visibilityPointA());
+ //
+ // // VisibilityPointB
+ // save(out, fe->visibilityPointB());
+
+ unsigned index;
+ if(fe->isSmooth()){
+ // normal
+ save(out, fesmooth->normal());
+ // material
+ index = fesmooth->frs_materialIndex();
+ WRITE(index);
+ }else{
+ // aNormal
+ save(out, fesharp->normalA());
+ // bNormal
+ save(out, fesharp->normalB());
+ // aMaterial
+ index = fesharp->aFrsMaterialIndex();
+ WRITE(index);
+ // bMaterial
+ index = fesharp->bFrsMaterialIndex();
+ WRITE(index);
+ }
+
+
+ // VertexA
+ WRITE_IF_NON_NULL(fe->vertexA());
+
+ // VertexB
+ WRITE_IF_NON_NULL(fe->vertexB());
+
+ // NextEdge
+ WRITE_IF_NON_NULL(fe->nextEdge());
+
+ // PreviousEdge
+ WRITE_IF_NON_NULL(fe->previousEdge());
+
+ // ViewEdge
+ WRITE_IF_NON_NULL(fe->viewedge());
+
+ // Face
+ // Not necessary (only used during view map computatiom)
+
+ // aFace
+ save(out, (Polygon3r&)fe->aFace());
+
+ // occludeeEmpty
+ b = fe->getOccludeeEmpty();
+ WRITE(b);
+
+ // occludeeIntersection
+ save(out, fe->getOccludeeIntersection());
+
+ return 0;
+ }
+
+
+ int save(ostream& out, SVertex* sv) {
+
+ if (!sv) {
+ cerr << "Warning: null SVertex" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id = sv->getId().getFirst();
+ WRITE(id);
+ id = sv->getId().getSecond();
+ WRITE(id);
+
+ Vec3r v;
+
+ // Point3D
+ v = sv->point3D();
+ save(out, sv->point3D());
+
+ // Point2D
+ v = sv->point2D();
+ save(out, v);
+
+ // Shape
+ WRITE_IF_NON_NULL(sv->shape());
+
+ // pViewVertex
+ WRITE_IF_NON_NULL(sv->viewvertex());
+
+ // Normals (List)
+ // Note: the 'size()' method of a set doesn't seem to return the
+ // actual size of the given set, so we have to hack it...
+ set<Vec3r>::const_iterator i;
+ for (i = sv->normals().begin(), tmp = 0;
+ i != sv->normals().end();
+ i++, tmp++);
+ WRITE(tmp);
+ for (i = sv->normals().begin(); i != sv->normals().end(); i++)
+ save(out, *i);
+
+ // FEdges (List)
+ tmp = sv->fedges().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator j = sv->fedges_begin();
+ j != sv->fedges_end(); j++)
+ WRITE_IF_NON_NULL(*j);
+
+ return 0;
+ }
+
+
+ int save(ostream& out, ViewEdge* ve) {
+
+ if (!ve) {
+ cerr << "Warning: null ViewEdge" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id = ve->getId().getFirst();
+ WRITE(id);
+ id = ve->getId().getSecond();
+ WRITE(id);
+
+ // Nature
+ Nature::EdgeNature nature = ve->getNature();
+ WRITE(nature);
+
+ // QI
+ unsigned qi = ve->qi();
+ WRITE(qi);
+
+ // Shape
+ WRITE_IF_NON_NULL(ve->shape());
+
+ // aShape
+ WRITE_IF_NON_NULL(ve->aShape());
+
+ // FEdgeA
+ WRITE_IF_NON_NULL(ve->fedgeA());
+
+ // FEdgeB
+ WRITE_IF_NON_NULL(ve->fedgeB());
+
+ // A
+ WRITE_IF_NON_NULL(ve->A());
+
+ // B
+ WRITE_IF_NON_NULL(ve->B());
+
+ // Occluders (List)
+ if (!(Options::getFlags() & Options::NO_OCCLUDERS)) {
+ tmp = ve->occluders().size();
+ WRITE(tmp);
+ for (vector<ViewShape*>::const_iterator i = ve->occluders().begin();
+ i != ve->occluders().end(); i++)
+ WRITE_IF_NON_NULL((*i));
+ }
+
+ return 0;
+ }
+
+
+ int save(ostream& out, ViewVertex* vv) {
+
+ if (!vv) {
+ cerr << "Warning: null ViewVertex" << endl;
+ return 1;
+ }
+
+ // Nature
+ Nature::VertexNature nature = vv->getNature();
+ WRITE(nature);
+
+ if (vv->getNature() & Nature::T_VERTEX) {
+ TVertex* tv = dynamic_cast<TVertex*>(vv);
+
+ // Id
+ Id::id_type id = tv->getId().getFirst();
+ WRITE(id);
+ id = tv->getId().getSecond();
+ WRITE(id);
+
+ // FrontSVertex
+ WRITE_IF_NON_NULL(tv->frontSVertex());
+
+ // BackSVertex
+ WRITE_IF_NON_NULL(tv->backSVertex());
+
+ // FrontEdgeA
+ WRITE_IF_NON_NULL(tv->frontEdgeA().first);
+ WRITE(tv->frontEdgeA().second);
+
+ // FrontEdgeB
+ WRITE_IF_NON_NULL(tv->frontEdgeB().first);
+ WRITE(tv->frontEdgeB().second);
+
+ // BackEdgeA
+ WRITE_IF_NON_NULL(tv->backEdgeA().first);
+ WRITE(tv->backEdgeA().second);
+
+ // BackEdgeB
+ WRITE_IF_NON_NULL(tv->backEdgeB().first);
+ WRITE(tv->backEdgeB().second);
+
+ }
+ else if (vv->getNature() & Nature::NON_T_VERTEX) {
+ NonTVertex* ntv = dynamic_cast<NonTVertex*>(vv);
+
+ // SVertex
+ WRITE_IF_NON_NULL(ntv->svertex());
+
+ // ViewEdges (List)
+ unsigned size = ntv->viewedges().size();
+ WRITE(size);
+ vector<ViewVertex::directedViewEdge>::const_iterator i = ntv->viewedges().begin();
+ for ( ; i != ntv->viewedges().end(); i++){
+ WRITE_IF_NON_NULL(i->first);
+ WRITE(i->second);
+ }
+
+ } else {
+ cerr << "Warning: unexpected ViewVertex nature" << endl;
+ return 1;
+ }
+
+ return 0;
+ }
+
+ } // End of namespace Internal
+
+
+ //////////////////// "Public" 'load' and 'save' functions ////////////////////
+
+#define SET_PROGRESS(n) if (pb) pb->setProgress((n))
+
+ int load(istream& in, ViewMap* vm, ProgressBar* pb) {
+
+ if (!vm)
+ return 1;
+
+ //soc unused - unsigned tmp;
+
+ int err = 0;
+
+ Internal::g_vm = vm;
+
+ // Management of the progress bar (if present)
+ if (pb) {
+ pb->reset();
+ pb->setLabelText("Loading View Map...");
+ pb->setTotalSteps(6);
+ pb->setProgress(0);
+ }
+
+ // Read and set the options
+ unsigned char flags;
+ READ(flags);
+ Options::setFlags(flags);
+
+ // Read the size of the five ViewMap's lists (with some extra informations for the ViewVertices)
+ // and instantiate them (with default costructors)
+ unsigned vs_s, fe_s, fe_rle1, fe_rle2, sv_s, ve_s, vv_s, vv_rle1, vv_rle2;
+ READ(vs_s);
+ READ(fe_s);
+
+ if (fe_s) {
+ bool b;
+ READ(b);
+ for (READ(fe_rle1), fe_rle2 = 0;
+ fe_rle1 < fe_s+1;
+ fe_rle2 = fe_rle1, READ(fe_rle1)) {
+ if (b) {
+ for (unsigned i = fe_rle2; i < fe_rle1; i++) {
+ FEdgeSmooth * fes = new FEdgeSmooth;
+ vm->AddFEdge(fes);
+ }
+ b = !b;
+ }
+ else if (!b) {
+ for (unsigned i = fe_rle2; i < fe_rle1; i++) {
+ FEdgeSharp * fes = new FEdgeSharp;
+ vm->AddFEdge(fes);
+ }
+ b = !b;
+ }
+ }
+ }
+
+ READ(sv_s);
+ READ(ve_s);
+ READ(vv_s);
+
+ if (vv_s) {
+ Nature::VertexNature nature;
+ READ(nature);
+ for (READ(vv_rle1), vv_rle2 = 0;
+ vv_rle1 < vv_s+1;
+ vv_rle2 = vv_rle1, READ(vv_rle1)) {
+ if (nature & Nature::T_VERTEX) {
+ for (unsigned i = vv_rle2; i < vv_rle1; i++) {
+ TVertex* tv = new TVertex();
+ vm->AddViewVertex(tv);
+ }
+ nature = Nature::NON_T_VERTEX;
+ }
+ else if (nature & Nature::NON_T_VERTEX) {
+ for (unsigned i = vv_rle2; i < vv_rle1; i++) {
+ NonTVertex* ntv = new NonTVertex();
+ vm->AddViewVertex(ntv);
+ }
+ nature = Nature::T_VERTEX;
+ }
+ }
+ }
+
+ for (unsigned i0 = 0; i0 < vs_s; i0++) {
+ SShape* ss = new SShape();
+ ViewShape* vs = new ViewShape();
+ vs->setSShape(ss);
+ ss->setViewShape(vs);
+ vm->AddViewShape(vs);
+ }
+ // for (unsigned i1 = 0; i1 < fe_s; i1++) {
+ // FEdge* fe = new FEdge();
+ // vm->AddFEdge(fe);
+ // }
+ for (unsigned i2 = 0; i2 < sv_s; i2++) {
+ SVertex* sv = new SVertex();
+ vm->AddSVertex(sv);
+ }
+ for (unsigned i3 = 0; i3 < ve_s; i3++) {
+ ViewEdge* ve = new ViewEdge();
+ vm->AddViewEdge(ve);
+ }
+
+
+ // Read the values for all the objects created above
+ SET_PROGRESS(1);
+ for (vector<ViewShape*>::const_iterator i4 = vm->ViewShapes().begin();
+ i4 != vm->ViewShapes().end(); i4++)
+ err += Internal::load(in, *i4);
+ SET_PROGRESS(2);
+ for (vector<FEdge*>::const_iterator i5 = vm->FEdges().begin();
+ i5 != vm->FEdges().end(); i5++)
+ err += Internal::load(in, *i5);
+ SET_PROGRESS(3);
+ for (vector<SVertex*>::const_iterator i6 = vm->SVertices().begin();
+ i6 != vm->SVertices().end(); i6++)
+ err += Internal::load(in, *i6);
+ SET_PROGRESS(4);
+ for (vector<ViewEdge*>::const_iterator i7 = vm->ViewEdges().begin();
+ i7 != vm->ViewEdges().end(); i7++)
+ err += Internal::load(in, *i7);
+ SET_PROGRESS(5);
+ for (vector<ViewVertex*>::const_iterator i8 = vm->ViewVertices().begin();
+ i8 != vm->ViewVertices().end(); i8++)
+ err += Internal::load(in, *i8);
+ SET_PROGRESS(6);
+
+ // Read the shape id to index mapping
+ unsigned map_s;
+ READ(map_s);
+ unsigned id,index;
+ for(unsigned i4=0;i4<map_s;++i4){
+ READ(id);
+ READ(index);
+ vm->shapeIdToIndexMap()[id] = index;
+ }
+
+ return err;
+ }
+
+
+ int save(ostream& out, ViewMap* vm, ProgressBar* pb) {
+
+ if (!vm)
+ return 1;
+
+ int err = 0;
+
+ // Management of the progress bar (if present)
+ if (pb) {
+ pb->reset();
+ pb->setLabelText("Saving View Map...");
+ pb->setTotalSteps(6);
+ pb->setProgress(0);
+ }
+
+ // For every object, initialize its userdata member to its index in the ViewMap list
+ for (unsigned i0 = 0; i0 < vm->ViewShapes().size(); i0++) {
+ vm->ViewShapes()[i0]->userdata = (void*)i0;
+ vm->ViewShapes()[i0]->sshape()->userdata = (void*)i0;
+ }
+ for (unsigned i1 = 0; i1 < vm->FEdges().size(); i1++)
+ vm->FEdges()[i1]->userdata = (void*)i1;
+ for (unsigned i2 = 0; i2 < vm->SVertices().size(); i2++)
+ vm->SVertices()[i2]->userdata = (void*)i2;
+ for (unsigned i3 = 0; i3 < vm->ViewEdges().size(); i3++)
+ vm->ViewEdges()[i3]->userdata = (void*)i3;
+ for (unsigned i4 = 0; i4 < vm->ViewVertices().size(); i4++)
+ vm->ViewVertices()[i4]->userdata = (void*)i4;
+
+ // Write the current options
+ unsigned char flags = Options::getFlags();
+ WRITE(flags);
+
+ // Write the size of the five lists (with some extra informations for the ViewVertices)
+ unsigned size;
+ size = vm->ViewShapes().size();
+ WRITE(size);
+ size = vm->FEdges().size();
+ WRITE(size);
+ if (size) {
+ bool b = vm->FEdges()[0]->isSmooth();
+ WRITE(b);
+ for (unsigned i = 0; i < size; i++) {
+ while (i < size && (vm->FEdges()[i]->isSmooth() == b))
+ i++;
+ if (i < size) {
+ WRITE(i);
+ b = !b;
+ }
+ }
+ WRITE(size);
+ size++;
+ WRITE(size);
+ }
+ size = vm->SVertices().size();
+ WRITE(size);
+ size = vm->ViewEdges().size();
+ WRITE(size);
+ size = vm->ViewVertices().size();
+ WRITE(size);
+ if (size) {
+ Nature::VertexNature nature = vm->ViewVertices()[0]->getNature();
+ WRITE(nature);
+ nature &= ~Nature::VIEW_VERTEX;
+ for (unsigned i = 0; i < size; i++) {
+ while (i < size && (vm->ViewVertices()[i]->getNature() & nature))
+ i++;
+ if (i < size) {
+ WRITE(i);
+ nature = vm->ViewVertices()[i]->getNature() & ~Nature::VIEW_VERTEX;
+ }
+ }
+ WRITE(size);
+ size++;
+ WRITE(size);
+ }
+
+
+ // Write all the elts of the ViewShapes List
+ SET_PROGRESS(1);
+ for (vector<ViewShape*>::const_iterator i5 = vm->ViewShapes().begin();
+ i5 != vm->ViewShapes().end(); i5++)
+ err += Internal::save(out, *i5);
+ SET_PROGRESS(2);
+ for (vector<FEdge*>::const_iterator i6 = vm->FEdges().begin();
+ i6 != vm->FEdges().end(); i6++)
+ err += Internal::save(out, *i6);
+ SET_PROGRESS(3);
+ for (vector<SVertex*>::const_iterator i7 = vm->SVertices().begin();
+ i7 != vm->SVertices().end(); i7++)
+ err += Internal::save(out, *i7);
+ SET_PROGRESS(4);
+ for (vector<ViewEdge*>::const_iterator i8 = vm->ViewEdges().begin();
+ i8 != vm->ViewEdges().end(); i8++)
+ err += Internal::save(out, *i8);
+ SET_PROGRESS(5);
+ for (vector<ViewVertex*>::const_iterator i9 = vm->ViewVertices().begin();
+ i9 != vm->ViewVertices().end(); i9++)
+ err += Internal::save(out, *i9);
+
+ // Write the shape id to index mapping
+ size = vm->shapeIdToIndexMap().size();
+ WRITE(size);
+ unsigned id,index;
+ for(ViewMap::id_to_index_map::iterator mit=vm->shapeIdToIndexMap().begin(), mitend=vm->shapeIdToIndexMap().end(); mit!=mitend; ++mit){
+ id = mit->first;
+ index = mit->second;
+ WRITE(id);
+ WRITE(index);
+ }
+
+ // Reset 'userdata' members
+ for (vector<ViewShape*>::const_iterator j0 = vm->ViewShapes().begin();
+ j0 != vm->ViewShapes().end(); j0++) {
+ (*j0)->userdata = 0;
+ (*j0)->sshape()->userdata = 0;
+ }
+ for (vector<FEdge*>::const_iterator j1 = vm->FEdges().begin();
+ j1 != vm->FEdges().end(); j1++)
+ (*j1)->userdata = 0;
+ for (vector<SVertex*>::const_iterator j2 = vm->SVertices().begin();
+ j2 != vm->SVertices().end(); j2++)
+ (*j2)->userdata = 0;
+ for (vector<ViewEdge*>::const_iterator j3 = vm->ViewEdges().begin();
+ j3 != vm->ViewEdges().end(); j3++)
+ (*j3)->userdata = 0;
+ for (vector<ViewVertex*>::const_iterator j4 = vm->ViewVertices().begin();
+ j4 != vm->ViewVertices().end(); j4++)
+ (*j4)->userdata = 0;
+ SET_PROGRESS(6);
+
+ return err;
+ }
+
+
+ //////////////////// Options ////////////////////
+
+ namespace Options {
+
+ namespace Internal {
+
+ static unsigned char g_flags = 0;
+ static string g_models_path;
+
+ } // End of namespace Internal
+
+ void setFlags(const unsigned char flags) {
+ Internal::g_flags = flags;
+ }
+
+ void addFlags(const unsigned char flags) {
+ Internal::g_flags |= flags;
+ }
+
+ void rmFlags(const unsigned char flags) {
+ Internal::g_flags &= ~flags;
+ }
+
+ unsigned char getFlags() {
+ return Internal::g_flags;
+ }
+
+ void setModelsPath(const string& path) {
+ Internal::g_models_path = path;
+ }
+
+ string getModelsPath() {
+ return Internal::g_models_path;
+ }
+
+ }; // End of namepace Options
+
+} // End of namespace ViewMapIO
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.h b/source/blender/freestyle/intern/view_map/ViewMapIO.h
new file mode 100755
index 00000000000..185841a90ec
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIO.h
@@ -0,0 +1,116 @@
+//
+// Filename : ViewMapIO.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Functions to manage I/O for the view map
+// Date of creation : 09/01/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPIO_H
+# define VIEWMAPIO_H
+
+# include "ViewMap.h"
+# include <fstream>
+# include <string>
+# include "../system/FreestyleConfig.h"
+# include "../system/ProgressBar.h"
+
+namespace ViewMapIO {
+
+ static const unsigned ZERO = UINT_MAX;
+
+ LIB_VIEW_MAP_EXPORT
+ int load(istream& in, ViewMap* vm, ProgressBar* pb = NULL);
+
+ LIB_VIEW_MAP_EXPORT
+ int save(ostream& out, ViewMap* vm, ProgressBar* pb = NULL);
+
+ namespace Options {
+
+ static const unsigned char FLOAT_VECTORS = 1;
+ static const unsigned char NO_OCCLUDERS = 2;
+
+ LIB_VIEW_MAP_EXPORT
+ void setFlags(const unsigned char flags);
+
+ LIB_VIEW_MAP_EXPORT
+ void addFlags(const unsigned char flags);
+
+ LIB_VIEW_MAP_EXPORT
+ void rmFlags(const unsigned char flags);
+
+ LIB_VIEW_MAP_EXPORT
+ unsigned char getFlags();
+
+ LIB_VIEW_MAP_EXPORT
+ void setModelsPath(const string& path);
+
+ LIB_VIEW_MAP_EXPORT
+ string getModelsPath();
+
+ }; // End of namepace Options
+
+# ifdef IRIX
+
+ namespace Internal {
+
+ template <unsigned S>
+ ostream& write(ostream& out, const char* str) {
+ out.put(str[S - 1]);
+ return write<S - 1>(out, str);
+ }
+
+ template<>
+ ostream& write<1>(ostream& out, const char* str) {
+ return out.put(str[0]);
+ }
+
+ template<>
+ ostream& write<0>(ostream& out, const char*) {
+ return out;
+ }
+
+ template <unsigned S>
+ istream& read(istream& in, char* str) {
+ in.get(str[S - 1]);
+ return read<S - 1>(in, str);
+ }
+
+ template<>
+ istream& read<1>(istream& in, char* str) {
+ return in.get(str[0]);
+ }
+
+ template<>
+ istream& read<0>(istream& in, char*) {
+ return in;
+ }
+
+ } // End of namespace Internal
+
+# endif // IRIX
+
+} // End of namespace ViewMapIO
+
+#endif // VIEWMAPIO_H
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIterators.h b/source/blender/freestyle/intern/view_map/ViewMapIterators.h
new file mode 100755
index 00000000000..789aec0d5c3
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIterators.h
@@ -0,0 +1,549 @@
+//
+// Filename : ViewMapIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the various elements
+// of the ViewMap
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPITERATORS_H
+# define VIEWMAPITERATORS_H
+
+#include "ViewMap.h"
+#include "../system/Iterator.h" //soc
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewMap */
+ /* */
+ /* */
+ /**********************************/
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewVertex */
+ /* */
+ /* */
+ /**********************************/
+
+namespace ViewVertexInternal{
+
+ /*! Class representing an iterator over oriented ViewEdges
+ * around a ViewVertex. This iterator allows a CCW iteration
+ * (in the image plane).
+ * An instance of an orientedViewEdgeIterator can only
+ * be obtained from a ViewVertex by calling edgesBegin() or edgesEnd().
+ */
+ class orientedViewEdgeIterator : public Iterator
+ {
+ public:
+ friend class ViewVertex;
+ friend class TVertex;
+ friend class NonTVertex;
+ friend class ViewEdge;
+
+ // FIXME
+ typedef ::TVertex::edge_pointers_container edge_pointers_container;
+ typedef ::NonTVertex::edges_container edges_container;
+ protected:
+
+ Nature::VertexNature _Nature; // the nature of the underlying vertex
+ // T vertex attributes
+ edge_pointers_container::iterator _tbegin;
+ edge_pointers_container::iterator _tend;
+ edge_pointers_container::iterator _tvertex_iter;
+
+ // Non TVertex attributes
+ edges_container::iterator _begin;
+ edges_container::iterator _end;
+ edges_container::iterator _nontvertex_iter;
+
+ public:
+ /*! Default constructor */
+ inline orientedViewEdgeIterator() {}
+ inline orientedViewEdgeIterator(Nature::VertexNature iNature)
+ {_Nature = iNature;}
+ /*! Copy constructor */
+ orientedViewEdgeIterator(const orientedViewEdgeIterator& iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if(_Nature & Nature::T_VERTEX)
+ {
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else
+ {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+ virtual ~orientedViewEdgeIterator() {}
+
+ public:
+ inline orientedViewEdgeIterator(edge_pointers_container::iterator begin,
+ edge_pointers_container::iterator end,
+ edge_pointers_container::iterator iter)
+ {
+ _Nature = Nature::T_VERTEX;
+ _tbegin = begin;
+ _tend = end;
+ _tvertex_iter = iter;
+ }
+ inline orientedViewEdgeIterator(edges_container::iterator begin,
+ edges_container::iterator end,
+ edges_container::iterator iter)
+ {
+ _Nature = Nature::NON_T_VERTEX;
+ _begin = begin;
+ _end = end;
+ _nontvertex_iter = iter;
+ }
+
+ public:
+
+
+ /*! Tells whether the ViewEdge pointed
+ * by this iterator is the first one of the
+ * iteration list or not.
+ */
+ virtual bool isBegin() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tbegin);
+ else
+ return (_nontvertex_iter == _begin);
+ }
+ /*! Tells whether the ViewEdge pointed
+ * by this iterator is after the last one of the
+ * iteration list or not.
+ */
+ virtual bool isEnd() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tend);
+ else
+ return (_nontvertex_iter == _end);
+ }
+
+ // operators
+ /*! Increments.In the scripting language, call
+ * "increment()".
+ */
+ virtual orientedViewEdgeIterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ /*! Increments.In the scripting language, call
+ * "increment()".
+ */
+ virtual orientedViewEdgeIterator operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ orientedViewEdgeIterator tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ /*! operator != */
+ virtual bool operator!=(const orientedViewEdgeIterator& b) const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter != b._tvertex_iter);
+ else
+ return (_nontvertex_iter != b._nontvertex_iter);
+ }
+
+ /*! operator == */
+ virtual bool operator==(const orientedViewEdgeIterator& b) const
+ {return !(*this != b);}
+
+ // dereferencing
+ /*! Returns a reference to the pointed orientedViewEdge.
+ * In the scripting language, you must call
+ * "getObject()"instead.
+ */
+ virtual ::ViewVertex::directedViewEdge& operator*() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ //return _tvertex_iter;
+ return **_tvertex_iter;
+ else
+ return (*_nontvertex_iter);
+ }
+ /*! Returns a pointer to the pointed orientedViewEdge.
+ * Can't be called in the scripting language.
+ */
+ virtual ::ViewVertex::directedViewEdge* operator->() const { return &(operator*());}
+
+ public:
+ /*! increments.*/
+ virtual inline int increment()
+ {
+ if(_Nature & Nature::T_VERTEX)
+ {
+ ::ViewVertex::directedViewEdge tmp = (**_tvertex_iter);
+ ++_tvertex_iter;
+ if(_tvertex_iter != _tend){
+ // FIXME : pquoi deja ?
+ ::ViewVertex::directedViewEdge tmp2 = (**_tvertex_iter);
+ if(tmp2.first == tmp.first)
+ ++_tvertex_iter;
+ }
+ }
+ else
+ ++_nontvertex_iter;
+ return 0;
+ }
+ };
+
+ }
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+namespace ViewEdgeInternal {
+//
+// SVertexIterator
+//
+/////////////////////////////////////////////////
+
+ class SVertexIterator : public Interface0DIteratorNested
+ {
+ public:
+
+ SVertexIterator() {
+ _vertex = NULL;
+ _begin = NULL;
+ _previous_edge = NULL;
+ _next_edge = NULL;
+ _t = 0;
+ }
+
+ SVertexIterator(const SVertexIterator& vi) {
+ _vertex = vi._vertex;
+ _begin = vi._begin;
+ _previous_edge = vi._previous_edge;
+ _next_edge = vi._next_edge;
+ _t = vi._t;
+ }
+
+ SVertexIterator(SVertex* v, SVertex* begin, FEdge* prev, FEdge* next, float t) {
+ _vertex = v;
+ _begin = begin;
+ _previous_edge = prev;
+ _next_edge = next;
+ _t = t;
+ }
+
+ SVertexIterator& operator=(const SVertexIterator& vi) {
+ _vertex = vi._vertex;
+ _begin = vi._begin;
+ _previous_edge = vi._previous_edge;
+ _next_edge = vi._next_edge;
+ _t = vi._t;
+ return *this;
+ }
+
+ virtual ~SVertexIterator() {}
+
+ virtual string getExactTypeName() const {
+ return "SVertexIterator";
+ }
+
+ virtual SVertex& operator*() {
+ return *_vertex;
+ }
+
+ virtual SVertex* operator->() {
+ return &(operator*());
+ }
+
+ virtual SVertexIterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ virtual SVertexIterator operator++(int) {
+ SVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ virtual SVertexIterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ virtual SVertexIterator operator--(int) {
+ SVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ virtual int increment(){
+ if (!_next_edge) {
+ _vertex = 0;
+ return 0;
+ }
+ _t += (float)_next_edge->getLength2D();
+ _vertex = _next_edge->vertexB();
+ _previous_edge = _next_edge;
+ _next_edge = _next_edge->nextEdge();
+ return 0;
+
+ }
+ virtual int decrement(){
+ if (!_previous_edge) {
+ _vertex = 0;
+ return 0;
+ }
+ if((!_next_edge) && (!_vertex)){
+ _vertex = _previous_edge->vertexB();
+ return 0;
+ }
+ _t -= (float)_previous_edge->getLength2D();
+ _vertex = _previous_edge->vertexA();
+ _next_edge = _previous_edge;
+ _previous_edge = _previous_edge->previousEdge();
+ return 0;
+ }
+
+ virtual bool isBegin() const {
+ return _vertex == _begin;
+ }
+
+ virtual bool isEnd() const {
+ return (!_vertex) || (_vertex == _begin && _previous_edge);
+ }
+
+ virtual float t() const {
+ return _t;
+ }
+ virtual float u() const {
+ return _t/(float)_next_edge->viewedge()->getLength2D();
+ }
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const {
+ const SVertexIterator* it_exact = dynamic_cast<const SVertexIterator*>(&it);
+ if (!it_exact)
+ return false;
+ return (_vertex == it_exact->_vertex);
+ }
+
+ virtual SVertexIterator* copy() const {
+ return new SVertexIterator(*this);
+ }
+
+ private:
+
+ SVertex* _vertex;
+ SVertex* _begin;
+ FEdge* _previous_edge;
+ FEdge* _next_edge;
+ float _t; // curvilinear abscissa
+ };
+
+
+
+//
+// ViewEdgeIterator (base class)
+//
+///////////////////////////////////////////////////////////
+
+ /*! Base class for iterators over ViewEdges of the ViewMap Graph.
+ * Basically the "increment()" operator of this class should
+ * be able to take the decision of "where" (on which ViewEdge) to go
+ * when pointing on a given ViewEdge.
+ * ::Caution::: the dereferencing operator returns a *pointer* to
+ * the pointed ViewEdge.
+ */
+class ViewEdgeIterator : public Iterator
+{
+public:
+
+ /*! Builds a ViewEdgeIterator from a starting ViewEdge and its orientation.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the
+ * ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding
+ * the ending ViewVertex of begin.
+ */
+ ViewEdgeIterator(ViewEdge* begin = 0, bool orientation = true) {
+ _orientation = orientation;
+ _edge = begin;
+ _begin = begin;
+ }
+
+ /*! Copy constructor */
+ ViewEdgeIterator(const ViewEdgeIterator& it) {
+ _orientation = it._orientation;
+ _edge = it._edge;
+ _begin = it._begin;
+ }
+
+ virtual ~ViewEdgeIterator() {}
+
+ /*! Returns the string "ViewEdgeIterator" */
+ virtual string getExactTypeName() const {
+ return "ViewEdgeIterator";
+ }
+
+ /*! Returns the current pointed ViewEdge. */
+ ViewEdge* getCurrentEdge() {
+ return _edge;
+ }
+
+ /*! Sets the current pointed ViewEdge. */
+ void setCurrentEdge(ViewEdge* edge) {
+ _edge = edge;
+ }
+
+ /*! Returns the first ViewEdge used for the iteration. */
+ ViewEdge* getBegin() {
+ return _begin;
+ }
+
+ /*! Sets the first ViewEdge used for the iteration. */
+ void setBegin(ViewEdge* begin) {
+ _begin = begin;
+ }
+
+ /*! Gets the orientation of the pointed ViewEdge in the iteration. */
+ bool getOrientation() const {
+ return _orientation;
+ }
+
+ /*! Sets the orientation of the pointed ViewEdge in the iteration. */
+ void setOrientation(bool orientation) {
+ _orientation = orientation;
+ }
+
+ /*! Changes the current orientation. */
+ void changeOrientation() {
+ _orientation = !_orientation;
+ }
+
+ /*! Returns a *pointer* to the pointed ViewEdge. */
+ virtual ViewEdge* operator*() {
+ return _edge;
+ }
+
+ virtual ViewEdge* operator->() {
+ return operator*();
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ virtual ViewEdgeIterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ virtual ViewEdgeIterator operator++(int) {
+ ViewEdgeIterator tmp(*this);
+ increment();
+ return tmp;
+ }
+
+ /*! increments. */
+ virtual int increment() {
+ cerr << "Warning: method increment() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ virtual ViewEdgeIterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ virtual ViewEdgeIterator operator--(int) {
+ ViewEdgeIterator tmp(*this);
+ decrement();
+ return tmp;
+ }
+
+ /*! decrements. */
+ virtual int decrement(){
+ cerr << "Warning: method decrement() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns true if the pointed ViewEdge is the
+ * first one used for the iteration.
+ */
+ virtual bool isBegin() const {
+ return _edge == _begin;
+ }
+
+ /*! Returns true if the pointed ViewEdge* equals 0.
+ */
+ virtual bool isEnd() const {
+ return !_edge;
+ }
+
+ /*! operator == */
+ virtual bool operator==(ViewEdgeIterator& it) const {
+ return _edge == it._edge;
+ }
+
+ /*! operator != */
+ virtual bool operator!=(ViewEdgeIterator& it) const {
+ return !(*this == it);
+ }
+
+protected:
+
+ bool _orientation;
+ ViewEdge* _edge;
+ ViewEdge* _begin;
+};
+
+} // end of namespace ViewEdgeInternal
+
+#endif // VIEWMAPITERATORS_H
+
diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp
new file mode 100755
index 00000000000..6041f527d17
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp
@@ -0,0 +1,36 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewMapTesselator.h"
+
+NodeGroup* ViewMapTesselator::Tesselate(ViewMap *iViewMap)
+{
+ if(0 == iViewMap->ViewEdges().size())
+ return NULL;
+
+ const vector<ViewEdge*>& viewedges = iViewMap->ViewEdges();
+ return Tesselate(viewedges.begin(), viewedges.end());
+}
+
+NodeGroup* ViewMapTesselator::Tesselate(WShape *)
+{
+ return NULL;
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
new file mode 100755
index 00000000000..0177dc630b8
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
@@ -0,0 +1,196 @@
+//
+// Filename : ViewMapTesselator.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build a Node Tree designed to be displayed
+// from a Silhouette View Map structure.
+// Date of creation : 26/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPTESSELATOR_H
+# define VIEWMAPTESSELATOR_H
+
+# include "Silhouette.h"
+# include "ViewMap.h"
+# include "../scene_graph/NodeShape.h"
+# include "../winged_edge/WEdge.h"
+# include "../scene_graph/NodeGroup.h"
+# include "../scene_graph/LineRep.h"
+# include "../scene_graph/OrientedLineRep.h"
+# include "../scene_graph/VertexRep.h"
+
+class NodeShape;
+class NodeGroup;
+class SShape;
+class WShape;
+
+class LIB_VIEW_MAP_EXPORT ViewMapTesselator
+{
+public:
+
+ inline ViewMapTesselator() {_nature = Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE;_FrsMaterial.setDiffuse(0,0,0,1);_overloadFrsMaterial=false;}
+ virtual ~ViewMapTesselator() {}
+
+ /*! Builds a set of lines rep contained under a
+ * a NodeShape, itself contained under a NodeGroup from a ViewMap
+ */
+ NodeGroup* Tesselate(ViewMap* iViewMap) ;
+
+ /*! Builds a set of lines rep contained under a
+ * a NodeShape, itself contained under a NodeGroup from a
+ * set of view edges
+ */
+ template<class ViewEdgesIterator>
+ NodeGroup* Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end) ;
+
+ /*! Builds a set of lines rep contained among a
+ * a NodeShape, from a WShape
+ */
+ NodeGroup* Tesselate(WShape* iWShape);
+
+
+ inline void setNature(Nature::EdgeNature iNature) {_nature = iNature;}
+ inline void setFrsMaterial(const FrsMaterial& iMaterial) {_FrsMaterial=iMaterial;_overloadFrsMaterial=true;}
+ inline Nature::EdgeNature nature() {return _nature;}
+ inline const FrsMaterial& frs_material() const {return _FrsMaterial;}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v) = 0;
+
+private:
+ Nature::EdgeNature _nature;
+ FrsMaterial _FrsMaterial;
+ bool _overloadFrsMaterial;
+};
+
+/*! Class to tesselate the 2D projected silhouette */
+class ViewMapTesselator2D : public ViewMapTesselator
+{
+public:
+ inline ViewMapTesselator2D() : ViewMapTesselator() {}
+ virtual ~ViewMapTesselator2D() {}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v)
+ {
+ iLine->AddVertex(v->point2D());
+ }
+};
+
+/*! Class to tesselate the 3D silhouette */
+class ViewMapTesselator3D : public ViewMapTesselator
+{
+public:
+ inline ViewMapTesselator3D() : ViewMapTesselator() {}
+ virtual ~ViewMapTesselator3D() {}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v)
+ {
+ iLine->AddVertex(v->point3D());
+ }
+};
+
+//
+// Implementation
+//
+///////////////////////////////////////////////
+
+template<class ViewEdgesIterator>
+NodeGroup * ViewMapTesselator::Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end)
+{
+ NodeGroup *group = new NodeGroup;
+ NodeShape *tshape = new NodeShape;
+ group->AddChild(tshape);
+ //tshape->frs_material().setDiffuse(0.f, 0.f, 0.f, 1.f);
+ tshape->setFrsMaterial(_FrsMaterial);
+
+ LineRep* line;
+
+
+ FEdge *firstEdge;
+ FEdge *nextFEdge, *currentEdge;
+
+ int id=0;
+ // for(vector<ViewEdge*>::const_iterator c=viewedges.begin(),cend=viewedges.end();
+ // c!=cend;
+ // c++)
+ for(ViewEdgesIterator c=begin, cend=end;
+ c!=cend;
+ c++)
+ {
+ // if((*c)->qi() > 0){
+ // continue;
+ // }
+ // if(!((*c)->nature() & (_nature)))
+ // continue;
+ //
+ firstEdge = (*c)->fedgeA();
+
+ // if(firstEdge->invisibility() > 0)
+ // continue;
+
+ line = new OrientedLineRep();
+ if(_overloadFrsMaterial)
+ line->setFrsMaterial(_FrsMaterial);
+
+ // there might be chains containing a single element
+ if(0 == (firstEdge)->nextEdge())
+ {
+ line->setStyle(LineRep::LINES);
+ // line->AddVertex((*c)->vertexA()->point3D());
+ // line->AddVertex((*c)->vertexB()->point3D());
+ AddVertexToLine(line, firstEdge->vertexA());
+ AddVertexToLine(line, firstEdge->vertexB());
+ }
+ else
+ {
+ line->setStyle(LineRep::LINE_STRIP);
+
+ //firstEdge = (*c);
+ nextFEdge = firstEdge;
+ currentEdge = firstEdge;
+ do
+ {
+ //line->AddVertex(nextFEdge->vertexA()->point3D());
+ AddVertexToLine(line, nextFEdge->vertexA());
+ currentEdge = nextFEdge;
+ nextFEdge = nextFEdge->nextEdge();
+ }while((nextFEdge != NULL) && (nextFEdge != firstEdge));
+ // Add the last vertex
+ //line->AddVertex(currentEdge->vertexB()->point3D());
+ AddVertexToLine(line, currentEdge->vertexB());
+
+ }
+
+ line->setId((*c)->getId().getFirst());
+ line->ComputeBBox();
+ tshape->AddRep(line);
+ id++;
+ }
+
+ return group;
+}
+
+#endif // VIEWMAPTESSELATOR_H
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
new file mode 100755
index 00000000000..f8854b11d7b
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
@@ -0,0 +1,646 @@
+/* GTS - Library for the manipulation of triangulated surfaces
+ * Copyright (C) 1999-2002 Ray Jones, Stéphane Popinet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cstdlib> // for malloc and free
+#include "Curvature.h"
+#include <math.h>
+#include <assert.h>
+#include "WEdge.h"
+#include "../system/FreestyleConfig.h"
+#include "../geometry/normal_cycle.h"
+#include <set>
+#include <stack>
+
+static bool angle_obtuse (WVertex * v, WFace * f)
+{
+ WOEdge * e;
+ f->getOppositeEdge (v, e);
+
+ Vec3r vec1(e->GetaVertex()->GetVertex()-v->GetVertex());
+ Vec3r vec2(e->GetbVertex()->GetVertex()-v->GetVertex());
+ return ((vec1 * vec2) < 0);
+}
+
+// FIXME
+// WVvertex is useless but kept for history reasons
+static bool triangle_obtuse (WVertex*, WFace * f)
+{
+ bool b=false;
+ for (int i=0; i<3; i++)
+ b = b ||
+ ((f->getEdgeList()[i]->GetVec() * f->getEdgeList()[(i+1)%3]->GetVec()) < 0);
+ return b;
+}
+
+static real cotan (WVertex * vo, WVertex * v1, WVertex * v2)
+{
+ /* cf. Appendix B of [Meyer et al 2002] */
+ real udotv, denom;
+
+ Vec3r u(v1->GetVertex()- vo->GetVertex());
+ Vec3r v(v2->GetVertex()- vo->GetVertex());
+
+ udotv = u * v;
+ denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv);
+
+ /* denom can be zero if u==v. Returning 0 is acceptable, based on
+ * the callers of this function below. */
+ if (denom == 0.0) return (0.0);
+
+ return (udotv / denom);
+}
+
+static real angle_from_cotan (WVertex * vo, WVertex * v1, WVertex * v2)
+{
+ /* cf. Appendix B and the caption of Table 1 from [Meyer et al 2002] */
+ real udotv, denom;
+
+ Vec3r u (v1->GetVertex()-vo->GetVertex());
+ Vec3r v(v2->GetVertex()-vo->GetVertex());
+
+ udotv = u * v;
+ denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv);
+
+ /* Note: I assume this is what they mean by using atan2 (). -Ray Jones */
+
+ /* tan = denom/udotv = y/x (see man page for atan2) */
+ return (fabs (atan2 (denom, udotv)));
+}
+
+/**
+ * gts_vertex_mean_curvature_normal:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kh: the Mean Curvature Normal at @v.
+ *
+ * Computes the Discrete Mean Curvature Normal approximation at @v.
+ * The mean curvature at @v is half the magnitude of the vector @Kh.
+ *
+ * Note: the normal computed is not unit length, and may point either
+ * into or out of the surface, depending on the curvature at @v. It
+ * is the responsibility of the caller of the function to use the mean
+ * curvature normal appropriately.
+ *
+ * This approximation is from the paper:
+ * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds
+ * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr
+ * VisMath '02, Berlin (Germany)
+ * http://www-grail.usc.edu/pubs.html
+ *
+ * Returns: %TRUE if the operator could be evaluated, %FALSE if the
+ * evaluation failed for some reason (@v is boundary or is the
+ * endpoint of a non-manifold edge.)
+ */
+bool gts_vertex_mean_curvature_normal (WVertex * v, Vec3r &Kh)
+{
+ real area = 0.0;
+
+ if (!v) return false;
+
+ /* this operator is not defined for boundary edges */
+ if (v->isBoundary()) return false;
+
+ WVertex::incoming_edge_iterator itE;
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ area+=(*itE)->GetaFace()->getArea();
+
+ Kh=Vec3r(0.0, 0.0, 0.0);
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ {
+ WOEdge * e = (*itE)->getPrevOnFace();
+ //if ((e->GetaVertex()==v) || (e->GetbVertex()==v)) cerr<< "BUG ";
+
+ WVertex * v1 = e->GetaVertex();
+ WVertex * v2 = e->GetbVertex();
+ real temp;
+
+ temp = cotan (v1, v, v2);
+ Kh = Vec3r(Kh+temp*(v2->GetVertex()-v->GetVertex()));
+
+ temp = cotan (v2, v, v1);
+ Kh = Vec3r(Kh+temp*(v1->GetVertex()-v->GetVertex()));
+ }
+ if (area > 0.0)
+ {
+ Kh[0] /= 2*area;
+ Kh[1] /= 2*area;
+ Kh[2] /= 2*area;
+ }
+ else return false;
+
+ return true;
+}
+
+/**
+ * gts_vertex_gaussian_curvature:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kg: the Discrete Gaussian Curvature approximation at @v.
+ *
+ * Computes the Discrete Gaussian Curvature approximation at @v.
+ *
+ * This approximation is from the paper:
+ * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds
+ * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr
+ * VisMath '02, Berlin (Germany)
+ * http://www-grail.usc.edu/pubs.html
+ *
+ * Returns: %TRUE if the operator could be evaluated, %FALSE if the
+ * evaluation failed for some reason (@v is boundary or is the
+ * endpoint of a non-manifold edge.)
+ */
+bool gts_vertex_gaussian_curvature (WVertex * v, real * Kg)
+{
+ real area = 0.0;
+ real angle_sum = 0.0;
+
+ if (!v) return false;
+ if (!Kg) return false;
+
+ /* this operator is not defined for boundary edges */
+ if (v->isBoundary()) {*Kg=0.0 ;return false;}
+
+ WVertex::incoming_edge_iterator itE;
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ area+=(*itE)->GetaFace()->getArea();
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ {
+ WOEdge * e = (*itE)->getPrevOnFace();
+ WVertex * v1 = e->GetaVertex();
+ WVertex * v2 = e->GetbVertex();
+ angle_sum += angle_from_cotan (v, v1, v2);
+ }
+
+ *Kg = (2.0*M_PI - angle_sum)/area;
+
+ return true;
+}
+
+/**
+ * gts_vertex_principal_curvatures:
+ * @Kh: mean curvature.
+ * @Kg: Gaussian curvature.
+ * @K1: first principal curvature.
+ * @K2: second principal curvature.
+ *
+ * Computes the principal curvatures at a point given the mean and
+ * Gaussian curvatures at that point.
+ *
+ * The mean curvature can be computed as one-half the magnitude of the
+ * vector computed by gts_vertex_mean_curvature_normal().
+ *
+ * The Gaussian curvature can be computed with
+ * gts_vertex_gaussian_curvature().
+ */
+void gts_vertex_principal_curvatures (real Kh, real Kg,
+ real * K1, real * K2)
+{
+ real temp = Kh*Kh - Kg;
+
+ if (!K1) return;
+ if (!K1) return;
+
+ if (temp < 0.0) temp = 0.0;
+ temp = sqrt (temp);
+ *K1 = Kh + temp;
+ *K2 = Kh - temp;
+}
+
+/* from Maple */
+static void linsolve (real m11, real m12, real b1,
+ real m21, real m22, real b2,
+ real * x1, real * x2)
+{
+ real temp;
+
+ temp = 1.0 / (m21*m12 - m11*m22);
+ *x1 = (m12*b2 - m22*b1)*temp;
+ *x2 = (m11*b2 - m21*b1)*temp;
+}
+
+/* from Maple - largest eigenvector of [a b; b c] */
+static void eigenvector (real a, real b, real c,
+ Vec3r e)
+{
+ if (b == 0.0) {
+ e[0] = 0.0;
+ } else {
+ e[0] = -(c - a - sqrt (c*c - 2*a*c + a*a + 4*b*b))/(2*b);
+ }
+ e[1] = 1.0;
+ e[2] = 0.0;
+}
+
+/**
+ * gts_vertex_principal_directions:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kh: mean curvature normal (a #Vec3r).
+ * @Kg: Gaussian curvature (a real).
+ * @e1: first principal curvature direction (direction of largest curvature).
+ * @e2: second principal curvature direction.
+ *
+ * Computes the principal curvature directions at a point given @Kh
+ * and @Kg, the mean curvature normal and Gaussian curvatures at that
+ * point, computed with gts_vertex_mean_curvature_normal() and
+ * gts_vertex_gaussian_curvature(), respectively.
+ *
+ * Note that this computation is very approximate and tends to be
+ * unstable. Smoothing of the surface or the principal directions may
+ * be necessary to achieve reasonable results.
+ */
+void gts_vertex_principal_directions (WVertex * v,
+ Vec3r Kh, real Kg,
+ Vec3r &e1, Vec3r &e2)
+{
+ Vec3r N;
+ real normKh;
+
+ Vec3r basis1, basis2, d, eig;
+ real ve2, vdotN;
+ real aterm_da, bterm_da, cterm_da, const_da;
+ real aterm_db, bterm_db, cterm_db, const_db;
+ real a, b, c;
+ real K1, K2;
+ real *weights, *kappas, *d1s, *d2s;
+ int edge_count;
+ real err_e1, err_e2;
+ int e;
+ WVertex::incoming_edge_iterator itE;
+
+ /* compute unit normal */
+ normKh = Kh.norm();
+
+ if (normKh > 0.0) {
+ Kh.normalize();
+ } else {
+ /* This vertex is a point of zero mean curvature (flat or saddle
+ * point). Compute a normal by averaging the adjacent triangles
+ */
+ N[0] = N[1] = N[2] = 0.0;
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ N=Vec3r(N+(*itE)->GetaFace()->GetNormal());
+ real normN = N.norm();
+ if (normN <= 0.0)
+ return;
+ N.normalize();
+ }
+
+
+ /* construct a basis from N: */
+ /* set basis1 to any component not the largest of N */
+ basis1[0] = basis1[1] = basis1[2] = 0.0;
+ if (fabs (N[0]) > fabs (N[1]))
+ basis1[1] = 1.0;
+ else
+ basis1[0] = 1.0;
+
+ /* make basis2 orthogonal to N */
+ basis2 = (N ^ basis1);
+ basis2.normalize();
+
+ /* make basis1 orthogonal to N and basis2 */
+ basis1 = (N ^ basis2);
+ basis1.normalize();
+
+ aterm_da = bterm_da = cterm_da = const_da = 0.0;
+ aterm_db = bterm_db = cterm_db = const_db = 0.0;
+ int nb_edges=v->GetEdges().size();
+
+ weights = (real *) malloc (sizeof (real)*nb_edges);
+ kappas = (real*) malloc (sizeof (real)*nb_edges);
+ d1s = (real*) malloc (sizeof (real)*nb_edges);
+ d2s = (real*) malloc (sizeof (real)*nb_edges);
+ edge_count = 0;
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ {
+ WOEdge * e;
+ WFace * f1, * f2;
+ real weight, kappa, d1, d2;
+ Vec3r vec_edge;
+ if (! *itE) continue;
+ e = *itE;
+
+ /* since this vertex passed the tests in
+ * gts_vertex_mean_curvature_normal(), this should be true. */
+ //g_assert (gts_edge_face_number (e, s) == 2);
+
+ /* identify the two triangles bordering e in s */
+ f1=e->GetaFace();
+ f2=e->GetbFace();
+
+ /* We are solving for the values of the curvature tensor
+ * B = [ a b ; b c ].
+ * The computations here are from section 5 of [Meyer et al 2002].
+ *
+ * The first step is to calculate the linear equations governing
+ * the values of (a,b,c). These can be computed by setting the
+ * derivatives of the error E to zero (section 5.3).
+ *
+ * Since a + c = norm(Kh), we only compute the linear equations
+ * for dE/da and dE/db. (NB: [Meyer et al 2002] has the
+ * equation a + b = norm(Kh), but I'm almost positive this is
+ * incorrect.)
+ *
+ * Note that the w_ij (defined in section 5.2) are all scaled by
+ * (1/8*A_mixed). We drop this uniform scale factor because the
+ * solution of the linear equations doesn't rely on it.
+ *
+ * The terms of the linear equations are xterm_dy with x in
+ * {a,b,c} and y in {a,b}. There are also const_dy terms that are
+ * the constant factors in the equations.
+ */
+
+ /* find the vector from v along edge e */
+ vec_edge=Vec3r(-1*e->GetVec());
+
+ ve2 = vec_edge.squareNorm();
+ vdotN = vec_edge * N;
+
+ /* section 5.2 - There is a typo in the computation of kappa. The
+ * edges should be x_j-x_i.
+ */
+ kappa = 2.0 * vdotN / ve2;
+
+ /* section 5.2 */
+
+ /* I don't like performing a minimization where some of the
+ * weights can be negative (as can be the case if f1 or f2 are
+ * obtuse). To ensure all-positive weights, we check for
+ * obtuseness. */
+ weight = 0.0;
+ if (! triangle_obtuse(v, f1)) {
+ weight += ve2 *
+ cotan (f1->GetNextOEdge(e->twin())->GetbVertex(),
+ e->GetaVertex(), e->GetbVertex()) / 8.0;
+ } else {
+ if (angle_obtuse (v, f1)) {
+ weight += ve2 * f1->getArea() / 4.0;
+ } else {
+ weight += ve2 * f1->getArea() / 8.0;
+ }
+ }
+
+ if (! triangle_obtuse(v, f2)) {
+ weight += ve2 *
+ cotan (f2->GetNextOEdge(e)->GetbVertex(),
+ e->GetaVertex(), e->GetbVertex()) / 8.0;
+ } else {
+ if (angle_obtuse (v, f2)) {
+ weight += ve2 * f1->getArea() / 4.0;
+ } else {
+ weight += ve2 * f1->getArea() / 8.0;
+ }
+ }
+
+ /* projection of edge perpendicular to N (section 5.3) */
+ d[0] = vec_edge[0] - vdotN * N[0];
+ d[1] = vec_edge[1] - vdotN * N[1];
+ d[2] = vec_edge[2] - vdotN * N[2];
+ d.normalize();
+
+ /* not explicit in the paper, but necessary. Move d to 2D basis. */
+ d1 = d * basis1;
+ d2 = d * basis2;
+
+ /* store off the curvature, direction of edge, and weights for later use */
+ weights[edge_count] = weight;
+ kappas[edge_count] = kappa;
+ d1s[edge_count] = d1;
+ d2s[edge_count] = d2;
+ edge_count++;
+
+ /* Finally, update the linear equations */
+ aterm_da += weight * d1 * d1 * d1 * d1;
+ bterm_da += weight * d1 * d1 * 2 * d1 * d2;
+ cterm_da += weight * d1 * d1 * d2 * d2;
+ const_da += weight * d1 * d1 * (- kappa);
+
+ aterm_db += weight * d1 * d2 * d1 * d1;
+ bterm_db += weight * d1 * d2 * 2 * d1 * d2;
+ cterm_db += weight * d1 * d2 * d2 * d2;
+ const_db += weight * d1 * d2 * (- kappa);
+
+ }
+
+ /* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */
+ aterm_da -= cterm_da;
+ const_da += cterm_da * normKh;
+
+ aterm_db -= cterm_db;
+ const_db += cterm_db * normKh;
+
+ /* check for solvability of the linear system */
+ if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) &&
+ ((const_da != 0.0) || (const_db != 0.0))) {
+ linsolve (aterm_da, bterm_da, -const_da,
+ aterm_db, bterm_db, -const_db,
+ &a, &b);
+
+ c = normKh - a;
+
+ eigenvector (a, b, c, eig);
+ } else {
+ /* region of v is planar */
+ eig[0] = 1.0;
+ eig[1] = 0.0;
+ }
+
+ /* Although the eigenvectors of B are good estimates of the
+ * principal directions, it seems that which one is attached to
+ * which curvature direction is a bit arbitrary. This may be a bug
+ * in my implementation, or just a side-effect of the inaccuracy of
+ * B due to the discrete nature of the sampling.
+ *
+ * To overcome this behavior, we'll evaluate which assignment best
+ * matches the given eigenvectors by comparing the curvature
+ * estimates computed above and the curvatures calculated from the
+ * discrete differential operators. */
+
+ gts_vertex_principal_curvatures (0.5 * normKh, Kg, &K1, &K2);
+
+ err_e1 = err_e2 = 0.0;
+ /* loop through the values previously saved */
+ for (e = 0; e < edge_count; e++) {
+ real weight, kappa, d1, d2;
+ real temp1, temp2;
+ real delta;
+
+ weight = weights[e];
+ kappa = kappas[e];
+ d1 = d1s[e];
+ d2 = d2s[e];
+
+ temp1 = fabs (eig[0] * d1 + eig[1] * d2);
+ temp1 = temp1 * temp1;
+ temp2 = fabs (eig[1] * d1 - eig[0] * d2);
+ temp2 = temp2 * temp2;
+
+ /* err_e1 is for K1 associated with e1 */
+ delta = K1 * temp1 + K2 * temp2 - kappa;
+ err_e1 += weight * delta * delta;
+
+ /* err_e2 is for K1 associated with e2 */
+ delta = K2 * temp1 + K1 * temp2 - kappa;
+ err_e2 += weight * delta * delta;
+ }
+ free (weights);
+ free (kappas);
+ free (d1s);
+ free (d2s);
+
+ /* rotate eig by a right angle if that would decrease the error */
+ if (err_e2 < err_e1) {
+ real temp = eig[0];
+
+ eig[0] = eig[1];
+ eig[1] = -temp;
+ }
+
+ e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0];
+ e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1];
+ e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2];
+ e1.normalize();
+
+ /* make N,e1,e2 a right handed coordinate sytem */
+ e2 = N ^ e1;
+ e2.normalize();
+}
+
+namespace OGF {
+ inline static real angle(WOEdge * h) {
+ const Vec3r& n1 = h->GetbFace()->GetNormal();
+ const Vec3r& n2 = h->GetaFace()->GetNormal();
+ const Vec3r v = h->getVec3r();
+ real sine = (n1 ^ n2) * v / v.norm() ;
+ if(sine >= 1.0) {
+ return M_PI / 2.0 ;
+ }
+ if(sine <= -1.0) {
+ return -M_PI / 2.0 ;
+ }
+ return ::asin(sine) ;
+ }
+
+ // precondition1: P is inside the sphere
+ // precondition2: P,V points to the outside of
+ // the sphere (i.e. OP.V > 0)
+ static bool sphere_clip_vector(
+ const Vec3r& O, real r,
+ const Vec3r& P, Vec3r& V
+ ) {
+
+ Vec3r W = P - O ;
+ real a = V.squareNorm() ;
+ real b = 2.0 * V * W ;
+ real c = W.squareNorm() - r*r ;
+ real delta = b*b - 4*a*c ;
+ if(delta < 0) {
+ // Should not happen, but happens sometimes (numerical precision)
+ return true ;
+ }
+ real t = - b + ::sqrt(delta) / (2.0 * a) ;
+ if(t < 0.0) {
+ // Should not happen, but happens sometimes (numerical precision)
+ return true ;
+ }
+ if(t >= 1.0) {
+ // Inside the sphere
+ return false ;
+ }
+
+ V[0] = (t * V.x()) ;
+ V[1] = (t * V.y()) ;
+ V[2] = (t * V.z()) ;
+
+ return true ;
+ }
+
+ // TODO: check optimizations:
+ // use marking ? (measure *timings* ...)
+ void compute_curvature_tensor(
+ WVertex* start, real radius, NormalCycle& nc
+ ) {
+ // in case we have a non-manifold vertex, skip it...
+ if(start->isBoundary())
+ return;
+
+ std::set<WVertex*> vertices ;
+ const Vec3r& O = start->GetVertex() ;
+ std::stack<WVertex*> S ;
+ S.push(start) ;
+ vertices.insert(start) ;
+ while(!S.empty()) {
+ WVertex* v = S.top() ;
+ S.pop() ;
+ if(v->isBoundary())
+ continue;
+ const Vec3r& P = v->GetVertex() ;
+ WVertex::incoming_edge_iterator woeit = v->incoming_edges_begin();
+ WVertex::incoming_edge_iterator woeitend = v->incoming_edges_end();
+ for(;woeit!=woeitend; ++woeit){
+ WOEdge *h = *woeit;
+ if((v == start) || h->GetVec() * (O - P) > 0.0) {
+ Vec3r V(-1 * h->GetVec());
+ bool isect = sphere_clip_vector(O, radius, P, V) ;
+ assert (h->GetOwner()->GetNumberOfOEdges() == 2); // Because otherwise v->isBoundary() would be true
+ nc.accumulate_dihedral_angle(V, h->GetAngle()) ;
+
+ if(!isect) {
+ WVertex* w = h->GetaVertex() ;
+ if(vertices.find(w) == vertices.end()) {
+ vertices.insert(w) ;
+ S.push(w) ;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ void compute_curvature_tensor_one_ring(
+ WVertex* start, NormalCycle& nc
+ ) {
+ // in case we have a non-manifold vertex, skip it...
+ if(start->isBoundary())
+ return;
+
+ WVertex::incoming_edge_iterator woeit = start->incoming_edges_begin();
+ WVertex::incoming_edge_iterator woeitend = start->incoming_edges_end();
+ for(;woeit!=woeitend; ++woeit){
+ WOEdge *h = (*woeit)->twin();
+ nc.accumulate_dihedral_angle(h->GetVec(), h->GetAngle()) ;
+ WOEdge *hprev = h->getPrevOnFace();
+ nc.accumulate_dihedral_angle(hprev->GetVec(), hprev->GetAngle()) ;
+ }
+ }
+
+}
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.h b/source/blender/freestyle/intern/winged_edge/Curvature.h
new file mode 100755
index 00000000000..214a32ca922
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.h
@@ -0,0 +1,156 @@
+
+/* GTS - Library for the manipulation of triangulated surfaces
+ * Copyright (C) 1999 Stéphane Popinet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __CURVATURE_H__
+#define __CURVATURE_H__
+
+# include "../system/FreestyleConfig.h"
+# include "../system/Precision.h"
+# include "../geometry/Geom.h"
+using namespace Geometry;
+
+class WVertex;
+
+class LIB_WINGED_EDGE_EXPORT CurvatureInfo
+{
+public:
+
+ CurvatureInfo()
+ {
+ K1 = 0.0;
+ K2 = 0.0;
+ e1 = Vec3r(0.0,0.0,0.0);
+ e2 = Vec3r(0.0,0.0,0.0);
+ Kr = 0.0;
+ dKr = 0.0;
+ er = Vec3r(0.0,0.0,0.0);
+ }
+
+ CurvatureInfo(const CurvatureInfo& iBrother){
+ K1 = iBrother.K1;
+ K2 = iBrother.K2;
+ e1 = iBrother.e1;
+ e2 = iBrother.e2;
+ Kr = iBrother.Kr;
+ dKr = iBrother.dKr;
+ er = iBrother.er;
+ }
+
+ CurvatureInfo(const CurvatureInfo& ca, const CurvatureInfo& cb, real t) {
+ K1 = ca.K1 + t * (cb.K1 - ca.K1);
+ K2 = ca.K2 + t * (cb.K2 - ca.K2);
+ e1 = ca.e1 + t * (cb.e1 - ca.e1);
+ e2 = ca.e2 + t * (cb.e2 - ca.e2);
+ Kr = ca.Kr + t * (cb.Kr - ca.Kr);
+ dKr = ca.dKr + t * (cb.dKr - ca.dKr);
+ er = ca.er + t * (cb.er - ca.er);
+ }
+
+ real K1; // maximum curvature
+ real K2; // minimum curvature
+ Vec3r e1; // maximum curvature direction
+ Vec3r e2; // minimum curvature direction
+ real Kr; // radial curvature
+ real dKr; // radial curvature
+ Vec3r er; // radial curvature direction
+};
+
+class Face_Curvature_Info{
+public:
+ Face_Curvature_Info() {}
+ ~Face_Curvature_Info(){
+ for(vector<CurvatureInfo*>::iterator ci=vec_curvature_info.begin(), ciend=vec_curvature_info.end();
+ ci!=ciend;
+ ++ci){
+ delete (*ci);
+ }
+ vec_curvature_info.clear();
+ }
+ vector<CurvatureInfo *> vec_curvature_info;
+};
+
+bool LIB_WINGED_EDGE_EXPORT gts_vertex_mean_curvature_normal (WVertex * v,
+ Vec3r &n);
+
+bool LIB_WINGED_EDGE_EXPORT gts_vertex_gaussian_curvature (WVertex * v,
+ real * Kg);
+
+void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_curvatures (real Kh,
+ real Kg,
+ real * K1,
+ real * K2);
+
+void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_directions (WVertex * v,
+ Vec3r Kh,
+ real Kg,
+ Vec3r &e1,
+ Vec3r &e2);
+
+/*
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000-2003 Bruno Levy
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Note that the GNU General Public License does not permit incorporating
+ * the Software into proprietary programs.
+ */
+ namespace OGF {
+
+ class NormalCycle ;
+
+ void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor(
+ WVertex* start, double radius, NormalCycle& nc
+ ) ;
+
+ void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor_one_ring(
+ WVertex* start, NormalCycle& nc
+ ) ;
+ }
+
+
+#endif /* __CURVATURE_H__ */
+
diff --git a/source/blender/freestyle/intern/winged_edge/Nature.h b/source/blender/freestyle/intern/winged_edge/Nature.h
new file mode 100755
index 00000000000..62171fae111
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Nature.h
@@ -0,0 +1,79 @@
+//
+// Filename : Nature.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Different natures for both vertices and edges
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef NATURE_H
+# define NATURE_H
+
+/*! \file Nature.h
+ * Definitions of Natures of the ViewMap's elements
+ */
+
+/*! Namespace gathering the different possible
+ * natures of 0D and 1D elements of the ViewMap
+ */
+namespace Nature {
+
+ typedef unsigned short VertexNature;
+
+ /*! true for any 0D element */
+ static const VertexNature POINT = 0; // 0
+ /*! true for SVertex */
+ static const VertexNature S_VERTEX = (1 << 0); // 1
+ /*! true for ViewVertex */
+ static const VertexNature VIEW_VERTEX = (1 << 1); // 2
+ /*! true for NonTVertex */
+ static const VertexNature NON_T_VERTEX = (1 << 2); // 4
+ /*! true for TVertex */
+ static const VertexNature T_VERTEX = (1 << 3); // 8
+ /*! true for CUSP */
+ static const VertexNature CUSP = (1 << 4); // 16
+
+ typedef unsigned short EdgeNature;
+ /*! true for non feature edges (always false for 1D elements of the ViewMap) */
+ static const EdgeNature NO_FEATURE = 0; // 0
+ /*! true for silhouettes */
+ static const EdgeNature SILHOUETTE = (1 << 0); // 1
+ /*! true for borders */
+ static const EdgeNature BORDER = (1 << 1); // 2
+ /*! true for creases */
+ static const EdgeNature CREASE = (1 << 2); // 4
+ /*! true for ridges */
+ static const EdgeNature RIDGE = (1 << 3); // 8
+ /*! true for valleys */
+ static const EdgeNature VALLEY = (1 << 4); // 16
+ /*! true for suggestive contours */
+ static const EdgeNature SUGGESTIVE_CONTOUR = (1 << 5); // 32
+ /*! true for material boundaries */
+ static const EdgeNature MATERIAL_BOUNDARY = (1 << 6); // 64
+ /*! true for user-defined edge marks */
+ static const EdgeNature EDGE_MARK = (1 << 7); // 128
+
+} // end of namespace Nature
+
+#endif // NATURE_H
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
new file mode 100755
index 00000000000..6ef99186a2c
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
@@ -0,0 +1,752 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+#include "WEdge.h"
+
+/*! Temporary structures */
+class vertexdata
+{
+public:
+ WVertex *_copy;
+};
+
+class oedgedata
+{
+public:
+ WOEdge *_copy;
+};
+
+class edgedata
+{
+public:
+ WEdge *_copy;
+};
+
+class facedata
+{
+public:
+ WFace *_copy;
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WVertex */
+ /* */
+ /* */
+ /**********************************/
+
+WVertex::WVertex(WVertex& iBrother)
+{
+ _Id = iBrother._Id;
+ _Vertex = iBrother._Vertex;
+ _EdgeList = iBrother._EdgeList;
+
+ _Shape = iBrother._Shape;
+ _Smooth = iBrother._Smooth;
+ _Border = iBrother._Border;
+ userdata = NULL;
+ iBrother.userdata = new vertexdata;
+ ((vertexdata*)(iBrother.userdata))->_copy = this;
+}
+
+WVertex* WVertex::duplicate()
+{
+ WVertex *clone = new WVertex(*this);
+ return clone;
+}
+
+
+WOEdge* WVertex::incoming_edge_iterator::operator*()
+
+{
+ return _current;
+}
+void WVertex::incoming_edge_iterator::increment(){
+ WOEdge *twin = _current->twin();
+ if(!twin){
+ // we reached a hole
+ _current = 0;
+ return;
+ }
+ WOEdge *next = twin->getPrevOnFace();
+ if(next == _begin){
+ next = 0;
+ }
+ _current = next;
+}
+
+WFace* WVertex::face_iterator::operator*(){
+ WOEdge * woedge = *_edge_it;
+ if(woedge == 0)
+ return 0;
+ return (woedge)->GetbFace();
+}
+
+//bool WVertex::isBoundary () const{
+// return _Border;
+//}
+bool WVertex::isBoundary ()
+{
+ if(_Border == 1)
+ return true;
+ else if(_Border == 0)
+ return false;
+
+ vector<WEdge *>::const_iterator it;
+ for(it=_EdgeList.begin(); it!=_EdgeList.end(); it++){
+ if((*it)->GetNumberOfOEdges() == 1){
+ _Border = 1;
+ return true;
+ }
+ }
+ //if (!(*it)->GetaOEdge()->GetaFace()) return true;
+ _Border = 0;
+ return false;
+}
+
+void WVertex::AddEdge(WEdge *iEdge) {
+ _EdgeList.push_back(iEdge);
+}
+
+WVertex::incoming_edge_iterator WVertex::incoming_edges_begin(){
+ WOEdge *begin;
+ WEdge * wedge = _EdgeList.front();
+ WOEdge* aOEdge = wedge->GetaOEdge();
+ if(aOEdge->GetbVertex() == this)
+ begin = aOEdge;
+ else
+ begin = _EdgeList.front()->GetbOEdge();
+ return incoming_edge_iterator(this, begin, begin);
+}
+WVertex::incoming_edge_iterator WVertex::incoming_edges_end(){
+ WOEdge *begin;
+ WOEdge* aOEdge = _EdgeList.front()->GetaOEdge();
+ if(aOEdge->GetbVertex() == this)
+ begin = aOEdge;
+ else
+ begin = _EdgeList.front()->GetbOEdge();
+ return incoming_edge_iterator(this, begin, 0);
+}
+//WOEdge** WVertex::incoming_edge_iterator::operator->()
+//{
+// WOEdge ** ppaOEdge = (*_iter)->GetaOEdge();
+// if(aOEdge->GetbVertex() == _vertex)
+// return ppaOEdge;
+// else
+// {
+// WOEdge *bOEdge = (*_iter)->GetbOEdge();
+// return &bOEdge;
+// }
+//
+//}
+ /**********************************/
+ /* */
+ /* */
+ /* WOEdge */
+ /* */
+ /* */
+ /**********************************/
+
+WOEdge::WOEdge(WOEdge& iBrother)
+{
+ _paVertex = iBrother.GetaVertex();
+ _pbVertex = iBrother.GetbVertex();
+ _paFace = iBrother.GetaFace();
+ _pbFace = iBrother.GetbFace();
+ _pOwner = iBrother.GetOwner();
+ userdata = NULL;
+ iBrother.userdata = new oedgedata;
+ ((oedgedata*)(iBrother.userdata))->_copy = this;
+
+ _vec = iBrother._vec;
+ _angle = iBrother._angle;
+}
+
+WOEdge * WOEdge::duplicate()
+{
+ WOEdge *clone = new WOEdge(*this);
+ return clone;
+}
+
+Vec3r
+WOEdge::getVec3r ()
+{
+ return Vec3r(_pbVertex->GetVertex() - _paVertex->GetVertex());
+}
+
+WOEdge * WOEdge::twin ()
+{
+ return GetOwner()->GetOtherOEdge(this);
+}
+
+WOEdge *
+WOEdge::getPrevOnFace()
+{
+ return _pbFace->GetPrevOEdge(this);
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* WEdge */
+ /* */
+ /* */
+ /**********************************/
+
+WEdge::WEdge(WEdge& iBrother)
+{
+ _paOEdge = NULL;
+ _pbOEdge = NULL;
+ WOEdge *aoedge = iBrother.GetaOEdge();
+ WOEdge *boedge = iBrother.GetbOEdge();
+ userdata = NULL;
+
+ if(NULL != aoedge)
+ //_paOEdge = new WOEdge(*aoedge);
+ _paOEdge = aoedge->duplicate();
+ if(NULL != boedge)
+ //_pbOEdge = new WOEdge(*boedge);
+ _pbOEdge = boedge->duplicate();
+
+ _nOEdges = iBrother.GetNumberOfOEdges();
+ _Id = iBrother.GetId();
+ iBrother.userdata = new edgedata;
+ ((edgedata*)(iBrother.userdata))->_copy = this;
+}
+
+WEdge * WEdge::duplicate()
+{
+ WEdge *clone = new WEdge(*this);
+ return clone;
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* WFace */
+ /* */
+ /* */
+ /**********************************/
+
+
+WFace::WFace(WFace& iBrother)
+{
+ _OEdgeList = iBrother.getEdgeList();
+ _Normal = iBrother.GetNormal();
+ _VerticesNormals = iBrother._VerticesNormals;
+ _VerticesTexCoords = iBrother._VerticesTexCoords;
+ _Id = iBrother.GetId();
+ _FrsMaterialIndex = iBrother._FrsMaterialIndex;
+ _Mark = iBrother._Mark;
+ userdata = NULL;
+ iBrother.userdata = new facedata;
+ ((facedata*)(iBrother.userdata))->_copy = this;
+}
+
+WFace * WFace::duplicate()
+{
+ WFace * clone = new WFace(*this);
+ return clone;
+}
+
+const FrsMaterial& WFace::frs_material() {
+ return getShape()->frs_material(_FrsMaterialIndex);
+}
+
+WOEdge * WFace::MakeEdge(WVertex *v1, WVertex *v2)
+{
+ // First check whether the same oriented edge already exists
+ // or not:
+ vector<WEdge *>& v1Edges = v1->GetEdges();
+ for(vector<WEdge*>::iterator it1=v1Edges.begin(), end=v1Edges.end();
+ it1!=end;
+ it1++)
+ {
+
+ WEdge *we=(*it1);
+
+ WOEdge *woea = we->GetaOEdge();
+
+ if((woea->GetaVertex() == v1) && (woea->GetbVertex() == v2))
+ //if((*it1)->GetbVertex() == v2)
+ {
+ // The oriented edge already exists
+ cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl;
+ // Adds the edge to the face
+ //AddEdge((*it1)->GetaOEdge());
+ AddEdge(woea);
+ (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1);
+ //sets these vertices as border:
+ v1->setBorder(true);
+ v2->setBorder(true);
+ //return (*it1)->GetaOEdge();
+ return woea;
+ }
+
+ WOEdge *woeb = we->GetbOEdge();
+ if((woeb != 0) && (woeb->GetaVertex() == v1) && (woeb->GetbVertex() == v2))
+
+ //if((*it1)->GetbVertex() == v2)
+
+ {
+ // The oriented edge already exists
+ cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl;
+ // Adds the edge to the face
+ //AddEdge((*it1)->GetaOEdge());
+ AddEdge(woeb);
+ (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1);
+ //sets these vertices as border:
+ v1->setBorder(true);
+ v2->setBorder(true);
+ //return (*it1)->GetaOEdge();
+ return woeb;
+ }
+ }
+
+ // the oriented edge we're about to build
+ WOEdge *pOEdge = new WOEdge;
+
+ WEdge * edge; // The edge containing the oriented edge.
+
+ // checks whether this edge already exists or not
+ // If it exists, it points outward v2
+
+ bool exist = false;
+ WOEdge *pInvertEdge = NULL; // The inverted edge if it exists
+ vector<WEdge *>& v2Edges = v2->GetEdges();
+ vector<WEdge *>::iterator it;
+ for(it=v2Edges.begin(); it!=v2Edges.end(); it++)
+ {
+ if((*it)->GetbVertex() == v1)
+ {
+ // The invert edge already exists
+ exist = true;
+ pInvertEdge = (*it)->GetaOEdge();
+ break;
+ }
+ }
+
+ //DEBUG:
+
+
+ if(true == exist) // The invert edge already exists
+ {
+ // Retrieves the corresponding edge
+ edge = pInvertEdge->GetOwner();
+
+ // Sets the a Face (retrieved from pInvertEdge
+ pOEdge->setaFace(pInvertEdge->GetbFace());
+
+ // Updates the invert edge:
+ pInvertEdge->setaFace(this);
+ }
+ else // The invert edge does not exist yet
+ {
+ // we must create a new edge
+ //edge = new WEdge;
+ edge = instanciateEdge();
+
+ // updates the a,b vertex edges list:
+ v1->AddEdge(edge);
+ v2->AddEdge(edge);
+
+ }
+
+ pOEdge->setOwner(edge);
+ // Add the vertices:
+ pOEdge->setaVertex(v1);
+ pOEdge->setbVertex(v2);
+
+ // Debug:
+ if(v1->GetId() == v2->GetId())
+ cerr << "Warning: edge " << this << " null with vertex " << v1->GetId() << endl;
+
+ edge->AddOEdge(pOEdge);
+ //edge->setNumberOfOEdges(edge->GetNumberOfOEdges()+1);
+
+ // Add this face (the b face)
+ pOEdge->setbFace(this);
+
+ // Adds the edge to the face
+ AddEdge(pOEdge);
+
+ return pOEdge;
+}
+
+
+bool
+WFace::getOppositeEdge (const WVertex *v, WOEdge* &e)
+{
+ if (_OEdgeList.size()!=3) return false;
+
+ vector<WOEdge *>::iterator it;
+ e=NULL;
+ for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++)
+ if ((*it)->GetaVertex()==v) e=*it;
+ if (!e) return false;
+ e=NULL;
+ for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++)
+ if (((*it)->GetaVertex()!=v) && ((*it)->GetbVertex()!=v)) e=*it;
+ if (!e) return false;
+ else return true;
+}
+
+real
+WFace::getArea ()
+{
+ vector<WOEdge *>::iterator it;
+ Vec3r origin=(*(_OEdgeList.begin()))->GetaVertex()->GetVertex();
+ it=_OEdgeList.begin();
+ real a=0;
+ for (it=it++; it!=_OEdgeList.end(); it++) {
+ Vec3r v1=Vec3r((*it)->GetaVertex()->GetVertex() - origin);
+ Vec3r v2=Vec3r((*it)->GetbVertex()->GetVertex() - origin);
+ a += (v1 ^ v2).norm() / 2.0;
+ }
+ return a;
+}
+
+
+WOEdge*
+WFace::GetPrevOEdge(WOEdge* iOEdge)
+ {
+ vector<WOEdge*>::iterator woe,woend, woefirst;
+ woefirst = _OEdgeList.begin();
+ woend=_OEdgeList.end();
+ WOEdge *prev =*woefirst;
+ woe=woefirst;
+ woe++;
+ for(;
+ woe!=woend;
+ woe++)
+ {
+ if((*woe) == iOEdge)
+ return prev;
+ prev= *woe;
+ }
+ // We left the loop. That means that the first
+ // OEdge was the good one:
+ if((*woefirst)==iOEdge)
+ return prev;
+
+ return NULL;
+ }
+
+WShape * WFace::getShape()
+{
+ return GetVertex(0)->shape();
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* WShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+LIB_WINGED_EDGE_EXPORT
+unsigned WShape::_SceneCurrentId = 0;
+
+WShape * WShape::duplicate()
+{
+ WShape *clone = new WShape(*this);
+ return clone;
+}
+
+WShape::WShape(WShape& iBrother)
+{
+ _Id = iBrother.GetId();
+ _Name = iBrother._Name;
+ _FrsMaterials = iBrother._FrsMaterials;
+ _meanEdgeSize = iBrother._meanEdgeSize;
+ iBrother.bbox(_min, _max);
+ vector<WVertex*>& vertexList = iBrother.getVertexList();
+ vector<WVertex*>::iterator v=vertexList.begin(), vend=vertexList.end();
+ for(;
+ v!=vend;
+ v++)
+ {
+ //WVertex *newVertex = new WVertex(*(*v));
+ WVertex *newVertex = (*v)->duplicate();
+
+ newVertex->setShape(this);
+ AddVertex(newVertex);
+ }
+
+ vector<WEdge*>& edgeList = iBrother.getEdgeList();
+ vector<WEdge*>::iterator e=edgeList.begin(), eend=edgeList.end();
+ for(;
+ e!=eend;
+ e++)
+ {
+ //WEdge *newEdge = new WEdge(*(*e));
+ WEdge *newEdge = (*e)->duplicate();
+ AddEdge(newEdge);
+ }
+
+ vector<WFace*>& faceList = iBrother.GetFaceList();
+ vector<WFace*>::iterator f=faceList.begin(), fend=faceList.end();
+ for(;
+ f!=fend;
+ f++)
+ {
+ //WFace *newFace = new WFace(*(*f));
+ WFace *newFace = (*f)->duplicate();
+ AddFace(newFace);
+ }
+
+ // update all pointed addresses thanks to the newly created objects:
+ vend=_VertexList.end();
+ for(v=_VertexList.begin();
+ v!=vend;
+ v++)
+ {
+ const vector<WEdge*>& vedgeList = (*v)->GetEdges();
+ vector<WEdge*> newvedgelist;
+ unsigned int i;
+ for(i=0; i<vedgeList.size(); i++)
+ {
+ WEdge *current = vedgeList[i];
+ edgedata * currentvedata = (edgedata*)current->userdata;
+ newvedgelist.push_back(currentvedata->_copy);
+ }
+ (*v)->setEdges(newvedgelist);
+ }
+
+ eend = _EdgeList.end();
+ for(e=_EdgeList.begin();
+ e!=eend;
+ e++)
+ {
+ // update aOedge:
+ WOEdge *aoEdge = (*e)->GetaOEdge();
+ aoEdge->setaVertex(((vertexdata*)(aoEdge->GetaVertex()->userdata))->_copy);
+ aoEdge->setbVertex(((vertexdata*)(aoEdge->GetbVertex()->userdata))->_copy);
+ if(NULL != aoEdge->GetaFace())
+ aoEdge->setaFace(((facedata*)(aoEdge->GetaFace()->userdata))->_copy);
+ aoEdge->setbFace(((facedata*)(aoEdge->GetbFace()->userdata))->_copy);
+ aoEdge->setOwner(((edgedata*)(aoEdge->GetOwner()->userdata))->_copy);
+ // update bOedge:
+
+ WOEdge *boEdge = (*e)->GetbOEdge();
+ if(boEdge != 0)
+ {
+ boEdge->setaVertex(((vertexdata*)(boEdge->GetaVertex()->userdata))->_copy);
+ boEdge->setbVertex(((vertexdata*)(boEdge->GetbVertex()->userdata))->_copy);
+ if(NULL != boEdge->GetaFace())
+ boEdge->setaFace(((facedata*)(boEdge->GetaFace()->userdata))->_copy);
+ boEdge->setbFace(((facedata*)(boEdge->GetbFace()->userdata))->_copy);
+ boEdge->setOwner(((edgedata*)(boEdge->GetOwner()->userdata))->_copy);
+ }
+ }
+
+ fend = _FaceList.end();
+ for(f=_FaceList.begin();
+ f!=fend;
+ f++)
+ {
+ unsigned i;
+ const vector<WOEdge*>& oedgeList = (*f)->getEdgeList();
+ vector<WOEdge*> newoedgelist;
+
+ unsigned n = oedgeList.size();
+ for(i=0; i<n; i++)
+ {
+ WOEdge *current = oedgeList[i];
+ oedgedata * currentoedata = (oedgedata*)current->userdata;
+ newoedgelist.push_back(currentoedata->_copy);
+ //oedgeList[i] = currentoedata->_copy;
+ //oedgeList[i] = ((oedgedata*)(oedgeList[i]->userdata))->_copy;
+ }
+ (*f)->setEdgeList(newoedgelist);
+ }
+
+ // Free all memory (arghh!)
+ // Vertex
+ vend = iBrother.getVertexList().end();
+ for(v=iBrother.getVertexList().begin();
+ v!=vend;
+ v++)
+ {
+ delete (vertexdata*)((*v)->userdata);
+ (*v)->userdata = NULL;
+ }
+
+ // Edges and OEdges:
+ eend = iBrother.getEdgeList().end();
+ for(e=iBrother.getEdgeList().begin();
+ e!=eend;
+ e++)
+ {
+ delete (edgedata*)((*e)->userdata);
+ (*e)->userdata = NULL;
+ // OEdge a :
+ delete (oedgedata*)((*e)->GetaOEdge()->userdata);
+ (*e)->GetaOEdge()->userdata = NULL;
+ // OEdge b:
+ WOEdge* oedgeb = (*e)->GetbOEdge();
+ if(NULL != oedgeb)
+ {
+ delete (oedgedata*)(oedgeb->userdata);
+ oedgeb->userdata = NULL;
+ }
+ }
+ // Faces
+ fend = iBrother.GetFaceList().end();
+ for(f=iBrother.GetFaceList().begin();
+ f!=fend;
+ f++)
+ {
+ delete (facedata*)((*f)->userdata);
+ (*f)->userdata = NULL;
+ }
+}
+
+WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterial)
+{
+ // allocate the new face
+ WFace *face = instanciateFace();
+
+ WFace *result = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial, face);
+ if (0 == result) {
+ delete face;
+ return 0;
+ }
+ return result;
+}
+
+WFace * WShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterial)
+{
+ // allocate the new face
+ WFace *face = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial);
+
+ if(0 == face)
+
+ return 0;
+
+ // set the list of per-vertex normals
+ face->setNormalList(iNormalsList);
+ // set the list of per-vertex tex coords
+ face->setTexCoordsList(iTexCoordsList);
+
+ return face;
+}
+
+WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterial, WFace *face)
+{
+
+ int id = _FaceList.size();
+
+ face->setFrsMaterialIndex(iMaterial);
+
+ // Check whether we have a degenerated face:
+
+ // LET'S HACK IT FOR THE TRIANGLE CASE:
+
+ if(3 == iVertexList.size())
+
+ {
+
+ if((iVertexList[0] == iVertexList[1])
+
+ || (iVertexList[0] == iVertexList[2])
+
+ || (iVertexList[2] == iVertexList[1]))
+
+ {
+
+ cerr << "Warning: degenerated triangle detected, correcting" << endl;
+ return 0;
+
+ }
+
+ }
+
+ vector<WVertex*>::iterator it;
+
+ // compute the face normal (v1v2 ^ v1v3)
+ WVertex *v1, *v2, *v3;
+ it = iVertexList.begin();
+ v1 = *it;
+ it++;
+ v2 = *it;
+ it++;
+ v3 = *it;
+
+ Vec3r vector1(v2->GetVertex()-v1->GetVertex());
+ Vec3r vector2(v3->GetVertex()-v1->GetVertex());
+
+ Vec3r normal(vector1 ^ vector2);
+ normal.normalize();
+ face->setNormal(normal);
+
+ vector<bool>::iterator mit = iFaceEdgeMarksList.begin();
+ face->setMark(*mit);
+ mit++;
+
+ // vertex pointers used to build each edge
+ vector<WVertex*>::iterator va, vb;
+
+ va = iVertexList.begin();
+ vb = va;
+ for(; va != iVertexList.end(); va = vb)
+ {
+ vb++;
+ // Adds va to the vertex list:
+ //face->AddVertex(*va);
+
+ WOEdge * oedge;
+ if(*va == iVertexList.back())
+ oedge = face->MakeEdge(*va, iVertexList.front()); //for the last (closing) edge
+ else
+ oedge = face->MakeEdge(*va, *vb);
+
+
+ if(oedge == 0)
+ return 0;
+
+
+ WEdge *edge = oedge->GetOwner();
+ if(1 == edge->GetNumberOfOEdges())
+ {
+ // means that we just created a new edge and that we must add it to the
+ // shape's edges list
+ edge->setId(_EdgeList.size());
+ AddEdge(edge);
+ // compute the mean edge value:
+ _meanEdgeSize += edge->GetaOEdge()->GetVec().norm();
+ }
+
+ edge->setMark(*mit);
+ mit++;
+ }
+
+ // Add the face to the shape's faces list:
+ face->setId(id);
+ AddFace(face);
+
+ return face;
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h
new file mode 100755
index 00000000000..dc920448add
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.h
@@ -0,0 +1,991 @@
+//
+// Filename : WEdge.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define a Winged Edge data structure.
+// Date of creation : 18/02/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef WEDGE_H
+# define WEDGE_H
+
+# include <vector>
+# include <iterator>
+# include <math.h>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../scene_graph/FrsMaterial.h"
+
+using namespace std;
+using namespace Geometry;
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WVertex */
+ /* */
+ /* */
+ /**********************************/
+
+
+class WOEdge;
+class WEdge;
+class WShape;
+class WFace;
+class LIB_WINGED_EDGE_EXPORT WVertex
+{
+protected:
+ int _Id; // an identificator
+ Vec3r _Vertex;
+ vector<WEdge*> _EdgeList;
+ WShape * _Shape; // the shape to which the vertex belongs
+ bool _Smooth; // flag to indicate whether the Vertex belongs to a smooth edge or not
+ int _Border; // 1 -> border, 0 -> no border, -1 -> not set
+
+public:
+ void * userdata; // designed to store specific user data
+ inline WVertex(const Vec3r &v) {_Id = 0; _Vertex = v; userdata = NULL; _Shape = NULL;_Smooth=true;_Border=-1;}
+ /*! Copy constructor */
+ WVertex(WVertex& iBrother);
+ virtual WVertex * duplicate();
+ virtual ~WVertex() {}
+
+ /*! accessors */
+ inline Vec3r& GetVertex() {return _Vertex;}
+ inline vector<WEdge*>& GetEdges() {return _EdgeList;}
+ inline int GetId() {return _Id;}
+ inline WShape * shape() const {return _Shape;}
+ inline bool isSmooth() const {return _Smooth;}
+ bool isBoundary();
+
+ /*! modifiers */
+ inline void setVertex(const Vec3r& v) {_Vertex = v;}
+ inline void setEdges(const vector<WEdge *>& iEdgeList) {_EdgeList = iEdgeList;}
+ inline void setId(int id) {_Id = id;}
+ inline void setShape(WShape *iShape) {_Shape = iShape;}
+ inline void setSmooth(bool b) {_Smooth = b;}
+ inline void setBorder(bool b) {if(b) _Border= 1; else _Border = 0;}
+
+ /*! Adds an edge to the edges list */
+ void AddEdge(WEdge *iEdge) ;
+
+ virtual void ResetUserData() {userdata = 0;}
+
+
+
+public:
+
+
+
+ /*! Iterator to iterate over a vertex incoming edges in the CCW order*/
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ class incoming_edge_iterator : public input_iterator<WOEdge*,ptrdiff_t>
+# else
+ class LIB_WINGED_EDGE_EXPORT incoming_edge_iterator : public iterator<input_iterator_tag, WOEdge*,ptrdiff_t>
+# endif
+ {
+ private:
+ WVertex *_vertex;
+ //
+ WOEdge *_begin;
+ WOEdge *_current;
+
+ public:
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ inline incoming_edge_iterator() : input_iterator<WOEdge*,ptrdiff_t>() {}
+# else
+ inline incoming_edge_iterator() : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>() {}
+# endif
+ virtual ~incoming_edge_iterator() {}; //soc
+
+ protected:
+ friend class WVertex;
+ inline incoming_edge_iterator(
+ WVertex *iVertex,
+ WOEdge * iBegin,
+ WOEdge * iCurrent)
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WOEdge*,ptrdiff_t>()
+# else
+ : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>()
+# endif
+ {
+ _vertex = iVertex;
+ _begin = iBegin;
+ _current = iCurrent;
+ }
+
+ public:
+ inline incoming_edge_iterator(const incoming_edge_iterator& iBrother)
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WOEdge*,ptrdiff_t>(iBrother)
+# else
+ : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>(iBrother)
+# endif
+ {
+ _vertex = iBrother._vertex;
+ _begin = iBrother._begin;
+ _current = iBrother._current;
+ }
+
+ public:
+ // operators
+ virtual incoming_edge_iterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ virtual incoming_edge_iterator operator++(int) // operator corresponding to i++
+ {
+ incoming_edge_iterator tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const incoming_edge_iterator& b) const
+ {
+ return ((_current) != (b._current));
+ }
+
+ virtual bool operator==(const incoming_edge_iterator& b) const
+ {
+ return ((_current)== (b._current));
+ }
+
+ // dereferencing
+ virtual WOEdge* operator*();
+ //virtual WOEdge** operator->();
+ protected:
+ virtual void increment();
+ };
+
+
+ /*! Iterator to iterate over a vertex faces in the CCW order */
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ class face_iterator : public input_iterator<WFace*,ptrdiff_t>
+# else
+ class LIB_WINGED_EDGE_EXPORT face_iterator : public iterator<input_iterator_tag, WFace*,ptrdiff_t>
+# endif
+ {
+ private:
+ incoming_edge_iterator _edge_it;
+
+ public:
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ inline face_iterator() : input_iterator<WFace*,ptrdiff_t>() {}
+# else
+ inline face_iterator() : iterator<input_iterator_tag, WFace*,ptrdiff_t>() {}
+# endif
+ virtual ~face_iterator() {}; //soc
+
+ protected:
+ friend class WVertex;
+ inline face_iterator(
+ incoming_edge_iterator it)
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WFace*,ptrdiff_t>()
+# else
+ : iterator<input_iterator_tag, WFace*,ptrdiff_t>()
+# endif
+ {
+ _edge_it = it;
+ }
+
+ public:
+ inline face_iterator(const face_iterator& iBrother)
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WFace*,ptrdiff_t>(iBrother)
+# else
+ : iterator<input_iterator_tag, WFace*,ptrdiff_t>(iBrother)
+# endif
+ {
+ _edge_it = iBrother._edge_it;
+ }
+
+ public:
+ // operators
+ virtual face_iterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ virtual face_iterator operator++(int) // operator corresponding to i++
+ {
+ face_iterator tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const face_iterator& b) const
+ {
+ return ((_edge_it) != (b._edge_it));
+ }
+
+ virtual bool operator==(const face_iterator& b) const
+ {
+ return ((_edge_it)== (b._edge_it));
+ }
+
+ // dereferencing
+ virtual WFace* operator*();
+ //virtual WOEdge** operator->();
+ protected:
+ inline void increment(){
+ ++_edge_it;
+ }
+ };
+
+public:
+ /*! iterators access */
+ virtual incoming_edge_iterator incoming_edges_begin();
+ virtual incoming_edge_iterator incoming_edges_end() ;
+
+ virtual face_iterator faces_begin() {
+ return face_iterator(incoming_edges_begin());
+ }
+ virtual face_iterator faces_end() {
+ return face_iterator(incoming_edges_end());
+ }
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WOEdge */
+ /* */
+ /* */
+ /**********************************/
+class WFace;
+class WEdge;
+
+class LIB_WINGED_EDGE_EXPORT WOEdge
+{
+protected:
+ // WOEdge *_paCWEdge; // edge reached when traveling clockwise on aFace from the edge
+ // WOEdge *_pbCWEdge; // edge reached when traveling clockwise on bFace from the edge
+ // WOEdge *_paCCWEdge; // edge reached when traveling counterclockwise on aFace from the edge
+ // WOEdge *_pbCCWEdge; // edge reached when traveling counterclockwise on bFace from the edge
+ WVertex *_paVertex; // starting vertex
+ WVertex *_pbVertex; // ending vertex
+ WFace *_paFace; // when following the edge, face on the right
+ WFace *_pbFace; // when following the edge, face on the left
+ WEdge *_pOwner; // Edge
+
+ Vec3r _vec;
+ real _angle;
+
+public:
+
+ void *userdata;
+ inline WOEdge()
+ {
+ // _paCWEdge = NULL;
+ // _pbCWEdge = NULL;
+ // _paCCWEdge = NULL;
+ // _pbCCWEdge = NULL;
+ _paVertex = NULL;
+ _pbVertex = NULL;
+ _paFace = NULL;
+ _pbFace = NULL;
+ _pOwner = NULL;
+ userdata = NULL;
+ }
+ virtual ~WOEdge() {}; //soc
+
+ /*! copy constructor */
+ WOEdge(WOEdge& iBrother);
+ virtual WOEdge * duplicate();
+
+ /*! accessors */
+ // inline WOEdge *GetaCWEdge() {return _paCWEdge;}
+ // inline WOEdge *GetbCWEdge() {return _pbCWEdge;}
+ // inline WOEdge *GetaCCWEdge() {return _paCCWEdge;}
+ // inline WOEdge *GetbCCWEdge() {return _pbCCWEdge;}
+ inline WVertex *GetaVertex() {return _paVertex;}
+ inline WVertex *GetbVertex() {return _pbVertex;}
+ inline WFace *GetaFace() {return _paFace;}
+ inline WFace *GetbFace() {return _pbFace;}
+ inline WEdge *GetOwner() {return _pOwner;}
+
+ inline const Vec3r& GetVec() { return _vec; }
+ inline const real GetAngle() { return _angle; }
+
+
+ /*! modifiers */
+ // inline void SetaCWEdge(WOEdge *pe) {_paCWEdge = pe;}
+ // inline void SetbCWEdge(WOEdge *pe) {_pbCWEdge = pe;}
+ // inline void SetaCCWEdge(WOEdge *pe) {_paCCWEdge = pe;}
+ // inline void SetbCCCWEdge(WOEdge *pe) {_pbCCWEdge = pe;}
+ inline void setVecAndAngle();
+ inline void setaVertex(WVertex *pv) {_paVertex = pv; setVecAndAngle(); }
+ inline void setbVertex(WVertex *pv) {_pbVertex = pv; setVecAndAngle(); }
+ inline void setaFace(WFace *pf) {_paFace = pf; setVecAndAngle(); }
+ inline void setbFace(WFace *pf) {_pbFace = pf; setVecAndAngle(); }
+ inline void setOwner(WEdge *pe) {_pOwner = pe;}
+
+ /*! Retrieves the list of edges in CW order */
+ inline void RetrieveCWOrderedEdges(vector<WEdge*>& oEdges);
+ /*! returns the vector between the two vertices */
+ Vec3r getVec3r ();
+ WOEdge * twin ();
+ WOEdge * getPrevOnFace();
+ virtual void ResetUserData() {userdata = 0;}
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WEdge */
+ /* */
+ /* */
+ /**********************************/
+
+class LIB_WINGED_EDGE_EXPORT WEdge
+{
+protected:
+ WOEdge *_paOEdge; // first oriented edge
+ WOEdge *_pbOEdge; // second oriented edge
+ int _nOEdges; // number of oriented edges associated with this edge. (1 means border edge)
+ bool _Mark; // user-specified edge mark for feature edge detection
+ int _Id; // Identifier for the edge
+
+public:
+ void * userdata; // designed to store specific user data
+ inline WEdge()
+ {
+ _paOEdge = NULL;
+ _pbOEdge = NULL;
+ _nOEdges = 0;
+ userdata = NULL;
+ }
+
+ inline WEdge(WOEdge *iOEdge)
+ {
+ _paOEdge = iOEdge;
+ _pbOEdge = NULL;
+ _nOEdges = 1;
+ userdata = NULL;
+ }
+
+ inline WEdge(WOEdge *iaOEdge, WOEdge *ibOEdge)
+ {
+ _paOEdge = iaOEdge;
+ _pbOEdge = ibOEdge;
+ _nOEdges = 2;
+ userdata = NULL;
+ }
+
+ /*! Copy constructor */
+ WEdge(WEdge& iBrother);
+ virtual WEdge * duplicate();
+
+ virtual ~WEdge()
+ {
+ if(NULL != _paOEdge)
+ {
+ delete _paOEdge;
+ _paOEdge = NULL;
+ }
+
+ if(NULL != _pbOEdge)
+ {
+ delete _pbOEdge;
+ _pbOEdge = NULL;
+ }
+ }
+
+ /*! checks whether two WEdge have a common vertex.
+ * Returns a pointer on the common vertex if it exists,
+ * NULL otherwise.
+ */
+ static inline WVertex* CommonVertex(WEdge *iEdge1, WEdge* iEdge2)
+ {
+ if((NULL == iEdge1) || (NULL == iEdge2))
+ return NULL;
+
+ WVertex *wv1 = iEdge1->GetaOEdge()->GetaVertex();
+ WVertex *wv2 = iEdge1->GetaOEdge()->GetbVertex();
+ WVertex *wv3 = iEdge2->GetaOEdge()->GetaVertex();
+ WVertex *wv4 = iEdge2->GetaOEdge()->GetbVertex();
+
+ if((wv1 == wv3) || (wv1 == wv4))
+ {
+ return wv1;
+ }
+ else if((wv2 == wv3) || (wv2 == wv4))
+ {
+ return wv2;
+ }
+
+ return NULL;
+ }
+ /*! accessors */
+ inline WOEdge * GetaOEdge() {return _paOEdge;}
+ inline WOEdge * GetbOEdge() {return _pbOEdge;}
+ inline int GetNumberOfOEdges() {return _nOEdges;}
+ inline bool GetMark() {return _Mark;}
+ inline int GetId() {return _Id;}
+ inline WVertex * GetaVertex() {return _paOEdge->GetaVertex();}
+ inline WVertex * GetbVertex() {return _paOEdge->GetbVertex();}
+ inline WFace * GetaFace() {return _paOEdge->GetaFace();}
+ inline WFace * GetbFace() {return _paOEdge->GetbFace();}
+ inline WOEdge* GetOtherOEdge(WOEdge* iOEdge)
+ {
+ if(iOEdge == _paOEdge)
+ return _pbOEdge;
+ else
+ return _paOEdge;
+ }
+
+ /*! modifiers */
+ inline void setaOEdge(WOEdge *iEdge) {_paOEdge = iEdge;}
+ inline void setbOEdge(WOEdge *iEdge) {_pbOEdge = iEdge;}
+ inline void AddOEdge(WOEdge *iEdge)
+ {
+ if(NULL == _paOEdge)
+ {
+ _paOEdge = iEdge;
+ _nOEdges++;
+ return;
+ }
+ if(NULL == _pbOEdge)
+ {
+ _pbOEdge = iEdge;
+ _nOEdges++;
+ return;
+ }
+ }
+ inline void setNumberOfOEdges(int n) {_nOEdges = n;}
+ inline void setMark(bool mark) {_Mark = mark;}
+ inline void setId(int id) {_Id = id;}
+ virtual void ResetUserData() {userdata = 0;}
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* WFace */
+ /* */
+ /* */
+ /**********************************/
+
+
+class LIB_WINGED_EDGE_EXPORT WFace
+{
+protected:
+ vector<WOEdge *> _OEdgeList; // list of oriented edges of bording the face
+ Vec3r _Normal; // normal to the face
+ vector<Vec3r> _VerticesNormals; // in case there is a normal per vertex.
+ // The normal number i corresponds to the
+ // aVertex of the oedge number i, for that face
+ vector<Vec2r> _VerticesTexCoords;
+
+ int _Id;
+ unsigned _FrsMaterialIndex;
+ bool _Mark; // Freestyle face mark (if true, feature edges on this face are ignored)
+
+public:
+ void *userdata;
+ inline WFace() {userdata = NULL;_FrsMaterialIndex = 0;}
+ /*! copy constructor */
+ WFace(WFace& iBrother);
+ virtual WFace * duplicate();
+ virtual ~WFace() {}
+
+ /*! accessors */
+ inline const vector<WOEdge*>& getEdgeList() {return _OEdgeList;}
+ inline WOEdge * GetOEdge(int i) {return _OEdgeList[i];}
+ inline Vec3r& GetNormal() {return _Normal;}
+ inline int GetId() {return _Id;}
+ inline unsigned frs_materialIndex() const {return _FrsMaterialIndex;}
+ inline bool GetMark() const {return _Mark;}
+ const FrsMaterial& frs_material() ;
+
+ /*! The vertex of index i corresponds to the a vertex
+ * of the edge of index i
+ */
+ inline WVertex* GetVertex(unsigned int index)
+ {
+ // if(index >= _OEdgeList.size())
+ // return NULL;
+ return _OEdgeList[index]->GetaVertex();
+ }
+ /*! returns the index at which iVertex is stored in the
+ * array.
+ * returns -1 if iVertex doesn't belong to the face.
+ */
+ inline int GetIndex(WVertex *iVertex){
+ int index = 0;
+ for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end();
+ woe!=woend;
+ woe++){
+ if((*woe)->GetaVertex() == iVertex)
+ return index;
+ ++index;
+ }
+ return -1;
+ }
+ inline void RetrieveVertexList(vector<WVertex*>& oVertices)
+ {
+ for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end();
+ woe!=woend;
+ woe++)
+ {
+ oVertices.push_back((*woe)->GetaVertex());
+ }
+ }
+ inline void RetrieveBorderFaces(vector<const WFace*>& oWFaces)
+ {
+ for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end();
+ woe!=woend;
+ woe++)
+ {
+ WFace *af;
+ if(NULL != (af = (*woe)->GetaFace()))
+ oWFaces.push_back(af);
+ }
+ }
+ inline WFace * GetBordingFace(int index)
+ {
+ // if(index >= _OEdgeList.size())
+ // return 0;
+ return _OEdgeList[index]->GetaFace();
+ }
+ inline WFace * GetBordingFace(WOEdge *iOEdge)
+ {
+ return iOEdge->GetaFace();
+ }
+ inline vector<Vec3r>& GetPerVertexNormals()
+ {
+ return _VerticesNormals;
+ }
+ inline vector<Vec2r>& GetPerVertexTexCoords()
+ {
+ return _VerticesTexCoords;
+ }
+ /*! Returns the normal of the vertex of index index */
+ inline Vec3r& GetVertexNormal(int index)
+ {
+ return _VerticesNormals[index];
+ }
+ /*! Returns the tex coords of the vertex of index index */
+ inline Vec2r& GetVertexTexCoords(int index)
+ {
+ return _VerticesTexCoords[index];
+ }
+ /*! Returns the normal of the vertex iVertex for that face */
+ inline Vec3r& GetVertexNormal(WVertex *iVertex)
+ {
+ int i = 0;
+ int index = 0;
+ for(vector<WOEdge*>::const_iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end();
+ woe!=woend;
+ woe++)
+ {
+ if((*woe)->GetaVertex() == iVertex)
+ {
+ index = i;
+ break;
+ }
+ ++i;
+ }
+
+ return _VerticesNormals[index];
+ }
+ inline WOEdge* GetNextOEdge(WOEdge* iOEdge)
+ {
+ bool found = false;
+ vector<WOEdge*>::iterator woe,woend, woefirst;
+ woefirst = _OEdgeList.begin();
+ for(woe=woefirst,woend=_OEdgeList.end();
+ woe!=woend;
+ woe++)
+ {
+ if(true == found)
+ return (*woe);
+
+ if((*woe) == iOEdge)
+ {
+ found = true;
+ }
+ }
+
+ // We left the loop. That means that the first
+ // OEdge was the good one:
+ if(found)
+ return (*woefirst);
+
+ return NULL;
+ }
+ WOEdge* GetPrevOEdge(WOEdge* iOEdge);
+
+ inline int numberOfEdges() const { return _OEdgeList.size();}
+ inline int numberOfVertices() const { return _OEdgeList.size();}
+ /*! Returns true if the face has one ot its edge which is a border
+ * edge
+ */
+ inline bool isBorder() const
+ {
+ for(vector<WOEdge*>::const_iterator woe=_OEdgeList.begin(), woeend=_OEdgeList.end();
+ woe!=woeend;
+ ++woe)
+ {
+ if((*woe)->GetOwner()->GetbOEdge() == 0)
+ return true;
+ }
+ return false;
+ }
+ /*! modifiers */
+ inline void setEdgeList(const vector<WOEdge*>& iEdgeList) {_OEdgeList = iEdgeList;}
+ inline void setNormal(const Vec3r& iNormal) {_Normal = iNormal;}
+ inline void setNormalList(const vector<Vec3r>& iNormalsList) {_VerticesNormals = iNormalsList;}
+ inline void setTexCoordsList(const vector<Vec2r>& iTexCoordsList) {_VerticesTexCoords = iTexCoordsList;}
+ inline void setId(int id) {_Id = id;}
+ inline void setFrsMaterialIndex(unsigned iMaterialIndex) {_FrsMaterialIndex = iMaterialIndex;}
+ inline void setMark(bool iMark) {_Mark = iMark;}
+
+ /*! designed to build a specialized WEdge
+ * for use in MakeEdge
+ */
+ virtual WEdge * instanciateEdge() const {return new WEdge;}
+
+ /*! Builds an oriented edge
+ * Returns the built edge.
+ * v1, v2
+ * Vertices at the edge's extremities
+ * The edge is oriented from v1 to v2.
+ */
+ virtual WOEdge * MakeEdge(WVertex *v1, WVertex *v2);
+
+ /*! Adds an edge to the edges list */
+ inline void AddEdge(WOEdge *iEdge) {_OEdgeList.push_back(iEdge);}
+
+ /*! For triangles, returns the edge opposite to the vertex in e.
+ returns flase if the face is not a triangle or if the vertex is not found*/
+ bool getOppositeEdge (const WVertex *v, WOEdge* &e);
+
+ /*! compute the area of the face */
+ real getArea ();
+
+ WShape * getShape() ;
+ virtual void ResetUserData() {userdata = 0;}
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+class LIB_WINGED_EDGE_EXPORT WShape
+{
+protected:
+ vector<WVertex*> _VertexList;
+ vector<WEdge*> _EdgeList;
+ vector<WFace*> _FaceList;
+ int _Id;
+ string _Name;
+ static unsigned _SceneCurrentId;
+ Vec3r _min;
+ Vec3r _max;
+ vector<FrsMaterial> _FrsMaterials;
+ real _meanEdgeSize;
+
+public:
+ inline WShape() {_meanEdgeSize = 0;_Id = _SceneCurrentId; _SceneCurrentId++;}
+ /*! copy constructor */
+ WShape(WShape& iBrother);
+ virtual WShape * duplicate();
+ virtual ~WShape()
+ {
+ if(_EdgeList.size() != 0)
+ {
+ vector<WEdge *>::iterator e;
+ for(e=_EdgeList.begin(); e!=_EdgeList.end(); e++)
+ {
+ delete (*e);
+ }
+ _EdgeList.clear();
+ }
+
+ if(_VertexList.size() != 0)
+ {
+ vector<WVertex *>::iterator v;
+ for(v=_VertexList.begin(); v!=_VertexList.end(); v++)
+ {
+ delete (*v);
+ }
+ _VertexList.clear();
+ }
+
+ if(_FaceList.size() != 0)
+ {
+ vector<WFace *>::iterator f;
+ for(f=_FaceList.begin(); f!=_FaceList.end(); f++)
+ {
+ delete (*f);
+ }
+ _FaceList.clear();
+ }
+ }
+
+ /*! accessors */
+ inline vector<WEdge *>& getEdgeList() {return _EdgeList;}
+ inline vector<WVertex*>& getVertexList() {return _VertexList;}
+ inline vector<WFace*>& GetFaceList() {return _FaceList;}
+ inline unsigned GetId() {return _Id;}
+ inline void bbox(Vec3r& min, Vec3r& max) {min=_min; max=_max;}
+ inline const FrsMaterial& frs_material(unsigned i) const {return _FrsMaterials[i];}
+ inline const vector<FrsMaterial>& frs_materials() const {return _FrsMaterials;}
+ inline const real getMeanEdgeSize() const {return _meanEdgeSize;}
+ inline const string& getName() const {return _Name;}
+ /*! modifiers */
+ static inline void setCurrentId(const unsigned id) { _SceneCurrentId = id; }
+ inline void setEdgeList(const vector<WEdge*>& iEdgeList) {_EdgeList = iEdgeList;}
+ inline void setVertexList(const vector<WVertex*>& iVertexList) {_VertexList = iVertexList;}
+ inline void setFaceList(const vector<WFace*>& iFaceList) {_FaceList = iFaceList;}
+ inline void setId(int id) {_Id = id;}
+ inline void setBBox(const Vec3r& min, const Vec3r& max) {_min = min; _max=max;}
+ inline void setFrsMaterial(const FrsMaterial& frs_material, unsigned i) {_FrsMaterials[i]=frs_material;}
+ inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials) {_FrsMaterials = iMaterials;}
+ inline void setName(const string& name) {_Name = name;}
+
+ /*! designed to build a specialized WFace
+ * for use in MakeFace
+ */
+ virtual WFace * instanciateFace() const {return new WFace;}
+
+ /*! adds a new face to the shape
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The material index for this face
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
+
+ /*! adds a new face to the shape. The difference with
+ * the previous method is that this one is designed
+ * to build a WingedEdge structure for which there are
+ * per vertex normals, opposed to per face normals.
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The materialIndex for this face
+ * iNormalsList
+ * The list of normals, iNormalsList[i] corresponding to the
+ * normal of the vertex iVertexList[i] for that face.
+ * iTexCoordsList
+ * The list of tex coords, iTexCoordsList[i] corresponding to the
+ * normal of the vertex iVertexList[i] for that face.
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
+
+ inline void AddEdge(WEdge *iEdge) {_EdgeList.push_back(iEdge);}
+ inline void AddFace(WFace* iFace) {_FaceList.push_back(iFace);}
+ inline void AddVertex(WVertex *iVertex) {iVertex->setShape(this); _VertexList.push_back(iVertex);}
+
+ inline void ResetUserData()
+ {
+ for(vector<WVertex*>::iterator v=_VertexList.begin(),vend=_VertexList.end();
+ v!=vend;
+ v++)
+ {
+ (*v)->ResetUserData();
+ }
+
+ for(vector<WEdge*>::iterator e=_EdgeList.begin(),eend=_EdgeList.end();
+ e!=eend;
+ e++)
+ {
+ (*e)->ResetUserData();
+ // manages WOEdge:
+ WOEdge *oe = (*e)->GetaOEdge();
+ if(oe != NULL)
+ oe->ResetUserData();
+ oe = (*e)->GetbOEdge();
+ if(oe != NULL)
+ oe->ResetUserData();
+ }
+
+ for(vector<WFace*>::iterator f=_FaceList.begin(),fend=_FaceList.end();
+ f!=fend;
+ f++)
+ {
+ (*f)->ResetUserData();
+ }
+
+ }
+
+ inline void ComputeBBox()
+ {
+ _min = _VertexList[0]->GetVertex();
+ _max = _VertexList[0]->GetVertex();
+
+ Vec3r v;
+ for(vector<WVertex*>::iterator wv=_VertexList.begin(), wvend=_VertexList.end();
+ wv!=wvend;
+ wv++)
+ {
+ for(unsigned int i=0; i<3; i++)
+ {
+ v = (*wv)->GetVertex();
+ if(v[i] < _min[i])
+ _min[i] = v[i];
+ if(v[i] > _max[i])
+ _max[i] = v[i];
+ }
+ }
+ }
+
+ inline real ComputeMeanEdgeSize(){
+ _meanEdgeSize = _meanEdgeSize/(_EdgeList.size());
+ return _meanEdgeSize;
+ }
+
+protected:
+ /*! Builds the face passed as argument (which as already been allocated)
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The material index for this face
+ * face
+ * The Face that is filled in
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex, WFace *face);
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WingedEdge */
+ /* */
+ /* */
+ /**********************************/
+
+class WingedEdge {
+
+ public:
+
+ WingedEdge() {}
+
+ ~WingedEdge() {
+ clear();
+ }
+
+ void clear() {
+ for (vector<WShape*>::iterator it = _wshapes.begin();
+ it != _wshapes.end();
+ it++)
+ delete *it;
+ _wshapes.clear();
+ }
+
+ void addWShape(WShape* wshape) {
+ _wshapes.push_back(wshape);
+ }
+
+ vector<WShape*>& getWShapes() {
+ return _wshapes;
+ }
+
+ private:
+
+ vector<WShape*> _wshapes;
+};
+
+
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+/* for inline functions */
+void WOEdge::RetrieveCWOrderedEdges(vector<WEdge*>& oEdges)
+{
+
+ WOEdge *currentOEdge = this;
+ do
+ {
+ WOEdge* nextOEdge = currentOEdge->GetbFace()->GetNextOEdge(currentOEdge);
+ oEdges.push_back(nextOEdge->GetOwner());
+ currentOEdge = nextOEdge->GetOwner()->GetOtherOEdge(nextOEdge);
+
+ } while((currentOEdge != NULL) && (currentOEdge->GetOwner() != GetOwner()));
+}
+
+inline void WOEdge::setVecAndAngle() {
+ if ( _paVertex != NULL && _pbVertex != NULL ) {
+ _vec = _pbVertex->GetVertex() - _paVertex->GetVertex();
+ if ( _paFace != NULL && _pbFace != NULL ) {
+ real sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm() ;
+ if(sine >= 1.0) {
+ _angle = M_PI / 2.0 ;
+ return;
+ }
+ if(sine <= -1.0) {
+ _angle = -M_PI / 2.0 ;
+ return;
+ }
+ _angle = ::asin(sine);
+ }
+ }
+}
+
+#endif // WEDGE_H
diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp
new file mode 100755
index 00000000000..7d0a2d3c561
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp
@@ -0,0 +1,60 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "WEdge.h"
+#include "WFillGrid.h"
+
+void WFillGrid::fillGrid() {
+ if (!_winged_edge || !_grid)
+ return;
+
+ vector<WShape*> wshapes = _winged_edge->getWShapes();
+ vector<WVertex*> fvertices;
+ vector<Vec3r> vectors;
+ vector<WFace*> faces;
+
+ for (vector<WShape*>::const_iterator it = wshapes.begin();
+ it != wshapes.end();
+ it++) {
+ faces = (*it)->GetFaceList();
+
+ for (vector<WFace*>::const_iterator f = faces.begin();
+ f != faces.end();
+ f++) {
+ (*f)->RetrieveVertexList(fvertices);
+
+ for (vector<WVertex*>::const_iterator wv = fvertices.begin();
+ wv != fvertices.end();
+ wv++)
+ vectors.push_back(Vec3r((*wv)->GetVertex()));
+
+ // occluder will be deleted by the grid
+ Polygon3r *occluder =
+ new Polygon3r(vectors, (*f)->GetNormal());
+ occluder->setId(_polygon_id++);
+ occluder->userdata = (void*)(*f);
+ _grid->insertOccluder(occluder);
+ vectors.clear();
+ fvertices.clear();
+ }
+ faces.clear();
+ }
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.h b/source/blender/freestyle/intern/winged_edge/WFillGrid.h
new file mode 100755
index 00000000000..2ebbc2f359a
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.h
@@ -0,0 +1,80 @@
+//
+// Filename : WFillGrid.h
+// Author(s) : Stephane Grabli
+// Emmanuel Turquin
+// Purpose : Class to fill in a grid from a SceneGraph
+// (uses only the WingedEdge structures)
+// Date of creation : 03/05/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef W_FILL_GRID_H
+# define W_FILL_GRID_H
+
+# include "../geometry/Grid.h"
+# include "../geometry/Polygon.h"
+# include "WEdge.h"
+
+class LIB_WINGED_EDGE_EXPORT WFillGrid
+{
+public:
+
+ inline WFillGrid(Grid* grid = 0, WingedEdge* winged_edge = 0) {
+ _winged_edge = winged_edge;
+ _grid = grid;
+ _polygon_id = 0;
+ }
+
+ virtual ~WFillGrid() {}
+
+ void fillGrid();
+
+ /*! Accessors */
+ WingedEdge* getWingedEdge() {
+ return _winged_edge;
+ }
+
+ Grid* getGrid() {
+ return _grid;
+ }
+
+ /*! Modifiers */
+ void setWingedEdge(WingedEdge* winged_edge) {
+ if (winged_edge)
+ _winged_edge = winged_edge;
+ }
+
+ void setGrid(Grid* grid) {
+ if (grid)
+ _grid = grid;
+ }
+
+private:
+
+ Grid* _grid;
+ WingedEdge* _winged_edge;
+ unsigned _polygon_id;
+};
+
+#endif // WS_FILL_GRID_H
diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp
new file mode 100755
index 00000000000..55fa418d4f5
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp
@@ -0,0 +1,60 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "WEdge.h"
+#include "WSFillGrid.h"
+
+void WSFillGrid::fillGrid() {
+ if (!_winged_edge || !_grid)
+ return;
+
+ vector<WShape*> wshapes = _winged_edge->getWShapes();
+ vector<WVertex*> fvertices;
+ vector<Vec3r> vectors;
+ vector<WFace*> faces;
+
+ for (vector<WShape*>::const_iterator it = wshapes.begin();
+ it != wshapes.end();
+ it++) {
+ faces = (*it)->GetFaceList();
+
+ for (vector<WFace*>::const_iterator f = faces.begin();
+ f != faces.end();
+ f++) {
+ (*f)->RetrieveVertexList(fvertices);
+
+ for (vector<WVertex*>::const_iterator wv = fvertices.begin();
+ wv != fvertices.end();
+ wv++)
+ vectors.push_back(Vec3r((*wv)->GetVertex()));
+
+ // occluder will be deleted by the grid
+ Polygon3r *occluder =
+ new Polygon3r(vectors, (*f)->GetNormal());
+ occluder->setId(_polygon_id++);
+ occluder->userdata = (void*)(*f);
+ _grid->insertOccluder(occluder);
+ vectors.clear();
+ fvertices.clear();
+ }
+ faces.clear();
+ }
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.h b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h
new file mode 100755
index 00000000000..2ea5bc6c621
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h
@@ -0,0 +1,79 @@
+//
+// Filename : WSFillGrid.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to fill in a grid from a SceneGraph
+// (uses only the WingedEdge structures)
+// Date of creation : 03/05/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef WS_FILL_GRID_H
+# define WS_FILL_GRID_H
+
+# include "../geometry/Grid.h"
+# include "../geometry/Polygon.h"
+# include "WEdge.h"
+
+class LIB_WINGED_EDGE_EXPORT WSFillGrid
+{
+public:
+
+ inline WSFillGrid(Grid* grid = 0, WingedEdge* winged_edge = 0) {
+ _winged_edge = winged_edge;
+ _grid = grid;
+ _polygon_id = 0;
+ }
+
+ virtual ~WSFillGrid() {}
+
+ void fillGrid();
+
+ /*! Accessors */
+ WingedEdge* getWingedEdge() {
+ return _winged_edge;
+ }
+
+ Grid* getGrid() {
+ return _grid;
+ }
+
+ /*! Modifiers */
+ void setWingedEdge(WingedEdge* winged_edge) {
+ if (winged_edge)
+ _winged_edge = winged_edge;
+ }
+
+ void setGrid(Grid* grid) {
+ if (grid)
+ _grid = grid;
+ }
+
+private:
+
+ Grid* _grid;
+ WingedEdge* _winged_edge;
+ unsigned _polygon_id;
+};
+
+#endif // WS_FILL_GRID_H
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
new file mode 100755
index 00000000000..d238749570c
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
@@ -0,0 +1,296 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "WXEdge.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXFace */
+ /* */
+ /* */
+ /**********************************/
+
+unsigned int WXFaceLayer::Get0VertexIndex() const {
+ int i = 0;
+ int nEdges = _pWXFace->numberOfEdges();
+ for(i=0; i<nEdges; ++i){
+ if(_DotP[i] == 0){
+ return i;
+ }
+ }
+ return -1;
+}
+unsigned int WXFaceLayer::GetSmoothEdgeIndex() const{
+ int i = 0;
+ int nEdges = _pWXFace->numberOfEdges();
+ for(i=0; i<nEdges; ++i){
+ if((_DotP[i] == 0) && (_DotP[(i+1)%nEdges] == 0)){
+ return i;
+ }
+ }
+ return -1;
+}
+
+void WXFaceLayer::RetrieveCuspEdgesIndices(vector<int>& oCuspEdges){
+ int i = 0;
+ int nEdges = _pWXFace->numberOfEdges();
+ for(i=0; i<nEdges; ++i){
+ if(_DotP[i]*_DotP[(i+1)%nEdges] < 0){
+ // we got one
+ oCuspEdges.push_back(i);
+ }
+ }
+}
+
+WXSmoothEdge* WXFaceLayer::BuildSmoothEdge(){
+ // if the smooth edge has already been
+ // built: exit
+ if(0 != _pSmoothEdge)
+ return _pSmoothEdge;
+ real ta, tb;
+ WOEdge *woea(0), *woeb(0);
+ bool ok = false;
+ vector<int> cuspEdgesIndices;
+ int indexStart, indexEnd;
+ unsigned nedges = _pWXFace->numberOfEdges();
+ if(_nNullDotP == nedges){
+ _pSmoothEdge = 0;
+ return _pSmoothEdge;
+ }
+ if((_nPosDotP != 0) && (_nPosDotP != _DotP.size()) && (_nNullDotP == 0)){
+ // that means that we have a smooth edge that starts from
+ // an edge and ends at an edge
+ //-----------------------------
+ // We retrieve the 2 edges for which we have
+ // opposite signs for each extremity
+ RetrieveCuspEdgesIndices(cuspEdgesIndices);
+ if(cuspEdgesIndices.size() != 2) // we necessarly have 2 cusp edges
+ return 0;
+
+ // let us determine which cusp edge corresponds to the starting:
+ // We can do that because we defined that
+ // a silhouette edge had the back facing part on its right.
+ // So if the WOEdge woea is such that woea[0].dotp > 0 and
+ // woea[1].dotp < 0, it is the starting edge.
+ //-------------------------------------------
+
+ if(_DotP[cuspEdgesIndices[0]] > 0){
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
+ indexStart = cuspEdgesIndices[0];
+ indexEnd = cuspEdgesIndices[1];
+ }else{
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ indexStart = cuspEdgesIndices[1];
+ indexEnd = cuspEdgesIndices[0];
+ }
+
+ // Compute the interpolation:
+ ta = _DotP[indexStart]/(_DotP[indexStart]-_DotP[(indexStart+1)%nedges]);
+ tb = _DotP[indexEnd]/(_DotP[indexEnd]-_DotP[(indexEnd+1)%nedges]);
+ ok = true;
+ }else if(_nNullDotP == 1){
+ // that means that we have exactly one of the
+ // 2 extremities of our silhouette edge is
+ // a vertex of the mesh
+ if((_nPosDotP == 2) || (_nPosDotP == 0)){
+ _pSmoothEdge = 0;
+ return _pSmoothEdge;
+ }
+ RetrieveCuspEdgesIndices(cuspEdgesIndices);
+ // We should have only one EdgeCusp:
+ if(cuspEdgesIndices.size() != 1){
+ cout << "Warning in BuildSmoothEdge: weird WXFace configuration" << endl;
+ _pSmoothEdge = 0;
+ return 0;
+ }
+ unsigned index0 = Get0VertexIndex(); // retrieve the 0 vertex index
+ unsigned nedges = _pWXFace->numberOfEdges();
+ if(_DotP[cuspEdgesIndices[0]] > 0){
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ woeb = _pWXFace->GetOEdge(index0);
+ indexStart = cuspEdgesIndices[0];
+ ta = _DotP[indexStart]/(_DotP[indexStart]-_DotP[(indexStart+1)%nedges]);
+ tb = 0.0;
+ }else{
+ woea = _pWXFace->GetOEdge(index0);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ indexEnd = cuspEdgesIndices[0];
+ ta = 0.0;
+ tb = _DotP[indexEnd]/(_DotP[indexEnd]-_DotP[(indexEnd+1)%nedges]);
+ }
+ ok = true;
+ }else if(_nNullDotP == 2){
+ // that means that the silhouette edge
+ // is an edge of the mesh
+ int index = GetSmoothEdgeIndex();
+ if(!_pWXFace->front()) {// is it in the right order ?
+ // the order of the WOEdge index is wrong
+ woea = _pWXFace->GetOEdge((index+1)%nedges);
+ woeb = _pWXFace->GetOEdge((index-1)%nedges);
+ ta = 0;
+ tb = 1;
+ ok = true;
+ }else{
+ // here it's not good, our edge is a single point -> skip that face
+ ok = false;
+ // the order of the WOEdge index is good
+ // woea = _pWXFace->GetOEdge((index-1)%nedges);
+ // woeb = _pWXFace->GetOEdge((index+1)%nedges);
+ // ta = 1;
+ // tb = 0;
+ }
+ }
+ if(ok){
+ _pSmoothEdge = new WXSmoothEdge;
+ _pSmoothEdge->setWOeA(woea);
+ _pSmoothEdge->setWOeB(woeb);
+ _pSmoothEdge->setTa(ta);
+ _pSmoothEdge->setTb(tb);
+ if(_Nature & Nature::SILHOUETTE){
+ if(_nNullDotP != 2){
+ if(_DotP[_ClosestPointIndex] + 0.01 > 0)
+ _pSmoothEdge->setFront(true);
+ else
+ _pSmoothEdge->setFront(false);
+ }
+ }
+ }
+
+ // check bording edges to see if they have different dotp values
+ // in bording faces.
+ // for(int i=0; i<numberOfEdges(); i++)
+ // {
+ // WSFace * bface = (WSFace*)GetBordingFace(i);
+ // if(bface != 0)
+ // {
+ // if((front())^(bface->front())) // fA->front XOR fB->front (true if one is 0 and the other is 1)
+ // {
+ // // that means that the edge i of the face is
+ // // a silhouette edge
+ // // TESTER D'ABORD SI LE EXACTSILHOUETTEEDGE N'A PAS
+ // // ETE CONSTRUIT SUR L'AUTRE FACE.(1 suffit)
+ // if(0 != ((WSExactFace*)bface)->exactSilhouetteEdge())
+ // {
+ // // that means that this silhouette edge has already been built
+ // return ((WSExactFace*)bface)->exactSilhouetteEdge();
+ // }
+ // // Else we must build it
+ // WOEdge *woea, *woeb;
+ // real ta, tb;
+ // if(!front()) // is it in the right order ?
+ // {
+ // // the order of the WOEdge index is wrong
+ // woea = _OEdgeList[(i+1)%numberOfEdges()];
+ // if(0 == i)
+ // woeb = _OEdgeList[numberOfEdges()-1];
+ // else
+ // woeb = _OEdgeList[(i-1)];
+ // ta = 0;
+ // tb = 1;
+ // }
+ // else
+ // {
+ // // the order of the WOEdge index is good
+ // if(0 == i)
+ // woea = _OEdgeList[numberOfEdges()-1];
+ // else
+ // woea = _OEdgeList[(i-1)];
+ // woeb = _OEdgeList[(i+1)%numberOfEdges()];
+ // ta = 1;
+ // tb = 0;
+ // }
+ //
+ // _pSmoothEdge = new ExactSilhouetteEdge(ExactSilhouetteEdge::VERTEX_VERTEX);
+ // _pSmoothEdge->setWOeA(woea);
+ // _pSmoothEdge->setWOeA(woeb);
+ // _pSmoothEdge->setTa(ta);
+ // _pSmoothEdge->setTb(tb);
+ //
+ // return _pSmoothEdge;
+ // }
+ // }
+ //}
+ return _pSmoothEdge;
+}
+
+
+void WXFace::ComputeCenter()
+{
+ vector<WVertex*> iVertexList;
+ RetrieveVertexList(iVertexList);
+ Vec3r center;
+ for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end();
+ wv!=wvend;
+ wv++)
+ {
+ center += (*wv)->GetVertex();
+ }
+ center /= (real)iVertexList.size();
+ setCenter(center);
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+WFace* WXShape::MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex)
+{
+ WFace *face = WShape::MakeFace(iVertexList, iFaceEdgeMarksList, iMaterialIndex);
+ if(0 == face)
+ return 0;
+
+ Vec3r center;
+ for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end();
+ wv!=wvend;
+ wv++)
+ {
+ center += (*wv)->GetVertex();
+ }
+ center /= (real)iVertexList.size();
+ ((WXFace*)face)->setCenter(center);
+
+ return face;
+}
+
+WFace * WXShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex)
+{
+ WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iFaceEdgeMarksList, iMaterialIndex);
+
+ // Vec3r center;
+ // for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end();
+ // wv!=wvend;
+ // wv++)
+ // {
+ // center += (*wv)->GetVertex();
+ // }
+ // center /= (real)iVertexList.size();
+ // ((WSFace*)face)->setCenter(center);
+
+ return face;
+}
+
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h
new file mode 100755
index 00000000000..c51b6a84a98
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h
@@ -0,0 +1,582 @@
+//
+// Filename : WXEdge.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define an Extended Winged Edge data structure.
+// Date of creation : 26/10/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef WXEDGE_H
+# define WXEDGE_H
+
+# include "WEdge.h"
+# include "Nature.h"
+# include "Curvature.h"
+
+typedef Nature::EdgeNature WXNature;
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXVertex */
+ /* */
+ /* */
+ /**********************************/
+
+class WXVertex : public WVertex
+{
+private:
+ // Curvature info
+ CurvatureInfo *_curvatures;
+
+public:
+ inline WXVertex(const Vec3r &v)
+ : WVertex(v)
+ {_curvatures = 0;}
+ /*! Copy constructor */
+ WXVertex(WXVertex& iBrother)
+ : WVertex(iBrother)
+ {_curvatures = new CurvatureInfo(*iBrother._curvatures);}
+ virtual WVertex * duplicate()
+ {
+ WXVertex *clone = new WXVertex(*this);
+ return clone;
+ }
+ virtual ~WXVertex() {if(_curvatures) delete _curvatures;}
+ virtual void Reset() {if(_curvatures) _curvatures->Kr = 0.0;}
+ inline void setCurvatures(CurvatureInfo *ci) {_curvatures = ci;}
+
+ inline bool isFeature();
+ inline CurvatureInfo* curvatures() {return _curvatures;}
+
+};
+
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXEdge */
+ /* */
+ /* */
+ /**********************************/
+class WXEdge : public WEdge
+{
+private:
+ WXNature _nature; // flag to indicate whether the edge is a silhouette edge or not
+ int _order; // 0: the order doesn't matter. 1: the order is the orginal one. -1: the order is not good
+ bool _front; // a front facing edge is an edge for which the bording face which is the nearest
+ // from the viewpoint is front. A back facing edge is the opposite.
+
+public:
+ inline WXEdge()
+ : WEdge(){
+ _nature = Nature::NO_FEATURE;
+ _front = false;
+ _order=0;
+ }
+
+ inline WXEdge(WOEdge *iOEdge)
+ : WEdge(iOEdge)
+ { _nature = Nature::NO_FEATURE;_front = false;_order=0;}
+
+ inline WXEdge(WOEdge *iaOEdge, WOEdge *ibOEdge)
+ : WEdge(iaOEdge, ibOEdge)
+ { _nature = Nature::NO_FEATURE;_front = false;_order=0;}
+
+ /*! Copy constructor */
+ inline WXEdge(WXEdge& iBrother)
+ : WEdge(iBrother)
+ {_nature = iBrother.nature();_front = iBrother._front;_order = iBrother._order;}
+ virtual WEdge * duplicate()
+ {
+ WXEdge *clone = new WXEdge(*this);
+ return clone;
+ }
+
+ virtual ~WXEdge()
+ {}
+
+ virtual void Reset(){
+ _nature = _nature & ~Nature::SILHOUETTE;
+ _nature = _nature & ~Nature::SUGGESTIVE_CONTOUR;
+ }
+
+ /*! accessors */
+ inline WXNature nature() {return _nature;}
+ inline bool front() {return _front;}
+ inline int order() const {return _order;}
+
+ /*! modifiers */
+ inline void setFront(bool iFront) {_front = iFront;}
+ inline void setNature(WXNature iNature) {_nature = iNature;}
+ inline void AddNature(WXNature iNature) {_nature = _nature|iNature;}
+ inline void setOrder(int i) {_order = i;}
+
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXFace */
+ /* */
+ /* */
+ /**********************************/
+
+/*! Class to store a smooth edge (i.e Hertzman & Zorin smooth silhouette edges) */
+class WXSmoothEdge{
+public:
+ typedef enum{
+ EDGE_EDGE,
+ VERTEX_EDGE,
+ EDGE_VERTEX
+ } Configuration;
+
+ WOEdge *_woea; // Oriented edge from which the silhouette edge starts
+ WOEdge *_woeb; // Oriented edge where the silhouette edge ends
+ real _ta; // The silhouette starting point's coordinates are : _woea[0]+ta*(_woea[1]-_woea[0])
+ real _tb; // The silhouette ending point's coordinates are : _woeb[0]+ta*(_woeb[1]-_woeb[0])
+ bool _front;
+ Configuration _config;
+
+ WXSmoothEdge(){
+ _woea = 0;
+ _woeb = 0;
+ _ta = 0;
+ _tb = 0;
+ _front = false;
+ _config = EDGE_EDGE;
+ }
+ WXSmoothEdge(const WXSmoothEdge& iBrother){
+ _woea = iBrother._woea;
+ _woeb = iBrother._woeb;
+ _ta = iBrother._ta;
+ _tb = iBrother._tb;
+ _config = iBrother._config;
+ _front = iBrother._front;
+ }
+ ~WXSmoothEdge() {}
+
+ inline WOEdge * woea() {return _woea;}
+ inline WOEdge * woeb() {return _woeb;}
+ inline real ta() const {return _ta;}
+ inline real tb() const {return _tb;}
+ inline bool front() const {return _front;}
+ inline Configuration configuration() const {return _config;}
+
+ /*! modifiers */
+ inline void setWOeA(WOEdge *iwoea) {_woea = iwoea;}
+ inline void setWOeB(WOEdge *iwoeb) {_woeb = iwoeb;}
+ inline void setTa(real ta) {_ta = ta;}
+ inline void setTb(real tb) {_tb = tb;}
+ inline void setFront(bool iFront) {_front = iFront;}
+ inline void setConfiguration(Configuration iConf) {_config = iConf;}
+
+};
+/* Class to store a value per vertex and a smooth edge.
+ * The WXFace stores a list of these
+ */
+class WXFace;
+class LIB_WINGED_EDGE_EXPORT WXFaceLayer{
+public:
+ void * userdata;
+ WXFace * _pWXFace;
+ vector<real> _DotP;// in case of silhouette: the values obtained when computing the normal-view direction
+ // dot product. _DotP[i] is this value for the vertex i for that
+ // face.
+ WXSmoothEdge * _pSmoothEdge;
+ WXNature _Nature;
+
+ //oldtmp values
+ unsigned _nPosDotP; // count the number of positive dot products for vertices.
+ // if this number is != 0 and !=_DotP.size() -> it is a silhouette fac
+
+ unsigned _nNullDotP; // count the number of null dot products for vertices.
+ unsigned _ClosestPointIndex;
+ bool _viewDependant;
+
+ WXFaceLayer(WXFace *iFace, WXNature iNature, bool viewDependant){
+ _pWXFace = iFace;
+ _pSmoothEdge = 0;
+ _nPosDotP = 0;
+ _nNullDotP=0;
+ _Nature = iNature;
+ _viewDependant = viewDependant;
+ userdata = 0;
+ }
+ WXFaceLayer(const WXFaceLayer& iBrother){
+ _pWXFace = iBrother._pWXFace;
+ _pSmoothEdge = 0;
+ _DotP = iBrother._DotP;
+ _nPosDotP = iBrother._nPosDotP;
+ _nNullDotP = iBrother._nNullDotP;
+ _Nature = iBrother._Nature;
+ if(0 != iBrother._pSmoothEdge)
+ {
+ _pSmoothEdge = new WXSmoothEdge(*(iBrother._pSmoothEdge));
+ }
+ _viewDependant = iBrother._viewDependant;
+ userdata = 0;
+ }
+ virtual ~WXFaceLayer() {
+ if(!_DotP.empty())
+ _DotP.clear();
+ if(0 != _pSmoothEdge){
+ delete _pSmoothEdge;
+ _pSmoothEdge = 0;
+ }
+ }
+ inline const real dotP(int i) const {return _DotP[i];}
+ inline unsigned nPosDotP() const {return _nPosDotP;}
+ inline unsigned nNullDotP() const {return _nNullDotP;}
+ inline int closestPointIndex() const {return _ClosestPointIndex;}
+ inline Nature::EdgeNature nature() const {return _Nature;}
+ inline bool hasSmoothEdge() const {if(_pSmoothEdge) return true; return false;}
+ inline WXFace * getFace() {return _pWXFace;}
+ inline WXSmoothEdge * getSmoothEdge() {return _pSmoothEdge;}
+ inline bool isViewDependant() const {return _viewDependant;}
+ inline void setClosestPointIndex(int iIndex) {_ClosestPointIndex = iIndex;}
+
+ inline void removeSmoothEdge() {
+ if(!_DotP.empty())
+ _DotP.clear();
+ if (_pSmoothEdge) {
+ delete _pSmoothEdge;
+ _pSmoothEdge = 0;
+ }
+ }
+
+ /*! If one of the face layer vertex has a DotP equal
+ * to 0, this method returns the vertex where it happens
+ */
+ unsigned int Get0VertexIndex() const ;
+
+ /*! In case one of the edge of the triangle
+ * is a smooth edge, this method
+ * allows to retrieve the concerned edge
+ */
+ unsigned int GetSmoothEdgeIndex() const;
+ /*! retrieves the edges of the triangle for which
+ * the signs are different (a null value is not considered) for the dotp
+ * values at each edge extrimity
+ */
+ void RetrieveCuspEdgesIndices(vector<int>& oCuspEdges);
+ WXSmoothEdge * BuildSmoothEdge();
+ inline void setDotP(const vector<real>& iDotP) {_DotP = iDotP;}
+ inline void PushDotP(real iDotP) {
+ _DotP.push_back(iDotP);
+ if(iDotP > 0)
+ ++_nPosDotP;
+ if(iDotP == 0)
+ ++_nNullDotP;
+ }
+ inline void ReplaceDotP(unsigned int index, real newDotP){
+ _DotP[index] = newDotP;
+ updateDotPInfos();
+ }
+ inline void updateDotPInfos() {
+ _nPosDotP = 0;
+ _nNullDotP = 0;
+ for(vector<real>::iterator d=_DotP.begin(), dend=_DotP.end();
+ d!=dend;
+ ++d){
+ if((*d) > 0)
+ ++_nPosDotP;
+ if((*d) == 0)
+ ++_nNullDotP;
+ }
+ }
+};
+
+
+class WXFace : public WFace
+{
+protected:
+ Vec3r _center; // center of the face
+ real _Z; // distance from viewpoint to the center of the face
+ bool _front; // flag to tell whether the face is front facing or back facing
+ real _dotp; // value obtained when computing the normal-viewpoint dot product
+
+ vector<WXFaceLayer*> _SmoothLayers; // The data needed to store one or several smooth edges that traverse the face
+public:
+ inline WXFace() : WFace() {_Z=0.0;_front = false;}
+ /*! Copy constructor */
+ WXFace(WXFace& iBrother)
+ : WFace(iBrother)
+ {
+ _center = iBrother.center();
+ _Z = iBrother.Z();
+ _front = iBrother.front();
+ for(vector<WXFaceLayer*>::iterator wxf = iBrother._SmoothLayers.begin(), wxfend = iBrother._SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ _SmoothLayers.push_back(new WXFaceLayer(**wxf));
+ }
+ }
+ virtual WFace * duplicate()
+ {
+ WXFace * clone = new WXFace(*this);
+ return clone;
+ }
+
+ virtual ~WXFace() {
+ if(!_SmoothLayers.empty()){
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ delete (*wxf);
+ }
+ _SmoothLayers.clear();
+ }
+ }
+
+ /*! designed to build a specialized WEdge
+ * for use in MakeEdge
+ */
+ virtual WEdge * instanciateEdge() const {return new WXEdge;}
+
+ /*! accessors */
+ inline Vec3r& center() {return _center;}
+ inline real Z() {return _Z;}
+ inline bool front() {return _front;}
+ inline real dotp() {return _dotp;}
+ inline bool hasSmoothEdges() const {
+ for(vector<WXFaceLayer*>::const_iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if( ((*wxf)->hasSmoothEdge())){
+ return true;
+ }
+ }
+ return false;
+ }
+ vector<WXFaceLayer*>& getSmoothLayers() {return _SmoothLayers;}
+ /*! retrieve the smooth edges that match the Nature given as argument */
+ void retrieveSmoothEdges(WXNature iNature, vector<WXSmoothEdge*>& oSmoothEdges){
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if( ((*wxf)->hasSmoothEdge()) && ((*wxf)->_Nature & iNature) ){
+ oSmoothEdges.push_back((*wxf)->_pSmoothEdge);
+ }
+ }
+ }
+ void retrieveSmoothEdgesLayers(WXNature iNature, vector<WXFaceLayer*>& oSmoothEdgesLayers){
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if( ((*wxf)->hasSmoothEdge()) && ((*wxf)->_Nature & iNature) ){
+ oSmoothEdgesLayers.push_back((*wxf));
+ }
+ }
+ }
+ void retrieveSmoothLayers(WXNature iNature, vector<WXFaceLayer*>& oSmoothLayers){
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if((*wxf)->_Nature & iNature){
+ oSmoothLayers.push_back(*wxf);
+ }
+ }
+ }
+ /*! modifiers */
+ inline void setCenter(const Vec3r& iCenter) {_center = iCenter;}
+ void ComputeCenter();
+ inline void setZ(real z) {_Z = z;}
+ inline void setFront(bool iFront) {_front = iFront;}
+ inline void setDotP(real iDotP)
+ {
+ _dotp = iDotP;
+ if(_dotp > 0)
+ _front = true;
+ else
+ _front = false;
+ }
+ inline void AddSmoothLayer(WXFaceLayer * iLayer){
+ _SmoothLayers.push_back(iLayer);
+ }
+ inline void Reset() {
+ vector<WXFaceLayer*> layersToKeep;
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if((*wxf)->isViewDependant())
+ delete (*wxf);
+ else
+ layersToKeep.push_back(*wxf);
+ }
+ _SmoothLayers = layersToKeep;
+ }
+ /*! Clears everything */
+ inline void Clear() {
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ delete (*wxf);
+ }
+ _SmoothLayers.clear();
+ }
+ virtual void ResetUserData() {
+ WFace::ResetUserData();
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ (*wxf)->userdata = 0;
+ }
+ }
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+class WXShape : public WShape
+{
+public:
+ typedef WXShape type_name;
+protected:
+ bool _computeViewIndependant; // flag to indicate whether the view independant stuff must be computed or not
+public:
+ inline WXShape() : WShape() {_computeViewIndependant = true;}
+ /*! copy constructor */
+ inline WXShape(WXShape& iBrother)
+ :WShape(iBrother)
+ {
+ _computeViewIndependant = iBrother._computeViewIndependant;
+ }
+ virtual WShape * duplicate()
+ {
+ WXShape *clone = new WXShape(*this);
+ return clone;
+ }
+
+ virtual ~WXShape()
+ {
+ }
+
+ inline bool getComputeViewIndependantFlag() const {return _computeViewIndependant;}
+ inline void setComputeViewIndependantFlag(bool iFlag) {_computeViewIndependant = iFlag;}
+
+ /*! designed to build a specialized WFace
+ * for use in MakeFace
+ */
+ virtual WFace * instanciateFace() const {return new WXFace;}
+
+ /*! adds a new face to the shape
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
+
+ /*! adds a new face to the shape. The difference with
+ * the previous method is that this one is designed
+ * to build a WingedEdge structure for which there are
+ * per vertex normals, opposed to per face normals.
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ * iNormalsList
+ * The list of normals, iNormalsList[i] corresponding to the
+ * normal of the vertex iVertexList[i] for that face.
+ * iTexCoordsList
+ * The list of tex coords, iTexCoordsList[i] corresponding to the
+ * normal of the vertex iVertexList[i] for that face.
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
+
+ /*! Reset all edges and vertices flags (which might
+ * have been set up on a previous pass)
+ */
+ virtual void Reset(){
+ // Reset Edges
+ vector<WEdge*>& wedges = getEdgeList();
+ for(vector<WEdge*>::iterator we=wedges.begin(),weend=wedges.end();
+ we!=weend;
+ we++){
+ ((WXEdge*)(*we))->Reset();
+ }
+
+ //Reset faces:
+ vector<WFace*>& wfaces = GetFaceList();
+ for(vector<WFace*>::iterator wf=wfaces.begin(),wfend=wfaces.end();
+ wf!=wfend;
+ wf++){
+ ((WXFace*)(*wf))->Reset();
+ }
+ }
+ /*! accessors */
+};
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+/* for inline functions */
+
+bool WXVertex::isFeature()
+{
+ int counter = 0;
+ vector<WEdge*>& vedges = GetEdges();
+ for(vector<WEdge*>::iterator ve=vedges.begin(), vend=vedges.end();
+ ve!=vend;
+ ve++)
+ {
+ if(((WXEdge*)(*ve))->nature() != Nature::NO_FEATURE)
+ counter++;
+ }
+
+ if((counter == 1) || (counter > 2))
+ return true;
+
+ return false;
+}
+
+
+#endif
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
new file mode 100755
index 00000000000..b29f0c7e9ee
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "WXEdgeBuilder.h"
+#include "WXEdge.h"
+
+void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs)
+{
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ return;
+ WXShape *shape = new WXShape;
+ buildWShape(*shape, ifs);
+ shape->setId(ifs.getId().getFirst());
+ shape->setName(ifs.getName());
+ //ifs.setId(shape->GetId());
+}
+
+void WXEdgeBuilder::buildWVertices(WShape& shape,
+ const real *vertices,
+ unsigned vsize) {
+ WXVertex *vertex;
+ for (unsigned i = 0; i < vsize; i += 3) {
+ vertex = new WXVertex(Vec3r(vertices[i],
+ vertices[i + 1],
+ vertices[i + 2]));
+ vertex->setId(i / 3);
+ shape.AddVertex(vertex);
+ }
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
new file mode 100755
index 00000000000..b646d66a285
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
@@ -0,0 +1,51 @@
+#ifndef WXEDGEBUILDER_H
+# define WXEDGEBUILDER_H
+
+//
+// Filename : WSBuilder.h
+// Author(s) : Stephane Grabli
+// Purpose : Class inherited from WingedEdgeBuilder and
+// designed to build a WX (WingedEdge + extended info(silhouette etc...))
+// structure from a polygonal model
+// Date of creation : 28/05/03
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "WingedEdgeBuilder.h"
+# include "../scene_graph/IndexedFaceSet.h"
+
+class LIB_WINGED_EDGE_EXPORT WXEdgeBuilder : public WingedEdgeBuilder
+{
+public:
+ WXEdgeBuilder() : WingedEdgeBuilder() {}
+ virtual ~WXEdgeBuilder() {}
+ VISIT_DECL(IndexedFaceSet)
+
+protected:
+ virtual void buildWVertices(WShape& shape,
+ const real *vertices,
+ unsigned vsize);
+};
+
+#endif // WXEDGEBUILDER_H
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
new file mode 100755
index 00000000000..e56ac0f9c42
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
@@ -0,0 +1,386 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "../geometry/GeomUtils.h"
+#include "../scene_graph/NodeShape.h"
+#include "WingedEdgeBuilder.h"
+#include <set>
+using namespace std;
+
+void WingedEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ return;
+ WShape *shape = new WShape;
+ buildWShape(*shape, ifs);
+ shape->setId(ifs.getId().getFirst());
+ //ifs.setId(shape->GetId());
+}
+
+void WingedEdgeBuilder::visitNodeShape(NodeShape& ns) {
+ //Sets the current material to iShapeode->material:
+ _current_frs_material = &(ns.frs_material());
+}
+
+void WingedEdgeBuilder::visitNodeTransform(NodeTransform& tn) {
+ if(!_current_matrix) {
+ _current_matrix = new Matrix44r(tn.matrix());
+ return;
+ }
+
+ _matrices_stack.push_back(_current_matrix);
+ Matrix44r *new_matrix = new Matrix44r(*_current_matrix * tn.matrix());
+ _current_matrix = new_matrix;
+}
+
+void WingedEdgeBuilder::visitNodeTransformAfter(NodeTransform&) {
+ if(_current_matrix)
+ delete _current_matrix;
+
+ if(_matrices_stack.empty()) {
+ _current_matrix = NULL;
+ return;
+ }
+
+ _current_matrix = _matrices_stack.back();
+ _matrices_stack.pop_back();
+}
+
+void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) {
+ unsigned vsize = ifs.vsize();
+ unsigned nsize = ifs.nsize();
+ //soc unused - unsigned tsize = ifs.tsize();
+
+ const real* vertices = ifs.vertices();
+ const real* normals = ifs.normals();
+ const real* texCoords = ifs.texCoords();
+
+ real* new_vertices;
+ real* new_normals;
+
+ new_vertices = new real[vsize];
+ new_normals = new real[nsize];
+
+ // transform coordinates from local to world system
+ if(_current_matrix) {
+ transformVertices(vertices, vsize, *_current_matrix, new_vertices);
+ transformNormals(normals, nsize, *_current_matrix, new_normals);
+ }
+ else {
+ memcpy(new_vertices, vertices, vsize * sizeof(*new_vertices));
+ memcpy(new_normals, normals, nsize * sizeof(*new_normals));
+ }
+
+ const IndexedFaceSet::TRIANGLES_STYLE* faceStyle = ifs.trianglesStyle();
+
+ vector<FrsMaterial> frs_materials;
+ if(ifs.msize()){
+ const FrsMaterial*const* mats = ifs.frs_materials();
+ for(unsigned i=0; i<ifs.msize(); ++i)
+ frs_materials.push_back(*(mats[i]));
+ shape.setFrsMaterials(frs_materials);
+ }
+
+ // const FrsMaterial * mat = (ifs.frs_material());
+ // if (mat)
+ // shape.setFrsMaterial(*mat);
+ // else if(_current_frs_material)
+ // shape.setFrsMaterial(*_current_frs_material);
+
+ const IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = ifs.faceEdgeMarks();
+
+ // sets the current WShape to shape
+ _current_wshape = &shape;
+
+ // create a WVertex for each vertex
+ buildWVertices(shape, new_vertices, vsize);
+
+ const unsigned* vindices = ifs.vindices();
+ const unsigned* nindices = ifs.nindices();
+ const unsigned* tindices = 0;
+ if(ifs.tsize()){
+ tindices = ifs.tindices();
+ }
+
+ const unsigned *mindices = 0;
+ if(ifs.msize())
+ mindices = ifs.mindices();
+ const unsigned* numVertexPerFace = ifs.numVertexPerFaces();
+ const unsigned numfaces = ifs.numFaces();
+
+ for (unsigned index = 0; index < numfaces; index++) {
+ switch(faceStyle[index]) {
+ case IndexedFaceSet::TRIANGLE_STRIP:
+ buildTriangleStrip(new_vertices,
+ new_normals,
+ frs_materials,
+ texCoords,
+ faceEdgeMarks,
+ vindices,
+ nindices,
+ mindices,
+ tindices,
+ numVertexPerFace[index]);
+ break;
+ case IndexedFaceSet::TRIANGLE_FAN:
+ buildTriangleFan(new_vertices,
+ new_normals,
+ frs_materials,
+ texCoords,
+ faceEdgeMarks,
+ vindices,
+ nindices,
+ mindices,
+ tindices,
+ numVertexPerFace[index]);
+ break;
+ case IndexedFaceSet::TRIANGLES:
+ buildTriangles(new_vertices,
+ new_normals,
+ frs_materials,
+ texCoords,
+ faceEdgeMarks,
+ vindices,
+ nindices,
+ mindices,
+ tindices,
+ numVertexPerFace[index]);
+ break;
+ }
+ vindices += numVertexPerFace[index];
+ nindices += numVertexPerFace[index];
+ if(mindices)
+ mindices += numVertexPerFace[index];
+ if(tindices)
+ tindices += numVertexPerFace[index];
+ faceEdgeMarks++;
+ }
+
+ delete[] new_vertices;
+ delete[] new_normals;
+
+ // compute bbox
+ shape.ComputeBBox();
+ // compute mean edge size:
+ shape.ComputeMeanEdgeSize();
+
+ // Parse the built winged-edge shape to update post-flags
+ set<Vec3r> normalsSet;
+ vector<WVertex*>& wvertices = shape.getVertexList();
+ for(vector<WVertex*>::iterator wv=wvertices.begin(), wvend=wvertices.end();
+ wv!=wvend;
+ ++wv){
+ if((*wv)->isBoundary())
+ continue;
+ if ((*wv)->GetEdges().size() == 0) // This means that the WVertex has no incoming edges... (12-Sep-2011 T.K.)
+ continue;
+ normalsSet.clear();
+ WVertex::face_iterator fit = (*wv)->faces_begin();
+ WVertex::face_iterator fitend = (*wv)->faces_end();
+ while(fit!=fitend){
+ WFace *face = *fit;
+ normalsSet.insert(face->GetVertexNormal(*wv));
+ if(normalsSet.size()!=1){
+ break;
+ }
+ ++fit;
+ }
+ if(normalsSet.size()!=1){
+ (*wv)->setSmooth(false);
+ }
+ }
+ // Adds the new WShape to the WingedEdge structure
+ _winged_edge->addWShape(&shape);
+}
+
+void WingedEdgeBuilder::buildWVertices(WShape& shape,
+ const real *vertices,
+ unsigned vsize) {
+ WVertex *vertex;
+ for (unsigned i = 0; i < vsize; i += 3) {
+ vertex = new WVertex(Vec3r(vertices[i],
+ vertices[i + 1],
+ vertices[i + 2]));
+ vertex->setId(i / 3);
+ shape.AddVertex(vertex);
+ }
+}
+
+void WingedEdgeBuilder::buildTriangleStrip( const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices) {
+ unsigned nDoneVertices = 2; // number of vertices already treated
+ unsigned nTriangle = 0; // number of the triangle currently being treated
+ //int nVertex = 0; // vertex number
+
+ WShape* currentShape = _current_wshape; // the current shape being built
+ vector<WVertex *> triangleVertices;
+ vector<Vec3r> triangleNormals;
+ vector<Vec2r> triangleTexCoords;
+ vector<bool> triangleFaceEdgeMarks;
+
+ while(nDoneVertices < nvertices)
+ {
+ //clear the vertices list:
+ triangleVertices.clear();
+ //Then rebuild it:
+ if(0 == nTriangle%2) // if nTriangle is even
+ {
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+1]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+2]/3]);
+
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]],normals[nindices[nTriangle]+1], normals[nindices[nTriangle]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+1]],normals[nindices[nTriangle+1]+1],normals[nindices[nTriangle+1]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+2]], normals[nindices[nTriangle+2]+1], normals[nindices[nTriangle+2]+2]));
+
+ if(texCoords){
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]],texCoords[tindices[nTriangle]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]],texCoords[tindices[nTriangle+1]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+2]], texCoords[tindices[nTriangle+2]+1]));
+ }
+ }
+ else // if nTriangle is odd
+ {
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+2]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+1]/3]);
+
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]],normals[nindices[nTriangle]+1], normals[nindices[nTriangle]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+2]],normals[nindices[nTriangle+2]+1],normals[nindices[nTriangle+2]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+1]], normals[nindices[nTriangle+1]+1], normals[nindices[nTriangle+1]+2]));
+
+ if(texCoords){
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]],texCoords[tindices[nTriangle]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+2]],texCoords[tindices[nTriangle+2]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]], texCoords[tindices[nTriangle+1]+1]));
+ }
+ }
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::FACE_MARK) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V1V2) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V2V3) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V3V1) != 0);
+ if(mindices)
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, mindices[nTriangle/3]);
+ else
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0);
+ nDoneVertices++; // with a strip, each triangle is one vertex more
+ nTriangle++;
+ }
+}
+
+void WingedEdgeBuilder::buildTriangleFan( const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices) {
+ // Nothing to be done
+}
+
+void WingedEdgeBuilder::buildTriangles(const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices) {
+ WShape * currentShape = _current_wshape; // the current shape begin built
+ vector<WVertex *> triangleVertices;
+ vector<Vec3r> triangleNormals;
+ vector<Vec2r> triangleTexCoords;
+ vector<bool> triangleFaceEdgeMarks;
+
+ // Each triplet of vertices is considered as an independent triangle
+ for(unsigned i = 0; i < nvertices / 3; i++)
+ {
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i+1]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i+2]/3]);
+
+ triangleNormals.push_back(Vec3r(normals[nindices[3*i]],normals[nindices[3*i]+1], normals[nindices[3*i]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[3*i+1]],normals[nindices[3*i+1]+1],normals[nindices[3*i+1]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[3*i+2]], normals[nindices[3*i+2]+1], normals[nindices[3*i+2]+2]));
+
+ if(texCoords){
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i]],texCoords[tindices[3*i]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+1]],texCoords[tindices[3*i+1]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+2]], texCoords[tindices[3*i+2]+1]));
+ }
+
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::FACE_MARK) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V1V2) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V2V3) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V3V1) != 0);
+ }
+ if(mindices)
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, mindices[0]);
+ else
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0);
+
+}
+
+void WingedEdgeBuilder::transformVertices(const real *vertices,
+ unsigned vsize,
+ const Matrix44r& transform,
+ real *res) {
+ const real *v = vertices;
+ real *pv = res;
+
+ for (unsigned i = 0; i < vsize / 3; i++) {
+ HVec3r hv_tmp(v[0], v[1], v[2]);
+ HVec3r hv(transform * hv_tmp);
+ for (unsigned j = 0; j < 3; j++)
+ pv[j] = hv[j] / hv[3];
+ v += 3;
+ pv += 3;
+ }
+}
+
+void WingedEdgeBuilder::transformNormals(const real *normals,
+ unsigned nsize,
+ const Matrix44r& transform,
+ real* res) {
+ const real *n = normals;
+ real *pn = res;
+
+ for (unsigned i = 0; i < nsize / 3; i++) {
+ Vec3r hn(n[0], n[1], n[2]);
+ hn = GeomUtils::rotateVector(transform, hn);
+ for (unsigned j = 0; j < 3; j++)
+ pn[j] = hn[j];
+ n += 3;
+ pn += 3;
+ }
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
new file mode 100755
index 00000000000..972d67355d2
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
@@ -0,0 +1,171 @@
+//
+// Filename : WingedEdgeBuilder.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to render a WingedEdge data structure
+// from a polyhedral data structure organized in
+// nodes of a scene graph
+// Date of creation : 28/05/03
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef WINGED_EDGE_BUILDER_H
+# define WINGED_EDGE_BUILDER_H
+
+# include "../system/FreestyleConfig.h"
+# include "../system/RenderMonitor.h"
+# include "../scene_graph/SceneVisitor.h"
+# include "WEdge.h"
+# include "../scene_graph/IndexedFaceSet.h"
+# include "../scene_graph/NodeTransform.h"
+
+class LIB_WINGED_EDGE_EXPORT WingedEdgeBuilder : public SceneVisitor
+{
+ public:
+
+ inline WingedEdgeBuilder() : SceneVisitor() {
+ _current_wshape = NULL;
+ _current_frs_material = NULL;
+ _current_matrix = NULL;
+ _winged_edge = new WingedEdge; // Not deleted by the destructor
+ _pRenderMonitor = NULL;
+ }
+
+ virtual ~WingedEdgeBuilder() {
+ for (vector<Matrix44r*>::iterator it = _matrices_stack.begin();
+ it != _matrices_stack.end();
+ it++)
+ delete *it;
+ _matrices_stack.clear();
+ }
+
+ VISIT_DECL(IndexedFaceSet)
+ VISIT_DECL(NodeShape)
+ VISIT_DECL(NodeTransform)
+
+ virtual void visitNodeTransformAfter(NodeTransform&);
+
+ //
+ // Accessors
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline WingedEdge* getWingedEdge() {
+ return _winged_edge;
+ }
+
+ inline WShape* getCurrentWShape() {
+ return _current_wshape;
+ }
+
+ inline FrsMaterial* getCurrentFrsMaterial() {
+ return _current_frs_material;
+ }
+
+ inline Matrix44r* getCurrentMatrix() {
+ return _current_matrix;
+ }
+
+ //
+ // Modifiers
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline void setCurrentWShape(WShape* wshape) {
+ _current_wshape = wshape;
+ }
+
+ inline void setCurrentFrsMaterial(FrsMaterial* mat) {
+ _current_frs_material = mat;
+ }
+
+ // inline void setCurrentMatrix(Matrix44r* matrix) {
+ // _current_matrix = matrix;
+ // }
+
+ inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {
+ _pRenderMonitor = iRenderMonitor;
+ }
+
+ protected:
+
+ virtual void buildWShape(WShape& shape, IndexedFaceSet& ifs);
+ virtual void buildWVertices(WShape& shape,
+ const real *vertices,
+ unsigned vsize);
+
+ RenderMonitor *_pRenderMonitor;
+
+ private:
+
+ void buildTriangleStrip(const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices);
+
+ void buildTriangleFan(const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices);
+
+ void buildTriangles(const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices);
+
+ void transformVertices(const real *vertices,
+ unsigned vsize,
+ const Matrix44r& transform,
+ real *res);
+
+ void transformNormals(const real *normals,
+ unsigned nsize,
+ const Matrix44r& transform,
+ real *res);
+
+ WShape* _current_wshape;
+ FrsMaterial* _current_frs_material;
+ WingedEdge* _winged_edge;
+ Matrix44r* _current_matrix;
+ vector<Matrix44r*> _matrices_stack;
+};
+
+#endif // WINGED_EDGE_BUILDER_H
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 1729ac06f5a..745ca1ef2ac 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -162,8 +162,9 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4],
struct MFace *mface, struct MVert *mvert,
int *face_indices, int totface);
-void GPU_update_mesh_buffers(GPU_Buffers *buffers, struct MVert *mvert,
- int *vert_indices, int totvert, const float *vmask);
+void GPU_update_mesh_buffers(GPU_Buffers *buffers, struct MFace *mface, int *face_indices, int totface,
+ struct MVert *mvert, int *vert_indices, int totvert,
+ int (*face_vert_indices)[4], const float *vmask);
GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid,
unsigned int **grid_hidden, int gridsize);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 467adbe10b8..7d829bd57bf 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -75,6 +75,8 @@ void GPU_end_object_materials(void);
int GPU_enable_material(int nr, void *attribs);
void GPU_disable_material(void);
+void GPU_material_diffuse_get(int nr, float diff[4]);
+
void GPU_set_material_alpha_blend(int alphablend);
int GPU_get_material_alpha_blend(void);
@@ -119,7 +121,7 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap);
/* Image updates and free
* - these deal with images bound as opengl textures */
-void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h, int mipmap);
+void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h);
void GPU_update_images_framechange(void);
int GPU_update_image_time(struct Image *ima, double time);
int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, int compare, int mipmap, int ncd);
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index c44a181841e..930573ec750 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -54,6 +54,7 @@
#include "DNA_userdef_types.h"
#include "GPU_buffers.h"
+#include "GPU_draw.h"
typedef enum {
GPU_BUFFER_VERTEX_STATE = 1,
@@ -1280,6 +1281,8 @@ typedef struct {
char pad[2];
unsigned char color[3];
+ float accum_color[3];
+ int tot_color;
} VertexBufferFormat;
struct GPU_Buffers {
@@ -1327,24 +1330,24 @@ static void gpu_colors_disable(VBO_State vbo_state)
static float gpu_color_from_mask(float mask)
{
- return (1.0f - mask) * 0.5f + 0.25f;
+ return 1.0f - mask;
}
-static void gpu_color_from_mask_copy(float mask, unsigned char out[3])
+static void gpu_color_from_mask_copy(float mask, const float diffuse_color[4], unsigned char out[3])
{
- unsigned char color;
-
- color = gpu_color_from_mask(mask) * 255.0f;
+ float mask_color;
+
+ mask_color = gpu_color_from_mask(mask) * 255.0f;
- out[0] = color;
- out[1] = color;
- out[2] = color;
+ out[0] = diffuse_color[0] * mask_color;
+ out[1] = diffuse_color[1] * mask_color;
+ out[2] = diffuse_color[2] * mask_color;
}
-static void gpu_color_from_mask_set(float mask)
+static void gpu_color_from_mask_set(float mask, float diffuse_color[4])
{
float color = gpu_color_from_mask(mask);
- glColor3f(color, color, color);
+ glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color);
}
static float gpu_color_from_mask_quad(const CCGKey *key,
@@ -1360,29 +1363,32 @@ static float gpu_color_from_mask_quad(const CCGKey *key,
static void gpu_color_from_mask_quad_copy(const CCGKey *key,
CCGElem *a, CCGElem *b,
CCGElem *c, CCGElem *d,
+ const float *diffuse_color,
unsigned char out[3])
{
- unsigned char color =
+ float mask_color =
gpu_color_from_mask((*CCG_elem_mask(key, a) +
*CCG_elem_mask(key, b) +
*CCG_elem_mask(key, c) +
*CCG_elem_mask(key, d)) * 0.25f) * 255.0f;
- out[0] = color;
- out[1] = color;
- out[2] = color;
+ out[0] = diffuse_color[0] * mask_color;
+ out[1] = diffuse_color[1] * mask_color;
+ out[2] = diffuse_color[2] * mask_color;
}
static void gpu_color_from_mask_quad_set(const CCGKey *key,
CCGElem *a, CCGElem *b,
- CCGElem *c, CCGElem *d)
+ CCGElem *c, CCGElem *d,
+ float diffuse_color[4])
{
float color = gpu_color_from_mask_quad(key, a, b, c, d);
- glColor3f(color, color, color);
+ glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color);
}
-void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert,
- int *vert_indices, int totvert, const float *vmask)
+void GPU_update_mesh_buffers(GPU_Buffers *buffers, MFace *mface, int *face_indices, int totface,
+ MVert *mvert, int *vert_indices, int totvert,
+ int (*face_vert_indices)[4], const float *vmask)
{
VertexBufferFormat *vert_data;
int i;
@@ -1404,8 +1410,40 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert,
copy_v3_v3(out->co, v->co);
memcpy(out->no, v->no, sizeof(short) * 3);
- gpu_color_from_mask_copy(vmask[vert_indices[i]],
- out->color);
+ zero_v3(out->accum_color);
+ out->tot_color = 0;
+ }
+
+#define UPDATE_VERTEX(face, vertex, index, diffuse_color) \
+ { \
+ VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \
+ add_v3_v3(out->accum_color, diffuse_color); \
+ out->tot_color++; \
+ } (void)0
+
+ for (i = 0; i < totface; ++i) {
+ MFace *f = mface + face_indices[i];
+ float diffuse_color[4];
+
+ GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+
+ UPDATE_VERTEX(i, f->v1, 0, diffuse_color);
+ UPDATE_VERTEX(i, f->v2, 1, diffuse_color);
+ UPDATE_VERTEX(i, f->v3, 2, diffuse_color);
+ if (f->v4)
+ UPDATE_VERTEX(i, f->v4, 3, diffuse_color);
+ }
+#undef UPDATE_VERTEX
+
+ for (i = 0; i < totvert; ++i) {
+ VertexBufferFormat *out = vert_data + i;
+ if (out->tot_color) {
+ float diffuse_color[4];
+
+ mul_v3_v3fl(diffuse_color, out->accum_color, 1.0f / out->tot_color);
+
+ gpu_color_from_mask_copy(vmask[vert_indices[i]], diffuse_color, out->color);
+ }
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
@@ -1517,6 +1555,10 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids,
for (i = 0; i < totgrid; ++i) {
VertexBufferFormat *vd = vert_data;
CCGElem *grid = grids[grid_indices[i]];
+ const DMFlagMat *flags = &grid_flag_mats[grid_indices[i]];
+ float diffuse_color[4];
+
+ GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
for (y = 0; y < key->grid_size; y++) {
for (x = 0; x < key->grid_size; x++) {
@@ -1524,11 +1566,9 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids,
copy_v3_v3(vd->co, CCG_elem_co(key, elem));
if (smooth) {
- normal_float_to_short_v3(vd->no,
- CCG_elem_no(key, elem));
+ normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem));
- gpu_color_from_mask_copy(*CCG_elem_mask(key, elem),
- vd->color);
+ gpu_color_from_mask_copy(*CCG_elem_mask(key, elem), diffuse_color, vd->color);
}
vd++;
}
@@ -1561,6 +1601,7 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids,
elems[1],
elems[2],
elems[3],
+ diffuse_color,
vd->color);
}
}
@@ -1769,6 +1810,9 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth)
{
const MVert *mvert = buffers->mvert;
int i, j;
+ float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
+
+ glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_color);
gpu_colors_enable(VBO_DISABLED);
@@ -1784,7 +1828,7 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth)
if (smooth) {
for (j = 0; j < S; j++) {
- gpu_color_from_mask_set(buffers->vmask[fv[j]]);
+ gpu_color_from_mask_set(buffers->vmask[fv[j]], diffuse_color);
glNormal3sv(mvert[fv[j]].no);
glVertex3fv(mvert[fv[j]].co);
}
@@ -1809,7 +1853,7 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth)
fmask = (fmask + buffers->vmask[fv[3]]) * 0.25;
else
fmask /= 3.0f;
- gpu_color_from_mask_set(fmask);
+ gpu_color_from_mask_set(fmask, diffuse_color);
for (j = 0; j < S; j++)
glVertex3fv(mvert[fv[j]].co);
@@ -1825,6 +1869,9 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth)
{
const CCGKey *key = &buffers->gridkey;
int i, j, x, y, gridsize = buffers->gridkey.grid_size;
+ float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
+
+ glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_color);
gpu_colors_enable(VBO_DISABLED);
@@ -1853,7 +1900,7 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth)
if (smooth) {
for (j = 0; j < 4; j++) {
- gpu_color_from_mask_set(*CCG_elem_mask(key, e[j]));
+ gpu_color_from_mask_set(*CCG_elem_mask(key, e[j]), diffuse_color);
glNormal3fv(CCG_elem_no(key, e[j]));
glVertex3fv(CCG_elem_co(key, e[j]));
}
@@ -1866,7 +1913,7 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth)
CCG_elem_co(key, e[2]),
CCG_elem_co(key, e[3]));
glNormal3fv(fno);
- gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3]);
+ gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3], diffuse_color);
for (j = 0; j < 4; j++)
glVertex3fv(CCG_elem_co(key, e[j]));
@@ -1883,10 +1930,10 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth)
CCGElem *a = CCG_grid_elem(key, grid, x, y);
CCGElem *b = CCG_grid_elem(key, grid, x, y + 1);
- gpu_color_from_mask_set(*CCG_elem_mask(key, a));
+ gpu_color_from_mask_set(*CCG_elem_mask(key, a), diffuse_color);
glNormal3fv(CCG_elem_no(key, a));
glVertex3fv(CCG_elem_co(key, a));
- gpu_color_from_mask_set(*CCG_elem_mask(key, b));
+ gpu_color_from_mask_set(*CCG_elem_mask(key, b), diffuse_color);
glNormal3fv(CCG_elem_no(key, b));
glVertex3fv(CCG_elem_co(key, b));
}
@@ -1912,7 +1959,7 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth)
CCG_elem_co(key, c));
glNormal3fv(fno);
- gpu_color_from_mask_quad_set(key, a, b, c, d);
+ gpu_color_from_mask_quad_set(key, a, b, c, d, diffuse_color);
}
glVertex3fv(CCG_elem_co(key, a));
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 9b027f7906d..60e3c19a419 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -709,7 +709,7 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int
*/
int GPU_upload_dxt_texture(ImBuf *ibuf)
{
-#if WITH_DDS
+#ifdef WITH_DDS
GLint format = 0;
int blocksize, height, width, i, size, offset = 0;
@@ -878,13 +878,13 @@ void GPU_paint_set_mipmap(int mipmap)
}
}
-void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap)
+void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
{
ImBuf *ibuf;
ibuf = BKE_image_get_ibuf(ima, NULL);
- if (ima->repbind || (GPU_get_mipmap() && mipmap) || !ima->bindcode || !ibuf ||
+ if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf ||
(!is_power_of_2_i(ibuf->x) || !is_power_of_2_i(ibuf->y)) ||
(w == 0) || (h == 0))
{
@@ -911,8 +911,14 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap)
MEM_freeN(buffer);
- if (ima->tpageflag & IMA_MIPMAP_COMPLETE)
+ /* we have already accounted for the case where GTS.gpu_mipmap is false
+ * so we will be using GPU mipmap generation here */
+ if (GPU_get_mipmap()) {
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+ else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+ }
return;
}
@@ -934,8 +940,13 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap)
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
- if (ima->tpageflag & IMA_MIPMAP_COMPLETE)
+ /* see comment above as to why we are using gpu mipmap generation here */
+ if (GPU_get_mipmap()) {
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+ else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+ }
}
}
@@ -1429,6 +1440,21 @@ void GPU_disable_material(void)
GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
}
+void GPU_material_diffuse_get(int nr, float diff[4])
+{
+ /* prevent index to use un-initialized array items */
+ if (nr >= GMS.totmat)
+ nr = 0;
+
+ /* no GPU_begin_object_materials, use default material */
+ if (!GMS.matbuf) {
+ mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit);
+ }
+ else {
+ copy_v4_v4(diff, GMS.matbuf[nr].diff);
+ }
+}
+
void GPU_end_object_materials(void)
{
GPU_disable_material();
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index c5722995d32..d88f954345f 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -393,7 +393,7 @@ static bool constraint_valid(bConstraint *con)
return true;
}
-int initialize_scene(Object *ob, bPoseChannel *pchan_tip)
+static int initialize_scene(Object *ob, bPoseChannel *pchan_tip)
{
bConstraint *con;
int treecount;
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index 8849265679a..bbe70a7d73f 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -76,10 +76,12 @@ set(SRC
IMB_thumbs.h
intern/IMB_allocimbuf.h
intern/IMB_anim.h
+ intern/IMB_colormanagement_intern.h
intern/IMB_filetype.h
intern/IMB_filter.h
intern/IMB_indexer.h
intern/IMB_metadata.h
+ intern/imbuf.h
intern/cineon/cin_debug_stuff.h
intern/cineon/cineonfile.h
intern/cineon/cineonlib.h
@@ -97,7 +99,6 @@ set(SRC
intern/dds/PixelFormat.h
intern/dds/Stream.h
intern/dds/dds_api.h
- intern/imbuf.h
intern/openexr/openexr_api.h
intern/openexr/openexr_multi.h
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index d09007985b0..5d0ab5e57d4 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -62,6 +62,7 @@ void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *d
struct ColorManagedViewSettings *view_settings);
const char *IMB_colormanagement_role_colorspace_name_get(int role);
+void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *name);
/* ** Color space transformation functions ** */
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels,
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 93e213dc486..f03f709f13f 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -131,6 +131,7 @@ typedef struct ImBuf {
struct ColorSpace *float_colorspace; /* color space of float buffer, used by sequencer only */
unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */
struct ColormanageCache *colormanage_cache; /* cache used by color management */
+ int colormanage_flag;
/* information for compressed textures */
struct DDSData dds_data;
@@ -260,4 +261,8 @@ extern const char *imb_ext_image_qt[];
extern const char *imb_ext_movie[];
extern const char *imb_ext_audio[];
+enum {
+ IMB_COLORMANAGE_IS_DATA = (1 << 0)
+};
+
#endif
diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
index 0c002b78848..059bdee00eb 100644
--- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h
+++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
@@ -48,6 +48,7 @@ typedef struct ColorSpace {
struct ConstProcessorRcPtr *from_scene_linear;
int is_invertible;
+ int is_data;
} ColorSpace;
typedef struct ColorManagedDisplay {
@@ -79,7 +80,7 @@ struct ColorManagedView *colormanage_view_add(const char *name);
struct ColorManagedView *colormanage_view_get_indexed(int index);
struct ColorManagedView *colormanage_view_get_named(const char *name);
-struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible);
+struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible, int is_data);
struct ColorSpace *colormanage_colorspace_get_named(const char *name);
struct ColorSpace *colormanage_colorspace_get_roled(int role);
struct ColorSpace *colormanage_colorspace_get_indexed(int index);
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 6db45f0308a..11dce3087c6 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -68,7 +68,8 @@
/*********************** Global declarations *************************/
-#define MAX_COLORSPACE_NAME 64
+#define MAX_COLORSPACE_NAME 64
+#define DISPLAY_BUFFER_CHANNELS 4
/* ** list of all supported color spaces, displays and views */
static char global_role_scene_linear[MAX_COLORSPACE_NAME];
@@ -329,8 +330,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
ColormnaageCacheData *cache_data;
BLI_assert(cache_ibuf->x == ibuf->x &&
- cache_ibuf->y == ibuf->y &&
- cache_ibuf->channels == ibuf->channels);
+ cache_ibuf->y == ibuf->y);
/* only buffers with different color space conversions are being stored
* in cache separately. buffer which were used only different exposure/gamma
@@ -411,12 +411,15 @@ static void colormanage_cache_handle_release(void *cache_handle)
/*********************** Initialization / De-initialization *************************/
-static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char *colorspace_name, const char *role)
+static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char *colorspace_name, const char *role, const char *backup_role)
{
ConstColorSpaceRcPtr *ociocs;
ociocs = OCIO_configGetColorSpace(config, role);
+ if (!ociocs && backup_role)
+ ociocs = OCIO_configGetColorSpace(config, backup_role);
+
if (ociocs) {
const char *name = OCIO_colorSpaceGetName(ociocs);
@@ -435,27 +438,28 @@ static void colormanage_load_config(ConstConfigRcPtr *config)
const char *name;
/* get roles */
- colormanage_role_color_space_name_get(config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR);
- colormanage_role_color_space_name_get(config, global_role_color_picking, OCIO_ROLE_COLOR_PICKING);
- colormanage_role_color_space_name_get(config, global_role_texture_painting, OCIO_ROLE_TEXTURE_PAINT);
- colormanage_role_color_space_name_get(config, global_role_default_sequencer, OCIO_ROLE_DEFAULT_SEQUENCER);
- colormanage_role_color_space_name_get(config, global_role_default_byte, OCIO_ROLE_DEFAULT_BYTE);
- colormanage_role_color_space_name_get(config, global_role_default_float, OCIO_ROLE_DEFAULT_FLOAT);
+ colormanage_role_color_space_name_get(config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR, NULL);
+ colormanage_role_color_space_name_get(config, global_role_color_picking, OCIO_ROLE_COLOR_PICKING, NULL);
+ colormanage_role_color_space_name_get(config, global_role_texture_painting, OCIO_ROLE_TEXTURE_PAINT, NULL);
+ colormanage_role_color_space_name_get(config, global_role_default_sequencer, OCIO_ROLE_DEFAULT_SEQUENCER, OCIO_ROLE_SCENE_LINEAR);
+ colormanage_role_color_space_name_get(config, global_role_default_byte, OCIO_ROLE_DEFAULT_BYTE, OCIO_ROLE_TEXTURE_PAINT);
+ colormanage_role_color_space_name_get(config, global_role_default_float, OCIO_ROLE_DEFAULT_FLOAT, OCIO_ROLE_SCENE_LINEAR);
/* load colorspaces */
tot_colorspace = OCIO_configGetNumColorSpaces(config);
for (index = 0 ; index < tot_colorspace; index++) {
ConstColorSpaceRcPtr *ocio_colorspace;
const char *description;
- int is_invertible;
+ int is_invertible, is_data;
name = OCIO_configGetColorSpaceNameByIndex(config, index);
ocio_colorspace = OCIO_configGetColorSpace(config, name);
description = OCIO_colorSpaceGetDescription(ocio_colorspace);
is_invertible = OCIO_colorSpaceIsInvertible(ocio_colorspace);
+ is_data = OCIO_colorSpaceIsData(ocio_colorspace);
- colormanage_colorspace_add(name, description, is_invertible);
+ colormanage_colorspace_add(name, description, is_invertible, is_data);
OCIO_colorSpaceRelease(ocio_colorspace);
}
@@ -565,6 +569,10 @@ void IMB_colormanagement_init(void)
}
}
+ if (config == NULL) {
+ config = OCIO_getDefaultConfig();
+ }
+
if (config) {
OCIO_setCurrentConfig(config);
@@ -789,10 +797,12 @@ static void init_default_view_settings(const ColorManagedDisplaySettings *displa
ColorManagedViewSettings *view_settings)
{
ColorManagedDisplay *display;
- ColorManagedView *default_view;
+ ColorManagedView *default_view = NULL;
display = colormanage_display_get_named(display_settings->display_device);
- default_view = colormanage_view_get_default(display);
+
+ if (display)
+ default_view = colormanage_view_get_default(display);
if (default_view)
BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
@@ -837,6 +847,13 @@ void colormanage_imbuf_set_default_spaces(ImBuf *ibuf)
void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
{
+ ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace);
+
+ if (colorspace->is_data) {
+ ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA;
+ return;
+ }
+
if (ibuf->rect_float) {
const char *to_colorspace = global_role_scene_linear;
int predivide = ibuf->flags & IB_cm_predivide;
@@ -874,11 +891,13 @@ static void colormanage_check_view_settings(ColorManagedDisplaySettings *display
ColorManagedViewSettings *view_settings, const char *what)
{
ColorManagedDisplay *display;
- ColorManagedView *default_view;
+ ColorManagedView *default_view = NULL;
if (view_settings->view_transform[0] == '\0') {
display = colormanage_display_get_named(display_settings->display_device);
- default_view = colormanage_view_get_default(display);
+
+ if (display)
+ default_view = colormanage_view_get_default(display);
if (default_view)
BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
@@ -888,7 +907,9 @@ static void colormanage_check_view_settings(ColorManagedDisplaySettings *display
if (!view) {
display = colormanage_display_get_named(display_settings->display_device);
- default_view = colormanage_view_get_default(display);
+
+ if (display)
+ default_view = colormanage_view_get_default(display);
if (default_view) {
printf("Color management: %s view \"%s\" not found, setting default \"%s\".\n",
@@ -970,11 +991,13 @@ void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_
ColorManagedViewSettings *view_settings)
{
ColorManagedDisplay *display;
- ColorManagedView *default_view;
+ ColorManagedView *default_view = NULL;
LinkData *view_link;
display = colormanage_display_get_named(display_settings->display_device);
- default_view = colormanage_view_get_default(display);
+
+ if (display)
+ default_view = colormanage_view_get_default(display);
for (view_link = display->views.first; view_link; view_link = view_link->next) {
ColorManagedView *view = view_link->data;
@@ -983,7 +1006,7 @@ void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_
break;
}
- if (view_link == NULL)
+ if (view_link == NULL && default_view)
BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
}
@@ -1016,6 +1039,19 @@ const char *IMB_colormanagement_role_colorspace_name_get(int role)
return NULL;
}
+void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name)
+{
+ ColorSpace *colorspace = colormanage_colorspace_get_named(name);
+ if (colorspace) {
+ ibuf->rect_colorspace = colorspace;
+
+ if (colorspace->is_data)
+ ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA;
+ else
+ ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA;
+ }
+}
+
/*********************** Threaded display buffer transform routines *************************/
typedef struct DisplayBufferThread {
@@ -1034,6 +1070,7 @@ typedef struct DisplayBufferThread {
int channels;
float dither;
int predivide;
+ int is_data;
const char *byte_colorspace;
const char *float_colorspace;
@@ -1063,8 +1100,10 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
int predivide = ibuf->flags & IB_cm_predivide;
int channels = ibuf->channels;
float dither = ibuf->dither;
+ int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
int offset = channels * start_line * ibuf->x;
+ int display_buffer_byte_offset = DISPLAY_BUFFER_CHANNELS * start_line * ibuf->x;
memset(handle, 0, sizeof(DisplayBufferThread));
@@ -1080,7 +1119,7 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
handle->display_buffer = init_data->display_buffer + offset;
if (init_data->display_buffer_byte)
- handle->display_buffer_byte = init_data->display_buffer_byte + offset;
+ handle->display_buffer_byte = init_data->display_buffer_byte + display_buffer_byte_offset;
handle->width = ibuf->x;
@@ -1090,6 +1129,7 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
handle->channels = channels;
handle->dither = dither;
handle->predivide = predivide;
+ handle->is_data = is_data;
handle->byte_colorspace = init_data->byte_colorspace;
handle->float_colorspace = init_data->float_colorspace;
@@ -1106,6 +1146,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
int buffer_size = channels * width * height;
int predivide = handle->predivide;
+ int is_data = handle->is_data;
linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer");
@@ -1127,9 +1168,11 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
*fp = (float)(*cp) / 255.0f;
}
- /* convert float buffer to scene linear space */
- IMB_colormanagement_transform(linear_buffer, width, height, channels,
- from_colorspace, to_colorspace, predivide);
+ if (!is_data) {
+ /* convert float buffer to scene linear space */
+ IMB_colormanagement_transform(linear_buffer, width, height, channels,
+ from_colorspace, to_colorspace, predivide);
+ }
}
else if (handle->float_colorspace) {
/* currently float is non-linear only in sequencer, which is working
@@ -1166,7 +1209,6 @@ static void *do_display_buffer_apply_thread(void *handle_v)
{
DisplayBufferThread *handle = (DisplayBufferThread *) handle_v;
ColormanageProcessor *cm_processor = handle->cm_processor;
- float *buffer = handle->buffer;
float *display_buffer = handle->display_buffer;
unsigned char *display_buffer_byte = handle->display_buffer_byte;
int channels = handle->channels;
@@ -1174,25 +1216,45 @@ static void *do_display_buffer_apply_thread(void *handle_v)
int height = handle->tot_line;
float dither = handle->dither;
int predivide = handle->predivide;
+ int is_data = handle->is_data;
- float *linear_buffer = display_buffer_apply_get_linear_buffer(handle);
-
- /* apply processor */
- IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide);
+ if (cm_processor == NULL) {
+ if (display_buffer_byte) {
+ IMB_buffer_byte_from_byte(display_buffer_byte, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ FALSE, width, height, width, width);
+ }
- /* copy result to output buffers */
- if (display_buffer_byte) {
- /* do conversion */
- IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer,
- channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- predivide, width, height, width, width);
+ if (display_buffer) {
+ IMB_buffer_float_from_byte(display_buffer, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ FALSE, width, height, width, width);
+ }
}
+ else {
+ float *linear_buffer = display_buffer_apply_get_linear_buffer(handle);
+
+ if (is_data) {
+ /* special case for data buffers - no color space conversions,
+ * only generate byte buffers
+ */
+ }
+ else {
+ /* apply processor */
+ IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide);
+ }
- if (display_buffer)
- memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float));
+ /* copy result to output buffers */
+ if (display_buffer_byte) {
+ /* do conversion */
+ IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer,
+ channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ predivide, width, height, width, width);
+ }
+
+ if (display_buffer)
+ memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float));
- if (linear_buffer != buffer)
MEM_freeN(linear_buffer);
+ }
return NULL;
}
@@ -1235,14 +1297,43 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings)
{
- ColormanageProcessor *cm_processor;
+ ColormanageProcessor *cm_processor = NULL;
+ int skip_transform = FALSE;
- cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+ /* if we're going to transform byte buffer, check whether transformation would
+ * happen to the same color space as byte buffer itself is
+ * this would save byte -> float -> byte conversions making display buffer
+ * computation noticeable faster
+ */
+ if (ibuf->rect_float == NULL && ibuf->rect_colorspace) {
+ if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 &&
+ view_settings->exposure == 0.0f &&
+ view_settings->gamma == 1.0f)
+ {
+ ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+
+ if (config) {
+ const char *display = display_settings->display_device;
+ const char *view = view_settings->view_transform;
+ const char *from_colorspace = ibuf->rect_colorspace->name;
+ const char *to_colorspace = OCIO_configGetDisplayColorSpaceName(config, display, view);
+
+ if (!strcmp(from_colorspace, to_colorspace))
+ skip_transform = TRUE;
+
+ OCIO_configRelease(config);
+ }
+ }
+ }
+
+ if (skip_transform == FALSE)
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect,
display_buffer, display_buffer_byte, cm_processor);
- IMB_colormanagement_processor_free(cm_processor);
+ if (cm_processor)
+ IMB_colormanagement_processor_free(cm_processor);
}
static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer,
@@ -1622,7 +1713,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
return display_buffer;
}
- buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float);
+ buffer_size = DISPLAY_BUFFER_CHANNELS * ibuf->x * ibuf->y * sizeof(float);
display_buffer = MEM_callocN(buffer_size, "imbuf display buffer");
colormanage_display_buffer_process(ibuf, display_buffer, applied_view_settings, display_settings);
@@ -1667,7 +1758,7 @@ void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *li
const ColorManagedDisplaySettings *display_settings, int predivide)
{
if (global_tot_display == 0 || global_tot_view == 0) {
- IMB_buffer_byte_from_float(display_buffer, linear_buffer, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE,
+ IMB_buffer_byte_from_float(display_buffer, linear_buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE,
width, height, width, width);
}
else {
@@ -1890,11 +1981,13 @@ const char *IMB_colormanagement_view_get_indexed_name(int index)
const char *IMB_colormanagement_view_get_default_name(const char *display_name)
{
ColorManagedDisplay *display = colormanage_display_get_named(display_name);
- ColorManagedView *view = colormanage_view_get_default(display);
+ ColorManagedView *view = NULL;
+
+ if (display)
+ view = colormanage_view_get_default(display);
- if (view) {
+ if (view)
return view->name;
- }
return NULL;
}
@@ -1921,7 +2014,7 @@ static void colormanage_description_strip(char *description)
}
}
-ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible)
+ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible, int is_data)
{
ColorSpace *colorspace, *prev_space;
int counter = 1;
@@ -1937,6 +2030,7 @@ ColorSpace *colormanage_colorspace_add(const char *name, const char *description
}
colorspace->is_invertible = is_invertible;
+ colorspace->is_data = is_data;
for (prev_space = global_colorspaces.first; prev_space; prev_space = prev_space->next) {
if (BLI_strcasecmp(prev_space->name, colorspace->name) > 0)
@@ -2124,6 +2218,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
float *display_buffer_float = NULL;
int width = xmax - xmin;
int height = ymax - ymin;
+ int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
if (dither != 0.0f) {
display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither");
@@ -2144,10 +2239,12 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace);
}
- if (predivide)
- IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
- else
- IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+ if (!is_data) {
+ if (predivide)
+ IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+ else
+ IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+ }
if (display_buffer_float) {
int index = ((y - ymin) * width + (x - xmin)) * channels;
@@ -2283,7 +2380,8 @@ void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor,
if (cm_processor->curve_mapping)
curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
- OCIO_processorApplyRGBA(cm_processor->processor, pixel);
+ if (cm_processor->processor)
+ OCIO_processorApplyRGBA(cm_processor->processor, pixel);
}
void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3])
@@ -2291,7 +2389,8 @@ void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor,
if (cm_processor->curve_mapping)
curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
- OCIO_processorApplyRGB(cm_processor->processor, pixel);
+ if (cm_processor->processor)
+ OCIO_processorApplyRGB(cm_processor->processor, pixel);
}
void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height,
@@ -2310,7 +2409,7 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo
}
}
- {
+ if (cm_processor->processor && channels >= 3) {
PackedImageDesc *img;
/* apply OCIO processor */
@@ -2330,8 +2429,8 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
{
if (cm_processor->curve_mapping)
curvemapping_free(cm_processor->curve_mapping);
-
- OCIO_processorRelease(cm_processor->processor);
+ if (cm_processor->processor)
+ OCIO_processorRelease(cm_processor->processor);
MEM_freeN(cm_processor);
}
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
index 82f355e1bb2..d9d0cb86ee0 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -305,7 +305,7 @@ static const uint DDPF_SRGB = 0x40000000U;
};
- const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat)
+ static const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat)
{
#define CASE(format) case DXGI_FORMAT_##format: return #format
switch (dxgiFormat)
@@ -429,7 +429,7 @@ static const uint DDPF_SRGB = 0x40000000U;
#undef CASE
}
- const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension)
+ static const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension)
{
switch (resourceDimension)
{
@@ -534,7 +534,7 @@ namespace
} // namespace
-uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
+static uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
{
for (int i = 0; i < s_d3dFormatCount; i++)
{
diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c
index 3fd25fff92f..549a28a0453 100644
--- a/source/blender/imbuf/intern/iris.c
+++ b/source/blender/imbuf/intern/iris.c
@@ -83,21 +83,21 @@ typedef struct {
#define OFFSET_R 0 /* this is byte order dependent */
#define OFFSET_G 1
#define OFFSET_B 2
-#define OFFSET_A 3
+// #define OFFSET_A 3
#define CHANOFFSET(z) (3 - (z)) /* this is byte order dependent */
-#define TYPEMASK 0xff00
+// #define TYPEMASK 0xff00
#define BPPMASK 0x00ff
-#define ITYPE_VERBATIM 0x0000
+// #define ITYPE_VERBATIM 0x0000 // UNUSED
#define ITYPE_RLE 0x0100
#define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE)
-#define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM)
+// #define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM)
#define BPP(type) ((type) & BPPMASK)
#define RLE(bpp) (ITYPE_RLE | (bpp))
-#define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp))
-#define IBUFSIZE(pixels) ((pixels + (pixels >> 6)) << 2)
-#define RLE_NOP 0x00
+// #define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp)) // UNUSED
+// #define IBUFSIZE(pixels) ((pixels + (pixels >> 6)) << 2) // UNUSED
+// #define RLE_NOP 0x00
/* funcs */
static void readheader(FILE *inf, IMAGE *image);
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index 691db96989d..61275a8937c 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -51,9 +51,9 @@
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
-#define IS_jpg(x) (x->ftype & JPG)
+// #define IS_jpg(x) (x->ftype & JPG) // UNUSED
#define IS_stdjpg(x) ((x->ftype & JPG_MSK) == JPG_STD)
-#define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID)
+// #define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID) // UNUSED
#define IS_jstjpg(x) ((x->ftype & JPG_MSK) == JPG_JST)
#define IS_maxjpg(x) ((x->ftype & JPG_MSK) == JPG_MAX)
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index 78a989ad48f..d5aa635f548 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -386,7 +386,7 @@ ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey)
void IMB_moviecache_free(MovieCache *cache)
{
- PRINT("%s: create '%s' free\n", __func__, cache->name);
+ PRINT("%s: cache '%s' free\n", __func__, cache->name);
BLI_ghash_free(cache->hash, moviecache_keyfree, moviecache_valfree);
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 389c3c42b6d..527f334d6a4 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -1051,7 +1051,7 @@ static ImBuf *scaledowny(struct ImBuf *ibuf, int newy)
sample -= 1.0f;
}
- }
+ }
if (do_rect) {
// printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size);
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index a769ce742c9..476ee4fa369 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -207,6 +207,7 @@ typedef struct PreviewImage {
#define ID_WM MAKE_ID2('W', 'M') /* WindowManager */
#define ID_MC MAKE_ID2('M', 'C') /* MovieClip */
#define ID_MSK MAKE_ID2('M', 'S') /* Mask */
+#define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
#define ID_SEQ MAKE_ID2('S', 'Q')
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index ffe25a7b1ec..9a7feb77cfc 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -556,6 +556,7 @@ typedef enum eDopeSheet_FilterFlag {
ADS_FILTER_NONTREE = (1 << 19),
ADS_FILTER_NOTEX = (1 << 20),
ADS_FILTER_NOSPK = (1 << 21),
+ ADS_FILTER_NOLINESTYLE = (1 << 22),
/* NLA-specific filters */
ADS_FILTER_NLA_NOACT = (1 << 25), /* if the AnimData block has no NLA data, don't include to just show Action-line */
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 377af042922..c22de3cb7eb 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -74,7 +74,7 @@ typedef struct CustomData {
/* CustomData.type */
#define CD_MVERT 0
-#define CD_MSTICKY 1
+#define CD_MSTICKY 1 /* DEPRECATED */
#define CD_MDEFORMVERT 2
#define CD_MEDGE 3
#define CD_MFACE 4
@@ -118,7 +118,7 @@ typedef struct CustomData {
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
-#define CD_MASK_MSTICKY (1 << CD_MSTICKY)
+#define CD_MASK_MSTICKY (1 << CD_MSTICKY) /* DEPRECATED */
#define CD_MASK_MDEFORMVERT (1 << CD_MDEFORMVERT)
#define CD_MASK_MEDGE (1 << CD_MEDGE)
#define CD_MASK_MFACE (1 << CD_MFACE)
diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h
new file mode 100644
index 00000000000..f6e9421fa34
--- /dev/null
+++ b/source/blender/makesdna/DNA_freestyle_types.h
@@ -0,0 +1,133 @@
+/* DNA_freestyle_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef DNA_FREESTYLE_TYPES_H
+#define DNA_FREESTYLE_TYPES_H
+
+#include "DNA_listBase.h"
+
+struct FreestyleLineStyle;
+
+/* FreestyleConfig::flags */
+#define FREESTYLE_SUGGESTIVE_CONTOURS_FLAG 1
+#define FREESTYLE_RIDGES_AND_VALLEYS_FLAG 2
+#define FREESTYLE_MATERIAL_BOUNDARIES_FLAG 4
+#define FREESTYLE_FACE_SMOOTHNESS_FLAG 8
+#define FREESTYLE_ADVANCED_OPTIONS_FLAG 16
+
+/* FreestyleConfig::mode */
+#define FREESTYLE_CONTROL_SCRIPT_MODE 1
+#define FREESTYLE_CONTROL_EDITOR_MODE 2
+
+/* FreestyleLineSet::flags */
+#define FREESTYLE_LINESET_CURRENT 1l
+#define FREESTYLE_LINESET_ENABLED 2
+#define FREESTYLE_LINESET_FE_NOT 4
+#define FREESTYLE_LINESET_FE_AND 8
+#define FREESTYLE_LINESET_GR_NOT 16
+#define FREESTYLE_LINESET_FM_NOT 32
+#define FREESTYLE_LINESET_FM_BOTH 64
+
+/* FreestyleLineSet::selection */
+#define FREESTYLE_SEL_VISIBILITY 1
+#define FREESTYLE_SEL_EDGE_TYPES 2
+#define FREESTYLE_SEL_GROUP 4
+#define FREESTYLE_SEL_IMAGE_BORDER 8
+#define FREESTYLE_SEL_FACE_MARK 16
+
+/* FreestyleLineSet::edge_types, exclude_edge_types */
+#define FREESTYLE_FE_SILHOUETTE 1
+#define FREESTYLE_FE_BORDER 2
+#define FREESTYLE_FE_CREASE 4
+#define FREESTYLE_FE_RIDGE_VALLEY 8
+/* Note: FREESTYLE_FE_VALLEY = 16 is no longer used */
+#define FREESTYLE_FE_SUGGESTIVE_CONTOUR 32
+#define FREESTYLE_FE_MATERIAL_BOUNDARY 64
+#define FREESTYLE_FE_CONTOUR 128
+#define FREESTYLE_FE_EXTERNAL_CONTOUR 512
+#define FREESTYLE_FE_EDGE_MARK 1024
+
+/* FreestyleLineSet::qi */
+#define FREESTYLE_QI_VISIBLE 1
+#define FREESTYLE_QI_HIDDEN 2
+#define FREESTYLE_QI_RANGE 3
+
+/* FreestyleConfig::raycasting_algorithm */
+// Defines should be replaced with ViewMapBuilder::visibility_algo
+#define FREESTYLE_ALGO_REGULAR 1
+#define FREESTYLE_ALGO_FAST 2
+#define FREESTYLE_ALGO_VERYFAST 3
+#define FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL 4
+#define FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL 5
+#define FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE 6
+#define FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE 7
+
+typedef struct FreestyleLineSet {
+ struct FreestyleLineSet *next, *prev;
+
+ char name[32]; /* line set name */
+ int flags;
+
+ int selection; /* selection criteria */
+ short qi; /* quantitative invisibility */
+ short pad1;
+ int qi_start, qi_end;
+ int edge_types, exclude_edge_types; /* feature edge types */
+ int pad2;
+ struct Group *group; /* group of target objects */
+
+ struct FreestyleLineStyle *linestyle;
+
+} FreestyleLineSet;
+
+typedef struct FreestyleModuleConfig {
+ struct FreestyleModuleConfig *next, *prev;
+
+ char module_path[256];
+ short is_displayed;
+ short pad[3];
+
+} FreestyleModuleConfig;
+
+typedef struct FreestyleConfig {
+ ListBase modules;
+
+ int mode; /* scripting, editor */
+ int raycasting_algorithm; /* regular, fast, very fast, etc. */
+ int flags; /* suggestive contours, ridges/valleys, material boundaries */
+ float sphere_radius;
+ float dkr_epsilon;
+ float crease_angle;
+
+ ListBase linesets;
+
+} FreestyleConfig;
+
+#endif
diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h
index 8494e663fbe..6e5861043c1 100644
--- a/source/blender/makesdna/DNA_key_types.h
+++ b/source/blender/makesdna/DNA_key_types.h
@@ -105,7 +105,7 @@ typedef struct Key {
/* Key->type: KeyBlocks are interpreted as... */
enum {
- /* Sequencial positions over time (using KeyBlock->pos and Key->ctime) */
+ /* Sequential positions over time (using KeyBlock->pos and Key->ctime) */
KEY_NORMAL = 0,
/* States to blend between (default) */
diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h
new file mode 100644
index 00000000000..9ffb53e83b6
--- /dev/null
+++ b/source/blender/makesdna/DNA_linestyle_types.h
@@ -0,0 +1,433 @@
+/* DNA_linestyle_types.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef DNA_LINESTYLE_TYPES_H
+#define DNA_LINESTYLE_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+struct ColorBand;
+struct CurveMapping;
+
+typedef struct LineStyleModifier {
+ struct LineStyleModifier *next, *prev;
+
+ char name[32];
+ int type;
+ float influence;
+ int flags;
+ int blend;
+
+} LineStyleModifier;
+
+/* LineStyleModifier::type */
+#define LS_MODIFIER_ALONG_STROKE 1
+#define LS_MODIFIER_DISTANCE_FROM_CAMERA 2
+#define LS_MODIFIER_DISTANCE_FROM_OBJECT 3
+#define LS_MODIFIER_MATERIAL 4
+#define LS_MODIFIER_SAMPLING 5
+#define LS_MODIFIER_BEZIER_CURVE 6
+#define LS_MODIFIER_SINUS_DISPLACEMENT 7
+#define LS_MODIFIER_SPATIAL_NOISE 8
+#define LS_MODIFIER_PERLIN_NOISE_1D 9
+#define LS_MODIFIER_PERLIN_NOISE_2D 10
+#define LS_MODIFIER_BACKBONE_STRETCHER 11
+#define LS_MODIFIER_TIP_REMOVER 12
+#define LS_MODIFIER_CALLIGRAPHY 13
+#define LS_MODIFIER_POLYGONIZATION 14
+#define LS_MODIFIER_GUIDING_LINES 15
+#define LS_MODIFIER_BLUEPRINT 16
+#define LS_MODIFIER_2D_OFFSET 17
+#define LS_MODIFIER_2D_TRANSFORM 18
+#define LS_MODIFIER_NUM 19
+
+/* LineStyleModifier::flags */
+#define LS_MODIFIER_ENABLED 1
+#define LS_MODIFIER_EXPANDED 2
+
+/* flags (for color) */
+#define LS_MODIFIER_USE_RAMP 1
+
+/* flags (for alpha & thickness) */
+#define LS_MODIFIER_USE_CURVE 1
+#define LS_MODIFIER_INVERT 2
+
+/* blend (for alpha & thickness) */
+#define LS_VALUE_BLEND 0
+#define LS_VALUE_ADD 1
+#define LS_VALUE_MULT 2
+#define LS_VALUE_SUB 3
+#define LS_VALUE_DIV 4
+#define LS_VALUE_DIFF 5
+#define LS_VALUE_MIN 6
+#define LS_VALUE_MAX 7
+
+/* Along Stroke modifiers */
+
+typedef struct LineStyleColorModifier_AlongStroke {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+
+} LineStyleColorModifier_AlongStroke;
+
+typedef struct LineStyleAlphaModifier_AlongStroke {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ int pad;
+
+} LineStyleAlphaModifier_AlongStroke;
+
+typedef struct LineStyleThicknessModifier_AlongStroke {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float value_min, value_max;
+ int pad;
+
+} LineStyleThicknessModifier_AlongStroke;
+
+/* Distance from Camera modifiers */
+
+typedef struct LineStyleColorModifier_DistanceFromCamera {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+ float range_min, range_max;
+
+} LineStyleColorModifier_DistanceFromCamera;
+
+typedef struct LineStyleAlphaModifier_DistanceFromCamera {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float range_min, range_max;
+ int pad;
+
+} LineStyleAlphaModifier_DistanceFromCamera;
+
+typedef struct LineStyleThicknessModifier_DistanceFromCamera {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float range_min, range_max;
+ float value_min, value_max;
+ int pad;
+
+} LineStyleThicknessModifier_DistanceFromCamera;
+
+/* Distance from Object modifiers */
+
+typedef struct LineStyleColorModifier_DistanceFromObject {
+ struct LineStyleModifier modifier;
+
+ struct Object *target;
+ struct ColorBand *color_ramp;
+ float range_min, range_max;
+
+} LineStyleColorModifier_DistanceFromObject;
+
+typedef struct LineStyleAlphaModifier_DistanceFromObject {
+ struct LineStyleModifier modifier;
+
+ struct Object *target;
+ struct CurveMapping *curve;
+ int flags;
+ float range_min, range_max;
+ int pad;
+
+} LineStyleAlphaModifier_DistanceFromObject;
+
+typedef struct LineStyleThicknessModifier_DistanceFromObject {
+ struct LineStyleModifier modifier;
+
+ struct Object *target;
+ struct CurveMapping *curve;
+ int flags;
+ float range_min, range_max;
+ float value_min, value_max;
+ int pad;
+
+} LineStyleThicknessModifier_DistanceFromObject;
+
+/* Material modifiers */
+
+/* mat_attr */
+#define LS_MODIFIER_MATERIAL_DIFF 1
+#define LS_MODIFIER_MATERIAL_DIFF_R 2
+#define LS_MODIFIER_MATERIAL_DIFF_G 3
+#define LS_MODIFIER_MATERIAL_DIFF_B 4
+#define LS_MODIFIER_MATERIAL_SPEC 5
+#define LS_MODIFIER_MATERIAL_SPEC_R 6
+#define LS_MODIFIER_MATERIAL_SPEC_G 7
+#define LS_MODIFIER_MATERIAL_SPEC_B 8
+#define LS_MODIFIER_MATERIAL_SPEC_HARD 9
+#define LS_MODIFIER_MATERIAL_ALPHA 10
+
+typedef struct LineStyleColorModifier_Material {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+ int flags;
+ int mat_attr;
+
+} LineStyleColorModifier_Material;
+
+typedef struct LineStyleAlphaModifier_Material {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ int mat_attr;
+
+} LineStyleAlphaModifier_Material;
+
+typedef struct LineStyleThicknessModifier_Material {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float value_min, value_max;
+ int mat_attr;
+
+} LineStyleThicknessModifier_Material;
+
+/* Geometry modifiers */
+
+typedef struct LineStyleGeometryModifier_Sampling {
+ struct LineStyleModifier modifier;
+
+ float sampling;
+ int pad;
+
+} LineStyleGeometryModifier_Sampling;
+
+typedef struct LineStyleGeometryModifier_BezierCurve {
+ struct LineStyleModifier modifier;
+
+ float error;
+ int pad;
+
+} LineStyleGeometryModifier_BezierCurve;
+
+typedef struct LineStyleGeometryModifier_SinusDisplacement {
+ struct LineStyleModifier modifier;
+
+ float wavelength, amplitude, phase;
+ int pad;
+
+} LineStyleGeometryModifier_SinusDisplacement;
+
+/* LineStyleGeometryModifier_SpatialNoise::flags */
+#define LS_MODIFIER_SPATIAL_NOISE_SMOOTH 1
+#define LS_MODIFIER_SPATIAL_NOISE_PURERANDOM 2
+
+typedef struct LineStyleGeometryModifier_SpatialNoise {
+ struct LineStyleModifier modifier;
+
+ float amplitude, scale;
+ unsigned int octaves;
+ int flags;
+
+} LineStyleGeometryModifier_SpatialNoise;
+
+typedef struct LineStyleGeometryModifier_PerlinNoise1D {
+ struct LineStyleModifier modifier;
+
+ float frequency, amplitude, angle;
+ unsigned int octaves;
+ int seed;
+ int pad1;
+
+} LineStyleGeometryModifier_PerlinNoise1D;
+
+typedef struct LineStyleGeometryModifier_PerlinNoise2D {
+ struct LineStyleModifier modifier;
+
+ float frequency, amplitude, angle;
+ unsigned int octaves;
+ int seed;
+ int pad1;
+
+} LineStyleGeometryModifier_PerlinNoise2D;
+
+typedef struct LineStyleGeometryModifier_BackboneStretcher {
+ struct LineStyleModifier modifier;
+
+ float backbone_length;
+ int pad;
+
+} LineStyleGeometryModifier_BackboneStretcher;
+
+typedef struct LineStyleGeometryModifier_TipRemover {
+ struct LineStyleModifier modifier;
+
+ float tip_length;
+ int pad;
+
+} LineStyleGeometryModifier_TipRemover;
+
+typedef struct LineStyleGeometryModifier_Polygonalization {
+ struct LineStyleModifier modifier;
+
+ float error;
+ int pad;
+
+} LineStyleGeometryModifier_Polygonalization;
+
+typedef struct LineStyleGeometryModifier_GuidingLines {
+ struct LineStyleModifier modifier;
+
+ float offset;
+ int pad;
+
+} LineStyleGeometryModifier_GuidingLines;
+
+/* LineStyleGeometryModifier_BluePrintLines::shape */
+#define LS_MODIFIER_BLUEPRINT_CIRCLES 1
+#define LS_MODIFIER_BLUEPRINT_ELLIPSES 2
+#define LS_MODIFIER_BLUEPRINT_SQUARES 4
+
+typedef struct LineStyleGeometryModifier_Blueprint {
+ struct LineStyleModifier modifier;
+
+ int flags;
+ unsigned int rounds;
+ float backbone_length;
+ unsigned int random_radius;
+ unsigned int random_center;
+ unsigned int random_backbone;
+
+} LineStyleGeometryModifier_Blueprint;
+
+typedef struct LineStyleGeometryModifier_2DOffset {
+ struct LineStyleModifier modifier;
+
+ float start, end;
+ float x, y;
+
+} LineStyleGeometryModifier_2DOffset;
+
+/* LineStyleGeometryModifier_2DTransform::pivot */
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_CENTER 1
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_START 2
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_END 3
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_PARAM 4
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_ABSOLUTE 5
+
+typedef struct LineStyleGeometryModifier_2DTransform {
+ struct LineStyleModifier modifier;
+
+ int pivot;
+ float scale_x, scale_y;
+ float angle;
+ float pivot_u;
+ float pivot_x, pivot_y;
+ int pad;
+
+} LineStyleGeometryModifier_2DTransform;
+
+/* Calligraphic thickness modifier */
+
+typedef struct LineStyleThicknessModifier_Calligraphy {
+ struct LineStyleModifier modifier;
+
+ float min_thickness, max_thickness;
+ float orientation;
+ int pad;
+
+} LineStyleThicknessModifier_Calligraphy;
+
+/* FreestyleLineStyle::panel */
+#define LS_PANEL_STROKES 1
+#define LS_PANEL_COLOR 2
+#define LS_PANEL_ALPHA 3
+#define LS_PANEL_THICKNESS 4
+#define LS_PANEL_GEOMETRY 5
+#define LS_PANEL_MISC 6
+
+/* FreestyleLineStyle::flag */
+#define LS_DS_EXPAND 1 /* for animation editors */
+#define LS_SAME_OBJECT 2
+#define LS_DASHED_LINE 4
+#define LS_MATERIAL_BOUNDARY 8
+#define LS_MIN_2D_LENGTH 16
+#define LS_MAX_2D_LENGTH 32
+#define LS_NO_CHAINING 64
+#define LS_MIN_2D_ANGLE 128
+#define LS_MAX_2D_ANGLE 256
+#define LS_SPLIT_LENGTH 512
+
+/* FreestyleLineStyle::chaining */
+#define LS_CHAINING_PLAIN 1
+#define LS_CHAINING_SKETCHY 2
+
+/* FreestyleLineStyle::caps */
+#define LS_CAPS_BUTT 1
+#define LS_CAPS_ROUND 2
+#define LS_CAPS_SQUARE 3
+
+/* FreestyleLineStyle::thickness_position */
+#define LS_THICKNESS_CENTER 1
+#define LS_THICKNESS_INSIDE 2
+#define LS_THICKNESS_OUTSIDE 3
+#define LS_THICKNESS_RELATIVE 4 /* thickness_ratio is used */
+
+typedef struct FreestyleLineStyle {
+ ID id;
+ struct AnimData *adt;
+
+ float r, g, b, alpha;
+ float thickness;
+ int thickness_position;
+ float thickness_ratio;
+ int flag, caps;
+ int chaining;
+ unsigned int rounds;
+ float split_length;
+ float min_angle, max_angle; /* for splitting */
+ float min_length, max_length;
+ unsigned short dash1, gap1, dash2, gap2, dash3, gap3;
+ int panel; /* for UI */
+
+ ListBase color_modifiers;
+ ListBase alpha_modifiers;
+ ListBase thickness_modifiers;
+ ListBase geometry_modifiers;
+
+} FreestyleLineStyle;
+
+#endif
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 940c5c5f30b..f3c527b6531 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -130,8 +130,11 @@ typedef struct Material {
/* for buttons and render*/
char rgbsel, texact, pr_type, use_nodes;
- short pr_back, pr_lamp, pr_texture, ml_flag; /* ml_flag is for disable base material */
+ short pr_lamp, pr_texture, ml_flag; /* ml_flag is for disable base material */
+ /* mapping */
+ char mapflag, pad;
+
/* shaders */
short diff_shader, spec_shader;
float roughness, refrac;
@@ -140,6 +143,8 @@ typedef struct Material {
float param[4]; /* size, smooth, size, smooth, for toonshader, 0 (fac) and 1 (fresnel) also for fresnel shader */
float rms;
float darkness;
+
+ /* runtime - OR'd from 'mtex' */
short texco, mapto;
/* ramp colors */
@@ -172,6 +177,9 @@ typedef struct Material {
short shadowonly_flag; /* "shadowsonly" type */
short index; /* custom index for render passes */
+ short vcol_alpha;
+ short pad4[3];
+
ListBase gpumaterial; /* runtime */
} Material;
@@ -271,6 +279,9 @@ typedef struct Material {
#define MA_MODE_MASK 0x6fffffff /* all valid mode bits */
+/* mapflag */
+#define MA_MAPFLAG_UVPROJECT (1 << 0)
+
/* ray mirror fadeout */
#define MA_RAYMIR_FADETOSKY 0
#define MA_RAYMIR_FADETOMAT 1
@@ -337,7 +348,7 @@ typedef struct Material {
#define TEXCO_OBJECT 32
#define TEXCO_LAVECTOR 64
#define TEXCO_VIEW 128
-#define TEXCO_STICKY 256
+#define TEXCO_STICKY_ 256 // DEPRECATED
#define TEXCO_OSA 512
#define TEXCO_WINDOW 1024
#define NEED_UV 2048
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index e584cfd76ac..1196ce20a6b 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -89,8 +89,7 @@ typedef struct Mesh {
/* array of colors for the tessellated faces, must be number of tessellated
* faces * 4 in length */
- struct MCol *mcol;
- struct MSticky *msticky;
+ struct MCol *mcol;
struct Mesh *texcomesh;
/* When the object is available, the preferred access method is: BMEdit_FromObject(ob) */
@@ -195,6 +194,9 @@ typedef struct TFace {
/* debug only option */
#define ME_DRAWEXTRA_INDICES (1 << 13)
+#define ME_DRAW_FREESTYLE_EDGE (1 << 14)
+#define ME_DRAW_FREESTYLE_FACE (1 << 15)
+
/* Subsurf Type */
#define ME_CC_SUBSURF 0
#define ME_SIMPLE_SUBSURF 1
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 54e1e762f8b..f28c0328acc 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -146,13 +146,9 @@ typedef struct MLoopCol {
mcol__tmp->a = mloopcol__tmp->a; \
} (void)0
-typedef struct MSticky {
- float co[2];
-} MSticky;
-
typedef struct MSelect {
int index;
- int type; /* EDITVERT/EDITEDGE/EDITFACE */
+ int type; /* ME_VSEL/ME_ESEL/ME_FSEL */
} MSelect;
/*tessellation uv face data*/
@@ -294,6 +290,7 @@ typedef struct MVertSkin {
#define ME_LOOSEEDGE (1<<7)
/* #define ME_SEAM_LAST (1<<8) */ /* UNUSED */
#define ME_SHARP (1<<9) /* only reason this flag remains a 'short' */
+#define ME_FREESTYLE_EDGE (1<<10)
/* puno = vertexnormal (mface) */
#define ME_PROJXY 16
@@ -310,6 +307,7 @@ typedef struct MVertSkin {
/* flag (mface) */
#define ME_SMOOTH 1
#define ME_FACE_SEL 2
+#define ME_FREESTYLE_FACE 4
/* flag ME_HIDE==16 is used here too */
#define ME_POLY_LOOP_PREV(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + (mp)->totloop - 1) % (mp)->totloop)])
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index e3a8863714a..3f8f043efad 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -45,6 +45,7 @@ extern "C" {
#include "DNA_vec_types.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
+#include "DNA_freestyle_types.h"
struct Object;
struct Brush;
@@ -187,6 +188,9 @@ typedef struct SceneRenderLayer {
int samples;
int pad;
+
+ struct FreestyleConfig freestyleConfig;
+
} SceneRenderLayer;
/* srl->layflag */
@@ -196,7 +200,8 @@ typedef struct SceneRenderLayer {
#define SCE_LAY_EDGE 8
#define SCE_LAY_SKY 16
#define SCE_LAY_STRAND 32
- /* flags between 32 and 0x8000 are set to 1 already, for future options */
+#define SCE_LAY_FRS 64
+ /* flags between 64 and 0x8000 are set to 1 already, for future options */
#define SCE_LAY_ALL_Z 0x8000
#define SCE_LAY_XOR 0x10000
@@ -527,6 +532,10 @@ typedef struct RenderData {
float pad2;
struct Text *dometext DNA_DEPRECATED; // XXX deprecated since 2.5
+ /* Freestyle line thickness options */
+ int line_thickness_mode;
+ float unit_line_thickness; /* in pixels */
+
/* render engine */
char engine[32];
} RenderData;
@@ -829,14 +838,15 @@ typedef struct VPaint {
void *paintcursor; /* wm handle */
} VPaint;
-/* VPaint flag */
-#define VP_COLINDEX 1
-#define VP_AREA 2 /* vertex paint only */
-
-#define VP_NORMALS 8
-#define VP_SPRAY 16
-// #define VP_MIRROR_X 32 // deprecated in 2.5x use (me->editflag & ME_EDIT_MIRROR_X)
-#define VP_ONLYVGROUP 128 /* weight paint only */
+/* VPaint.flag */
+enum {
+ // VP_COLINDEX = (1 << 0), /* only paint onto active material*/ /* deprecated since before 2.49 */
+ VP_AREA = (1 << 1),
+ VP_NORMALS = (1 << 3),
+ VP_SPRAY = (1 << 4),
+ // VP_MIRROR_X = (1 << 5), /* deprecated in 2.5x use (me->editflag & ME_EDIT_MIRROR_X) */
+ VP_ONLYVGROUP = (1 << 7) /* weight paint only */
+};
/* *************************************************************** */
/* Transform Orientations */
@@ -1183,6 +1193,7 @@ typedef struct Scene {
#define R_NO_OVERWRITE 0x400000 /* skip existing files */
#define R_TOUCH 0x800000 /* touch files before rendering */
#define R_SIMPLIFY 0x1000000
+#define R_EDGE_FRS 0x2000000 /* R_EDGE for Freestyle */
/* seq_flag */
#define R_SEQ_GL_PREV 1
@@ -1297,6 +1308,10 @@ typedef struct Scene {
/* simplify_flag */
#define R_SIMPLE_NO_TRIANGULATE 1
+/* line_thickness_mode */
+#define R_LINE_THICKNESS_ABSOLUTE 1
+#define R_LINE_THICKNESS_RELATIVE 2
+
/* sequencer seq_prev_type seq_rend_type */
@@ -1489,6 +1504,7 @@ typedef enum SculptFlags {
#define EDGE_MODE_TAG_SHARP 2
#define EDGE_MODE_TAG_CREASE 3
#define EDGE_MODE_TAG_BEVEL 4
+#define EDGE_MODE_TAG_FREESTYLE 5
/* toolsettings->gpencil_flags */
#define GP_TOOL_FLAG_PAINTSESSIONS_ON (1<<0)
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 218027209a8..96f0c0e7a9a 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -217,6 +217,7 @@ typedef struct ThemeSpace {
char bone_solid[4], bone_pose[4], bone_pose_active[4];
char strip[4], strip_select[4];
char cframe[4];
+ char freestyle_edge_mark[4], freestyle_face_mark[4];
char nurb_uline[4], nurb_vline[4];
char act_spline[4], nurb_sel_uline[4], nurb_sel_vline[4], lastsel_point[4];
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index fec3aa22e92..d55810deeac 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -133,6 +133,8 @@ static const char *includefiles[] = {
"DNA_tracking_types.h",
"DNA_dynamicpaint_types.h",
"DNA_mask_types.h",
+ "DNA_freestyle_types.h",
+ "DNA_linestyle_types.h",
/* empty string to indicate end of includefiles */
""
@@ -1247,4 +1249,6 @@ int main(int argc, char **argv)
#include "DNA_tracking_types.h"
#include "DNA_dynamicpaint_types.h"
#include "DNA_mask_types.h"
+#include "DNA_freestyle_types.h"
+#include "DNA_linestyle_types.h"
/* end of list */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 8e387dd4eba..fe3fd10b680 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -239,6 +239,10 @@ extern StructRNA RNA_FluidFluidSettings;
extern StructRNA RNA_FluidSettings;
extern StructRNA RNA_FluidSimulationModifier;
extern StructRNA RNA_FollowPathConstraint;
+extern StructRNA RNA_FreestyleLineStyle;
+extern StructRNA RNA_FreestyleLineSet;
+extern StructRNA RNA_FreestyleModuleSettings;
+extern StructRNA RNA_FreestyleSettings;
extern StructRNA RNA_Function;
extern StructRNA RNA_GPencilFrame;
extern StructRNA RNA_GPencilLayer;
@@ -294,6 +298,37 @@ extern StructRNA RNA_LimitDistanceConstraint;
extern StructRNA RNA_LimitLocationConstraint;
extern StructRNA RNA_LimitRotationConstraint;
extern StructRNA RNA_LimitScaleConstraint;
+extern StructRNA RNA_LineStyleAlphaModifier;
+extern StructRNA RNA_LineStyleAlphaModifier_AlongStroke;
+extern StructRNA RNA_LineStyleAlphaModifier_DistanceFromCamera;
+extern StructRNA RNA_LineStyleAlphaModifier_DistanceFromObject;
+extern StructRNA RNA_LineStyleAlphaModifier_Material;
+extern StructRNA RNA_LineStyleColorModifier;
+extern StructRNA RNA_LineStyleColorModifier_AlongStroke;
+extern StructRNA RNA_LineStyleColorModifier_DistanceFromCamera;
+extern StructRNA RNA_LineStyleColorModifier_DistanceFromObject;
+extern StructRNA RNA_LineStyleColorModifier_Material;
+extern StructRNA RNA_LineStyleGeometryModifier;
+extern StructRNA RNA_LineStyleGeometryModifier_2DOffset;
+extern StructRNA RNA_LineStyleGeometryModifier_2DTransform;
+extern StructRNA RNA_LineStyleGeometryModifier_BackboneStretcher;
+extern StructRNA RNA_LineStyleGeometryModifier_BezierCurve;
+extern StructRNA RNA_LineStyleGeometryModifier_Blueprint;
+extern StructRNA RNA_LineStyleGeometryModifier_GuidingLines;
+extern StructRNA RNA_LineStyleGeometryModifier_PerlinNoise1D;
+extern StructRNA RNA_LineStyleGeometryModifier_PerlinNoise2D;
+extern StructRNA RNA_LineStyleGeometryModifier_Polygonalization;
+extern StructRNA RNA_LineStyleGeometryModifier_Sampling;
+extern StructRNA RNA_LineStyleGeometryModifier_SinusDisplacement;
+extern StructRNA RNA_LineStyleGeometryModifier_SpatialNoise;
+extern StructRNA RNA_LineStyleGeometryModifier_TipRemover;
+extern StructRNA RNA_LineStyleModifier;
+extern StructRNA RNA_LineStyleThicknessModifier;
+extern StructRNA RNA_LineStyleThicknessModifier_AlongStroke;
+extern StructRNA RNA_LineStyleThicknessModifier_Calligraphy;
+extern StructRNA RNA_LineStyleThicknessModifier_DistanceFromCamera;
+extern StructRNA RNA_LineStyleThicknessModifier_DistanceFromObject;
+extern StructRNA RNA_LineStyleThicknessModifier_Material;
extern StructRNA RNA_LockedTrackConstraint;
extern StructRNA RNA_Macro;
extern StructRNA RNA_MagicTexture;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index b651d4d5e5c..1c41c67b39c 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -131,6 +131,11 @@ extern EnumPropertyItem prop_dynamicpaint_type_items[];
extern EnumPropertyItem clip_editor_mode_items[];
+extern EnumPropertyItem linestyle_color_modifier_type_items[];
+extern EnumPropertyItem linestyle_alpha_modifier_type_items[];
+extern EnumPropertyItem linestyle_thickness_modifier_type_items[];
+extern EnumPropertyItem linestyle_geometry_modifier_type_items[];
+
struct bContext;
struct PointerRNA;
struct PropertyRNA;
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index 29910121e2a..5379de52ca8 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -12,6 +12,7 @@ incs += ' ../render/extern/include #/intern/cycles/blender'
incs += ' ../nodes'
incs += ' #/extern/glew/include'
incs += ' #/intern/smoke/extern'
+incs += ' ../freestyle'
incs += ' ../bmesh'
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 82c0757456d..24bf6ff4aa1 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -54,6 +54,7 @@ set(DEFSRC
rna_key.c
rna_lamp.c
rna_lattice.c
+ rna_linestyle.c
rna_main.c
rna_mask.c
rna_material.c
@@ -253,6 +254,7 @@ blender_include_dirs(
../../windowmanager
../../editors/include
../../render/extern/include
+ ../../freestyle
../../../../intern/audaspace/intern
../../../../intern/cycles/blender
../../../../intern/guardedalloc
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index ef3c7f42e96..4b65d7e0185 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -2698,6 +2698,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_key.c", NULL, RNA_def_key},
{"rna_lamp.c", NULL, RNA_def_lamp},
{"rna_lattice.c", NULL, RNA_def_lattice},
+ {"rna_linestyle.c", NULL, RNA_def_linestyle},
{"rna_main.c", "rna_main_api.c", RNA_def_main},
{"rna_material.c", "rna_material_api.c", RNA_def_material},
{"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh},
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 897e784c8e4..2c3bc0360fc 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -56,6 +56,7 @@ EnumPropertyItem id_type_items[] = {
{ID_KE, "KEY", ICON_SHAPEKEY_DATA, "Key", ""},
{ID_LA, "LAMP", ICON_LAMP_DATA, "Lamp", ""},
{ID_LI, "LIBRARY", ICON_LIBRARY_DATA_DIRECT, "Library", ""},
+ {ID_LS, "LINESTYLE", ICON_PARTICLE_DATA, "FreestyleLineStyle", ""}, /* FIXME proper icon */
{ID_LT, "LATTICE", ICON_LATTICE_DATA, "Lattice", ""},
{ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""},
{ID_MB, "META", ICON_META_DATA, "MetaBall", ""},
@@ -131,6 +132,7 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_Key)) return ID_KE;
if (RNA_struct_is_a(type, &RNA_Lamp)) return ID_LA;
if (RNA_struct_is_a(type, &RNA_Library)) return ID_LI;
+ if (RNA_struct_is_a(type, &RNA_FreestyleLineStyle)) return ID_LS;
if (RNA_struct_is_a(type, &RNA_Lattice)) return ID_LT;
if (RNA_struct_is_a(type, &RNA_Material)) return ID_MA;
if (RNA_struct_is_a(type, &RNA_MetaBall)) return ID_MB;
@@ -167,6 +169,7 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_KE: return &RNA_Key;
case ID_LA: return &RNA_Lamp;
case ID_LI: return &RNA_Library;
+ case ID_LS: return &RNA_FreestyleLineStyle;
case ID_LT: return &RNA_Lattice;
case ID_MA: return &RNA_Material;
case ID_MB: return &RNA_MetaBall;
@@ -256,7 +259,7 @@ StructRNA *rna_PropertyGroup_refine(PointerRNA *ptr)
return ptr->type;
}
-ID *rna_ID_copy(ID *id)
+static ID *rna_ID_copy(ID *id)
{
ID *newid;
@@ -309,7 +312,7 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag)
DAG_id_tag_update(id, flag);
}
-void rna_ID_user_clear(ID *id)
+static void rna_ID_user_clear(ID *id)
{
id->us = 0; /* don't save */
id->flag &= ~LIB_FAKEUSER;
@@ -341,7 +344,7 @@ int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assig
}
}
-void rna_IDMaterials_append_id(ID *id, Material *ma)
+static void rna_IDMaterials_append_id(ID *id, Material *ma)
{
material_append_id(id, ma);
@@ -349,7 +352,7 @@ void rna_IDMaterials_append_id(ID *id, Material *ma)
WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id);
}
-Material *rna_IDMaterials_pop_id(ID *id, int index_i, int remove_material_slot)
+static Material *rna_IDMaterials_pop_id(ID *id, int index_i, int remove_material_slot)
{
Material *ma = material_pop_id(id, index_i, remove_material_slot);
@@ -360,7 +363,7 @@ Material *rna_IDMaterials_pop_id(ID *id, int index_i, int remove_material_slot)
return ma;
}
-void rna_Library_filepath_set(PointerRNA *ptr, const char *value)
+static void rna_Library_filepath_set(PointerRNA *ptr, const char *value)
{
Library *lib = (Library *)ptr->data;
BKE_library_filepath_set(lib, value);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 4c1c377cb9f..c88944b4584 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -233,7 +233,7 @@ static void rna_idproperty_touch(IDProperty *idprop)
}
/* return a UI local ID prop definition for this prop */
-IDProperty *rna_idproperty_ui(PropertyRNA *prop)
+static IDProperty *rna_idproperty_ui(PropertyRNA *prop)
{
IDProperty *idprop;
@@ -618,7 +618,7 @@ PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
}
/* Find the property which uses the given nested struct */
-PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
+static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
{
PropertyRNA *prop = NULL;
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 00a257ab4f9..b3ef977a5c0 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -380,6 +380,12 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_LAMP_DATA, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ prop = RNA_def_property(srna, "show_linestyles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOLINESTYLE);
+ RNA_def_property_ui_text(prop, "Display Line Style", "Include visualization of Line Style related Animation data");
+ RNA_def_property_ui_icon(prop, ICON_BRUSH_DATA, 0); /* FIXME */
+ RNA_def_property_update(prop, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+
prop = RNA_def_property(srna, "show_textures", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOTEX);
RNA_def_property_ui_text(prop, "Display Texture", "Include visualization of Texture related Animation data");
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index bb714043002..12a41f213b7 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -29,6 +29,7 @@
#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
#include "DNA_constraint_types.h"
@@ -110,7 +111,7 @@ static StructRNA *rna_Actuator_refine(struct PointerRNA *ptr)
}
}
-void rna_Actuator_name_set(PointerRNA *ptr, const char *value)
+static void rna_Actuator_name_set(PointerRNA *ptr, const char *value)
{
bActuator *act = (bActuator *)ptr->data;
@@ -530,7 +531,7 @@ static void rna_Actuator_action_action_set(PointerRNA *ptr, PointerRNA value)
#else
-void rna_def_actuator(BlenderRNA *brna)
+static void rna_def_actuator(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 69f785c32de..d50cb663b97 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -829,7 +829,7 @@ void rna_def_animdata_common(StructRNA *srna)
RNA_def_property_ui_text(prop, "Animation Data", "Animation data for this datablock");
}
-void rna_def_animdata(BlenderRNA *brna)
+static void rna_def_animdata(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_animation_api.c b/source/blender/makesrna/intern/rna_animation_api.c
index 32472c8d415..39128b48cd8 100644
--- a/source/blender/makesrna/intern/rna_animation_api.c
+++ b/source/blender/makesrna/intern/rna_animation_api.c
@@ -39,6 +39,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "rna_internal.h" /* own include */
#ifdef RNA_RUNTIME
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index be70405d165..a645930f09a 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -100,7 +100,7 @@ static void rna_Armature_act_edit_bone_set(PointerRNA *ptr, PointerRNA value)
}
}
-EditBone *rna_Armature_edit_bone_new(bArmature *arm, ReportList *reports, const char *name)
+static EditBone *rna_Armature_edit_bone_new(bArmature *arm, ReportList *reports, const char *name)
{
if (arm->edbo == NULL) {
BKE_reportf(reports, RPT_ERROR, "Armature '%s' not in editmode, cant add an editbone", arm->id.name + 2);
@@ -109,7 +109,7 @@ EditBone *rna_Armature_edit_bone_new(bArmature *arm, ReportList *reports, const
return ED_armature_edit_bone_add(arm, name);
}
-void rna_Armature_edit_bone_remove(bArmature *arm, ReportList *reports, EditBone *ebone)
+static void rna_Armature_edit_bone_remove(bArmature *arm, ReportList *reports, EditBone *ebone)
{
if (arm->edbo == NULL) {
BKE_reportf(reports, RPT_ERROR, "Armature '%s' not in editmode, cant remove an editbone", arm->id.name + 2);
diff --git a/source/blender/makesrna/intern/rna_armature_api.c b/source/blender/makesrna/intern/rna_armature_api.c
index 29dc23b7bef..96c5350e5b7 100644
--- a/source/blender/makesrna/intern/rna_armature_api.c
+++ b/source/blender/makesrna/intern/rna_armature_api.c
@@ -36,18 +36,20 @@
#include "RNA_define.h"
+#include "rna_internal.h" /* own include */
+
#ifdef RNA_RUNTIME
#include <stddef.h>
#include "BKE_armature.h"
-void rna_EditBone_align_roll(EditBone *ebo, float no[3])
+static void rna_EditBone_align_roll(EditBone *ebo, float no[3])
{
ebo->roll = ED_rollBoneToVector(ebo, no, FALSE);
}
-float rna_Bone_do_envelope(Bone *bone, float *vec)
+static float rna_Bone_do_envelope(Bone *bone, float *vec)
{
float scale = (bone->flag & BONE_MULT_VG_ENV) == BONE_MULT_VG_ENV ? bone->weight : 1.0f;
return distfactor_to_bone(vec, bone->arm_head, bone->arm_tail, bone->rad_head * scale,
diff --git a/source/blender/makesrna/intern/rna_camera_api.c b/source/blender/makesrna/intern/rna_camera_api.c
index 75941fa224f..bf916806e40 100644
--- a/source/blender/makesrna/intern/rna_camera_api.c
+++ b/source/blender/makesrna/intern/rna_camera_api.c
@@ -31,6 +31,8 @@
#include "RNA_define.h"
+#include "rna_internal.h" /* own include */
+
#ifdef RNA_RUNTIME
#include "DNA_scene_types.h"
@@ -39,8 +41,8 @@
#include "BKE_context.h"
#include "BKE_object.h"
-void rna_camera_view_frame(struct Camera *camera, struct Scene *scene,
- float vec1_r[3], float vec2_r[3], float vec3_r[3], float vec4_r[3])
+static void rna_camera_view_frame(struct Camera *camera, struct Scene *scene,
+ float vec1_r[3], float vec2_r[3], float vec3_r[3], float vec4_r[3])
{
float vec[4][3];
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 0edcad59577..bf8b687139b 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -54,6 +54,7 @@
#include "BKE_movieclip.h"
#include "BKE_node.h"
#include "BKE_texture.h"
+#include "BKE_linestyle.h"
#include "ED_node.h"
@@ -186,6 +187,14 @@ static char *rna_ColorRamp_path(PointerRNA *ptr)
/* everything else just uses 'color_ramp' */
path = BLI_strdup("color_ramp");
break;
+
+ case ID_LS:
+ {
+ char *path = FRS_path_from_ID_to_color_ramp((FreestyleLineStyle *)id, (ColorBand *)ptr->data);
+ if (path)
+ return path;
+ }
+ break;
}
}
else {
@@ -257,6 +266,20 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr)
}
break;
+ case ID_LS:
+ {
+ ListBase listbase;
+ LinkData *link;
+
+ FRS_list_modifier_color_ramps((FreestyleLineStyle *)id, &listbase);
+ for (link = (LinkData *)listbase.first; link; link = link->next) {
+ RNA_pointer_create(id, &RNA_ColorRamp, link->data, &ramp_ptr);
+ COLRAMP_GETPATH;
+ }
+ BLI_freelistN(&listbase);
+ }
+ break;
+
default: /* everything else should have a "color_ramp" property */
{
/* create pointer to the ID block, and try to resolve "color_ramp" pointer */
@@ -308,6 +331,13 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
WM_main_add_notifier(NC_TEXTURE, tex);
}
break;
+ case ID_LS:
+ {
+ FreestyleLineStyle *linestyle= ptr->id.data;
+
+ WM_main_add_notifier(NC_LINESTYLE, linestyle);
+ }
+ break;
default:
break;
}
@@ -377,6 +407,9 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(b
{
ID *id = ptr->id.data;
+ if (!id)
+ return;
+
if (GS(id->name) == ID_SCE) {
Scene *scene = (Scene *) id;
@@ -486,13 +519,16 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
{
ID *id = ptr->id.data;
+ if (!id)
+ return;
+
if (GS(id->name) == ID_SCE) {
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
}
/* this function only exists because #curvemap_evaluateF uses a 'const' qualifier */
-float rna_CurveMap_evaluateF(struct CurveMap *cuma, float value)
+static float rna_CurveMap_evaluateF(struct CurveMap *cuma, float value)
{
return curvemap_evaluateF(cuma, value);
}
diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c
index 44c8a2b412b..aef1f765fe2 100644
--- a/source/blender/makesrna/intern/rna_controller.c
+++ b/source/blender/makesrna/intern/rna_controller.c
@@ -77,7 +77,7 @@ static StructRNA *rna_Controller_refine(struct PointerRNA *ptr)
}
}
-void rna_Constroller_name_set(PointerRNA *ptr, const char *value)
+static void rna_Constroller_name_set(PointerRNA *ptr, const char *value)
{
bController *cont = (bController *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_controller_api.c b/source/blender/makesrna/intern/rna_controller_api.c
index 6fe90e1721b..639d6a330a5 100644
--- a/source/blender/makesrna/intern/rna_controller_api.c
+++ b/source/blender/makesrna/intern/rna_controller_api.c
@@ -35,6 +35,8 @@
#include "WM_types.h"
#include "RNA_define.h"
+#include "rna_internal.h" /* own include */
+
#ifdef RNA_RUNTIME
#include "BKE_sca.h"
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index b2a2bab0f4b..c47cb8ef2af 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -432,20 +432,20 @@ static void rna_Curve_offset_set(PointerRNA *ptr, float value)
}
/* name functions that ignore the first two ID characters */
-void rna_Curve_body_get(PointerRNA *ptr, char *value)
+static void rna_Curve_body_get(PointerRNA *ptr, char *value)
{
Curve *cu = (Curve *)ptr->id.data;
BLI_strncpy(value, cu->str, cu->len + 1);
}
-int rna_Curve_body_length(PointerRNA *ptr)
+static int rna_Curve_body_length(PointerRNA *ptr)
{
Curve *cu = (Curve *)ptr->id.data;
return cu->len;
}
/* TODO - check UTF & python play nice */
-void rna_Curve_body_set(PointerRNA *ptr, const char *value)
+static void rna_Curve_body_set(PointerRNA *ptr, const char *value)
{
int len = strlen(value);
Curve *cu = (Curve *)ptr->id.data;
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index a0d64723a5c..24b14fdb884 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -403,13 +403,13 @@ static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value)
}
}
-DriverVar *rna_Driver_new_variable(ChannelDriver *driver)
+static DriverVar *rna_Driver_new_variable(ChannelDriver *driver)
{
/* call the API function for this */
return driver_add_new_variable(driver);
}
-void rna_Driver_remove_variable(ChannelDriver *driver, ReportList *reports, DriverVar *dvar)
+static void rna_Driver_remove_variable(ChannelDriver *driver, ReportList *reports, DriverVar *dvar)
{
if (BLI_findindex(&driver->variables, dvar) == -1) {
BKE_report(reports, RPT_ERROR, "Variable does not exist in this driver");
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index eb12a02aa99..131611d3002 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -90,7 +90,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value)
}
}
-void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
+static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
{
bGPdata *gpd = ptr->id.data;
bGPDlayer *gpl = ptr->data;
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 495d60df49c..fdab874cf01 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -147,7 +147,7 @@ static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *
}
-char *rna_ImageUser_path(PointerRNA *ptr)
+static char *rna_ImageUser_path(PointerRNA *ptr)
{
if (ptr->id.data) {
/* ImageUser *iuser= ptr->data; */
@@ -660,7 +660,7 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings");
RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
- RNA_def_property_ui_text(prop, "Colorspace Settings", "Input color space settings");
+ RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
RNA_api_image(srna);
}
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index e8e40d307fb..b85688e156c 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -34,8 +34,14 @@
#define RNA_MAGIC ((int)~0)
+struct ColorBand;
struct ID;
struct IDProperty;
+struct Main;
+struct Mesh;
+struct Object;
+struct RenderEngine;
+struct ReportList;
struct SDNA;
struct Sequence;
@@ -145,6 +151,7 @@ void RNA_def_image(struct BlenderRNA *brna);
void RNA_def_key(struct BlenderRNA *brna);
void RNA_def_lamp(struct BlenderRNA *brna);
void RNA_def_lattice(struct BlenderRNA *brna);
+void RNA_def_linestyle(struct BlenderRNA *brna);
void RNA_def_main(struct BlenderRNA *brna);
void RNA_def_material(struct BlenderRNA *brna);
void RNA_def_mesh(struct BlenderRNA *brna);
@@ -303,6 +310,7 @@ void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop);
+void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop);
/* ID Properties */
@@ -398,6 +406,22 @@ void rna_mtex_texture_slots_clear(struct ID *self, struct bContext *C, struct Re
int rna_IDMaterials_assign_int(struct PointerRNA *ptr, int key, const struct PointerRNA *assign_ptr);
+
+/* Internal functions that cycles uses so we need to declare (tsk tsk) */
+struct Mesh *rna_Object_to_mesh(struct Object *ob, struct ReportList *reports, struct Scene *sce, int apply_modifiers, int settings);
+void rna_Main_meshes_remove(struct Main *bmain, struct ReportList *reports, struct Mesh *mesh);
+void rna_Object_create_duplilist(struct Object *ob, struct ReportList *reports, struct Scene *sce);
+void rna_Object_free_duplilist(struct Object *ob);
+void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
+void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
+int rna_Object_is_modified(struct Object *ob, struct Scene *scene, int settings);
+int rna_Object_is_deform_modified(struct Object *ob, struct Scene *scene, int settings);
+void rna_ColorRamp_eval(struct ColorBand *coba, float position, float color[4]);
+void rna_Scene_frame_set(struct Scene *scene, int frame, float subframe);
+
+void engine_tag_redraw(struct RenderEngine *engine);
+void engine_tag_update(struct RenderEngine *engine);
+
#endif /* __RNA_INTERNAL_H__ */
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 5334c10c4c6..33bbaeec282 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -61,12 +61,12 @@ static Key *rna_ShapeKey_find_key(ID *id)
case ID_KE: return (Key *)id;
case ID_LT: return ((Lattice *)id)->key;
case ID_ME: return ((Mesh *)id)->key;
- case ID_OB: return ob_get_key((Object *)id);
+ case ID_OB: return BKE_key_from_object((Object *)id);
default: return NULL;
}
}
-void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value)
+static void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value)
{
KeyBlock *kb = ptr->data;
char oldname[sizeof(kb->name)];
@@ -360,7 +360,7 @@ static void rna_Key_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *p
Object *ob;
for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (ob_get_key(ob) == key) {
+ if (BKE_key_from_object(ob) == key) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
new file mode 100644
index 00000000000..abb715f2471
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -0,0 +1,1082 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation (2008).
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
+#include "DNA_linestyle_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+EnumPropertyItem linestyle_color_modifier_type_items[] ={
+ {LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""},
+ {LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""},
+ {LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""},
+ {LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+EnumPropertyItem linestyle_alpha_modifier_type_items[] ={
+ {LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""},
+ {LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""},
+ {LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""},
+ {LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+EnumPropertyItem linestyle_thickness_modifier_type_items[] ={
+ {LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""},
+ {LS_MODIFIER_CALLIGRAPHY, "CALLIGRAPHY", ICON_MODIFIER, "Calligraphy", ""},
+ {LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""},
+ {LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""},
+ {LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+EnumPropertyItem linestyle_geometry_modifier_type_items[] ={
+ {LS_MODIFIER_2D_OFFSET, "2D_OFFSET", ICON_MODIFIER, "2D Offset", ""},
+ {LS_MODIFIER_2D_TRANSFORM, "2D_TRANSFORM", ICON_MODIFIER, "2D Transform", ""},
+ {LS_MODIFIER_BACKBONE_STRETCHER, "BACKBONE_STRETCHER", ICON_MODIFIER, "Backbone Stretcher", ""},
+ {LS_MODIFIER_BEZIER_CURVE, "BEZIER_CURVE", ICON_MODIFIER, "Bezier Curve", ""},
+ {LS_MODIFIER_BLUEPRINT, "BLUEPRINT", ICON_MODIFIER, "Blueprint", ""},
+ {LS_MODIFIER_GUIDING_LINES, "GUIDING_LINES", ICON_MODIFIER, "Guiding Lines", ""},
+ {LS_MODIFIER_PERLIN_NOISE_1D, "PERLIN_NOISE_1D", ICON_MODIFIER, "Perlin Noise 1D", ""},
+ {LS_MODIFIER_PERLIN_NOISE_2D, "PERLIN_NOISE_2D", ICON_MODIFIER, "Perlin Noise 2D", ""},
+ {LS_MODIFIER_POLYGONIZATION, "POLYGONIZATION", ICON_MODIFIER, "Polygonization", ""},
+ {LS_MODIFIER_SAMPLING, "SAMPLING", ICON_MODIFIER, "Sampling", ""},
+ {LS_MODIFIER_SINUS_DISPLACEMENT, "SINUS_DISPLACEMENT", ICON_MODIFIER, "Sinus Displacement", ""},
+ {LS_MODIFIER_SPATIAL_NOISE, "SPATIAL_NOISE", ICON_MODIFIER, "Spatial Noise", ""},
+ {LS_MODIFIER_TIP_REMOVER, "TIP_REMOVER", ICON_MODIFIER, "Tip Remover", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+#ifdef RNA_RUNTIME
+
+#include "BKE_linestyle.h"
+
+static StructRNA *rna_LineStyle_color_modifier_refine(struct PointerRNA *ptr)
+{
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ switch(m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ return &RNA_LineStyleColorModifier_AlongStroke;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ return &RNA_LineStyleColorModifier_DistanceFromCamera;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ return &RNA_LineStyleColorModifier_DistanceFromObject;
+ case LS_MODIFIER_MATERIAL:
+ return &RNA_LineStyleColorModifier_Material;
+ default:
+ return &RNA_LineStyleColorModifier;
+ }
+}
+
+static StructRNA *rna_LineStyle_alpha_modifier_refine(struct PointerRNA *ptr)
+{
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ switch(m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ return &RNA_LineStyleAlphaModifier_AlongStroke;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ return &RNA_LineStyleAlphaModifier_DistanceFromCamera;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ return &RNA_LineStyleAlphaModifier_DistanceFromObject;
+ case LS_MODIFIER_MATERIAL:
+ return &RNA_LineStyleAlphaModifier_Material;
+ default:
+ return &RNA_LineStyleAlphaModifier;
+ }
+}
+
+static StructRNA *rna_LineStyle_thickness_modifier_refine(struct PointerRNA *ptr)
+{
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ switch(m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ return &RNA_LineStyleThicknessModifier_AlongStroke;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ return &RNA_LineStyleThicknessModifier_DistanceFromCamera;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ return &RNA_LineStyleThicknessModifier_DistanceFromObject;
+ case LS_MODIFIER_MATERIAL:
+ return &RNA_LineStyleThicknessModifier_Material;
+ case LS_MODIFIER_CALLIGRAPHY:
+ return &RNA_LineStyleThicknessModifier_Calligraphy;
+ default:
+ return &RNA_LineStyleThicknessModifier;
+ }
+}
+
+static StructRNA *rna_LineStyle_geometry_modifier_refine(struct PointerRNA *ptr)
+{
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ switch(m->type) {
+ case LS_MODIFIER_SAMPLING:
+ return &RNA_LineStyleGeometryModifier_Sampling;
+ case LS_MODIFIER_BEZIER_CURVE:
+ return &RNA_LineStyleGeometryModifier_BezierCurve;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ return &RNA_LineStyleGeometryModifier_SinusDisplacement;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ return &RNA_LineStyleGeometryModifier_SpatialNoise;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ return &RNA_LineStyleGeometryModifier_PerlinNoise1D;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ return &RNA_LineStyleGeometryModifier_PerlinNoise2D;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ return &RNA_LineStyleGeometryModifier_BackboneStretcher;
+ case LS_MODIFIER_TIP_REMOVER:
+ return &RNA_LineStyleGeometryModifier_TipRemover;
+ case LS_MODIFIER_POLYGONIZATION:
+ return &RNA_LineStyleGeometryModifier_Polygonalization;
+ case LS_MODIFIER_GUIDING_LINES:
+ return &RNA_LineStyleGeometryModifier_GuidingLines;
+ case LS_MODIFIER_BLUEPRINT:
+ return &RNA_LineStyleGeometryModifier_Blueprint;
+ case LS_MODIFIER_2D_OFFSET:
+ return &RNA_LineStyleGeometryModifier_2DOffset;
+ case LS_MODIFIER_2D_TRANSFORM:
+ return &RNA_LineStyleGeometryModifier_2DTransform;
+ default:
+ return &RNA_LineStyleGeometryModifier;
+ }
+}
+
+static char *rna_LineStyle_color_modifier_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("color_modifiers[\"%s\"]", ((LineStyleModifier*)ptr->data)->name);
+}
+
+static char *rna_LineStyle_alpha_modifier_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("alpha_modifiers[\"%s\"]", ((LineStyleModifier*)ptr->data)->name);
+}
+
+static char *rna_LineStyle_thickness_modifier_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("thickness_modifiers[\"%s\"]", ((LineStyleModifier*)ptr->data)->name);
+}
+
+static char *rna_LineStyle_geometry_modifier_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("geometry_modifiers[\"%s\"]", ((LineStyleModifier*)ptr->data)->name);
+}
+
+static void rna_LineStyleColorModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ FreestyleLineStyle *linestyle= (FreestyleLineStyle*)ptr->id.data;
+ LineStyleModifier *m= (LineStyleModifier*)ptr->data;
+
+ BLI_strncpy_utf8(m->name, value, sizeof(m->name));
+ BLI_uniquename(&linestyle->color_modifiers, m, "ColorModifier", '.', offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+static void rna_LineStyleAlphaModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ FreestyleLineStyle *linestyle= (FreestyleLineStyle*)ptr->id.data;
+ LineStyleModifier *m= (LineStyleModifier*)ptr->data;
+
+ BLI_strncpy_utf8(m->name, value, sizeof(m->name));
+ BLI_uniquename(&linestyle->alpha_modifiers, m, "AlphaModifier", '.', offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+static void rna_LineStyleThicknessModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ FreestyleLineStyle *linestyle= (FreestyleLineStyle*)ptr->id.data;
+ LineStyleModifier *m= (LineStyleModifier*)ptr->data;
+
+ BLI_strncpy_utf8(m->name, value, sizeof(m->name));
+ BLI_uniquename(&linestyle->thickness_modifiers, m, "ThicknessModifier", '.', offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+static void rna_LineStyleGeometryModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ FreestyleLineStyle *linestyle= (FreestyleLineStyle*)ptr->id.data;
+ LineStyleModifier *m= (LineStyleModifier*)ptr->data;
+
+ BLI_strncpy_utf8(m->name, value, sizeof(m->name));
+ BLI_uniquename(&linestyle->geometry_modifiers, m, "GeometryModifier", '.', offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+#else
+
+#include "BLI_math.h"
+
+static void rna_def_modifier_type_common(StructRNA *srna, EnumPropertyItem *modifier_type_items,
+ char *set_name_func, int blend, int color)
+{
+ PropertyRNA *prop;
+
+ static EnumPropertyItem color_blend_items[] = {
+ {MA_RAMP_BLEND, "MIX", 0, "Mix", ""},
+ {MA_RAMP_ADD, "ADD", 0, "Add", ""},
+ {MA_RAMP_MULT, "MULTIPLY", 0, "Multiply", ""},
+ {MA_RAMP_SUB, "SUBTRACT", 0, "Subtract", ""},
+ {MA_RAMP_SCREEN, "SCREEN", 0, "Screen", ""},
+ {MA_RAMP_DIV, "DIVIDE", 0, "Divide", ""},
+ {MA_RAMP_DIFF, "DIFFERENCE", 0, "Difference", ""},
+ {MA_RAMP_DARK, "DARKEN", 0, "Darken", ""},
+ {MA_RAMP_LIGHT, "LIGHTEN", 0, "Lighten", ""},
+ {MA_RAMP_OVERLAY, "OVERLAY", 0, "Overlay", ""},
+ {MA_RAMP_DODGE, "DODGE", 0, "Dodge", ""},
+ {MA_RAMP_BURN, "BURN", 0, "Burn", ""},
+ {MA_RAMP_HUE, "HUE", 0, "Hue", ""},
+ {MA_RAMP_SAT, "SATURATION", 0, "Saturation", ""},
+ {MA_RAMP_VAL, "VALUE", 0, "Value", ""},
+ {MA_RAMP_COLOR, "COLOR", 0, "Color", ""},
+ {MA_RAMP_SOFT, "SOFT_LIGHT", 0, "Soft Light", ""},
+ {MA_RAMP_LINEAR, "LINEAR_LIGHT", 0, "Linear Light", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem value_blend_items[] = {
+ {LS_VALUE_BLEND, "MIX", 0, "Mix", ""},
+ {LS_VALUE_ADD, "ADD", 0, "Add", ""},
+ {LS_VALUE_SUB, "SUBTRACT", 0, "Subtract", ""},
+ {LS_VALUE_MULT, "MULTIPLY", 0, "Multiply", ""},
+ {LS_VALUE_DIV, "DIVIDE", 0, "Divide", ""},
+ {LS_VALUE_DIFF, "DIFFERENCE", 0, "Divide", ""},
+ {LS_VALUE_MIN, "MININUM", 0, "Minimum", ""},
+ {LS_VALUE_MAX, "MAXIMUM", 0, "Maximum", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "modifier.type");
+ RNA_def_property_enum_items(prop, modifier_type_items);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Modifier Type", "Type of the modifier");
+
+ prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "modifier.name");
+ RNA_def_property_string_funcs(prop, NULL, NULL, set_name_func);
+ RNA_def_property_ui_text(prop, "Modifier Name", "Name of the modifier");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ if (blend) {
+ prop= RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "modifier.blend");
+ RNA_def_property_enum_items(prop, (color) ? color_blend_items : value_blend_items);
+ RNA_def_property_ui_text(prop, "Blend", "Specify how the modifier value is blended into the base value");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "modifier.influence");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Influence", "Influence factor by which the modifier changes the property");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ }
+
+ prop= RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "modifier.flags", LS_MODIFIER_ENABLED);
+ RNA_def_property_ui_text(prop, "Use", "Enable or disable this modifier during stroke rendering");
+
+ prop= RNA_def_property(srna, "expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "modifier.flags", LS_MODIFIER_EXPANDED);
+ RNA_def_property_ui_text(prop, "Expanded", "True if the modifier tab is expanded");
+}
+
+static void rna_def_color_modifier(StructRNA *srna)
+{
+ rna_def_modifier_type_common(srna, linestyle_color_modifier_type_items,
+ "rna_LineStyleColorModifier_name_set", 1, 1);
+}
+
+static void rna_def_alpha_modifier(StructRNA *srna)
+{
+ rna_def_modifier_type_common(srna, linestyle_alpha_modifier_type_items,
+ "rna_LineStyleAlphaModifier_name_set", 1, 0);
+}
+
+static void rna_def_thickness_modifier(StructRNA *srna)
+{
+ rna_def_modifier_type_common(srna, linestyle_thickness_modifier_type_items,
+ "rna_LineStyleThicknessModifier_name_set", 1, 0);
+}
+
+static void rna_def_geometry_modifier(StructRNA *srna)
+{
+ rna_def_modifier_type_common(srna, linestyle_geometry_modifier_type_items,
+ "rna_LineStyleGeometryModifier_name_set", 0, 0);
+}
+
+static void rna_def_modifier_color_ramp_common(StructRNA *srna, int range)
+{
+ PropertyRNA *prop;
+
+ prop= RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "color_ramp");
+ RNA_def_property_struct_type(prop, "ColorRamp");
+ RNA_def_property_ui_text(prop, "Color Ramp", "Color ramp used to change line color");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ if (range) {
+ prop= RNA_def_property(srna, "range_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "range_min");
+ RNA_def_property_ui_text(prop, "Range Min", "Lower bound of the input range the mapping is applied");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "range_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "range_max");
+ RNA_def_property_ui_text(prop, "Range Max", "Upper bound of the input range the mapping is applied");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ }
+}
+
+static void rna_def_modifier_curve_common(StructRNA *srna, int range, int value)
+{
+ PropertyRNA *prop;
+
+ static EnumPropertyItem mapping_items[] = {
+ {0, "LINEAR", 0, "Linear", "Use linear mapping"},
+ {LS_MODIFIER_USE_CURVE, "CURVE", 0, "Curve", "Use curve mapping"},
+ {0, NULL, 0, NULL, NULL}};
+
+ prop= RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, mapping_items);
+ RNA_def_property_ui_text(prop, "Mapping", "Select the mapping type");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_MODIFIER_INVERT);
+ RNA_def_property_ui_text(prop, "Invert", "Invert the fade-out direction of the linear mapping");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Curve", "Curve used for the curve mapping");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ if (range) {
+ prop= RNA_def_property(srna, "range_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "range_min");
+ RNA_def_property_ui_text(prop, "Range Min", "Lower bound of the input range the mapping is applied");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "range_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "range_max");
+ RNA_def_property_ui_text(prop, "Range Max", "Upper bound of the input range the mapping is applied");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ }
+
+ if (value) {
+ prop= RNA_def_property(srna, "value_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "value_min");
+ RNA_def_property_ui_text(prop, "Value Min", "Minimum output value of the mapping");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "value_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "value_max");
+ RNA_def_property_ui_text(prop, "Value Max", "Maximum output value of the mapping");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ }
+}
+
+static void rna_def_modifier_material_common(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ static EnumPropertyItem mat_attr_items[] = {
+ {LS_MODIFIER_MATERIAL_DIFF, "DIFF", 0, "Diffuse", ""},
+ {LS_MODIFIER_MATERIAL_DIFF_R, "DIFF_R", 0, "Diffuse Red", ""},
+ {LS_MODIFIER_MATERIAL_DIFF_G, "DIFF_G", 0, "Diffuse Green", ""},
+ {LS_MODIFIER_MATERIAL_DIFF_B, "DIFF_B", 0, "Diffuse Blue", ""},
+ {LS_MODIFIER_MATERIAL_SPEC, "SPEC", 0, "Specular", ""},
+ {LS_MODIFIER_MATERIAL_SPEC_R, "SPEC_R", 0, "Specular Red", ""},
+ {LS_MODIFIER_MATERIAL_SPEC_G, "SPEC_G", 0, "Specular Green", ""},
+ {LS_MODIFIER_MATERIAL_SPEC_B, "SPEC_B", 0, "Specular Blue", ""},
+ {LS_MODIFIER_MATERIAL_SPEC_HARD, "SPEC_HARD", 0, "Specular Hardness", ""},
+ {LS_MODIFIER_MATERIAL_ALPHA, "ALPHA", 0, "Alpha", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ prop= RNA_def_property(srna, "material_attr", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mat_attr");
+ RNA_def_property_enum_items(prop, mat_attr_items);
+ RNA_def_property_ui_text(prop, "Material Attribute", "Specify which material attribute is used");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+}
+
+static void rna_def_linestyle_modifiers(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem blueprint_shape_items[] = {
+ {LS_MODIFIER_BLUEPRINT_CIRCLES, "CIRCLES", 0, "Circles", "Draw a blueprint using circular contour strokes"},
+ {LS_MODIFIER_BLUEPRINT_ELLIPSES, "ELLIPSES", 0, "Ellipses", "Draw a blueprint using elliptic contour strokes"},
+ {LS_MODIFIER_BLUEPRINT_SQUARES, "SQUARES", 0, "Squares", "Draw a blueprint using square contour strokes"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem transform_pivot_items[] = {
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_CENTER, "CENTER", 0, "Stroke Center", ""},
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_START, "START", 0, "Stroke Start", ""},
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_END, "END", 0, "Stroke End", ""},
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_PARAM, "PARAM", 0, "Stroke Point Parameter", ""},
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_ABSOLUTE, "ABSOLUTE", 0, "Absolute 2D Point", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ srna= RNA_def_struct(brna, "LineStyleModifier", NULL);
+ RNA_def_struct_ui_text(srna, "Line Style Modifier", "Base type to define modifiers");
+
+ /* line color modifiers */
+
+ srna= RNA_def_struct(brna, "LineStyleColorModifier", "LineStyleModifier");
+ RNA_def_struct_sdna(srna, "LineStyleModifier");
+ RNA_def_struct_refine_func(srna, "rna_LineStyle_color_modifier_refine");
+ RNA_def_struct_path_func(srna, "rna_LineStyle_color_modifier_path");
+ RNA_def_struct_ui_text(srna, "Line Style Color Modifier", "Base type to define line color modifiers");
+
+ srna= RNA_def_struct(brna, "LineStyleColorModifier_AlongStroke", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Along Stroke", "Change line color along stroke");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, 0);
+
+ srna= RNA_def_struct(brna, "LineStyleColorModifier_DistanceFromCamera", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Camera", "Change line color based on the distance from the camera");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, 1);
+
+ srna= RNA_def_struct(brna, "LineStyleColorModifier_DistanceFromObject", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Object", "Change line color based on the distance from an object");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, 1);
+
+ prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "target");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Target", "Target object from which the distance is measured");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleColorModifier_Material", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Material", "Change line color based on a material attribute");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_material_common(srna);
+ rna_def_modifier_color_ramp_common(srna, 0);
+
+ prop= RNA_def_property(srna, "use_ramp", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_MODIFIER_USE_RAMP);
+ RNA_def_property_ui_text(prop, "Ramp", "Use color ramp to map the BW average into an RGB color");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ /* alpha transparency modifiers */
+
+ srna= RNA_def_struct(brna, "LineStyleAlphaModifier", "LineStyleModifier");
+ RNA_def_struct_sdna(srna, "LineStyleModifier");
+ RNA_def_struct_refine_func(srna, "rna_LineStyle_alpha_modifier_refine");
+ RNA_def_struct_path_func(srna, "rna_LineStyle_alpha_modifier_path");
+ RNA_def_struct_ui_text(srna, "Line Style Alpha Modifier", "Base type to define alpha transparency modifiers");
+
+ srna= RNA_def_struct(brna, "LineStyleAlphaModifier_AlongStroke", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Along Stroke", "Change alpha transparency along stroke");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, 0, 0);
+
+ srna= RNA_def_struct(brna, "LineStyleAlphaModifier_DistanceFromCamera", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Camera", "Change alpha transparency based on the distance from the camera");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, 1, 0);
+
+ srna= RNA_def_struct(brna, "LineStyleAlphaModifier_DistanceFromObject", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Object", "Change alpha transparency based on the distance from an object");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, 1, 0);
+
+ prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "target");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Target", "Target object from which the distance is measured");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleAlphaModifier_Material", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Material", "Change alpha transparency based on a material attribute");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_material_common(srna);
+ rna_def_modifier_curve_common(srna, 0, 0);
+
+ /* line thickness modifiers */
+
+ srna= RNA_def_struct(brna, "LineStyleThicknessModifier", "LineStyleModifier");
+ RNA_def_struct_sdna(srna, "LineStyleModifier");
+ RNA_def_struct_refine_func(srna, "rna_LineStyle_thickness_modifier_refine");
+ RNA_def_struct_path_func(srna, "rna_LineStyle_thickness_modifier_path");
+ RNA_def_struct_ui_text(srna, "Line Style Thickness Modifier", "Base type to define line thickness modifiers");
+
+ srna= RNA_def_struct(brna, "LineStyleThicknessModifier_AlongStroke", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Along Stroke", "Change line thickness along stroke");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, 0, 1);
+
+ srna= RNA_def_struct(brna, "LineStyleThicknessModifier_DistanceFromCamera", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Camera", "Change line thickness based on the distance from the camera");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, 1, 1);
+
+ srna= RNA_def_struct(brna, "LineStyleThicknessModifier_DistanceFromObject", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Object", "Change line thickness based on the distance from an object");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, 1, 1);
+
+ prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "target");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Target", "Target object from which the distance is measured");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleThicknessModifier_Material", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Material", "Change line thickness based on a material attribute");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_material_common(srna);
+ rna_def_modifier_curve_common(srna, 0, 1);
+
+ srna= RNA_def_struct(brna, "LineStyleThicknessModifier_Calligraphy", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Calligraphy", "Change line thickness so that stroke looks like made with a calligraphic pen");
+ rna_def_thickness_modifier(srna);
+
+ prop= RNA_def_property(srna, "orientation", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "orientation");
+ RNA_def_property_ui_text(prop, "Orientation", "Angle of the main direction");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "min_thickness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Min Thickness", "Minimum thickness in the direction perpendicular to the main direction");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "max_thickness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness in the main direction");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ /* geometry modifiers */
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier", "LineStyleModifier");
+ RNA_def_struct_sdna(srna, "LineStyleModifier");
+ RNA_def_struct_refine_func(srna, "rna_LineStyle_geometry_modifier_refine");
+ RNA_def_struct_path_func(srna, "rna_LineStyle_geometry_modifier_path");
+ RNA_def_struct_ui_text(srna, "Line Style Geometry Modifier", "Base type to define stroke geometry modifiers");
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_Sampling", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Sampling", "Specify a new sampling value that determines the resolution of stroke polylines");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "sampling", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "sampling");
+ RNA_def_property_ui_text(prop, "Sampling", "New sampling value to be used for subsequent modifiers");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_BezierCurve", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Bezier Curve", "Replace stroke backbone geometry by a Bezier curve approximation of the original backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "error", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "error");
+ RNA_def_property_ui_text(prop, "Error", "Maximum distance allowed between the new Bezier curve and the original backbone geometry)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_SinusDisplacement", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Sinus Displacement", "Add sinus displacement to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "wavelength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "wavelength");
+ RNA_def_property_ui_text(prop, "Wavelength", "Wavelength of the sinus displacement");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the sinus displacement");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "phase", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "phase");
+ RNA_def_property_ui_text(prop, "Phase", "Phase of the sinus displacement");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_SpatialNoise", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Spatial Noise", "Add spatial noise to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the spatial noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale");
+ RNA_def_property_ui_text(prop, "Scale", "Scale of the spatial noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "octaves", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "octaves");
+ RNA_def_property_ui_text(prop, "Octaves", "Number of octaves (i.e., the amount of detail of the spatial noise)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "smooth", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_MODIFIER_SPATIAL_NOISE_SMOOTH);
+ RNA_def_property_ui_text(prop, "Smooth", "If true, the spatial noise is smooth");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "pure_random", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_MODIFIER_SPATIAL_NOISE_PURERANDOM);
+ RNA_def_property_ui_text(prop, "Pure Random", "If true, the spatial noise does not show any coherence");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_PerlinNoise1D", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Perlin Noise 1D", "Add one-dimensional Perlin noise to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "frequency", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "frequency");
+ RNA_def_property_ui_text(prop, "Frequency", "Frequency of the Perlin noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the Perlin noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "octaves", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "octaves");
+ RNA_def_property_ui_text(prop, "Octaves", "Number of octaves (i.e., the amount of detail of the Perlin noise)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "angle", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "angle");
+ RNA_def_property_ui_text(prop, "Angle", "Displacement direction in degrees");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "seed", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "seed");
+ RNA_def_property_ui_text(prop, "Seed", "Seed for random number generation. If negative, time is used as a seed instead");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_PerlinNoise2D", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Perlin Noise 2D", "Add two-dimensional Perlin noise to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "frequency", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "frequency");
+ RNA_def_property_ui_text(prop, "Frequency", "Frequency of the Perlin noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the Perlin noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "octaves", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "octaves");
+ RNA_def_property_ui_text(prop, "Octaves", "Number of octaves (i.e., the amount of detail of the Perlin noise)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "angle", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "angle");
+ RNA_def_property_ui_text(prop, "Angle", "Displacement direction in degrees");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "seed", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "seed");
+ RNA_def_property_ui_text(prop, "Seed", "Seed for random number generation. If negative, time is used as a seed instead");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_BackboneStretcher", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Backbone Stretcher", "Stretch the beginning and the end of stroke backbone");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "backbone_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "backbone_length");
+ RNA_def_property_ui_text(prop, "Backbone Length", "Amount of backbone stretching");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_TipRemover", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Tip Remover", "Remove a piece of stroke at the beginning and the end of stroke backbone");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "tip_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "tip_length");
+ RNA_def_property_ui_text(prop, "Tip Length", "Length of tips to be removed");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_Polygonalization", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Polygonalization", "Modify the stroke geometry so that it looks more \"polygonal\"");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "error", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "error");
+ RNA_def_property_ui_text(prop, "Error", "Maximum distance between the original stroke and its polygonal approximation");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_GuidingLines", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Guiding Lines", "Modify the stroke geometry so that it corresponds to its main direction line");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "offset");
+ RNA_def_property_ui_text(prop, "Offset", "Displacement that is applied to the main direction line along its normal");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_Blueprint", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Blueprint", "Produce a blueprint using circular, elliptic, and square contour strokes");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "shape", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, blueprint_shape_items);
+ RNA_def_property_ui_text(prop, "Shape", "Select the shape of blueprint contour strokes");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "rounds", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "rounds");
+ RNA_def_property_range(prop, 1, 1000);
+ RNA_def_property_ui_text(prop, "Rounds", "Number of rounds in contour strokes");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "backbone_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "backbone_length");
+ RNA_def_property_ui_text(prop, "Backbone Length", "Amount of backbone stretching");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "random_radius", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "random_radius");
+ RNA_def_property_ui_text(prop, "Random Radius", "Randomness of the radius");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "random_center", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "random_center");
+ RNA_def_property_ui_text(prop, "Random Center", "Randomness of the center");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "random_backbone", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "random_backbone");
+ RNA_def_property_ui_text(prop, "Random Backbone", "Randomness of the backbone stretching");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_2DOffset", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "2D Offset", "Add two-dimensional offsets to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "start", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "start");
+ RNA_def_property_ui_text(prop, "Start", "Displacement that is applied from the beginning of the stroke");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "end", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "end");
+ RNA_def_property_ui_text(prop, "End", "Displacement that is applied from the end of the stroke");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "x", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "x");
+ RNA_def_property_ui_text(prop, "X", "Displacement that is applied to the X coordinates of stroke vertices");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "y", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "y");
+ RNA_def_property_ui_text(prop, "Y", "Displacement that is applied to the Y coordinates of stroke vertices");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna= RNA_def_struct(brna, "LineStyleGeometryModifier_2DTransform", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "2D Transform", "Apply two-dimensional scaling and rotation to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop= RNA_def_property(srna, "pivot", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "pivot");
+ RNA_def_property_enum_items(prop, transform_pivot_items);
+ RNA_def_property_ui_text(prop, "Pivot", "Pivot of scaling and rotation operations");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale_x");
+ RNA_def_property_ui_text(prop, "Scale X", "Scaling factor that is applied along the X axis");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale_y");
+ RNA_def_property_ui_text(prop, "Scale Y", "Scaling factor that is applied along the Y axis");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "angle", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "angle");
+ RNA_def_property_ui_text(prop, "Rotation Angle", "Rotation angle in degrees");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "pivot_u", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "pivot_u");
+ RNA_def_property_range(prop, 0.f, 1.f);
+ RNA_def_property_ui_text(prop, "Stroke Point Parameter", "Pivot in terms of the stroke point parameter u (0 <= u <= 1)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "pivot_x", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "pivot_x");
+ RNA_def_property_ui_text(prop, "Pivot X", "2D X coordinate of the absolute pivot");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "pivot_y", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "pivot_y");
+ RNA_def_property_ui_text(prop, "Pivot Y", "2D Y coordinate of the absolute pivot");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+}
+
+static void rna_def_linestyle(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem panel_items[] = {
+ {LS_PANEL_STROKES, "STROKES", 0, "Strokes", "Show the panel for stroke construction"},
+ {LS_PANEL_COLOR, "COLOR", 0, "Color", "Show the panel for line color options"},
+ {LS_PANEL_ALPHA, "ALPHA", 0, "Alpha", "Show the panel for alpha transparency options"},
+ {LS_PANEL_THICKNESS, "THICKNESS", 0, "Thickness", "Show the panel for line thickness options"},
+ {LS_PANEL_GEOMETRY, "GEOMETRY", 0, "Geometry", "Show the panel for stroke geometry options"},
+ {LS_PANEL_MISC, "MISC", 0, "Misc", "Show the panel for miscellaneous options"},
+ {0, NULL, 0, NULL, NULL}};
+ static EnumPropertyItem chaining_items[] = {
+ {LS_CHAINING_PLAIN, "PLAIN", 0, "Plain", "Plain chaining"},
+ {LS_CHAINING_SKETCHY, "SKETCHY", 0, "Sketchy", "Sketchy chaining with a multiple touch"},
+ {0, NULL, 0, NULL, NULL}};
+ static EnumPropertyItem cap_items[] = {
+ {LS_CAPS_BUTT, "BUTT", 0, "Butt", "Butt cap (flat)"},
+ {LS_CAPS_ROUND, "ROUND", 0, "Round", "Round cap (half-circle)"},
+ {LS_CAPS_SQUARE, "SQUARE", 0, "Square", "Square cap (flat and extended)"},
+ {0, NULL, 0, NULL, NULL}};
+ static EnumPropertyItem thickness_position_items[] = {
+ {LS_THICKNESS_CENTER, "CENTER", 0, "Center", "Stroke is centered along stroke geometry"},
+ {LS_THICKNESS_INSIDE, "INSIDE", 0, "Inside", "Stroke is drawn inside stroke geometry"},
+ {LS_THICKNESS_OUTSIDE, "OUTSIDE", 0, "Outside", "Stroke is drawn outside stroke geometry"},
+ {LS_THICKNESS_RELATIVE, "RELATIVE", 0, "Relative", "Stroke thinkness is split by a user-defined ratio"},
+ {0, NULL, 0, NULL, NULL}};
+
+ srna= RNA_def_struct(brna, "FreestyleLineStyle", "ID");
+ RNA_def_struct_ui_text(srna, "Freestyle Line Style", "Freestyle line style, reusable by multiple line sets");
+ RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA); /* FIXME: use a proper icon */
+
+ prop= RNA_def_property(srna, "panel", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "panel");
+ RNA_def_property_enum_items(prop, panel_items);
+ RNA_def_property_ui_text(prop, "Panel", "Select the property panel to be shown");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "r");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Color", "Base line color, possibly modified by line color modifiers");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "alpha");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Alpha", "Base alpha transparency, possibly modified by alpha transparency modifiers");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Thickness", "Base line thickness, possibly modified by line thickness modifiers");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "thickness_position", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "thickness_position");
+ RNA_def_property_enum_items(prop, thickness_position_items);
+ RNA_def_property_ui_text(prop, "Thickness Position", "Select the position of stroke thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "thickness_ratio", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "thickness_ratio");
+ RNA_def_property_range(prop, 0.f, 1.f);
+ RNA_def_property_ui_text(prop, "Thickness Ratio", "A number between 0 (inside) and 1 (outside) specifying the relative position of stroke thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "color_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "color_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "LineStyleColorModifier");
+ RNA_def_property_ui_text(prop, "Color Modifiers", "List of line color modifiers");
+
+ prop= RNA_def_property(srna, "alpha_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "alpha_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "LineStyleAlphaModifier");
+ RNA_def_property_ui_text(prop, "Alpha Modifiers", "List of alpha trancparency modifiers");
+
+ prop= RNA_def_property(srna, "thickness_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "thickness_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "LineStyleThicknessModifier");
+ RNA_def_property_ui_text(prop, "Thickness Modifiers", "List of line thickness modifiers");
+
+ prop= RNA_def_property(srna, "use_chaining", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", LS_NO_CHAINING);
+ RNA_def_property_ui_text(prop, "Chaining", "Enable chaining of feature edges");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "chaining", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "chaining");
+ RNA_def_property_enum_items(prop, chaining_items);
+ RNA_def_property_ui_text(prop, "Chaining", "Select the way how feature edges are jointed to form chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "rounds", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "rounds");
+ RNA_def_property_range(prop, 1, 1000);
+ RNA_def_property_ui_text(prop, "Rounds", "Number of rounds in a sketchy multiple touch");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "geometry_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "geometry_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "LineStyleGeometryModifier");
+ RNA_def_property_ui_text(prop, "Geometry Modifiers", "List of stroke geometry modifiers");
+
+ prop= RNA_def_property(srna, "same_object", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SAME_OBJECT);
+ RNA_def_property_ui_text(prop, "Same Object", "If true, only feature edges of the same object are joined");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "use_split_length", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SPLIT_LENGTH);
+ RNA_def_property_ui_text(prop, "Use Split Length", "Enable chain splitting by curvilinear 2D length");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "split_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "split_length");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Split Length", "Curvilinear 2D length for chain splitting");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "use_min_angle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MIN_2D_ANGLE);
+ RNA_def_property_ui_text(prop, "Use Min 2D Angle", "Split chains at points with angles smaller than the minimum 2D angle");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "min_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "min_angle");
+ RNA_def_property_range(prop, 0.0f, (float)M_PI);
+ RNA_def_property_ui_text(prop, "Min 2D Angle", "Minimum 2D angle for splitting chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "use_max_angle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MAX_2D_ANGLE);
+ RNA_def_property_ui_text(prop, "Use Max 2D Angle", "Split chains at points with angles larger than the maximum 2D angle");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "max_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "max_angle");
+ RNA_def_property_range(prop, 0.0f, (float)M_PI);
+ RNA_def_property_ui_text(prop, "Max 2D Angle", "Maximum 2D angle for splitting chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "use_min_length", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MIN_2D_LENGTH);
+ RNA_def_property_ui_text(prop, "Use Min 2D Length", "Enable the selection of chains by a minimum 2D length");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "min_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_length");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Min 2D Length", "Minimum curvilinear 2D length for the selection of chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "use_max_length", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MAX_2D_LENGTH);
+ RNA_def_property_ui_text(prop, "Use Max 2D Length", "Enable the selection of chains by a maximum 2D length");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "max_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_length");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Max 2D Length", "Maximum curvilinear 2D length for the selection of chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "material_boundary", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MATERIAL_BOUNDARY);
+ RNA_def_property_ui_text(prop, "Material Boundary", "If true, chains of feature edges are split at material boundaries");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "use_dashed_line", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_DASHED_LINE);
+ RNA_def_property_ui_text(prop, "Dashed Line", "Enable or disable dashed line");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "caps", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "caps");
+ RNA_def_property_enum_items(prop, cap_items);
+ RNA_def_property_ui_text(prop, "Cap", "Select the shape of both ends of strokes");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "dash1", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "dash1");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Dash #1", "Length of the 1st dash");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "gap1", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "gap1");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Gap #1", "Length of the 1st gap");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "dash2", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "dash2");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Dash #2", "Length of the 2nd dash");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "gap2", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "gap2");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Gap #2", "Length of the 2nd gap");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "dash3", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "dash3");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Dash #3", "Length of the 3rd dash");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop= RNA_def_property(srna, "gap3", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "gap3");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Gap #3", "Length of the 3rd gap");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+}
+
+void RNA_def_linestyle(BlenderRNA *brna)
+{
+ rna_def_linestyle_modifiers(brna);
+ rna_def_linestyle(brna);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 74b3c431183..78e0fde5715 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -258,6 +258,12 @@ static void rna_Main_masks_begin(CollectionPropertyIterator *iter, PointerRNA *p
rna_iterator_listbase_begin(iter, &bmain->mask, NULL);
}
+static void rna_Main_linestyle_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Main *bmain= (Main*)ptr->data;
+ rna_iterator_listbase_begin(iter, &bmain->linestyle, NULL);
+}
+
#ifdef UNIT_TEST
static PointerRNA rna_Test_test_get(PointerRNA *ptr)
@@ -322,6 +328,7 @@ void RNA_def_main(BlenderRNA *brna)
{"grease_pencil", "GreasePencil", "rna_Main_gpencil_begin", "Grease Pencil", "Grease Pencil datablocks", RNA_def_main_gpencil},
{"movieclips", "MovieClip", "rna_Main_movieclips_begin", "Movie Clips", "Movie Clip datablocks", RNA_def_main_movieclips},
{"masks", "Mask", "rna_Main_masks_begin", "Masks", "Masks datablocks", RNA_def_main_masks},
+ {"linestyles", "FreestyleLineStyle", "rna_Main_linestyle_begin", "Line Styles", "Line Style datablocks", RNA_def_main_linestyles},
{NULL, NULL, NULL, NULL, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 307982e4bb1..100485dd714 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -71,6 +71,7 @@
#include "BKE_speaker.h"
#include "BKE_movieclip.h"
#include "BKE_mask.h"
+#include "BKE_linestyle.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
@@ -95,13 +96,13 @@
#include "ED_screen.h"
-Camera *rna_Main_cameras_new(Main *UNUSED(bmain), const char *name)
+static Camera *rna_Main_cameras_new(Main *UNUSED(bmain), const char *name)
{
ID *id = BKE_camera_add(name);
id_us_min(id);
return (Camera *)id;
}
-void rna_Main_cameras_remove(Main *bmain, ReportList *reports, struct Camera *camera)
+static void rna_Main_cameras_remove(Main *bmain, ReportList *reports, struct Camera *camera)
{
if (ID_REAL_USERS(camera) <= 0)
BKE_libblock_free(&bmain->camera, camera);
@@ -112,11 +113,11 @@ void rna_Main_cameras_remove(Main *bmain, ReportList *reports, struct Camera *ca
/* XXX python now has invalid pointer? */
}
-Scene *rna_Main_scenes_new(Main *UNUSED(bmain), const char *name)
+static Scene *rna_Main_scenes_new(Main *UNUSED(bmain), const char *name)
{
return BKE_scene_add(name);
}
-void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, struct Scene *scene)
+static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, struct Scene *scene)
{
/* don't call BKE_libblock_free(...) directly */
Scene *newscene;
@@ -136,7 +137,7 @@ void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, struc
BKE_scene_unlink(bmain, scene, newscene);
}
-Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const char *name, ID *data)
+static Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const char *name, ID *data)
{
Object *ob;
int type = OB_EMPTY;
@@ -190,7 +191,7 @@ Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const cha
return ob;
}
-void rna_Main_objects_remove(Main *bmain, ReportList *reports, struct Object *object)
+static void rna_Main_objects_remove(Main *bmain, ReportList *reports, struct Object *object)
{
if (ID_REAL_USERS(object) <= 0) {
BKE_object_unlink(object); /* needed or ID pointers to this are not cleared */
@@ -202,13 +203,13 @@ void rna_Main_objects_remove(Main *bmain, ReportList *reports, struct Object *ob
}
}
-Material *rna_Main_materials_new(Main *UNUSED(bmain), const char *name)
+static Material *rna_Main_materials_new(Main *UNUSED(bmain), const char *name)
{
ID *id = (ID *)BKE_material_add(name);
id_us_min(id);
return (Material *)id;
}
-void rna_Main_materials_remove(Main *bmain, ReportList *reports, struct Material *material)
+static void rna_Main_materials_remove(Main *bmain, ReportList *reports, struct Material *material)
{
if (ID_REAL_USERS(material) <= 0)
BKE_libblock_free(&bmain->mat, material);
@@ -219,14 +220,14 @@ void rna_Main_materials_remove(Main *bmain, ReportList *reports, struct Material
/* XXX python now has invalid pointer? */
}
-bNodeTree *rna_Main_nodetree_new(Main *UNUSED(bmain), const char *name, int type)
+static bNodeTree *rna_Main_nodetree_new(Main *UNUSED(bmain), const char *name, int type)
{
bNodeTree *tree = ntreeAddTree(name, type, NODE_GROUP);
id_us_min(&tree->id);
return tree;
}
-void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, struct bNodeTree *tree)
+static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, struct bNodeTree *tree)
{
if (ID_REAL_USERS(tree) <= 0)
BKE_libblock_free(&bmain->nodetree, tree);
@@ -237,7 +238,7 @@ void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, struct bNodeTree
/* XXX python now has invalid pointer? */
}
-Mesh *rna_Main_meshes_new(Main *UNUSED(bmain), const char *name)
+static Mesh *rna_Main_meshes_new(Main *UNUSED(bmain), const char *name)
{
Mesh *me = BKE_mesh_add(name);
id_us_min(&me->id);
@@ -254,14 +255,14 @@ void rna_Main_meshes_remove(Main *bmain, ReportList *reports, Mesh *mesh)
/* XXX python now has invalid pointer? */
}
-Lamp *rna_Main_lamps_new(Main *UNUSED(bmain), const char *name, int type)
+static Lamp *rna_Main_lamps_new(Main *UNUSED(bmain), const char *name, int type)
{
Lamp *lamp = BKE_lamp_add(name);
lamp->type = type;
id_us_min(&lamp->id);
return lamp;
}
-void rna_Main_lamps_remove(Main *bmain, ReportList *reports, Lamp *lamp)
+static void rna_Main_lamps_remove(Main *bmain, ReportList *reports, Lamp *lamp)
{
if (ID_REAL_USERS(lamp) <= 0)
BKE_libblock_free(&bmain->lamp, lamp);
@@ -272,14 +273,14 @@ void rna_Main_lamps_remove(Main *bmain, ReportList *reports, Lamp *lamp)
/* XXX python now has invalid pointer? */
}
-Image *rna_Main_images_new(Main *UNUSED(bmain), const char *name, int width, int height, int alpha, int float_buffer)
+static Image *rna_Main_images_new(Main *UNUSED(bmain), const char *name, int width, int height, int alpha, int float_buffer)
{
float color[4] = {0.0, 0.0, 0.0, 1.0};
Image *image = BKE_image_add_generated(width, height, name, alpha ? 32 : 24, float_buffer, 0, color);
id_us_min(&image->id);
return image;
}
-Image *rna_Main_images_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath)
+static Image *rna_Main_images_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath)
{
Image *ima;
@@ -292,7 +293,7 @@ Image *rna_Main_images_load(Main *UNUSED(bmain), ReportList *reports, const char
return ima;
}
-void rna_Main_images_remove(Main *bmain, ReportList *reports, Image *image)
+static void rna_Main_images_remove(Main *bmain, ReportList *reports, Image *image)
{
if (ID_REAL_USERS(image) <= 0)
BKE_libblock_free(&bmain->image, image);
@@ -303,13 +304,13 @@ void rna_Main_images_remove(Main *bmain, ReportList *reports, Image *image)
/* XXX python now has invalid pointer? */
}
-Lattice *rna_Main_lattices_new(Main *UNUSED(bmain), const char *name)
+static Lattice *rna_Main_lattices_new(Main *UNUSED(bmain), const char *name)
{
Lattice *lt = BKE_lattice_add(name);
id_us_min(&lt->id);
return lt;
}
-void rna_Main_lattices_remove(Main *bmain, ReportList *reports, struct Lattice *lt)
+static void rna_Main_lattices_remove(Main *bmain, ReportList *reports, struct Lattice *lt)
{
if (ID_REAL_USERS(lt) <= 0)
BKE_libblock_free(&bmain->latt, lt);
@@ -318,13 +319,13 @@ void rna_Main_lattices_remove(Main *bmain, ReportList *reports, struct Lattice *
lt->id.name + 2, ID_REAL_USERS(lt));
}
-Curve *rna_Main_curves_new(Main *UNUSED(bmain), const char *name, int type)
+static Curve *rna_Main_curves_new(Main *UNUSED(bmain), const char *name, int type)
{
Curve *cu = BKE_curve_add(name, type);
id_us_min(&cu->id);
return cu;
}
-void rna_Main_curves_remove(Main *bmain, ReportList *reports, struct Curve *cu)
+static void rna_Main_curves_remove(Main *bmain, ReportList *reports, struct Curve *cu)
{
if (ID_REAL_USERS(cu) <= 0)
BKE_libblock_free(&bmain->curve, cu);
@@ -333,13 +334,13 @@ void rna_Main_curves_remove(Main *bmain, ReportList *reports, struct Curve *cu)
cu->id.name + 2, ID_REAL_USERS(cu));
}
-MetaBall *rna_Main_metaballs_new(Main *UNUSED(bmain), const char *name)
+static MetaBall *rna_Main_metaballs_new(Main *UNUSED(bmain), const char *name)
{
MetaBall *mb = BKE_mball_add(name);
id_us_min(&mb->id);
return mb;
}
-void rna_Main_metaballs_remove(Main *bmain, ReportList *reports, struct MetaBall *mb)
+static void rna_Main_metaballs_remove(Main *bmain, ReportList *reports, struct MetaBall *mb)
{
if (ID_REAL_USERS(mb) <= 0)
BKE_libblock_free(&bmain->mball, mb);
@@ -348,7 +349,7 @@ void rna_Main_metaballs_remove(Main *bmain, ReportList *reports, struct MetaBall
mb->id.name + 2, ID_REAL_USERS(mb));
}
-VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepath)
+static VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepath)
{
VFont *font;
@@ -362,7 +363,7 @@ VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepat
return font;
}
-void rna_Main_fonts_remove(Main *bmain, ReportList *reports, VFont *vfont)
+static void rna_Main_fonts_remove(Main *bmain, ReportList *reports, VFont *vfont)
{
if (ID_REAL_USERS(vfont) <= 0)
BKE_libblock_free(&bmain->vfont, vfont);
@@ -373,14 +374,14 @@ void rna_Main_fonts_remove(Main *bmain, ReportList *reports, VFont *vfont)
/* XXX python now has invalid pointer? */
}
-Tex *rna_Main_textures_new(Main *UNUSED(bmain), const char *name, int type)
+static Tex *rna_Main_textures_new(Main *UNUSED(bmain), const char *name, int type)
{
Tex *tex = add_texture(name);
tex_set_type(tex, type);
id_us_min(&tex->id);
return tex;
}
-void rna_Main_textures_remove(Main *bmain, ReportList *reports, struct Tex *tex)
+static void rna_Main_textures_remove(Main *bmain, ReportList *reports, struct Tex *tex)
{
if (ID_REAL_USERS(tex) <= 0)
BKE_libblock_free(&bmain->tex, tex);
@@ -389,13 +390,13 @@ void rna_Main_textures_remove(Main *bmain, ReportList *reports, struct Tex *tex)
tex->id.name + 2, ID_REAL_USERS(tex));
}
-Brush *rna_Main_brushes_new(Main *UNUSED(bmain), const char *name)
+static Brush *rna_Main_brushes_new(Main *UNUSED(bmain), const char *name)
{
Brush *brush = BKE_brush_add(name);
id_us_min(&brush->id);
return brush;
}
-void rna_Main_brushes_remove(Main *bmain, ReportList *reports, struct Brush *brush)
+static void rna_Main_brushes_remove(Main *bmain, ReportList *reports, struct Brush *brush)
{
if (ID_REAL_USERS(brush) <= 0)
BKE_libblock_free(&bmain->brush, brush);
@@ -404,13 +405,13 @@ void rna_Main_brushes_remove(Main *bmain, ReportList *reports, struct Brush *bru
brush->id.name + 2, ID_REAL_USERS(brush));
}
-World *rna_Main_worlds_new(Main *UNUSED(bmain), const char *name)
+static World *rna_Main_worlds_new(Main *UNUSED(bmain), const char *name)
{
World *world = add_world(name);
id_us_min(&world->id);
return world;
}
-void rna_Main_worlds_remove(Main *bmain, ReportList *reports, struct World *world)
+static void rna_Main_worlds_remove(Main *bmain, ReportList *reports, struct World *world)
{
if (ID_REAL_USERS(world) <= 0)
BKE_libblock_free(&bmain->world, world);
@@ -419,24 +420,24 @@ void rna_Main_worlds_remove(Main *bmain, ReportList *reports, struct World *worl
world->id.name + 2, ID_REAL_USERS(world));
}
-Group *rna_Main_groups_new(Main *UNUSED(bmain), const char *name)
+static Group *rna_Main_groups_new(Main *UNUSED(bmain), const char *name)
{
return add_group(name);
}
-void rna_Main_groups_remove(Main *bmain, Group *group)
+static void rna_Main_groups_remove(Main *bmain, Group *group)
{
BKE_group_unlink(group);
BKE_libblock_free(&bmain->group, group);
/* XXX python now has invalid pointer? */
}
-Speaker *rna_Main_speakers_new(Main *UNUSED(bmain), const char *name)
+static Speaker *rna_Main_speakers_new(Main *UNUSED(bmain), const char *name)
{
Speaker *speaker = BKE_speaker_add(name);
id_us_min(&speaker->id);
return speaker;
}
-void rna_Main_speakers_remove(Main *bmain, ReportList *reports, Speaker *speaker)
+static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, Speaker *speaker)
{
if (ID_REAL_USERS(speaker) <= 0)
BKE_libblock_free(&bmain->speaker, speaker);
@@ -447,18 +448,18 @@ void rna_Main_speakers_remove(Main *bmain, ReportList *reports, Speaker *speaker
/* XXX python now has invalid pointer? */
}
-Text *rna_Main_texts_new(Main *UNUSED(bmain), const char *name)
+static Text *rna_Main_texts_new(Main *UNUSED(bmain), const char *name)
{
return BKE_text_add(name);
}
-void rna_Main_texts_remove(Main *bmain, Text *text)
+static void rna_Main_texts_remove(Main *bmain, Text *text)
{
BKE_text_unlink(bmain, text);
BKE_libblock_free(&bmain->text, text);
/* XXX python now has invalid pointer? */
}
-Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *filepath)
+static Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *filepath)
{
Text *txt;
@@ -472,13 +473,13 @@ Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *filepath
return txt;
}
-bArmature *rna_Main_armatures_new(Main *UNUSED(bmain), const char *name)
+static bArmature *rna_Main_armatures_new(Main *UNUSED(bmain), const char *name)
{
bArmature *arm = BKE_armature_add(name);
id_us_min(&arm->id);
return arm;
}
-void rna_Main_armatures_remove(Main *bmain, ReportList *reports, bArmature *arm)
+static void rna_Main_armatures_remove(Main *bmain, ReportList *reports, bArmature *arm)
{
if (ID_REAL_USERS(arm) <= 0)
BKE_libblock_free(&bmain->armature, arm);
@@ -489,14 +490,14 @@ void rna_Main_armatures_remove(Main *bmain, ReportList *reports, bArmature *arm)
/* XXX python now has invalid pointer? */
}
-bAction *rna_Main_actions_new(Main *UNUSED(bmain), const char *name)
+static bAction *rna_Main_actions_new(Main *UNUSED(bmain), const char *name)
{
bAction *act = add_empty_action(name);
id_us_min(&act->id);
act->id.flag &= ~LIB_FAKEUSER;
return act;
}
-void rna_Main_actions_remove(Main *bmain, ReportList *reports, bAction *act)
+static void rna_Main_actions_remove(Main *bmain, ReportList *reports, bAction *act)
{
if (ID_REAL_USERS(act) <= 0)
BKE_libblock_free(&bmain->action, act);
@@ -507,13 +508,13 @@ void rna_Main_actions_remove(Main *bmain, ReportList *reports, bAction *act)
/* XXX python now has invalid pointer? */
}
-ParticleSettings *rna_Main_particles_new(Main *bmain, const char *name)
+static ParticleSettings *rna_Main_particles_new(Main *bmain, const char *name)
{
ParticleSettings *part = psys_new_settings(name, bmain);
id_us_min(&part->id);
return part;
}
-void rna_Main_particles_remove(Main *bmain, ReportList *reports, ParticleSettings *part)
+static void rna_Main_particles_remove(Main *bmain, ReportList *reports, ParticleSettings *part)
{
if (ID_REAL_USERS(part) <= 0)
BKE_libblock_free(&bmain->particle, part);
@@ -524,7 +525,7 @@ void rna_Main_particles_remove(Main *bmain, ReportList *reports, ParticleSetting
/* XXX python now has invalid pointer? */
}
-MovieClip *rna_Main_movieclip_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath)
+static MovieClip *rna_Main_movieclip_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath)
{
MovieClip *clip;
@@ -538,14 +539,14 @@ MovieClip *rna_Main_movieclip_load(Main *UNUSED(bmain), ReportList *reports, con
return clip;
}
-void rna_Main_movieclips_remove(Main *bmain, MovieClip *clip)
+static void rna_Main_movieclips_remove(Main *bmain, MovieClip *clip)
{
BKE_movieclip_unlink(bmain, clip);
BKE_libblock_free(&bmain->movieclip, clip);
/* XXX python now has invalid pointer? */
}
-Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name)
+static Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name)
{
Mask *mask;
@@ -554,44 +555,62 @@ Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name)
return mask;
}
-void rna_Main_masks_remove(Main *bmain, Mask *mask)
+static void rna_Main_masks_remove(Main *bmain, Mask *mask)
{
BKE_mask_free(bmain, mask);
BKE_libblock_free(&bmain->mask, mask);
/* XXX python now has invalid pointer? */
}
+FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char* name)
+{
+ FreestyleLineStyle *linestyle = FRS_new_linestyle(name, bmain);
+ id_us_min(&linestyle->id);
+ return linestyle;
+}
+
+void rna_Main_linestyles_remove(Main *bmain, ReportList *reports, FreestyleLineStyle *linestyle)
+{
+ if(ID_REAL_USERS(linestyle) <= 0)
+ BKE_libblock_free(&bmain->linestyle, linestyle);
+ else
+ BKE_reportf(reports, RPT_ERROR, "Line style \"%s\" must have zero users to be removed, found %d.", linestyle->id.name+2, ID_REAL_USERS(linestyle));
+
+ /* XXX python now has invalid pointer? */
+}
+
/* tag functions, all the same */
-void rna_Main_cameras_tag(Main *bmain, int value) { tag_main_lb(&bmain->camera, value); }
-void rna_Main_scenes_tag(Main *bmain, int value) { tag_main_lb(&bmain->scene, value); }
-void rna_Main_objects_tag(Main *bmain, int value) { tag_main_lb(&bmain->object, value); }
-void rna_Main_materials_tag(Main *bmain, int value) { tag_main_lb(&bmain->mat, value); }
-void rna_Main_node_groups_tag(Main *bmain, int value) { tag_main_lb(&bmain->nodetree, value); }
-void rna_Main_meshes_tag(Main *bmain, int value) { tag_main_lb(&bmain->mesh, value); }
-void rna_Main_lamps_tag(Main *bmain, int value) { tag_main_lb(&bmain->lamp, value); }
-void rna_Main_libraries_tag(Main *bmain, int value) { tag_main_lb(&bmain->library, value); }
-void rna_Main_screens_tag(Main *bmain, int value) { tag_main_lb(&bmain->screen, value); }
-void rna_Main_window_managers_tag(Main *bmain, int value) { tag_main_lb(&bmain->wm, value); }
-void rna_Main_images_tag(Main *bmain, int value) { tag_main_lb(&bmain->image, value); }
-void rna_Main_lattices_tag(Main *bmain, int value) { tag_main_lb(&bmain->latt, value); }
-void rna_Main_curves_tag(Main *bmain, int value) { tag_main_lb(&bmain->curve, value); }
-void rna_Main_metaballs_tag(Main *bmain, int value) { tag_main_lb(&bmain->mball, value); }
-void rna_Main_fonts_tag(Main *bmain, int value) { tag_main_lb(&bmain->vfont, value); }
-void rna_Main_textures_tag(Main *bmain, int value) { tag_main_lb(&bmain->tex, value); }
-void rna_Main_brushes_tag(Main *bmain, int value) { tag_main_lb(&bmain->brush, value); }
-void rna_Main_worlds_tag(Main *bmain, int value) { tag_main_lb(&bmain->world, value); }
-void rna_Main_groups_tag(Main *bmain, int value) { tag_main_lb(&bmain->group, value); }
-void rna_Main_shape_keys_tag(Main *bmain, int value) { tag_main_lb(&bmain->key, value); }
-void rna_Main_scripts_tag(Main *bmain, int value) { tag_main_lb(&bmain->script, value); }
-void rna_Main_texts_tag(Main *bmain, int value) { tag_main_lb(&bmain->text, value); }
-void rna_Main_speakers_tag(Main *bmain, int value) { tag_main_lb(&bmain->speaker, value); }
-void rna_Main_sounds_tag(Main *bmain, int value) { tag_main_lb(&bmain->sound, value); }
-void rna_Main_armatures_tag(Main *bmain, int value) { tag_main_lb(&bmain->armature, value); }
-void rna_Main_actions_tag(Main *bmain, int value) { tag_main_lb(&bmain->action, value); }
-void rna_Main_particles_tag(Main *bmain, int value) { tag_main_lb(&bmain->particle, value); }
-void rna_Main_gpencil_tag(Main *bmain, int value) { tag_main_lb(&bmain->gpencil, value); }
-void rna_Main_movieclips_tag(Main *bmain, int value) { tag_main_lb(&bmain->movieclip, value); }
-void rna_Main_masks_tag(Main *bmain, int value) { tag_main_lb(&bmain->mask, value); }
+static void rna_Main_cameras_tag(Main *bmain, int value) { tag_main_lb(&bmain->camera, value); }
+static void rna_Main_scenes_tag(Main *bmain, int value) { tag_main_lb(&bmain->scene, value); }
+static void rna_Main_objects_tag(Main *bmain, int value) { tag_main_lb(&bmain->object, value); }
+static void rna_Main_materials_tag(Main *bmain, int value) { tag_main_lb(&bmain->mat, value); }
+static void rna_Main_node_groups_tag(Main *bmain, int value) { tag_main_lb(&bmain->nodetree, value); }
+static void rna_Main_meshes_tag(Main *bmain, int value) { tag_main_lb(&bmain->mesh, value); }
+static void rna_Main_lamps_tag(Main *bmain, int value) { tag_main_lb(&bmain->lamp, value); }
+static void rna_Main_libraries_tag(Main *bmain, int value) { tag_main_lb(&bmain->library, value); }
+static void rna_Main_screens_tag(Main *bmain, int value) { tag_main_lb(&bmain->screen, value); }
+static void rna_Main_window_managers_tag(Main *bmain, int value) { tag_main_lb(&bmain->wm, value); }
+static void rna_Main_images_tag(Main *bmain, int value) { tag_main_lb(&bmain->image, value); }
+static void rna_Main_lattices_tag(Main *bmain, int value) { tag_main_lb(&bmain->latt, value); }
+static void rna_Main_curves_tag(Main *bmain, int value) { tag_main_lb(&bmain->curve, value); }
+static void rna_Main_metaballs_tag(Main *bmain, int value) { tag_main_lb(&bmain->mball, value); }
+static void rna_Main_fonts_tag(Main *bmain, int value) { tag_main_lb(&bmain->vfont, value); }
+static void rna_Main_textures_tag(Main *bmain, int value) { tag_main_lb(&bmain->tex, value); }
+static void rna_Main_brushes_tag(Main *bmain, int value) { tag_main_lb(&bmain->brush, value); }
+static void rna_Main_worlds_tag(Main *bmain, int value) { tag_main_lb(&bmain->world, value); }
+static void rna_Main_groups_tag(Main *bmain, int value) { tag_main_lb(&bmain->group, value); }
+static void rna_Main_shape_keys_tag(Main *bmain, int value) { tag_main_lb(&bmain->key, value); }
+static void rna_Main_scripts_tag(Main *bmain, int value) { tag_main_lb(&bmain->script, value); }
+static void rna_Main_texts_tag(Main *bmain, int value) { tag_main_lb(&bmain->text, value); }
+static void rna_Main_speakers_tag(Main *bmain, int value) { tag_main_lb(&bmain->speaker, value); }
+static void rna_Main_sounds_tag(Main *bmain, int value) { tag_main_lb(&bmain->sound, value); }
+static void rna_Main_armatures_tag(Main *bmain, int value) { tag_main_lb(&bmain->armature, value); }
+static void rna_Main_actions_tag(Main *bmain, int value) { tag_main_lb(&bmain->action, value); }
+static void rna_Main_particles_tag(Main *bmain, int value) { tag_main_lb(&bmain->particle, value); }
+static void rna_Main_gpencil_tag(Main *bmain, int value) { tag_main_lb(&bmain->gpencil, value); }
+static void rna_Main_movieclips_tag(Main *bmain, int value) { tag_main_lb(&bmain->movieclip, value); }
+static void rna_Main_masks_tag(Main *bmain, int value) { tag_main_lb(&bmain->mask, value); }
+void rna_Main_linestyle_tag(Main *bmain, int value) { tag_main_lb(&bmain->linestyle, value); }
static int rna_Main_cameras_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CA); }
static int rna_Main_scenes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCE); }
@@ -635,6 +654,8 @@ void RNA_api_main(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "image", "Image", "", "New image");
RNA_def_function_return(func, parm);
+#else
+ (void)srna;
#endif
}
@@ -1573,4 +1594,30 @@ void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
}
+void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "BlendDataLineStyles");
+ srna= RNA_def_struct(brna, "BlendDataLineStyles", NULL);
+ RNA_def_struct_sdna(srna, "Main");
+ RNA_def_struct_ui_text(srna, "Main Line Styles", "Collection of line styles");
+
+ func= RNA_def_function(srna, "new", "rna_Main_linestyles_new");
+ RNA_def_function_ui_description(func, "Add a new line style instance to the main database");
+ parm= RNA_def_string(func, "name", "FreestyleLineStyle", 0, "", "New name for the datablock");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return type */
+ parm= RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "New line style datablock");
+ RNA_def_function_return(func, parm);
+
+ func= RNA_def_function(srna, "remove", "rna_Main_linestyles_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove a line style instance from the current blendfile");
+ parm= RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "Line style to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index 719baed8edb..97d9cc961ef 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -193,7 +193,7 @@ static void rna_MaskLayer_splines_begin(CollectionPropertyIterator *iter, Pointe
rna_iterator_listbase_begin(iter, &masklay->splines, NULL);
}
-void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value)
+static void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value)
{
Mask *mask = (Mask *)ptr->id.data;
MaskLayer *masklay = (MaskLayer *)ptr->data;
@@ -315,7 +315,7 @@ static MaskLayer *rna_Mask_layers_new(Mask *mask, const char *name)
return masklay;
}
-void rna_Mask_layers_remove(Mask *mask, ReportList *reports, MaskLayer *masklay)
+static void rna_Mask_layers_remove(Mask *mask, ReportList *reports, MaskLayer *masklay)
{
if (BLI_findindex(&mask->masklayers, masklay) == -1) {
BKE_reportf(reports, RPT_ERROR, "MaskLayer '%s' not found in mask '%s'", masklay->name, mask->id.name + 2);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 4523858d639..96529de074b 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -45,7 +45,6 @@ static EnumPropertyItem prop_texture_coordinates_items[] = {
{TEXCO_ORCO, "ORCO", 0, "Generated", "Use the original undeformed coordinates of the object"},
{TEXCO_STRAND, "STRAND", 0, "Strand / Particle",
"Use normalized strand texture coordinate (1D) or particle age (X) and trail position (Y)"},
- {TEXCO_STICKY, "STICKY", 0, "Sticky", "Use mesh's sticky coordinates for the texture coordinates"},
{TEXCO_WINDOW, "WINDOW", 0, "Window", "Use screen coordinates as texture coordinates"},
{TEXCO_NORM, "NORMAL", 0, "Normal", "Use normal vector as texture coordinates"},
{TEXCO_REFL, "REFLECTION", 0, "Reflection", "Use reflection vector as texture coordinates"},
@@ -303,7 +302,6 @@ static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED
else if (ELEM3(ma->material_type, MA_TYPE_SURFACE, MA_TYPE_HALO, MA_TYPE_WIRE)) {
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_UV);
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_STRAND);
- RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_STICKY);
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_WINDOW);
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_NORM);
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_REFL);
@@ -1939,6 +1937,12 @@ void RNA_def_material(BlenderRNA *brna)
"- for anisotropic shading effects");
RNA_def_property_update(prop, 0, "rna_Material_update");
+ prop = RNA_def_property(srna, "use_uv_project", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mapflag", MA_MAPFLAG_UVPROJECT);
+ RNA_def_property_ui_text(prop, "UV Project",
+ "Use to ensure UV interpolation is correct for camera projections (use with UV project modifier)");
+ RNA_def_property_update(prop, 0, "rna_Material_update");
+
/* nested structs */
prop = RNA_def_property(srna, "raytrace_mirror", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index fe5f8e574a0..ce86f90f018 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -149,7 +149,7 @@ void rna_Mesh_update_draw(Main *bmain, Scene *scene, PointerRNA *ptr)
}
-void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Mesh *me = ptr->data;
if ((me->editflag & ME_EDIT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_MASK)) {
@@ -158,7 +158,7 @@ void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_Mesh_update_draw(bmain, scene, ptr);
}
-void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Mesh *me = ptr->data;
if ((me->editflag & ME_EDIT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_MASK)) {
@@ -1204,11 +1204,6 @@ static char *rna_MeshColor_path(PointerRNA *ptr)
return rna_LoopCustomData_data_path(ptr, "vertex_colors", CD_MLOOPCOL);
}
-static char *rna_MeshSticky_path(PointerRNA *ptr)
-{
- return BLI_sprintfN("sticky[%d]", (int)((MSticky *)ptr->data - rna_mesh(ptr)->msticky));
-}
-
static char *rna_MeshIntPropertyLayer_path(PointerRNA *ptr)
{
return BLI_sprintfN("int_layers[\"%s\"]", ((CustomDataLayer *)ptr->data)->name);
@@ -1556,6 +1551,11 @@ static void rna_def_medge(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sharp", "Sharp edge for the EdgeSplit modifier");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+ prop = RNA_def_property(srna, "use_freestyle_edge_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FREESTYLE_EDGE);
+ RNA_def_property_ui_text(prop, "Freestyle Edge Mark", "Edge mark for Freestyle feature edge detection");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
prop = RNA_def_property(srna, "is_loose", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_LOOSEEDGE);
RNA_def_property_ui_text(prop, "Loose", "Loose edge");
@@ -1611,6 +1611,11 @@ static void rna_def_mface(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_SMOOTH);
RNA_def_property_ui_text(prop, "Smooth", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+ prop = RNA_def_property(srna, "use_freestyle_face_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FREESTYLE_FACE);
+ RNA_def_property_ui_text(prop, "Freestyle Face Mark", "Face mark for Freestyle feature edge detection");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
RNA_def_property_array(prop, 3);
@@ -1709,6 +1714,11 @@ static void rna_def_mpolygon(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Smooth", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+ prop = RNA_def_property(srna, "use_freestyle_face_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FREESTYLE_FACE);
+ RNA_def_property_ui_text(prop, "Freestyle Face Mark", "Face mark for Freestyle feature edge detection");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -1.0f, 1.0f);
@@ -1957,21 +1967,6 @@ static void rna_def_mtexpoly(BlenderRNA *brna)
#endif
}
-static void rna_def_msticky(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "MeshSticky", NULL);
- RNA_def_struct_sdna(srna, "MSticky");
- RNA_def_struct_ui_text(srna, "Mesh Vertex Sticky Texture Coordinate", "Sticky texture coordinate");
- RNA_def_struct_path_func(srna, "rna_MeshSticky_path");
-
- prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_ui_text(prop, "Location", "Sticky texture coordinate location");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-}
-
static void rna_def_mcol(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2609,7 +2604,7 @@ static void rna_def_uv_textures(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
-static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
{
StructRNA *srna;
PropertyRNA *prop;
@@ -2696,11 +2691,6 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Polygons", "Polygons of the mesh");
rna_def_mesh_polygons(brna, prop);
- prop = RNA_def_property(srna, "sticky", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "msticky", "totvert");
- RNA_def_property_struct_type(prop, "MeshSticky");
- RNA_def_property_ui_text(prop, "Sticky", "Sticky texture coordinates");
-
/* TODO, should this be allowed to be its self? */
prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");
@@ -2943,6 +2933,16 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Sharp", "Display sharp edges, used with the EdgeSplit modifier");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+ prop = RNA_def_property(srna, "show_freestyle_edge_marks", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_FREESTYLE_EDGE);
+ RNA_def_property_ui_text(prop, "Draw Freestyle Edge Marks", "Display Freestyle edge marks, used with the Freestyle renderer");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+
+ prop = RNA_def_property(srna, "show_freestyle_face_marks", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_FREESTYLE_FACE);
+ RNA_def_property_ui_text(prop, "Draw Freestyle Face Marks", "Display Freestyle face marks, used with the Freestyle renderer");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+
prop = RNA_def_property(srna, "show_extra_edge_length", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_EDGELEN);
RNA_def_property_ui_text(prop, "Edge Length",
@@ -3036,7 +3036,6 @@ void RNA_def_mesh(BlenderRNA *brna)
rna_def_mloopuv(brna);
rna_def_mtface(brna);
rna_def_mtexpoly(brna);
- rna_def_msticky(brna);
rna_def_mcol(brna);
rna_def_mloopcol(brna);
rna_def_mproperties(brna);
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index fe18e6254d0..b63390c65ed 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -41,8 +41,10 @@
#include "BKE_mesh.h"
#include "ED_mesh.h"
+#include "rna_internal.h" /* own include */
+
#ifdef RNA_RUNTIME
-const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, bContext *C, struct Mesh *mesh2)
+static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, bContext *C, struct Mesh *mesh2)
{
const char *ret = BKE_mesh_cmp(mesh, mesh2, FLT_EPSILON * 60);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 084cda87507..eb4660c18e8 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -215,7 +215,7 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
}
}
-void rna_Modifier_name_set(PointerRNA *ptr, const char *value)
+static void rna_Modifier_name_set(PointerRNA *ptr, const char *value)
{
ModifierData *md = ptr->data;
char oldname[sizeof(md->name)];
@@ -2658,7 +2658,7 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
#endif
}
-static void rna_def_modifier_weightvg_mask(BlenderRNA *brna, StructRNA *srna)
+static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), StructRNA *srna)
{
static EnumPropertyItem weightvg_mask_tex_map_items[] = {
{MOD_DISP_MAP_LOCAL, "LOCAL", 0, "Local", "Use local generated coordinates"},
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index 8d1105fd620..c221d1175df 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -187,8 +187,7 @@ static void rna_def_moviecliUser(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Movie Clip User",
"Parameters defining how a MovieClip datablock is used by another datablock");
- prop = RNA_def_property(srna, "current_frame", PROP_INT, PROP_TIME);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ prop = RNA_def_property(srna, "frame_current", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "framenr");
RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Current Frame", "Current frame number in movie or image sequence");
@@ -304,7 +303,7 @@ static void rna_def_movieclip(BlenderRNA *brna)
prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings");
RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
- RNA_def_property_ui_text(prop, "Colorspace Settings", "Input color space settings");
+ RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
}
void RNA_def_movieclip(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 16753961852..6e0f9f37d17 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -360,7 +360,7 @@ static void rna_NlaStrip_remove(NlaTrack *track, bContext *C, ReportList *report
/* Set the 'solo' setting for the given NLA-track, making sure that it is the only one
* that has this status in its AnimData block.
*/
-void rna_NlaTrack_solo_set(PointerRNA *ptr, int value)
+static void rna_NlaTrack_solo_set(PointerRNA *ptr, int value)
{
NlaTrack *data = (NlaTrack *)ptr->data;
AnimData *adt = BKE_animdata_from_id(ptr->id.data);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 55dda3fc315..6b543f9f576 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3839,7 +3839,7 @@ static void def_cmp_trackpos(StructRNA *srna)
RNA_def_property_ui_text(prop, "Position", "Which marker position to use for output");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
- prop = RNA_def_property(srna, "relative_frame", PROP_INT, PROP_NONE);
+ prop = RNA_def_property(srna, "frame_relative", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "custom2");
RNA_def_property_ui_text(prop, "Frame", "Frame to be used for relative position");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -4036,7 +4036,7 @@ static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop)
}
/* shared between all note tree types*/
-static void rna_def_nodetree_active_api(StructRNA *srna, PropertyRNA *cprop)
+static void rna_def_nodetree_active_api(StructRNA *srna, PropertyRNA *UNUSED(cprop))
{
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index e69d313b23b..a10c153515a 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -231,7 +231,7 @@ void rna_Object_internal_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene),
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data);
}
-void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Object *ob = ptr->id.data;
@@ -496,7 +496,7 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value)
"Cannot set dupli-group as object belongs in group being instanced thus causing a cycle");
}
-void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value)
+static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = (Object *)ptr->id.data;
bDeformGroup *dg = (bDeformGroup *)ptr->data;
@@ -1101,7 +1101,7 @@ static void rna_GameObjectSettings_used_state_get(PointerRNA *ptr, int *values)
static void rna_Object_active_shape_key_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
Object *ob = (Object *)ptr->id.data;
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
*min = 0;
if (key) {
@@ -1130,7 +1130,7 @@ static void rna_Object_active_shape_key_index_set(PointerRNA *ptr, int value)
static PointerRNA rna_Object_active_shape_key_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
KeyBlock *kb;
PointerRNA keyptr;
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 5bf1cc281ad..1263e7716dd 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -39,6 +39,8 @@
#include "DNA_object_types.h"
#include "DNA_modifier_types.h"
+#include "rna_internal.h" /* own include */
+
#ifdef RNA_RUNTIME
#include "BLI_math.h"
@@ -385,7 +387,7 @@ static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *
}
}
-int rna_Object_is_visible(Object *ob, Scene *sce)
+static int rna_Object_is_visible(Object *ob, Scene *sce)
{
return !(ob->restrictflag & OB_RESTRICT_VIEW) && (ob->lay & sce->lay);
}
@@ -428,8 +430,8 @@ static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int
#endif
/* BMESH_TODO, return polygon index, not tessface */
-void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], float ray_end[3],
- float r_location[3], float r_normal[3], int *index)
+static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], float ray_end[3],
+ float r_location[3], float r_normal[3], int *index)
{
BVHTreeFromMesh treeData = {NULL};
@@ -470,8 +472,8 @@ void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], fl
*index = -1;
}
-void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float point_co[3], float max_dist,
- float n_location[3], float n_normal[3], int *index)
+static void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float point_co[3], float max_dist,
+ float n_location[3], float n_normal[3], int *index)
{
BVHTreeFromMesh treeData = {NULL};
@@ -510,7 +512,7 @@ void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float poi
/* ObjectBase */
-void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d)
+static void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d)
{
base->lay = base->object->lay = v3d->lay;
}
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index fc3dfafe133..89638389fd2 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -502,7 +502,7 @@ static int rna_PartSettings_is_fluid_get(PointerRNA *ptr)
return part->type == PART_FLUID;
}
-void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value)
+static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = ptr->id.data;
ParticleSystem *part = (ParticleSystem *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 739f302fcbe..2b6fd2cb263 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -148,7 +148,7 @@ void rna_ActionGroup_colorset_set(PointerRNA *ptr, int value)
}
}
-void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value)
+static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = ptr->id.data;
bActionGroup *agrp = ptr->data;
@@ -257,7 +257,7 @@ static int rna_PoseChannel_has_ik_get(PointerRNA *ptr)
return ED_pose_channel_in_IK_chain(ob, pchan);
}
-StructRNA *rna_IKParam_refine(PointerRNA *ptr)
+static StructRNA *rna_IKParam_refine(PointerRNA *ptr)
{
bIKParam *param = (bIKParam *)ptr->data;
@@ -269,7 +269,7 @@ StructRNA *rna_IKParam_refine(PointerRNA *ptr)
}
}
-PointerRNA rna_Pose_ikparam_get(struct PointerRNA *ptr)
+static PointerRNA rna_Pose_ikparam_get(struct PointerRNA *ptr)
{
bPose *pose = (bPose *)ptr->data;
return rna_pointer_inherit_refine(ptr, &RNA_IKParam, pose->ikparam);
@@ -593,7 +593,7 @@ static int rna_PoseChannel_rotation_4d_editable(PointerRNA *ptr, int index)
}
/* not essential, but much faster then the default lookup function */
-int rna_PoseBones_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+static int rna_PoseBones_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
{
bPose *pose = (bPose *)ptr->data;
bPoseChannel *pchan = BKE_pose_channel_find_name(pose, key);
@@ -788,8 +788,6 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_location_editable");
RNA_def_property_ui_text(prop, "Location", "");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
- /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */
- RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
@@ -797,8 +795,6 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_scale_editable");
RNA_def_property_float_array_default(prop, default_scale);
RNA_def_property_ui_text(prop, "Scale", "");
- /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */
- RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
prop = RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION);
@@ -806,8 +802,6 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_4d_editable");
RNA_def_property_float_array_default(prop, default_quat);
RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions");
- /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */
- RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
/* XXX: for axis-angle, it would have been nice to have 2 separate fields for UI purposes, but
@@ -820,15 +814,11 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_4d_editable");
RNA_def_property_float_array_default(prop, default_axisAngle);
RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation");
- /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */
- RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
prop = RNA_def_property(srna, "rotation_euler", PROP_FLOAT, PROP_EULER);
RNA_def_property_float_sdna(prop, NULL, "eul");
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_euler_editable");
- /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */
- RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_ui_text(prop, "Euler Rotation", "Rotation in Eulers");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
diff --git a/source/blender/makesrna/intern/rna_property.c b/source/blender/makesrna/intern/rna_property.c
index bf9f924489b..fc3697633a4 100644
--- a/source/blender/makesrna/intern/rna_property.c
+++ b/source/blender/makesrna/intern/rna_property.c
@@ -89,7 +89,7 @@ static void rna_GameProperty_type_set(PointerRNA *ptr, int value)
if (prop->type != value) {
prop->type = value;
- init_property(prop);
+ BKE_bproperty_init(prop);
}
}
@@ -97,7 +97,7 @@ static void rna_GameProperty_name_set(PointerRNA *ptr, const char *value)
{
bProperty *prop = (bProperty *)(ptr->data);
BLI_strncpy_utf8(prop->name, value, sizeof(prop->name));
- unique_property(NULL, prop, 1);
+ BKE_bproperty_unique(NULL, prop, 1);
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 0227d9c1554..1c7f0b00caf 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -38,6 +38,7 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "DNA_world_types.h"
+#include "DNA_linestyle_types.h"
#include "BLI_math.h"
@@ -159,12 +160,13 @@ EnumPropertyItem snap_node_element_items[] = {
#define R_IMF_ENUM_TAGA_RAW {R_IMF_IMTYPE_RAWTGA, "TARGA_RAW", ICON_FILE_IMAGE, "Targa Raw", \
"Output image in uncompressed Targa format"},
-
+#if 0 /* UNUSED (so far) */
#ifdef WITH_DDS
# define R_IMF_ENUM_DDS {R_IMF_IMTYPE_DDS, "DDS", ICON_FILE_IMAGE, "DDS", "Output image in DDS format"},
#else
# define R_IMF_ENUM_DDS
#endif
+#endif
#ifdef WITH_OPENJPEG
# define R_IMF_ENUM_JPEG2K {R_IMF_IMTYPE_JP2, "JPEG2000", ICON_FILE_IMAGE, "JPEG 2000", \
@@ -322,6 +324,8 @@ EnumPropertyItem image_color_depth_items[] = {
#include "RE_engine.h"
+#include "FRS_freestyle.h"
+
static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
ED_space_image_uv_sculpt_update(bmain->wm.first, scene->toolsettings);
@@ -498,7 +502,7 @@ static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, Pointer
}
-static void rna_Scene_current_frame_set(PointerRNA *ptr, int value)
+static void rna_Scene_frame_current_set(PointerRNA *ptr, int value)
{
Scene *data = (Scene *)ptr->data;
@@ -1403,6 +1407,49 @@ static void rna_SceneCamera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
DAG_id_tag_update(&camera->id, 0);
}
+static PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr)
+{
+ FreestyleLineSet *lineset= (FreestyleLineSet *)ptr->data;
+
+ return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineStyle, lineset->linestyle);
+}
+
+static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value)
+{
+ FreestyleLineSet *lineset= (FreestyleLineSet*)ptr->data;
+
+ lineset->linestyle->id.us--;
+ lineset->linestyle = (FreestyleLineStyle *)value.data;
+ lineset->linestyle->id.us++;
+}
+
+static PointerRNA rna_FreestyleSettings_active_lineset_get(PointerRNA *ptr)
+{
+ FreestyleConfig *config= (FreestyleConfig *)ptr->data;
+ FreestyleLineSet *lineset= FRS_get_active_lineset(config);
+ return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineSet, lineset);
+}
+
+static void rna_FreestyleSettings_active_lineset_index_range(PointerRNA *ptr, int *min, int *max)
+{
+ FreestyleConfig *config= (FreestyleConfig *)ptr->data;
+ *min= 0;
+ *max= BLI_countlist(&config->linesets)-1;
+ *max= MAX2(0, *max);
+}
+
+static int rna_FreestyleSettings_active_lineset_index_get(PointerRNA *ptr)
+{
+ FreestyleConfig *config= (FreestyleConfig *)ptr->data;
+ return FRS_get_active_lineset_index(config);
+}
+
+static void rna_FreestyleSettings_active_lineset_index_set(PointerRNA *ptr, int value)
+{
+ FreestyleConfig *config= (FreestyleConfig *)ptr->data;
+ FRS_set_active_lineset_index(config, value);
+}
+
#else
static void rna_def_transform_orientation(BlenderRNA *brna)
@@ -1470,6 +1517,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{EDGE_MODE_TAG_SHARP, "SHARP", 0, "Tag Sharp", ""},
{EDGE_MODE_TAG_CREASE, "CREASE", 0, "Tag Crease", ""},
{EDGE_MODE_TAG_BEVEL, "BEVEL", 0, "Tag Bevel", ""},
+ {EDGE_MODE_TAG_FREESTYLE, "FREESTYLE", 0, "Tag Freestyle Edge Mark", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1629,7 +1677,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
"Project individual elements on the surface of other objects");
RNA_def_property_ui_icon(prop, ICON_RETOPO, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
-
+
prop = RNA_def_property(srna, "use_snap_self", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "snap_flag", SCE_SNAP_NO_SELF);
RNA_def_property_ui_text(prop, "Project to Self", "Snap onto itself (editmode)");
@@ -2011,6 +2059,12 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ prop= RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "layflag", SCE_LAY_FRS);
+ RNA_def_property_ui_text(prop, "Freestyle", "Render stylized strokes in this Layer");
+ if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+ else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
/* passes */
prop = RNA_def_property(srna, "use_pass_combined", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_COMBINED);
@@ -2231,6 +2285,374 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
+static void rna_def_freestyle_linesets(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "Linesets");
+ srna= RNA_def_struct(brna, "Linesets", NULL);
+ RNA_def_struct_sdna(srna, "FreestyleSettings");
+ RNA_def_struct_ui_text(srna, "Line Sets", "Line sets for associating lines and style parameters");
+
+ prop= RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FreestyleLineSet");
+ RNA_def_property_pointer_funcs(prop, "rna_FreestyleSettings_active_lineset_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Active Line Set", "Active line set being displayed");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_FreestyleSettings_active_lineset_index_get", "rna_FreestyleSettings_active_lineset_index_set", "rna_FreestyleSettings_active_lineset_index_range");
+ RNA_def_property_ui_text(prop, "Active Line Set Index", "Index of active line set slot");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+}
+
+static void rna_def_freestyle_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem edge_type_negation_items[] = {
+ {0, "INCLUSIVE", 0, "Inclusive", "Select feature edges satisfying the given edge type conditions"},
+ {FREESTYLE_LINESET_FE_NOT, "EXCLUSIVE", 0, "Exclusive", "Select feature edges not satisfying the given edge type conditions"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem edge_type_combination_items[] = {
+ {0, "OR", 0, "Logical OR", "Combine feature edge type conditions by logical OR (logical disjunction)"},
+ {FREESTYLE_LINESET_FE_AND, "AND", 0, "Logical AND", "Combine feature edge type conditions by logical AND (logical conjunction)"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem group_negation_items[] = {
+ {0, "INCLUSIVE", 0, "Inclusive", "Select feature edges belonging to some object in the group"},
+ {FREESTYLE_LINESET_GR_NOT, "EXCLUSIVE", 0, "Exclusive", "Select feature edges not belonging to any object in the group"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem face_mark_negation_items[] = {
+ {0, "INCLUSIVE", 0, "Inclusive", "Select feature edges satisfying the given face mark conditions"},
+ {FREESTYLE_LINESET_FM_NOT, "EXCLUSIVE", 0, "Exclusive", "Select feature edges not satisfying the given face mark conditions"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem face_mark_condition_items[] = {
+ {0, "ONE", 0, "One Face", "Select feature edges if one of faces on the right and left has a face mark"},
+ {FREESTYLE_LINESET_FM_BOTH, "BOTH", 0, "Both Faces", "Select feature edges if both faces on the right and left faces have a face mark"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem freestyle_ui_mode_items[] = {
+ {FREESTYLE_CONTROL_SCRIPT_MODE, "SCRIPT", 0, "Python Scripting Mode", "Advanced mode for using style modules in Python"},
+ {FREESTYLE_CONTROL_EDITOR_MODE, "EDITOR", 0, "Parameter Editor Mode", "Basic mode for interactive style parameter editing"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem visibility_items[] ={
+ {FREESTYLE_QI_VISIBLE, "VISIBLE", 0, "Visible", "Select visible feature edges"},
+ {FREESTYLE_QI_HIDDEN, "HIDDEN", 0, "Hidden", "Select hidden feature edges"},
+ {FREESTYLE_QI_RANGE, "RANGE", 0, "QI Range", "Select feature edges within a range of quantitative invisibility (QI) values"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem freestyle_raycasting_algorithm_items[] = {
+ {FREESTYLE_ALGO_REGULAR, "REGULAR", 0, "Normal Ray Casting", "Consider all FEdges in each ViewEdge"},
+ {FREESTYLE_ALGO_FAST, "FAST", 0, "Fast Ray Casting", "Sample some FEdges in each ViewEdge"},
+ {FREESTYLE_ALGO_VERYFAST, "VERYFAST", 0, "Very Fast Ray Casting", "Sample one FEdge in each ViewEdge; do not save list of occluders"},
+ {FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL, "CULLEDADAPTIVETRADITIONAL", 0, "Culled Traditional Visibility Detection", "Culled adaptive grid with heuristic density and traditional QI calculation"},
+ {FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL, "ADAPTIVETRADITIONAL", 0, "Unculled Traditional Visibility Detection", "Adaptive grid with heuristic density and traditional QI calculation"},
+ {FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE, "CULLEDADAPTIVECUMULATIVE", 0, "Culled Cumulative Visibility Detection", "Culled adaptive grid with heuristic density and cumulative QI calculation"},
+ {FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE, "ADAPTIVECUMULATIVE", 0, "Unculled Cumulative Visibility Detection", "Adaptive grid with heuristic density and cumulative QI calculation"},
+ {0, NULL, 0, NULL, NULL}};
+
+
+ /* FreestyleLineSet */
+
+ srna= RNA_def_struct(brna, "FreestyleLineSet", NULL);
+ RNA_def_struct_ui_text(srna, "Freestyle Line Set", "Line set for associating lines and style parameters");
+
+ /* access to line style settings is redirected through functions */
+ /* to allow proper id-buttons functionality */
+ prop= RNA_def_property(srna, "linestyle", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FreestyleLineStyle");
+ RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_NULL);
+ RNA_def_property_pointer_funcs(prop, "rna_FreestyleLineSet_linestyle_get", "rna_FreestyleLineSet_linestyle_set", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Line Style", "Line style settings");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "name");
+ RNA_def_property_ui_text(prop, "Line Set Name", "Line set name");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ prop= RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_LINESET_ENABLED);
+ RNA_def_property_ui_text(prop, "Use", "Enable or disable this line set during stroke rendering");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_by_visibility", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_VISIBILITY);
+ RNA_def_property_ui_text(prop, "Selection by Visibility", "Select feature edges based on visibility");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_by_edge_types", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_EDGE_TYPES);
+ RNA_def_property_ui_text(prop, "Selection by Edge Types", "Select feature edges based on edge types");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_by_group", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_GROUP);
+ RNA_def_property_ui_text(prop, "Selection by Group", "Select feature edges based on a group of objects");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_by_image_border", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_IMAGE_BORDER);
+ RNA_def_property_ui_text(prop, "Selection by Image Border", "Select feature edges by image border (less memory consumption)");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_by_face_marks", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_FACE_MARK);
+ RNA_def_property_ui_text(prop, "Selection by Face Marks", "Select feature edges by face marks");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "edge_type_negation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, edge_type_negation_items);
+ RNA_def_property_ui_text(prop, "Edge Type Negation", "Set the negation operation for conditions on feature edge types");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "edge_type_combination", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, edge_type_combination_items);
+ RNA_def_property_ui_text(prop, "Edge Type Combination", "Set the combination operation for conditions on feature edge types");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "group");
+ RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Group", "A group of objects based on which feature edges are selected");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "group_negation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, group_negation_items);
+ RNA_def_property_ui_text(prop, "Group Negation", "Set the negation operation for conditions on feature edge types");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "face_mark_negation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, face_mark_negation_items);
+ RNA_def_property_ui_text(prop, "Face Mark Negation", "Set the negation operation for the condition on face marks");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "face_mark_condition", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, face_mark_condition_items);
+ RNA_def_property_ui_text(prop, "Face Mark Condition", "Set a feature edge selection condition on face marks");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_silhouette", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SILHOUETTE);
+ RNA_def_property_ui_text(prop, "Silhouette", "Select silhouette edges");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_border", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_BORDER);
+ RNA_def_property_ui_text(prop, "Border", "Select border edges");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_crease", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CREASE);
+ RNA_def_property_ui_text(prop, "Crease", "Select crease edges");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_ridge_valley", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_RIDGE_VALLEY);
+ RNA_def_property_ui_text(prop, "Ridge & Valley", "Select ridges and valleys");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_suggestive_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR);
+ RNA_def_property_ui_text(prop, "Suggestive Contour", "Select suggestive contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_material_boundary", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY);
+ RNA_def_property_ui_text(prop, "Material Boundary", "Select edges at material boundaries");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CONTOUR);
+ RNA_def_property_ui_text(prop, "Contour", "Select contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_external_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR);
+ RNA_def_property_ui_text(prop, "External Contour", "Select external contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "select_edge_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EDGE_MARK);
+ RNA_def_property_ui_text(prop, "Edge Mark", "Select edge marks");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_silhouette", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_SILHOUETTE);
+ RNA_def_property_ui_text(prop, "Silhouette", "Exclude silhouette edges");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_border", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_BORDER);
+ RNA_def_property_ui_text(prop, "Border", "Exclude border edges");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_crease", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_CREASE);
+ RNA_def_property_ui_text(prop, "Crease", "Exclude crease edges");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_ridge_valley", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_RIDGE_VALLEY);
+ RNA_def_property_ui_text(prop, "Ridge & Valley", "Exclude ridges and valleys");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_suggestive_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR);
+ RNA_def_property_ui_text(prop, "Suggestive Contour", "Exclude suggestive contours");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_material_boundary", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY);
+ RNA_def_property_ui_text(prop, "Material Boundary", "Exclude edges at material boundaries");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_CONTOUR);
+ RNA_def_property_ui_text(prop, "Contour", "Exclude contours");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_external_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR);
+ RNA_def_property_ui_text(prop, "External Contour", "Exclude external contours");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "exclude_edge_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_EDGE_MARK);
+ RNA_def_property_ui_text(prop, "Edge Mark", "Exclude edge marks");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "visibility", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "qi");
+ RNA_def_property_enum_items(prop, visibility_items);
+ RNA_def_property_ui_text(prop, "Visibility", "Determine how to use visibility for feature edge selection");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "qi_start", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "qi_start");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_ui_text(prop, "Start", "First QI value of the QI range");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "qi_end", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "qi_end");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_ui_text(prop, "End", "Last QI value of the QI range");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ /* FreestyleModuleSettings */
+
+ srna= RNA_def_struct(brna, "FreestyleModuleSettings", NULL);
+ RNA_def_struct_sdna(srna, "FreestyleModuleConfig");
+ RNA_def_struct_ui_text(srna, "Freestyle Module", "Style module configuration for specifying a style module");
+
+ prop= RNA_def_property(srna, "module_path", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_string_sdna(prop, NULL, "module_path");
+ RNA_def_property_ui_text(prop, "Module Path", "Path to a style module file");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "is_displayed", 1);
+ RNA_def_property_ui_text(prop, "Use", "Enable or disable this style module during stroke rendering");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ /* FreestyleSettings */
+
+ srna= RNA_def_struct(brna, "FreestyleSettings", NULL);
+ RNA_def_struct_sdna(srna, "FreestyleConfig");
+ RNA_def_struct_nested(brna, srna, "SceneRenderLayer");
+ RNA_def_struct_ui_text(srna, "Frestyle Settings", "Freestyle settings for a SceneRenderLayer datablock");
+
+ prop= RNA_def_property(srna, "modules", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "modules", NULL);
+ RNA_def_property_struct_type(prop, "FreestyleModuleSettings");
+ RNA_def_property_ui_text(prop, "Style modules", "A list of style modules (to be applied from top to bottom)");
+
+ prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, freestyle_ui_mode_items);
+ RNA_def_property_ui_text(prop, "Control Mode", "Select the Freestyle control mode");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "raycasting_algorithm", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "raycasting_algorithm");
+ RNA_def_property_enum_items(prop, freestyle_raycasting_algorithm_items);
+ RNA_def_property_ui_text(prop, "Raycasting Algorithm", "Select the Freestyle raycasting algorithm");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "use_suggestive_contours", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_SUGGESTIVE_CONTOURS_FLAG);
+ RNA_def_property_ui_text(prop, "Suggestive Contours", "Enable suggestive contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "use_ridges_and_valleys", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_RIDGES_AND_VALLEYS_FLAG);
+ RNA_def_property_ui_text(prop, "Ridges and Valleys", "Enable ridges and valleys");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "use_material_boundaries", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_MATERIAL_BOUNDARIES_FLAG);
+ RNA_def_property_ui_text(prop, "Material Boundaries", "Enable material boundaries");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "use_smoothness", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_FACE_SMOOTHNESS_FLAG);
+ RNA_def_property_ui_text(prop, "Face Smoothness", "Take face smoothness into account in view map calculation");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "use_advanced_options", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_ADVANCED_OPTIONS_FLAG);
+ RNA_def_property_ui_text(prop, "Advanced Edge Detection Options", "Enable advanced edge detection options (sphere radius and Kr derivative epsilon)");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "sphere_radius", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "sphere_radius");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Sphere Radius", "Sphere radius for computing curvatures");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "kr_derivative_epsilon", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "dkr_epsilon");
+ RNA_def_property_range(prop, -1000.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Kr Derivative Epsilon", "Kr derivative epsilon for computing suggestive contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "crease_angle", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "crease_angle");
+ RNA_def_property_range(prop, 0.0, 180.0);
+ RNA_def_property_ui_text(prop, "Crease Angle", "Angular threshold in degrees (between 0 and 180) for detecting crease edges");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "linesets", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "linesets", NULL);
+ RNA_def_property_struct_type(prop, "FreestyleLineSet");
+ RNA_def_property_ui_text(prop, "Line Sets", "");
+ rna_def_freestyle_linesets(brna, prop);
+}
+
static void rna_def_scene_game_recast_data(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2745,12 +3167,23 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
static void rna_def_scene_render_layer(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
srna = RNA_def_struct(brna, "SceneRenderLayer", NULL);
RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer");
RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
rna_def_render_layer_common(srna, 1);
+
+ /* Freestyle */
+
+ rna_def_freestyle_settings(brna);
+
+ prop= RNA_def_property(srna, "freestyle_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "freestyleConfig");
+ RNA_def_property_struct_type(prop, "FreestyleSettings");
+ RNA_def_property_ui_text(prop, "Freestyle Settings", "");
}
/* curve.splines */
@@ -3333,6 +3766,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem freestyle_thickness_items[] = {
+ {R_LINE_THICKNESS_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Specify unit line thickness in pixels"},
+ {R_LINE_THICKNESS_RELATIVE, "RELATIVE", 0, "Relative", "Unit line thickness is scaled by the proportion of the present vertical image resolution to 480 pixels"},
+ {0, NULL, 0, NULL, NULL}};
+
rna_def_scene_ffmpeg_settings(brna);
#ifdef WITH_QUICKTIME
rna_def_scene_quicktime_settings(brna);
@@ -3577,6 +4015,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Edge Color", "Edge color");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ prop= RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", R_EDGE_FRS);
+ RNA_def_property_ui_text(prop, "Edge", "Draw stylized strokes using Freestyle");
+ RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+
/* threads */
prop = RNA_def_property(srna, "threads", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "threads");
@@ -3962,6 +4405,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_enum_items(prop, engine_items);
RNA_def_property_enum_funcs(prop, "rna_RenderSettings_engine_get", "rna_RenderSettings_engine_set",
"rna_RenderSettings_engine_itemf");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Engine", "Engine to use for rendering");
RNA_def_property_update(prop, NC_WINDOW, "rna_RenderSettings_engine_update");
@@ -4012,6 +4456,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", R_SIMPLE_NO_TRIANGULATE);
RNA_def_property_ui_text(prop, "Skip Quad to Triangles", "Disable non-planar quads being triangulated");
+ /* Freestyle line thickness options */
+ prop = RNA_def_property(srna, "line_thickness_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "line_thickness_mode");
+ RNA_def_property_enum_items(prop, freestyle_thickness_items);
+ RNA_def_property_ui_text(prop, "Line Thickness Mode", "Line thickness mode for Freestyle line drawing");
+
+ prop = RNA_def_property(srna, "unit_line_thickness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "unit_line_thickness");
+ RNA_def_property_range(prop, 0.f, 10000.f);
+ RNA_def_property_ui_text(prop, "Unit Line Thickness", "Unit line thickness in pixels");
+
/* Scene API */
RNA_api_scene_render(srna);
}
@@ -4299,7 +4754,7 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_sdna(prop, NULL, "r.cfra");
RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
- RNA_def_property_int_funcs(prop, NULL, "rna_Scene_current_frame_set", NULL);
+ RNA_def_property_int_funcs(prop, NULL, "rna_Scene_frame_current_set", NULL);
RNA_def_property_ui_text(prop, "Current Frame",
"Current Frame, to update animation data from python frame_set() instead");
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update");
@@ -4566,7 +5021,7 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "sequencer_colorspace_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "sequencer_colorspace_settings");
RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
- RNA_def_property_ui_text(prop, "Sequencer Colorspace Settings", "Settings of color space sequencer is working in");
+ RNA_def_property_ui_text(prop, "Sequencer Color Space Settings", "Settings of color space sequencer is working in");
/* Nestled Data */
rna_def_tool_settings(brna);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 69b61b47d8a..cdf7ac5e68f 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -40,6 +40,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "rna_internal.h" /* own include */
+
#ifdef RNA_RUNTIME
#include "BKE_animsys.h"
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index a6d4e473df4..32e388598f5 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -140,12 +140,12 @@ static void rna_Area_type_update(bContext *C, PointerRNA *ptr)
}
}
-void rna_View2D_region_to_view(struct View2D *v2d, int x, int y, float result[2])
+static void rna_View2D_region_to_view(struct View2D *v2d, int x, int y, float result[2])
{
UI_view2d_region_to_view(v2d, x, y, &result[0], &result[1]);
}
-void rna_View2D_view_to_region(struct View2D *v2d, float x, float y, int clip, int result[2])
+static void rna_View2D_view_to_region(struct View2D *v2d, float x, float y, int clip, int result[2])
{
if (clip)
UI_view2d_view_to_region(v2d, x, y, &result[0], &result[1]);
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index 314082dfd02..6097fa2ae96 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -104,7 +104,7 @@ static StructRNA *rna_Sensor_refine(struct PointerRNA *ptr)
}
}
-void rna_Sensor_name_set(PointerRNA *ptr, const char *value)
+static void rna_Sensor_name_set(PointerRNA *ptr, const char *value)
{
bSensor *sens = (bSensor *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index ab1dfbf22b0..c7c4b0817f6 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -37,8 +37,6 @@
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
-extern EnumPropertyItem blend_mode_items[];
-
#ifdef RNA_RUNTIME
//#include "DNA_anim_types.h"
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 246f9fef98a..ff5f4988cc1 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -478,7 +478,7 @@ static void rna_RegionView3D_view_matrix_set(PointerRNA *ptr, const float *value
}
/* api call */
-void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
+static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
{
bScreen *sc = (bScreen *)id;
@@ -849,7 +849,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s
adt = BKE_id_add_animdata(&obact->id); /* this only adds if non-existant */
}
else if (saction->mode == SACTCONT_SHAPEKEY) {
- Key *key = ob_get_key(obact);
+ Key *key = BKE_key_from_object(obact);
if (key)
adt = BKE_id_add_animdata(&key->id); /* this only adds if non-existant */
}
@@ -876,7 +876,7 @@ static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *sce
/* special exceptions for ShapeKey Editor mode */
if (saction->mode == SACTCONT_SHAPEKEY) {
- Key *key = ob_get_key(obact);
+ Key *key = BKE_key_from_object(obact);
/* 1) update the action stored for the editor */
if (key)
@@ -1102,7 +1102,7 @@ static void rna_def_space(BlenderRNA *brna)
}
/* for all spaces that use a mask */
-void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *mask_set_func)
+static void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *mask_set_func)
{
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c
index e62b3ecd804..a2880510958 100644
--- a/source/blender/makesrna/intern/rna_texture_api.c
+++ b/source/blender/makesrna/intern/rna_texture_api.c
@@ -32,6 +32,8 @@
#include "RNA_define.h"
+#include "rna_internal.h" /* own include */
+
#ifdef RNA_RUNTIME
#include "IMB_imbuf.h"
@@ -42,8 +44,8 @@
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
-void save_envmap(struct EnvMap *env, bContext *C, ReportList *reports, const char *filepath,
- struct Scene *scene, float layout[12])
+static void save_envmap(struct EnvMap *env, bContext *C, ReportList *reports, const char *filepath,
+ struct Scene *scene, float layout[12])
{
if (scene == NULL) {
scene = CTX_data_scene(C);
@@ -52,7 +54,7 @@ void save_envmap(struct EnvMap *env, bContext *C, ReportList *reports, const cha
RE_WriteEnvmapResult(reports, scene, env, filepath, scene->r.im_format.imtype, layout);
}
-void clear_envmap(struct EnvMap *env, bContext *C)
+static void clear_envmap(struct EnvMap *env, bContext *C)
{
Main *bmain = CTX_data_main(C);
Tex *tex;
@@ -66,7 +68,7 @@ void clear_envmap(struct EnvMap *env, bContext *C)
}
}
-void texture_evaluate(struct Tex *tex, float value[3], float color_r[4])
+static void texture_evaluate(struct Tex *tex, float value[3], float color_r[4])
{
TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
multitex_ext(tex, value, NULL, NULL, 1, &texres);
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 172a79970b5..0c62a280935 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -144,7 +144,7 @@ static void rna_tracking_active_track_set(PointerRNA *ptr, PointerRNA value)
clip->tracking.act_track = NULL;
}
-void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
+static void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTracking *tracking = &clip->tracking;
@@ -325,7 +325,7 @@ static void rna_tracking_active_object_set(PointerRNA *ptr, PointerRNA value)
else clip->tracking.objectnr = 0;
}
-void rna_trackingObject_name_set(PointerRNA *ptr, const char *value)
+static void rna_trackingObject_name_set(PointerRNA *ptr, const char *value)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
@@ -447,7 +447,7 @@ static MovieTrackingObject *rna_trackingObject_new(MovieTracking *tracking, cons
return object;
}
-void rna_trackingObject_remove(MovieTracking *tracking, MovieTrackingObject *object)
+static void rna_trackingObject_remove(MovieTracking *tracking, MovieTrackingObject *object)
{
BKE_tracking_object_delete(tracking, object);
@@ -477,7 +477,7 @@ static MovieTrackingMarker *rna_trackingMarkers_insert_frame(MovieTrackingTrack
return new_marker;
}
-void rna_trackingMarkers_delete_frame(MovieTrackingTrack *track, int framenr)
+static void rna_trackingMarkers_delete_frame(MovieTrackingTrack *track, int framenr)
{
if (track->markersnr == 1)
return;
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index ea38b60b25f..006e1ad3903 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -36,6 +36,8 @@
#include "UI_resources.h"
+#include "rna_internal.h"
+
#ifdef RNA_RUNTIME
static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, int icon,
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 666fa4d7b81..eada607ed97 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -927,6 +927,11 @@ static void rna_def_userdef_theme_spaces_edge(StructRNA *srna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Edge UV Face Select", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop= RNA_def_property(srna, "freestyle_edge_mark", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Freestyle Edge Mark", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_spaces_face(StructRNA *srna)
@@ -952,6 +957,11 @@ static void rna_def_userdef_theme_spaces_face(StructRNA *srna)
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Face Dot Size", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop= RNA_def_property(srna, "freestyle_face_mark", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Freestyle Face Mark", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, short incl_nurbs)
@@ -2984,8 +2994,9 @@ static void rna_def_userdef_system(BlenderRNA *brna)
/* Note: As this list is in alphabetical order, and not defined order,
* here is the highest define currently in use: 33 (Hebrew). */
static EnumPropertyItem language_items[] = {
- { 0, "", 0, N_("Nearly done"), ""},
+ { 0, "", 0, N_("Nearly Done"), ""},
{ 0, "DEFAULT", 0, "Default (Default)", ""},
+ /* using the utf8 flipped form of Arabic (العربية) */
{21, "ARABIC", 0, "Arabic (ﺔﻴﺑﺮﻌﻟïº)", "ar_EG"},
{32, "BRAZILIANPORTUGUESE", 0, "Brazilian Portuguese (Português do Brasil)", "pt_BR"},
{ 1, "ENGLISH", 0, "English (English)", "en_US"},
@@ -2998,8 +3009,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{ 9, "SPANISH", 0, "Spanish (Español)", "es"},
{14, "TRADITIONAL_CHINESE", 0, "Traditional Chinese (ç¹é«”中文)", "zh_TW"},
{18, "UKRAINIAN", 0, "Ukrainian (УкраїнÑький)", "uk_UA"},
- { 0, "", 0, N_("In progress"), ""},
- /* using the utf8 flipped form of Arabic (العربية) */
+ { 0, "", 0, N_("In Progress"), ""},
{22, "BULGARIAN", 0, "Bulgarian (БългарÑки)", "bg_BG"},
{10, "CATALAN", 0, "Catalan (Català)", "ca_AD"},
{16, "CROATIAN", 0, "Croatian (Hrvatski)", "hr_HR"},
@@ -3008,8 +3018,9 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{ 6, "FINNISH", 0, "Finnish (Suomi)", "fi_FI"},
{ 5, "GERMAN", 0, "German (Deutsch)", "de_DE"},
{23, "GREEK", 0, "Greek (Ελληνικά)", "el_GR"},
- {33, "HEBREW", 0, "Hebrew (עִבְרִית)", "he_IL"},
- {31, "HUNGARIAN", 0, "Hungarian (magyar)", "hu_HU"},
+ /* using the utf8 flipped form of Hebrew (עִבְרִית)) */
+ {33, "HEBREW", 0, "Hebrew (תירִבְעִ)", "he_IL"},
+ {31, "HUNGARIAN", 0, "Hungarian (Magyar)", "hu_HU"},
{27, "INDONESIAN", 0, "Indonesian (Bahasa indonesia)", "id_ID"},
{29, "KYRGYZ", 0, "Kyrgyz (Кыргыз тили)", "ky_KG"},
/* {24, "KOREAN", 0, "Korean (한국 언어)", "ko_KR"}, */ /* XXX No po's yet. */
@@ -3019,7 +3030,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{19, "POLISH", 0, "Polish (Polski)", "pl_PL"},
/* {20, "ROMANIAN", 0, "Romanian (Român)", "ro_RO"}, */ /* XXX No po's yet. */
{17, "SERBIAN", 0, "Serbian (СрпÑки)", "sr_RS"},
- {28, "SERBIAN_LATIN", 0, "Serbian latin (Srpski latinica)", "sr_RS@latin"},
+ {28, "SERBIAN_LATIN", 0, "Serbian Latin (Srpski latinica)", "sr_RS@latin"},
{ 7, "SWEDISH", 0, "Swedish (Svenska)", "sv_SE"},
{30, "TURKISH", 0, "Turkish (Türkçe)", "tr_TR"},
{ 0, NULL, 0, NULL, NULL}
@@ -3592,7 +3603,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
"Enables automatic saving of preview images in the .blend file");
}
-void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
FunctionRNA *func;
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 61c75e306cb..d8753f4ff43 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -765,14 +765,14 @@ static void rna_wmKeyMapItem_name_get(PointerRNA *ptr, char *value)
{
wmKeyMapItem *kmi = ptr->data;
wmOperatorType *ot = WM_operatortype_find(kmi->idname, 1);
- strcpy(value, ot ? ot->name : kmi->idname);
+ strcpy(value, ot ? RNA_struct_ui_name(ot->srna) : kmi->idname);
}
static int rna_wmKeyMapItem_name_length(PointerRNA *ptr)
{
wmKeyMapItem *kmi = ptr->data;
wmOperatorType *ot = WM_operatortype_find(kmi->idname, 1);
- return strlen(ot ? ot->name : kmi->idname);
+ return strlen(ot ? RNA_struct_ui_name(ot->srna) : kmi->idname);
}
static int rna_KeyMapItem_userdefined_get(PointerRNA *ptr)
@@ -1136,7 +1136,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
return dummyot.ext.srna;
}
-void **rna_Operator_instance(PointerRNA *ptr)
+static void **rna_Operator_instance(PointerRNA *ptr)
{
wmOperator *op = ptr->data;
return &op->py_instance;
@@ -1793,7 +1793,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
* fallback on the operator ID */
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Name", "Name of operator to call on input event");
+ RNA_def_property_ui_text(prop, "Name", "Name of operator (translated) to call on input event");
RNA_def_property_string_funcs(prop, "rna_wmKeyMapItem_name_get", "rna_wmKeyMapItem_name_length", NULL);
prop = RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index ae4d5dc493e..cb4e00a042e 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -39,6 +39,8 @@
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
+#include "rna_internal.h" /* own include */
+
#ifdef RNA_RUNTIME
#include "BKE_context.h"
@@ -72,12 +74,12 @@ static int rna_event_modal_handler_add(struct bContext *C, struct wmOperator *op
}
/* XXX, need a way for python to know event types, 0x0110 is hard coded */
-wmTimer *rna_event_timer_add(struct wmWindowManager *wm, float time_step, wmWindow *win)
+static wmTimer *rna_event_timer_add(struct wmWindowManager *wm, float time_step, wmWindow *win)
{
return WM_event_add_timer(wm, win, 0x0110, time_step);
}
-void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer)
+static void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer)
{
WM_event_remove_timer(wm, timer->win, timer);
}
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index cdb200ff180..638e91e22f1 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -88,10 +88,10 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-#define EDGE_MARK 1
-
#ifdef USE_BM_BEVEL_OP_AS_MOD
+#define EDGE_MARK 1
+
/* BMESH_TODO
*
* this bevel calls the operator which is missing many of the options
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 4fd2c658380..a94b4834d18 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -393,7 +393,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
mul_m4_v3(mtx_tx, vc->co);
/* length in 2d, don't sqrt because this is only for comparison */
- vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] +
+ vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] +
vc->co[other_axis_2] * vc->co[other_axis_2];
/* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
@@ -410,7 +410,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
vc->v[0] = vc->v[1] = -1;
/* length in 2d, don't sqrt because this is only for comparison */
- vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] +
+ vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] +
vc->co[other_axis_2] * vc->co[other_axis_2];
/* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
@@ -430,7 +430,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
vc->e[1] = med_new;
}
else {
- vc->v[0] = vc->v[1] = -2; /* erro value - don't use, 3 edges on vert */
+ vc->v[0] = vc->v[1] = -2; /* error value - don't use, 3 edges on vert */
}
vc = &vert_connect[med_new->v2];
@@ -445,7 +445,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
vc->e[1] = med_new;
}
else {
- vc->v[0] = vc->v[1] = -2; /* erro value - don't use, 3 edges on vert */
+ vc->v[0] = vc->v[1] = -2; /* error value - don't use, 3 edges on vert */
}
}
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 3353382fa3d..8ef86362edd 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -54,7 +54,7 @@ static void deformVerts(ModifierData *md, Object *ob,
int numVerts,
ModifierApplyFlag UNUSED(flag))
{
- KeyBlock *kb = ob_get_keyblock(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
float (*deformedVerts)[3];
if (kb && kb->totelem == numVerts) {
@@ -69,8 +69,8 @@ static void deformVerts(ModifierData *md, Object *ob,
static void deformMatrices(ModifierData *md, Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts)
{
- Key *key = ob_get_key(ob);
- KeyBlock *kb = ob_get_keyblock(ob);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
float scale[3][3];
(void)vertexCos; /* unused */
@@ -94,7 +94,7 @@ static void deformVertsEM(ModifierData *md, Object *ob,
float (*vertexCos)[3],
int numVerts)
{
- Key *key = ob_get_key(ob);
+ Key *key = BKE_key_from_object(ob);
if (key && key->type == KEY_RELATIVE)
deformVerts(md, ob, derivedData, vertexCos, numVerts, 0);
@@ -107,8 +107,8 @@ static void deformMatricesEM(ModifierData *UNUSED(md), Object *ob,
float (*defMats)[3][3],
int numVerts)
{
- Key *key = ob_get_key(ob);
- KeyBlock *kb = ob_get_keyblock(ob);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
float scale[3][3];
(void)vertexCos; /* unused */
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index eb5a74f0dcc..88951919272 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -157,7 +157,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
int num_projectors = 0;
- float aspect;
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
float aspx = umd->aspectx ? umd->aspectx : 1.0f;
float aspy = umd->aspecty ? umd->aspecty : 1.0f;
@@ -165,8 +164,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
float scay = umd->scaley ? umd->scaley : 1.0f;
int free_uci = 0;
- aspect = aspx / aspy;
-
for (i = 0; i < umd->num_projectors; ++i)
if (umd->projectors[i])
projectors[num_projectors++].ob = umd->projectors[i];
@@ -199,39 +196,23 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
free_uci = 1;
}
else {
- float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
- int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, aspx, aspy);
- float scale = (cam->type == CAM_PERSP) ? cam->clipsta * sensor / cam->lens : cam->ortho_scale;
- float xmax, xmin, ymax, ymin;
-
- if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
- xmax = 0.5f * scale;
- ymax = xmax / aspect;
- }
- else {
- ymax = 0.5f * scale;
- xmax = ymax * aspect;
- }
+ CameraParams params;
- xmin = -xmax;
- ymin = -ymax;
+ /* setup parameters */
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, projectors[i].ob);
- /* scale the matrix */
- xmin *= scax;
- xmax *= scax;
- ymin *= scay;
- ymax *= scay;
+ /* compute matrix, viewplane, .. */
+ BKE_camera_params_compute_viewplane(&params, 1, 1, aspx, aspy);
- if (cam->type == CAM_PERSP) {
- float perspmat[4][4];
- perspective_m4(perspmat, xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend);
- mult_m4_m4m4(tmpmat, perspmat, projectors[i].projmat);
- }
- else { /* if (cam->type == CAM_ORTHO) */
- float orthomat[4][4];
- orthographic_m4(orthomat, xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend);
- mult_m4_m4m4(tmpmat, orthomat, projectors[i].projmat);
- }
+ /* scale the view-plane */
+ params.viewplane.xmin *= scax;
+ params.viewplane.xmax *= scax;
+ params.viewplane.ymin *= scay;
+ params.viewplane.ymax *= scay;
+
+ BKE_camera_params_compute_matrix(&params);
+ mult_m4_m4m4(tmpmat, params.winmat, projectors[i].projmat);
}
}
else {
@@ -241,22 +222,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
unit_m4(offsetmat);
mul_mat3_m4_fl(offsetmat, 0.5);
offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5;
-
- if (cam) {
- if (aspx == aspy) {
- offsetmat[3][0] -= cam->shiftx;
- offsetmat[3][1] -= cam->shifty;
- }
- else if (aspx < aspy) {
- offsetmat[3][0] -= (cam->shiftx * aspy / aspx);
- offsetmat[3][1] -= cam->shifty;
- }
- else {
- offsetmat[3][0] -= cam->shiftx;
- offsetmat[3][1] -= (cam->shifty * aspx / aspy);
- }
- }
-
+
mult_m4_m4m4(projectors[i].projmat, offsetmat, tmpmat);
/* calculate worldspace projector normal (for best projector test) */
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index fe4eebc9492..8f01408d8c7 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -146,7 +146,7 @@ CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, in
if (disprect.xmin>= disprect.xmax) return NULL;
if (disprect.ymin>= disprect.ymax) return NULL;
- cbuf= alloc_compbuf(BLI_RCT_SIZE_X(&disprect), BLI_RCT_SIZE_Y(&disprect), type, 1);
+ cbuf= alloc_compbuf(BLI_rcti_size_x(&disprect), BLI_rcti_size_y(&disprect), type, 1);
outfp= cbuf->rect;
rectf += type*(disprect.ymin*rectx + disprect.xmin);
dx= type*cbuf->x;
diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c
index 53f1aa82f60..5e58b74ac3a 100644
--- a/source/blender/nodes/texture/node_texture_util.c
+++ b/source/blender/nodes/texture/node_texture_util.c
@@ -49,8 +49,6 @@
#include <assert.h>
#include "node_texture_util.h"
-#define PREV_RES 128 /* default preview resolution */
-
static void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread)
{
if (dg->node->need_exec) {
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index 012bc279cfb..b0164d24852 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -6,6 +6,7 @@ Import ('env')
incs = '. ../editors/include ../makesdna ../makesrna ../blenfont ../blenlib ../blenkernel ../nodes'
incs += ' ../imbuf ../blenloader ../bmesh ../gpu ../render/extern/include ../windowmanager'
+incs += ' ../freestyle/intern/python'
incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include #intern/cycles/blender'
incs += ' #intern/audaspace/intern ' + env['BF_PYTHON_INC']
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 604166eed3c..15aa5164c86 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
../../makesrna
../../windowmanager
../../gpu
+ ../../freestyle/intern/python
../../../../intern/guardedalloc
../../../../intern/cycles/blender
)
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index f2222825c42..360e041270f 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -59,6 +59,8 @@
#include "../generic/blf_py_api.h"
#include "../mathutils/mathutils.h"
+#include "BPy_Freestyle.h"
+
PyObject *bpy_package_py = NULL;
PyDoc_STRVAR(bpy_script_paths_doc,
@@ -228,7 +230,7 @@ static PyObject *bpy_import_test(const char *modname)
else {
PyErr_Print();
PyErr_Clear();
- }
+ }
return mod;
}
@@ -256,6 +258,7 @@ void BPy_init_modules(void)
}
/* stand alone utility modules not related to blender directly */
IDProp_Init_Types(); /* not actually a submodule, just types */
+ Freestyle_Init();
mod = PyModule_New("_bpy");
diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c
index 68fd9a99712..5ae2a11710a 100644
--- a/source/blender/python/intern/bpy_app_ffmpeg.c
+++ b/source/blender/python/intern/bpy_app_ffmpeg.c
@@ -77,8 +77,10 @@ static PyObject *make_ffmpeg_info(void)
return NULL;
}
+#if 0 // UNUSED
#define SetIntItem(flag) \
PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyLong_FromLong(flag))
+#endif
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyUnicode_FromString(str))
#define SetObjItem(obj) \
@@ -118,7 +120,7 @@ static PyObject *make_ffmpeg_info(void)
return NULL;
}
-#undef SetIntItem
+// #undef SetIntItem
#undef SetStrItem
#undef SetObjItem
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 9cd0bdd090a..85f6163c721 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -53,6 +53,7 @@
#include "BLI_path_util.h"
#include "BLI_fileops.h"
+#include "BLI_listbase.h"
#include "BLI_math_base.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
@@ -383,6 +384,7 @@ typedef struct {
static int python_script_exec(bContext *C, const char *fn, struct Text *text,
struct ReportList *reports, const short do_jump)
{
+ Main *bmain_old = CTX_data_main(C);
PyObject *main_mod = NULL;
PyObject *py_dict = NULL, *py_result = NULL;
PyGILState_STATE gilstate;
@@ -461,7 +463,11 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text,
if (!py_result) {
if (text) {
if (do_jump) {
- python_script_error_jump_text(text);
+ /* ensure text is valid before use, the script may have freed its self */
+ Main *bmain_new = CTX_data_main(C);
+ if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->text, text) != -1)) {
+ python_script_error_jump_text(text);
+ }
}
}
BPy_errors_to_report(reports);
@@ -680,11 +686,20 @@ void BPY_modules_load_user(bContext *C)
int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result)
{
- PyObject *pyctx = (PyObject *)CTX_py_dict_get(C);
- PyObject *item = PyDict_GetItemString(pyctx, member);
+ PyGILState_STATE gilstate;
+ int use_gil = !PYC_INTERPRETER_ACTIVE;
+
+ PyObject *pyctx;
+ PyObject *item;
PointerRNA *ptr = NULL;
int done = FALSE;
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ pyctx = (PyObject *)CTX_py_dict_get(C);
+ item = PyDict_GetItemString(pyctx, member);
+
if (item == NULL) {
/* pass */
}
@@ -720,7 +735,8 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data);
}
else {
- printf("List item not a valid type\n");
+ printf("PyContext: '%s' list item not a valid type in sequece type '%s'\n",
+ member, Py_TYPE(item)->tp_name);
}
}
@@ -740,6 +756,9 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
}
}
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
return done;
}
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index b7a45897668..69839514a12 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -52,9 +52,6 @@
#include "bpy_util.h"
#include "bpy_rna_anim.h"
-#define TRUE 1
-#define FALSE 0
-
/* for keyframes and drivers */
static int pyrna_struct_anim_args_parse(
PointerRNA *ptr, const char *error_prefix, const char *path,
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 19f9aa2dc88..818f30ec284 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -46,8 +46,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#define SWAP_FLOAT(a, b, tmp) tmp = a; a = b; b = tmp
-
/*-------------------------DOC STRINGS ---------------------------*/
PyDoc_STRVAR(M_Geometry_doc,
"The Blender geometry module"
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index a2d6e27bcb7..5be10f56d7a 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -37,6 +37,7 @@ set(INC
../../../intern/guardedalloc
../../../intern/mikktspace
../../../intern/smoke/extern
+ ../freestyle
)
set(INC_SYS
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript
index 8a044b19a79..5addc45571d 100644
--- a/source/blender/render/SConscript
+++ b/source/blender/render/SConscript
@@ -7,6 +7,7 @@ raysources = env.Glob('intern/raytrace/*.cpp')
incs = 'intern/include #/intern/guardedalloc ../blenlib ../makesdna ../makesrna'
incs += ' extern/include ../blenkernel ../imbuf ../blenfont'
incs += ' ../include ../blenloader ../../../intern/smoke/extern ../../../intern/mikktspace ../bmesh'
+incs += ' ../freestyle'
cflags_raytrace = env['CCFLAGS']
cxxflags_raytrace = env['CXXFLAGS']
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index b43824d6d5e..395fbf8f01c 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -216,6 +216,7 @@ void RE_TileProcessor(struct Render *re);
/* only RE_NewRender() needed, main Blender render calls */
void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, struct Object *camera_override, unsigned int lay, int frame, const short write_still);
void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene, struct Object *camera_override, unsigned int lay, int sfra, int efra, int tfra);
+void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, struct Scene *scene);
/* error reporting */
void RE_SetReports(struct Render *re, struct ReportList *reports);
@@ -225,7 +226,7 @@ void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene
int RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode);
int RE_WriteRenderResult(struct ReportList *reports, RenderResult *rr, const char *filename, int compress);
-struct RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty);
+struct RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty);
extern const float default_envmap_layout[];
int RE_WriteEnvmapResult(struct ReportList *reports, struct Scene *scene, struct EnvMap *env, const char *relpath, const char imtype, float layout[12]);
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index c07ed42332f..2a9a1becc42 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -39,10 +39,11 @@
/* called by meshtools */
struct View3D;
struct Scene;
+struct LinkNode;
-void RE_make_sticky(struct Scene *scene, struct View3D *v3d);
-
-/* for radiosity module */
+void RE_make_sticky(struct Scene *scene, struct Object *camera, struct LinkNode *objects);
+
+/* for radiosity module */
struct RadView;
struct RNode;
struct Render;
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 26a1b9908b3..57fb80f11c0 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -134,7 +134,7 @@ typedef struct ShadeInput {
int har; /* hardness */
/* texture coordinates */
- float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[4];
+ float lo[3], gl[3], ref[3], orn[3], winco[3], vcol[4];
float refcol[4], displace[3];
float strandco, tang[3], nmapnorm[3], nmaptang[4], stress, winspeed[4];
float duplilo[3], dupliuv[3];
@@ -150,7 +150,6 @@ typedef struct ShadeInput {
float dxno[3], dyno[3], dxview, dyview;
float dxlv[3], dylv[3];
float dxwin[3], dywin[3];
- float dxsticky[3], dysticky[3];
float dxrefract[3], dyrefract[3];
float dxstrand, dystrand;
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 999fb24ba32..5d61417cbaf 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -57,7 +57,7 @@ struct RenderResult *render_result_new(struct Render *re,
struct RenderResult *render_result_new_full_sample(struct Render *re,
struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers);
-struct RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty);
+struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty);
/* Merge */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 85dbd9356f4..60f3ced5652 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -224,6 +224,8 @@ struct Render
ListBase volumes;
ListBase volume_precache_parts;
+ ListBase freestyle_renders;
+
/* arena for allocating data for use during render, for
* example dynamic TFaces to go in the VlakRen structure.
*/
@@ -376,6 +378,7 @@ typedef struct VlakRen {
struct Material *mat;
char puno;
char flag, ec;
+ char freestyle_edge_mark;
int index;
} VlakRen;
@@ -607,6 +610,13 @@ typedef struct LampRen {
#define R_TANGENT 64
#define R_TRACEBLE 128
+/* vlakren->freestyle_edge_mark */
+#define R_EDGE_V1V2 1
+#define R_EDGE_V2V3 2
+#define R_EDGE_V3V4 4
+#define R_EDGE_V3V1 4
+#define R_EDGE_V4V1 8
+
/* strandbuffer->flag */
#define R_STRAND_BSPLINE 1
#define R_STRAND_B_UNITS 2
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h
index 584e56836fa..d116dfe7b17 100644
--- a/source/blender/render/intern/include/renderdatabase.h
+++ b/source/blender/render/intern/include/renderdatabase.h
@@ -55,7 +55,6 @@ struct RadFace;
typedef struct VertTableNode {
struct VertRen *vert;
float *rad;
- float *sticky;
float *strand;
float *tangent;
float *stress;
@@ -110,7 +109,6 @@ struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struc
struct ObjectInstanceRen *RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4], int lay);
void RE_makeRenderInstances(struct Render *re);
-float *RE_vertren_get_sticky(struct ObjectRen *obr, struct VertRen *ver, int verify);
float *RE_vertren_get_stress(struct ObjectRen *obr, struct VertRen *ver, int verify);
float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify);
float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify);
diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
index ddc84408e26..3926e8b8e51 100644
--- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
@@ -185,7 +185,7 @@ RTBuilder *rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp)
return tmp;
}
-void rtbuild_calc_bb(RTBuilder *b)
+static void rtbuild_calc_bb(RTBuilder *b)
{
if (b->bb[0] == 1.0e30f) {
for (RTBuilder::Object **index = b->sorted_begin[0]; index != b->sorted_end[0]; index++)
diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
index 9e7075438cb..85c9d0d402f 100644
--- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
@@ -152,7 +152,8 @@ void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *UNUSED(min), float *UNUSED(m
}
}
-void bfree(VBVHTree *tree)
+#if 0 /* UNUSED */
+static void bfree(VBVHTree *tree)
{
if (tot_pushup + tot_pushdown + tot_hints + tot_moves) {
if (G.debug & G_DEBUG) {
@@ -169,6 +170,7 @@ void bfree(VBVHTree *tree)
}
bvh_free(tree);
}
+#endif
/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */
template<class Tree, int STACK_SIZE>
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 51e5b30a31c..9bc639515c2 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -41,6 +41,8 @@
#include "BLI_rand.h"
#include "BLI_memarena.h"
#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_edgehash.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
@@ -2260,14 +2262,6 @@ static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, Ve
if ((texco & TEXCO_ORCO) && (vr->orco)) {
copy_v3_v3(shi->lo, vr->orco);
}
- if (texco & TEXCO_STICKY) {
- float *sticky= RE_vertren_get_sticky(obr, vr, 0);
- if (sticky) {
- shi->sticky[0]= sticky[0];
- shi->sticky[1]= sticky[1];
- shi->sticky[2]= 0.0f;
- }
- }
if (texco & TEXCO_GLOB) {
copy_v3_v3(shi->gl, shi->co);
mul_m4_v3(re->viewinv, shi->gl);
@@ -2733,7 +2727,7 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
v2= mface->v2;
v3= mface->v3;
v4= mface->v4;
- flag= mface->flag & ME_SMOOTH;
+ flag= mface->flag & (ME_SMOOTH | ME_FREESTYLE_FACE);
vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
@@ -3240,6 +3234,24 @@ static void add_volume(Render *re, ObjectRen *obr, Material *ma)
BLI_addtail(&re->volumes, vo);
}
+static EdgeHash *make_freestyle_edge_mark_hash(MEdge *medge, int totedge)
+{
+ EdgeHash *edge_hash= BLI_edgehash_new();
+ int a;
+
+ for(a=0; a<totedge; a++) {
+ if(medge[a].flag & ME_FREESTYLE_EDGE)
+ BLI_edgehash_insert(edge_hash, medge[a].v1, medge[a].v2, medge+a);
+ }
+ return edge_hash;
+}
+
+static int has_freestyle_edge_mark(EdgeHash *edge_hash, int v1, int v2)
+{
+ MEdge *medge= BLI_edgehash_lookup(edge_hash, v1, v2);
+ return (!medge) ? 0 : 1;
+}
+
static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
{
Object *ob= obr->ob;
@@ -3249,7 +3261,6 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
VlakRen *vlr; //, *vlr1;
VertRen *ver;
Material *ma;
- MSticky *ms = NULL;
DerivedMesh *dm;
CustomDataMask mask;
float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3],
@@ -3334,8 +3345,6 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if (do_autosmooth && me->totvert==totvert && me->totface==dm->getNumTessFaces(dm))
use_original_normals= TRUE;
- ms = (totvert==me->totvert)?me->msticky:NULL;
-
ma= give_render_material(re, ob, 1);
@@ -3354,19 +3363,23 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
normalize_v3(ver->n);
negate_v3(ver->n);
}
-
+
if (orco) {
ver->orco= orco;
orco+=3;
}
- if (ms) {
- float *sticky= RE_vertren_get_sticky(obr, ver, 1);
- copy_v2_v2(sticky, ms->co);
- ms++;
- }
}
if (!timeoffset) {
+ EdgeHash *edge_hash;
+ MEdge *medge;
+ int totedge;
+
+ /* create a hash table of Freestyle edge marks */
+ medge= dm->getEdgeArray(dm);
+ totedge= dm->getNumEdges(dm);
+ edge_hash= make_freestyle_edge_mark_hash(medge, totedge);
+
/* store customdata names, because DerivedMesh is freed */
RE_set_customdata_names(obr, &dm->faceData);
@@ -3409,13 +3422,14 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if ( mface->mat_nr==a1 ) {
float len;
+ int edge_mark= 0;
int reverse_verts = (negative_scale != 0 && do_autosmooth == FALSE);
int rev_tab[] = {reverse_verts==0 ? 0 : 2, 1, reverse_verts==0 ? 2 : 0, 3};
v1= reverse_verts==0 ? mface->v1 : mface->v3;
v2= mface->v2;
v3= reverse_verts==0 ? mface->v3 : mface->v1;
v4= mface->v4;
- flag= mface->flag & ME_SMOOTH;
+ flag= mface->flag & (ME_SMOOTH | ME_FREESTYLE_FACE);
vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
@@ -3424,6 +3438,17 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if (v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4);
else vlr->v4= 0;
+ /* Freestyle edge marks */
+ if(has_freestyle_edge_mark(edge_hash, v1, v2)) edge_mark |= R_EDGE_V1V2;
+ if(has_freestyle_edge_mark(edge_hash, v2, v3)) edge_mark |= R_EDGE_V2V3;
+ if (!v4) {
+ if(has_freestyle_edge_mark(edge_hash, v3, v1)) edge_mark |= R_EDGE_V3V1;
+ } else {
+ if(has_freestyle_edge_mark(edge_hash, v3, v4)) edge_mark |= R_EDGE_V3V4;
+ if(has_freestyle_edge_mark(edge_hash, v4, v1)) edge_mark |= R_EDGE_V4V1;
+ }
+ vlr->freestyle_edge_mark= edge_mark;
+
/* render normals are inverted in render */
if (use_original_normals) {
MFace *mf= me->mface+a;
@@ -3490,6 +3515,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
}
}
}
+
+ /* release the hash table of Freestyle edge marks */
+ BLI_edgehash_free(edge_hash, NULL);
/* exception... we do edges for wire mode. potential conflict when faces exist... */
end= dm->getNumEdges(dm);
@@ -4282,6 +4310,23 @@ static void check_non_flat_quads(ObjectRen *obr)
/* new normals */
normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co);
normal_tri_v3(vlr1->n, vlr1->v3->co, vlr1->v2->co, vlr1->v1->co);
+
+ /* Freestyle edge marks */
+ if (vlr->flag & R_DIVIDE_24) {
+ vlr1->freestyle_edge_mark=
+ ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V1V2 : 0) |
+ ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0);
+ vlr->freestyle_edge_mark=
+ ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) |
+ ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0);
+ } else {
+ vlr1->freestyle_edge_mark=
+ ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0) |
+ ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0);
+ vlr->freestyle_edge_mark=
+ ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) |
+ ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V2V3 : 0);
+ }
}
/* clear the flag when not divided */
else vlr->flag &= ~R_DIVIDE_24;
@@ -5242,11 +5287,11 @@ static void speedvector_project(Render *re, float zco[2], const float co[3], con
/* size of 1 pixel mapped to viewplane coords */
float psize;
- psize = BLI_RCT_SIZE_X(&re->viewplane) / (float)re->winx;
+ psize = BLI_rctf_size_x(&re->viewplane) / (float)re->winx;
/* x angle of a pixel */
pixelphix = atan(psize / re->clipsta);
- psize = BLI_RCT_SIZE_Y(&re->viewplane) / (float)re->winy;
+ psize = BLI_rctf_size_y(&re->viewplane) / (float)re->winy;
/* y angle of a pixel */
pixelphiy = atan(psize / re->clipsta);
}
@@ -5814,76 +5859,3 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
if (re->r.mode & R_SHADOW)
make_occ_tree(re);
}
-
-/* ------------------------------------------------------------------------- */
-/* Sticky texture coords */
-/* ------------------------------------------------------------------------- */
-
-void RE_make_sticky(Scene *scene, View3D *v3d)
-{
- Object *ob;
- Base *base;
- MVert *mvert;
- Mesh *me;
- MSticky *ms;
- Render *re;
- float ho[4], mat[4][4];
- int a;
- Object *camera= NULL;
-
- if (v3d==NULL) {
- printf("Need a 3d view to make sticky\n");
- return;
- }
-
- if (v3d) camera= V3D_CAMERA_LOCAL(v3d);
- if (camera == NULL) camera= scene->camera;
-
- if (camera==NULL) {
- printf("Need camera to make sticky\n");
- return;
- }
- if (scene->obedit) {
- printf("Unable to make sticky in Edit Mode\n");
- return;
- }
-
- re= RE_NewRender("_make sticky_");
- RE_InitState(re, NULL, &scene->r, NULL, scene->r.xsch, scene->r.ysch, NULL);
-
- /* use renderdata and camera to set viewplane */
- RE_SetCamera(re, camera);
-
- /* and set view matrix */
- normalize_m4(camera->obmat);
- invert_m4_m4(mat, camera->obmat);
- RE_SetView(re, mat);
-
- for (base= FIRSTBASE; base; base= base->next) {
- if (TESTBASELIB(v3d, base)) {
- if (base->object->type==OB_MESH) {
- ob= base->object;
-
- me= ob->data;
- mvert= me->mvert;
- if (me->msticky)
- CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
- me->msticky= CustomData_add_layer(&me->vdata, CD_MSTICKY,
- CD_CALLOC, NULL, me->totvert);
-
- BKE_object_where_is_calc(scene, ob);
- mult_m4_m4m4(mat, re->viewmat, ob->obmat);
-
- ms= me->msticky;
- for (a=0; a<me->totvert; a++, ms++, mvert++) {
- copy_v3_v3(ho, mvert->co);
- mul_m4_v3(mat, ho);
- projectverto(ho, re->winmat, ho);
- ms->co[0]= ho[0]/ho[3];
- ms->co[1]= ho[1]/ho[3];
- }
- }
- }
- }
-}
-
diff --git a/source/blender/render/intern/source/gammaCorrectionTables.c b/source/blender/render/intern/source/gammaCorrectionTables.c
index 64925e16ae2..1c2613e8d18 100644
--- a/source/blender/render/intern/source/gammaCorrectionTables.c
+++ b/source/blender/render/intern/source/gammaCorrectionTables.c
@@ -38,7 +38,7 @@
/* result remain identical (ton) */
/* gamma is only used here for correcting adding colors or alpha */
-#define RE_DEFAULT_GAMMA 2.0
+// #define RE_DEFAULT_GAMMA 2.0 // UNUSED
/* This 400 is sort of based on the number of intensity levels needed for */
/* the typical dynamic range of a medium, in this case CRTs. (Foley) */
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index 7f0484c8ee6..7a9df51e493 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -396,8 +396,8 @@ static float square_rctf(rctf *rf)
{
float x, y;
- x = BLI_RCT_SIZE_X(rf);
- y = BLI_RCT_SIZE_Y(rf);
+ x = BLI_rctf_size_x(rf);
+ y = BLI_rctf_size_y(rf);
return x * y;
}
@@ -405,7 +405,7 @@ static float clipx_rctf(rctf *rf, float x1, float x2)
{
float size;
- size = BLI_RCT_SIZE_X(rf);
+ size = BLI_rctf_size_x(rf);
if (rf->xmin<x1) {
rf->xmin = x1;
@@ -417,8 +417,8 @@ static float clipx_rctf(rctf *rf, float x1, float x2)
rf->xmin = rf->xmax;
return 0.0;
}
- else if (size!=0.0f) {
- return BLI_RCT_SIZE_X(rf) / size;
+ else if (size != 0.0f) {
+ return BLI_rctf_size_x(rf) / size;
}
return 1.0;
}
@@ -427,7 +427,7 @@ static float clipy_rctf(rctf *rf, float y1, float y2)
{
float size;
- size = BLI_RCT_SIZE_Y(rf);
+ size = BLI_rctf_size_y(rf);
if (rf->ymin<y1) {
rf->ymin = y1;
@@ -441,7 +441,7 @@ static float clipy_rctf(rctf *rf, float y1, float y2)
return 0.0;
}
else if (size != 0.0f) {
- return BLI_RCT_SIZE_Y(rf) / size;
+ return BLI_rctf_size_y(rf) / size;
}
return 1.0;
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 66f230a40f5..88c64b44b64 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -610,8 +610,8 @@ void initparts(Render *re, int do_crop)
}
else disprect.ymax = ymaxb;
- rectx = BLI_RCT_SIZE_X(&disprect);
- recty = BLI_RCT_SIZE_Y(&disprect);
+ rectx = BLI_rcti_size_x(&disprect);
+ recty = BLI_rcti_size_y(&disprect);
/* so, now can we add this part? */
if (rectx > 0 && recty > 0) {
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index 485dd005be7..c8aad21b322 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -61,7 +61,6 @@
/* ------------------------- Declarations --------------------------- */
-#define INVALID_INDEX ((int)(~0))
#define INVPI ((float)M_1_PI)
#define TOTCHILD 8
#define CACHE_STEP 3
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 599d91333e6..ecd8524016d 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -49,6 +49,7 @@
#include "BKE_camera.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_pointcache.h"
@@ -74,6 +75,8 @@
#include "RE_engine.h"
#include "RE_pipeline.h"
+#include "FRS_freestyle.h"
+
/* internal */
#include "render_result.h"
#include "render_types.h"
@@ -203,9 +206,9 @@ RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
}
}
-RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty)
+RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty)
{
- return render_result_new_from_exr(exrhandle, rectx, recty);
+ return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty);
}
RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
@@ -437,8 +440,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
re->winy = winy;
if (disprect) {
re->disprect = *disprect;
- re->rectx = BLI_RCT_SIZE_X(disprect);
- re->recty = BLI_RCT_SIZE_Y(disprect);
+ re->rectx = BLI_rcti_size_x(disprect);
+ re->recty = BLI_rcti_size_y(disprect);
}
else {
re->disprect.xmin = re->disprect.ymin = 0;
@@ -670,15 +673,15 @@ static void *do_part_thread(void *pa_v)
float panorama_pixel_rot(Render *re)
{
float psize, phi, xfac;
- float borderfac = (float)BLI_RCT_SIZE_X(&re->disprect) / (float)re->winx;
+ float borderfac = (float)BLI_rcti_size_x(&re->disprect) / (float)re->winx;
/* size of 1 pixel mapped to viewplane coords */
- psize = BLI_RCT_SIZE_X(&re->viewplane) / (float)re->winx;
+ psize = BLI_rctf_size_x(&re->viewplane) / (float)re->winx;
/* angle of a pixel */
phi = atan(psize / re->clipsta);
/* correction factor for viewplane shifting, first calculate how much the viewplane angle is */
- xfac = borderfac * BLI_RCT_SIZE_X(&re->viewplane) / (float)re->xparts;
+ xfac = borderfac * BLI_rctf_size_x(&re->viewplane) / (float)re->xparts;
xfac = atan(0.5f * xfac / re->clipsta);
/* and how much the same viewplane angle is wrapped */
psize = 0.5f * phi * ((float)re->partx);
@@ -711,8 +714,8 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
float phi = panorama_pixel_rot(re);
R.panodxp = (re->winx - (best->disprect.xmin + best->disprect.xmax) ) / 2;
- R.panodxv = (BLI_RCT_SIZE_X(viewplane) * R.panodxp) / (float)(re->winx);
-
+ R.panodxv = (BLI_rctf_size_x(viewplane) * R.panodxp) / (float)(re->winx);
+
/* shift viewplane */
R.viewplane.xmin = viewplane->xmin + R.panodxv;
R.viewplane.xmax = viewplane->xmax + R.panodxv;
@@ -738,8 +741,8 @@ static RenderPart *find_next_part(Render *re, int minx)
/* find center of rendered parts, image center counts for 1 too */
for (pa = re->parts.first; pa; pa = pa->next) {
if (pa->ready) {
- centx += BLI_RCT_CENTER_X(&pa->disprect);
- centy += BLI_RCT_CENTER_Y(&pa->disprect);
+ centx += BLI_rcti_cent_x(&pa->disprect);
+ centy += BLI_rcti_cent_y(&pa->disprect);
tot++;
}
}
@@ -749,8 +752,8 @@ static RenderPart *find_next_part(Render *re, int minx)
/* closest of the non-rendering parts */
for (pa = re->parts.first; pa; pa = pa->next) {
if (pa->ready == 0 && pa->nr == 0) {
- long long int distx = centx - BLI_RCT_CENTER_X(&pa->disprect);
- long long int disty = centy - BLI_RCT_CENTER_Y(&pa->disprect);
+ long long int distx = centx - BLI_rcti_cent_x(&pa->disprect);
+ long long int disty = centy - BLI_rcti_cent_y(&pa->disprect);
distx = (long long int)sqrt(distx * distx + disty * disty);
if (distx < mindist) {
if (re->r.mode & R_PANORAMA) {
@@ -912,6 +915,8 @@ void RE_TileProcessor(Render *re)
/* ************ This part uses API, for rendering Blender scenes ********** */
+static void add_freestyle(Render *re);
+
static void do_render_3d(Render *re)
{
/* try external */
@@ -944,6 +949,11 @@ static void do_render_3d(Render *re)
if (!re->test_break(re->tbh))
add_halo_flare(re);
+ /* Freestyle */
+ if( re->r.mode & R_EDGE_FRS)
+ if(!re->test_break(re->tbh))
+ add_freestyle(re);
+
/* free all render verts etc */
RE_Database_Free(re);
@@ -1382,12 +1392,79 @@ static void render_composit_stats(void *UNUSED(arg), char *str)
R.i.infostr = NULL;
}
+/* invokes Freestyle stroke rendering */
+static void add_freestyle(Render *re)
+{
+ SceneRenderLayer *srl, *actsrl;
+ LinkData *link;
+
+ actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
+
+ FRS_init_stroke_rendering(re);
+
+ for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
+
+ link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
+ BLI_addtail(&re->freestyle_renders, link);
+
+ if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+ continue;
+ if (FRS_is_freestyle_enabled(srl)) {
+ link->data = (void *)FRS_do_stroke_rendering(re, srl);
+ }
+ }
+
+ FRS_finish_stroke_rendering(re);
+}
+
+/* merges the results of Freestyle stroke rendering into a given render result */
+static void composite_freestyle_renders(Render *re, int sample)
+{
+ Render *freestyle_render;
+ SceneRenderLayer *srl, *actsrl;
+ LinkData *link;
+
+ actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
+
+ link = (LinkData *)re->freestyle_renders.first;
+ for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
+ if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+ continue;
+ if (FRS_is_freestyle_enabled(srl)) {
+ freestyle_render = (Render *)link->data;
+ render_result_exr_file_read(freestyle_render, sample);
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
+ link = link->next;
+ }
+}
+
+/* releases temporary scenes and renders for Freestyle stroke rendering */
+static void free_all_freestyle_renders(Scene *scene)
+{
+ Render *re1, *freestyle_render;
+ LinkData *link;
+
+ for (re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
+ for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) {
+ if (link->data) {
+ freestyle_render = (Render *)link->data;
+ BKE_scene_unlink(G.main, freestyle_render->scene, scene);
+ RE_FreeRender(freestyle_render);
+ }
+ }
+ BLI_freelistN( &re1->freestyle_renders );
+ }
+}
+
/* reads all buffers, calls optional composite, merges in first result->rectf */
static void do_merge_fullsample(Render *re, bNodeTree *ntree)
{
float *rectf, filt[3][3];
- int sample;
+ int x, y, sample;
/* interaction callbacks */
if (ntree) {
@@ -1408,7 +1485,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
for (sample = 0; sample < re->r.osa; sample++) {
Render *re1;
RenderResult rres;
- int x, y, mask;
+ int mask;
/* enable full sample print */
R.i.curfsa = sample + 1;
@@ -1423,6 +1500,8 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
if (sample) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
render_result_exr_file_read(re1, sample);
+ if( re1->r.mode & R_EDGE_FRS)
+ composite_freestyle_renders(re1, sample);
BLI_rw_mutex_unlock(&re->resultmutex);
}
ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */
@@ -1471,6 +1550,18 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
if (re->test_break(re->tbh))
break;
}
+
+ /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
+ for (y = 0; y < re->recty; y++) {
+ float *rf = rectf + 4 * y * re->rectx;
+
+ for (x = 0; x < re->rectx; x++, rf += 4) {
+ rf[0] = MAX2(rf[0], 0.0f);
+ rf[1] = MAX2(rf[1], 0.0f);
+ rf[2] = MAX2(rf[2], 0.0f);
+ CLAMP(rf[3], 0.0f, 1.0f);
+ }
+ }
/* clear interaction callbacks */
if (ntree) {
@@ -1612,6 +1703,8 @@ static void do_render_composite_fields_blur_3d(Render *re)
do_merge_fullsample(re, NULL);
}
+ free_all_freestyle_renders(re->scene);
+
/* weak... the display callback wants an active renderlayer pointer... */
re->result->renlay = render_get_active_layer(re, re->result);
re->display_draw(re->ddh, re->result, NULL);
@@ -1677,9 +1770,14 @@ static void do_render_seq(Render *re)
out = BKE_sequencer_give_ibuf(context, cfra, 0);
- ibuf = IMB_dupImBuf(out);
- IMB_freeImBuf(out);
- BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf);
+ if (out) {
+ ibuf = IMB_dupImBuf(out);
+ IMB_freeImBuf(out);
+ BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf);
+ }
+ else {
+ ibuf = NULL;
+ }
recurs_depth--;
@@ -1713,6 +1811,9 @@ static void do_render_seq(Render *re)
re->progress(re->prh, (float)(cfra - re->r.sfra) / (re->r.efra - re->r.sfra));
else
re->progress(re->prh, 1.0f);
+
+ /* would mark display buffers as invalid */
+ re->display_draw(re->ddh, re->result, NULL);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -2050,7 +2151,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
do_render_all_options(re);
-
+
if (write_still && !G.is_break) {
if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
/* operator checks this but in case its called from elsewhere */
@@ -2082,6 +2183,15 @@ static void colormanage_image_for_write(Scene *scene, ImBuf *ibuf)
imb_freerectfloatImBuf(ibuf);
}
+void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene)
+{
+ re->result_ok= 0;
+ if(render_initialize_from_main(re, bmain, scene, NULL, NULL, scene->lay, 0, 0)) {
+ do_render_fields_blur_3d(re);
+ }
+ re->result_ok= 1;
+}
+
static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
{
char name[FILE_MAX];
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index f11f84c9d3b..a226556828e 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -57,6 +57,8 @@
#include "render_result.h"
#include "render_types.h"
+#include "FRS_freestyle_config.h"
+
/********************************** Free *************************************/
void render_result_free(RenderResult *res)
@@ -422,8 +424,8 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
SceneRenderLayer *srl;
int rectx, recty, nr;
- rectx = BLI_RCT_SIZE_X(partrct);
- recty = BLI_RCT_SIZE_Y(partrct);
+ rectx = BLI_rcti_size_x(partrct);
+ recty = BLI_rcti_size_y(partrct);
if (rectx <= 0 || recty <= 0)
return NULL;
@@ -564,13 +566,14 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
rl->lay = (1 << 20) - 1;
rl->layflag = 0x7FFF; /* solid ztra halo strand */
rl->passflag = SCE_PASS_COMBINED;
+ FRS_add_freestyle_config( srl );
re->r.actlay = 0;
}
/* border render; calculate offset for use in compositor. compo is centralized coords */
- rr->xof = re->disprect.xmin + BLI_RCT_CENTER_X(&re->disprect) - (re->winx / 2);
- rr->yof = re->disprect.ymin + BLI_RCT_CENTER_Y(&re->disprect) - (re->winy / 2);
+ rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
+ rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
return rr;
}
@@ -627,12 +630,13 @@ static void ml_addpass_cb(void *UNUSED(base), void *lay, const char *str, float
}
/* from imbuf, if a handle was returned we convert this to render result */
-RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty)
+RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty)
{
RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__);
RenderLayer *rl;
RenderPass *rpass;
-
+ const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+
rr->rectx = rectx;
rr->recty = recty;
@@ -645,6 +649,11 @@ RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty)
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
rpass->rectx = rectx;
rpass->recty = recty;
+
+ if (rpass->channels >= 3) {
+ IMB_colormanagement_transform(rpass->rect, rpass->rectx, rpass->recty, rpass->channels,
+ colorspace, to_colorspace, predivide);
+ }
}
}
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 6d22d8991b4..982f7e7d824 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -98,7 +98,7 @@ static void init_render_texture(Render *re, Tex *tex)
{
/* imap test */
if (tex->ima && ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
- BKE_image_user_frame_calc(&tex->iuser, re->r.cfra, re?re->flag & R_SEC_FIELD:0);
+ BKE_image_user_frame_calc(&tex->iuser, re ? re->r.cfra : 0, re ? re->flag & R_SEC_FIELD:0);
}
else if (tex->type==TEX_ENVMAP) {
@@ -2153,9 +2153,6 @@ void do_material_tex(ShadeInput *shi, Render *re)
co= shi->lo; dx= shi->dxlo; dy= shi->dylo;
}
}
- else if (mtex->texco==TEXCO_STICKY) {
- co= shi->sticky; dx= shi->dxsticky; dy= shi->dysticky;
- }
else if (mtex->texco==TEXCO_OBJECT) {
Object *ob= mtex->object;
if (ob) {
@@ -2760,11 +2757,9 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
/* stencil maps on the texture control slider, not texture intensity value */
/* convert RGB to intensity if intensity info isn't provided */
- if (!(rgbnor & TEX_INT)) {
- if (rgbnor & TEX_RGB) {
- if (texres.talpha) texres.tin = texres.ta;
- else texres.tin = rgb_to_grayscale(&texres.tr);
- }
+ if (rgbnor & TEX_RGB) {
+ if (texres.talpha) texres.tin = texres.ta;
+ else texres.tin = rgb_to_grayscale(&texres.tr);
}
if ((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) {
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 97a05e6a4c9..0d894073cee 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -109,10 +109,10 @@ void calc_view_vector(float *view, float x, float y)
/* move x and y to real viewplane coords */
x = (x / (float)R.winx);
- view[0] = R.viewplane.xmin + x * BLI_RCT_SIZE_X(&R.viewplane);
+ view[0] = R.viewplane.xmin + x * BLI_rctf_size_x(&R.viewplane);
y = (y / (float)R.winy);
- view[1] = R.viewplane.ymin + y * BLI_RCT_SIZE_Y(&R.viewplane);
+ view[1] = R.viewplane.ymin + y * BLI_rctf_size_y(&R.viewplane);
// if (R.flag & R_SEC_FIELD) {
// if (R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart)*R.ycor;
@@ -990,6 +990,30 @@ static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl)
}
}
+/* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
+static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
+{
+ RenderLayer *rlpp[RE_MAX_OSA];
+ int y, sample, totsample;
+
+ totsample= get_sample_layers(pa, rl, rlpp);
+
+ /* not for full sample, there we clamp after compositing */
+ if (totsample > 1)
+ return;
+
+ for (sample= 0; sample<totsample; sample++) {
+ float *rectf= rlpp[sample]->rectf;
+
+ for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
+ rectf[0] = MAX2(rectf[0], 0.0f);
+ rectf[1] = MAX2(rectf[1], 0.0f);
+ rectf[2] = MAX2(rectf[2], 0.0f);
+ CLAMP(rectf[3], 0.0f, 1.0f);
+ }
+ }
+}
+
/* adds only alpha values */
static void edge_enhance_tile(RenderPart *pa, float *rectf, int *rectz)
{
@@ -1270,6 +1294,9 @@ void zbufshadeDA_tile(RenderPart *pa)
if (rl->passflag & SCE_PASS_VECTOR)
reset_sky_speed(pa, rl);
+
+ /* clamp alpha to 0..1 range, can go outside due to filter */
+ clamp_alpha_rgb_range(pa, rl);
/* de-premul alpha */
if (R.r.alphamode & R_ALPHAKEY)
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index db045284d5b..6395a04b534 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -97,13 +97,10 @@
* the index */
/* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */
-
-#define RE_STICKY_ELEMS 2
#define RE_STRESS_ELEMS 1
#define RE_RAD_ELEMS 4
#define RE_STRAND_ELEMS 1
#define RE_TANGENT_ELEMS 3
-#define RE_STRESS_ELEMS 1
#define RE_WINSPEED_ELEMS 4
#define RE_MTFACE_ELEMS 1
#define RE_MCOL_ELEMS 4
@@ -114,21 +111,6 @@
#define RE_FACE_ELEMS 1
#define RE_NMAP_TANGENT_ELEMS 16
-float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
-{
- float *sticky;
- int nr= ver->index>>8;
-
- sticky= obr->vertnodes[nr].sticky;
- if (sticky==NULL) {
- if (verify)
- sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
- else
- return NULL;
- }
- return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
-}
-
float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
{
float *stress;
@@ -218,12 +200,7 @@ VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
*v1= *ver;
v1->index= index;
-
- fp1= RE_vertren_get_sticky(obr, ver, 0);
- if (fp1) {
- fp2= RE_vertren_get_sticky(obr, v1, 1);
- memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float));
- }
+
fp1= RE_vertren_get_stress(obr, ver, 0);
if (fp1) {
fp2= RE_vertren_get_stress(obr, v1, 1);
@@ -740,8 +717,6 @@ void free_renderdata_vertnodes(VertTableNode *vertnodes)
if (vertnodes[a].rad)
MEM_freeN(vertnodes[a].rad);
- if (vertnodes[a].sticky)
- MEM_freeN(vertnodes[a].sticky);
if (vertnodes[a].strand)
MEM_freeN(vertnodes[a].strand);
if (vertnodes[a].tangent)
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 2d7a64bad04..bed3fb5f754 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -72,6 +72,9 @@
# define ACOMP 3
#endif
+#define RCT_SIZE_X(rct) ((rct)->xmax - (rct)->xmin)
+#define RCT_SIZE_Y(rct) ((rct)->ymax - (rct)->ymin)
+
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
/* only to be used here in this file, it's for speed */
@@ -1506,7 +1509,7 @@ static void isb_bsp_split_init(ISBBranch *root, MemArena *mem, int level)
root->divider[1]= 0.5f*(root->box.ymin+root->box.ymax);
/* find best splitpoint */
- if (BLI_RCT_SIZE_X(&root->box) > BLI_RCT_SIZE_Y(&root->box))
+ if (RCT_SIZE_X(&root->box) > RCT_SIZE_Y(&root->box))
i = root->index = 0;
else
i = root->index = 1;
@@ -1551,7 +1554,7 @@ static void isb_bsp_split(ISBBranch *root, MemArena *mem)
root->divider[1]/= BSPMAX_SAMPLE;
/* find best splitpoint */
- if (BLI_RCT_SIZE_X(&root->box) > BLI_RCT_SIZE_Y(&root->box))
+ if (RCT_SIZE_X(&root->box) > RCT_SIZE_Y(&root->box))
i = root->index = 0;
else
i = root->index = 1;
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index d1d2c66985e..35ab06cc564 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -574,10 +574,6 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
shi->dywin[1] = 0.0f;
}
}
-
- if (texco & TEXCO_STICKY) {
- /* not supported */
- }
}
if (shi->do_manage) {
@@ -1124,50 +1120,113 @@ void shade_input_set_shade_texco(ShadeInput *shi)
for (i = 0; (tface = RE_vlakren_get_tface(obr, vlr, i, &name, 0)); i++) {
ShadeInputUV *suv = &shi->uv[i];
- float *uv1, *uv2, *uv3;
+ const float *uv1 = tface->uv[j1];
+ const float *uv2 = tface->uv[j2];
+ const float *uv3 = tface->uv[j3];
shi->totuv++;
suv->name = name;
-
- uv1 = tface->uv[j1];
- uv2 = tface->uv[j2];
- uv3 = tface->uv[j3];
- suv->uv[0] = -1.0f + 2.0f * (l * uv3[0] - u * uv1[0] - v * uv2[0]);
- suv->uv[1] = -1.0f + 2.0f * (l * uv3[1] - u * uv1[1] - v * uv2[1]);
- suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
+ if ((shi->mat->mapflag & MA_MAPFLAG_UVPROJECT) && (shi->depth == 0)) {
+ float x = shi->xs;
+ float y = shi->ys;
+
+ float s1[2] = {-1.0f + 2.0f * uv1[0], -1.0f + 2.0f * uv1[1]};
+ float s2[2] = {-1.0f + 2.0f * uv2[0], -1.0f + 2.0f * uv2[1]};
+ float s3[2] = {-1.0f + 2.0f * uv3[0], -1.0f + 2.0f * uv3[1]};
+
+
+ float obwinmat[4][4], winmat[4][4], ho1[4], ho2[4], ho3[4];
+ float Zmulx, Zmuly;
+ float hox, hoy, l, dl, u, v;
+ float s00, s01, s10, s11, detsh;
+
+ /* old globals, localized now */
+ Zmulx = ((float)R.winx) / 2.0f;
+ Zmuly = ((float)R.winy) / 2.0f;
+
+ zbuf_make_winmat(&R, winmat);
+ if (shi->obi->flag & R_TRANSFORMED)
+ mult_m4_m4m4(obwinmat, winmat, obi->mat);
+ else
+ copy_m4_m4(obwinmat, winmat);
+
+ zbuf_render_project(obwinmat, v1->co, ho1);
+ zbuf_render_project(obwinmat, v2->co, ho2);
+ zbuf_render_project(obwinmat, v3->co, ho3);
+
+ s00 = ho3[0] / ho3[3] - ho1[0] / ho1[3];
+ s01 = ho3[1] / ho3[3] - ho1[1] / ho1[3];
+ s10 = ho3[0] / ho3[3] - ho2[0] / ho2[3];
+ s11 = ho3[1] / ho3[3] - ho2[1] / ho2[3];
+
+ detsh = s00 * s11 - s10 * s01;
+ detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
+ s00 *= detsh; s01 *= detsh;
+ s10 *= detsh; s11 *= detsh;
+
+ /* recalc u and v again */
+ hox = x / Zmulx - 1.0f;
+ hoy = y / Zmuly - 1.0f;
+ u = (hox - ho3[0] / ho3[3]) * s11 - (hoy - ho3[1] / ho3[3]) * s10;
+ v = (hoy - ho3[1] / ho3[3]) * s00 - (hox - ho3[0] / ho3[3]) * s01;
+ l = 1.0f + u + v;
+
+ suv->uv[0] = l * s3[0] - u * s1[0] - v * s2[0];
+ suv->uv[1] = l * s3[1] - u * s1[1] - v * s2[1];
+ suv->uv[2] = 0.0f;
- if (shi->osatex) {
- float duv[2];
-
- dl = shi->dx_u + shi->dx_v;
- duv[0] = shi->dx_u;
- duv[1] = shi->dx_v;
+ if (shi->osatex) {
+ float dxuv[2], dyuv[2];
+ dxuv[0] = s11 / Zmulx;
+ dxuv[1] = -s01 / Zmulx;
+ dyuv[0] = -s10 / Zmuly;
+ dyuv[1] = s00 / Zmuly;
+
+ dl = dxuv[0] + dxuv[1];
+ suv->dxuv[0] = dl * s3[0] - dxuv[0] * s1[0] - dxuv[1] * s2[0];
+ suv->dxuv[1] = dl * s3[1] - dxuv[0] * s1[1] - dxuv[1] * s2[1];
+ dl = dyuv[0] + dyuv[1];
+ suv->dyuv[0] = dl * s3[0] - dyuv[0] * s1[0] - dyuv[1] * s2[0];
+ suv->dyuv[1] = dl * s3[1] - dyuv[0] * s1[1] - dyuv[1] * s2[1];
+ }
+ }
+ else {
- suv->dxuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
- suv->dxuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
+ suv->uv[0] = -1.0f + 2.0f * (l * uv3[0] - u * uv1[0] - v * uv2[0]);
+ suv->uv[1] = -1.0f + 2.0f * (l * uv3[1] - u * uv1[1] - v * uv2[1]);
+ suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
- dl = shi->dy_u + shi->dy_v;
- duv[0] = shi->dy_u;
- duv[1] = shi->dy_v;
+ if (shi->osatex) {
+ float duv[2];
- suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
- suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
- }
+ dl = shi->dx_u + shi->dx_v;
+ duv[0] = shi->dx_u;
+ duv[1] = shi->dx_v;
- if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
- if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) {
- shi->vcol[0] = 1.0f;
- shi->vcol[1] = 1.0f;
- shi->vcol[2] = 1.0f;
- shi->vcol[3] = 1.0f;
+ suv->dxuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
+ suv->dxuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
+
+ dl = shi->dy_u + shi->dy_v;
+ duv[0] = shi->dy_u;
+ duv[1] = shi->dy_v;
+
+ suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
+ suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
}
- if (tface->tpage) {
- render_realtime_texture(shi, tface->tpage);
+
+ if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
+ if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) {
+ shi->vcol[0] = 1.0f;
+ shi->vcol[1] = 1.0f;
+ shi->vcol[2] = 1.0f;
+ shi->vcol[3] = 1.0f;
+ }
+ if (tface->tpage) {
+ render_realtime_texture(shi, tface->tpage);
+ }
}
}
-
-
}
shi->dupliuv[0] = -1.0f + 2.0f * obi->dupliuv[0];
@@ -1236,70 +1295,6 @@ void shade_input_set_shade_texco(ShadeInput *shi)
shi->dywin[0] = shi->dywin[2] = 0.0f;
}
}
-
- if (texco & TEXCO_STICKY) {
- float *s1, *s2, *s3;
-
- s1 = RE_vertren_get_sticky(obr, v1, 0);
- s2 = RE_vertren_get_sticky(obr, v2, 0);
- s3 = RE_vertren_get_sticky(obr, v3, 0);
-
- if (s1 && s2 && s3) {
- float obwinmat[4][4], winmat[4][4], ho1[4], ho2[4], ho3[4];
- float Zmulx, Zmuly;
- float hox, hoy, l, dl, u, v;
- float s00, s01, s10, s11, detsh;
-
- /* old globals, localized now */
- Zmulx = ((float)R.winx) / 2.0f; Zmuly = ((float)R.winy) / 2.0f;
-
- zbuf_make_winmat(&R, winmat);
- if (shi->obi->flag & R_TRANSFORMED)
- mult_m4_m4m4(obwinmat, winmat, obi->mat);
- else
- copy_m4_m4(obwinmat, winmat);
-
- zbuf_render_project(obwinmat, v1->co, ho1);
- zbuf_render_project(obwinmat, v2->co, ho2);
- zbuf_render_project(obwinmat, v3->co, ho3);
-
- s00 = ho3[0] / ho3[3] - ho1[0] / ho1[3];
- s01 = ho3[1] / ho3[3] - ho1[1] / ho1[3];
- s10 = ho3[0] / ho3[3] - ho2[0] / ho2[3];
- s11 = ho3[1] / ho3[3] - ho2[1] / ho2[3];
-
- detsh = s00 * s11 - s10 * s01;
- detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
- s00 *= detsh; s01 *= detsh;
- s10 *= detsh; s11 *= detsh;
-
- /* recalc u and v again */
- hox = x / Zmulx - 1.0f;
- hoy = y / Zmuly - 1.0f;
- u = (hox - ho3[0] / ho3[3]) * s11 - (hoy - ho3[1] / ho3[3]) * s10;
- v = (hoy - ho3[1] / ho3[3]) * s00 - (hox - ho3[0] / ho3[3]) * s01;
- l = 1.0f + u + v;
-
- shi->sticky[0] = l * s3[0] - u * s1[0] - v * s2[0];
- shi->sticky[1] = l * s3[1] - u * s1[1] - v * s2[1];
- shi->sticky[2] = 0.0f;
-
- if (shi->osatex) {
- float dxuv[2], dyuv[2];
- dxuv[0] = s11 / Zmulx;
- dxuv[1] = -s01 / Zmulx;
- dyuv[0] = -s10 / Zmuly;
- dyuv[1] = s00 / Zmuly;
-
- dl = dxuv[0] + dxuv[1];
- shi->dxsticky[0] = dl * s3[0] - dxuv[0] * s1[0] - dxuv[1] * s2[0];
- shi->dxsticky[1] = dl * s3[1] - dxuv[0] * s1[1] - dxuv[1] * s2[1];
- dl = dyuv[0] + dyuv[1];
- shi->dysticky[0] = dl * s3[0] - dyuv[0] * s1[0] - dyuv[1] * s2[0];
- shi->dysticky[1] = dl * s3[1] - dyuv[0] * s1[1] - dyuv[1] * s2[1];
- }
- }
- }
}
/* else {
* Note! For raytracing winco is not set,
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 6883710d1be..6742244ea61 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1688,6 +1688,12 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
if (ma->mode & (MA_FACETEXTURE_ALPHA))
shi->alpha= shi->vcol[3];
}
+ else if (ma->vcol_alpha) {
+ shi->r= shi->vcol[0];
+ shi->g= shi->vcol[1];
+ shi->b= shi->vcol[2];
+ shi->alpha= shi->vcol[3];
+ }
else if (ma->mode & (MA_VERTEXCOLP)) {
float neg_alpha = 1.0f - shi->vcol[3];
shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3];
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index e6782121b69..dae0e9193c2 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -32,6 +32,7 @@ set(INC
../editors/include
../editors/io
../gpu
+ ../freestyle
../imbuf
../makesdna
../makesrna
diff --git a/source/blender/windowmanager/SConscript b/source/blender/windowmanager/SConscript
index 68fdbec2cfa..de340ec4c9a 100644
--- a/source/blender/windowmanager/SConscript
+++ b/source/blender/windowmanager/SConscript
@@ -11,6 +11,7 @@ incs = '. ../editors/include ../python ../makesdna ../blenlib ../blenkernel'
incs += ' ../nodes ../imbuf ../blenloader ../render/extern/include'
incs += ' ../radiosity/extern/include'
incs += ' ../makesrna ../gpu ../blenfont ../bmesh ../compositor'
+incs += ' ../freestyle'
incs += ' #/intern/guardedalloc #/intern/memutil #/intern/ghost'
incs += ' #/intern/elbeem #/extern/glew/include'
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 1d509a87ffe..9570638fb25 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -71,8 +71,18 @@ void WM_init_state_normal_set(void);
void WM_init (struct bContext *C, int argc, const char **argv);
void WM_exit_ext (struct bContext *C, const short do_python);
-void WM_exit (struct bContext *C);
-void WM_main (struct bContext *C);
+
+void WM_exit (struct bContext *C)
+#if defined(__GNUC__) || defined(__clang__)
+__attribute__((noreturn))
+#endif
+;
+
+void WM_main (struct bContext *C)
+#if defined(__GNUC__) || defined(__clang__)
+__attribute__((noreturn))
+#endif
+;
int WM_init_game (struct bContext *C);
void WM_init_splash (struct bContext *C);
@@ -104,8 +114,8 @@ void WM_cursor_set (struct wmWindow *win, int curs);
void WM_cursor_modal (struct wmWindow *win, int curs);
void WM_cursor_restore (struct wmWindow *win);
void WM_cursor_wait (int val);
-void WM_cursor_grab_enable(struct wmWindow *win, int wrap, int hide, int *bounds);
-void WM_cursor_grab_disable(struct wmWindow *win);
+void WM_cursor_grab_enable(struct wmWindow *win, int wrap, int hide, int bounds[4]);
+void WM_cursor_grab_disable(struct wmWindow *win, int mouse_ungrab_xy[2]);
void WM_cursor_time (struct wmWindow *win, int nr);
void *WM_paint_cursor_activate(struct wmWindowManager *wm,
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index f9b22331f37..4ec3d8ea755 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -238,6 +238,7 @@ typedef struct wmNotifier {
#define NC_LOGIC (19<<24)
#define NC_MOVIECLIP (20<<24)
#define NC_MASK (21<<24)
+#define NC_LINESTYLE (22<<24)
/* data type, 256 entries is enough, it can overlap */
#define NOTE_DATA 0x00FF0000
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 6fc6a57ade1..7853b40c98a 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -179,7 +179,10 @@ void WM_cursor_wait(int val)
}
}
-void WM_cursor_grab_enable(wmWindow *win, int wrap, int hide, int *bounds)
+/**
+ * \param bounds can be NULL
+ */
+void WM_cursor_grab_enable(wmWindow *win, int wrap, int hide, int bounds[4])
{
/* Only grab cursor when not running debug.
* It helps not to get a stuck WM when hitting a breakpoint
@@ -193,20 +196,20 @@ void WM_cursor_grab_enable(wmWindow *win, int wrap, int hide, int *bounds)
const GHOST_TabletData *tabletdata = GHOST_GetTabletData(win->ghostwin);
/* Note: There is no tabletdata on Windows if no tablet device is connected. */
if (!tabletdata)
- GHOST_SetCursorGrab(win->ghostwin, mode, bounds);
+ GHOST_SetCursorGrab(win->ghostwin, mode, bounds, NULL);
else if (tabletdata->Active == GHOST_kTabletModeNone)
- GHOST_SetCursorGrab(win->ghostwin, mode, bounds);
+ GHOST_SetCursorGrab(win->ghostwin, mode, bounds, NULL);
win->grabcursor = mode;
}
}
}
-void WM_cursor_grab_disable(wmWindow *win)
+void WM_cursor_grab_disable(wmWindow *win, int mouse_ungrab_xy[2])
{
if ((G.debug & G_DEBUG) == 0) {
if (win && win->ghostwin) {
- GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL);
+ GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, mouse_ungrab_xy);
win->grabcursor = GHOST_kGrabDisable;
}
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 17f17baba0e..c05d9532f74 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1202,7 +1202,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
CTX_wm_region_set(C, region);
}
- WM_cursor_grab_disable(CTX_wm_window(C));
+ WM_cursor_grab_disable(CTX_wm_window(C), NULL);
WM_operator_free(handler->op);
}
else if (handler->ui_remove) {
@@ -1432,7 +1432,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
/* remove modal handler, operator itself should have been canceled and freed */
if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
- WM_cursor_grab_disable(CTX_wm_window(C));
+ WM_cursor_grab_disable(CTX_wm_window(C), NULL);
BLI_remlink(handlers, handler);
wm_event_free_handler(handler);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index eb6fabd03c6..594804d10f6 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -114,6 +114,8 @@
#include "BPY_extern.h"
#endif
+#include "FRS_freestyle.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "wm.h"
@@ -425,6 +427,7 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports)
BPY_app_handlers_reset(FALSE);
BPY_modules_load_user(C);
#endif
+ FRS_read_file(C);
/* important to do before NULL'ing the context */
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 2928ba024e5..b3ffb80243a 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -130,8 +130,8 @@ int wm_gesture_evaluate(wmGesture *gesture)
{
if (gesture->type == WM_GESTURE_TWEAK) {
rcti *rect = gesture->customdata;
- int dx = BLI_RCT_SIZE_X(rect);
- int dy = BLI_RCT_SIZE_Y(rect);
+ int dx = BLI_rcti_size_x(rect);
+ int dy = BLI_rcti_size_y(rect);
if (ABS(dx) + ABS(dy) > U.tweak_threshold) {
int theta = (int)floor(4.0f * atan2f((float)dy, (float)dx) / (float)M_PI + 0.5f);
int val = EVT_GESTURE_W;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 908f7e27f0b..534bfdc369e 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -32,8 +32,8 @@
#include <stdio.h>
#include <string.h>
-#if WIN32
-#include <Windows.h>
+#ifdef WIN32
+# include <Windows.h>
#endif
#include "MEM_guardedalloc.h"
@@ -144,15 +144,18 @@ void WM_init(bContext *C, int argc, const char **argv)
ED_spacetypes_init(); /* editors/space_api/spacetype.c */
+ /* initialize color management stuff
+ * do this before ED_file_init because that function would load images,
+ * so at least default byte color space should be already known
+ */
+ IMB_colormanagement_init();
+
ED_file_init(); /* for fsmenu */
ED_node_init_butfuncs();
BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */
BLF_lang_init();
- /* initialize color management stuff */
- IMB_colormanagement_init();
-
/* get the default database, plus a wm */
WM_homefile_read(C, NULL, G.factory_startup);
@@ -340,7 +343,7 @@ extern void free_anim_copybuf(void);
extern void free_anim_drivers_copybuf(void);
extern void free_fmodifiers_copybuf(void);
-#if WIN32
+#ifdef WIN32
/* Read console events until there is a key event. Also returns on any error. */
static void wait_for_console_key(void)
{
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index eb6da146a73..bcddc984ed3 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -867,7 +867,6 @@ static wmKeyMapItem *wm_keymap_item_find_props(
/* look into multiple handler lists to find the item */
if (win)
found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
-
if (sa && found == NULL)
found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
@@ -901,7 +900,7 @@ static wmKeyMapItem *wm_keymap_item_find_props(
found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
}
}
-
+
return found;
}
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index bff40faf1d1..35cc1545c40 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -713,14 +713,6 @@ static void playanim_window_open(const char *title, int posx, int posy, int size
inital_state,
GHOST_kDrawingContextTypeOpenGL,
FALSE /* no stereo */, FALSE);
-
- //if (ghostwin) {
- //if (win) {
- // GHOST_SetWindowUserData(ghostwin, win);
- //} else {
- // GHOST_DisposeWindow(g_WS.ghost_system, ghostwin);
- //}
- //}
}
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index adf54af240b..4078a88b2fd 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -116,8 +116,8 @@ void wm_subwindow_getsize(wmWindow *win, int swinid, int *x, int *y)
wmSubWindow *swin = swin_from_swinid(win, swinid);
if (swin) {
- *x = BLI_RCT_SIZE_X(&swin->winrct) + 1;
- *y = BLI_RCT_SIZE_Y(&swin->winrct) + 1;
+ *x = BLI_rcti_size_x(&swin->winrct) + 1;
+ *y = BLI_rcti_size_y(&swin->winrct) + 1;
}
}
@@ -256,13 +256,13 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, rcti *srct)
win->curswin = _curswin;
_curwindow = win;
- width = BLI_RCT_SIZE_X(&_curswin->winrct) + 1;
- height = BLI_RCT_SIZE_Y(&_curswin->winrct) + 1;
+ width = BLI_rcti_size_x(&_curswin->winrct) + 1;
+ height = BLI_rcti_size_y(&_curswin->winrct) + 1;
glViewport(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
if (srct) {
- width = BLI_RCT_SIZE_X(srct) + 1;
- height = BLI_RCT_SIZE_Y(srct) + 1;
+ width = BLI_rcti_size_x(srct) + 1;
+ height = BLI_rcti_size_y(srct) + 1;
glScissor(srct->xmin, srct->ymin, width, height);
}
else
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 59c8235faf0..18072d805fc 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -458,8 +458,8 @@ wmWindow *WM_window_open(bContext *C, rcti *rect)
win->posx = rect->xmin;
win->posy = rect->ymin;
- win->sizex = BLI_RCT_SIZE_X(rect);
- win->sizey = BLI_RCT_SIZE_Y(rect);
+ win->sizex = BLI_rcti_size_x(rect);
+ win->sizey = BLI_rcti_size_y(rect);
win->drawmethod = -1;
win->drawdata = NULL;
@@ -494,8 +494,8 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
win->posy = position->ymin;
}
- win->sizex = BLI_RCT_SIZE_X(position);
- win->sizey = BLI_RCT_SIZE_Y(position);
+ win->sizex = BLI_rcti_size_x(position);
+ win->sizey = BLI_rcti_size_y(position);
if (win->ghostwin) {
wm_window_set_size(win, win->sizex, win->sizey);
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index c6383b471f7..a9522e3618d 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -55,6 +55,8 @@ struct FCurve;
struct Heap;
struct HeapNode;
struct ID;
+struct FreestyleConfig;
+struct FreestyleLineSet;
struct ImBuf;
struct Image;
struct ImageUser;
@@ -83,6 +85,7 @@ struct RenderLayer;
struct RenderResult;
struct Scene;
struct Scene;
+struct SceneRenderLayer;
struct ScrArea;
struct SculptSession;
struct ShadeInput;
@@ -506,6 +509,13 @@ int pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) { return 0; }
struct PyObject *pyrna_id_CreatePyObject(struct ID *id) {return NULL; }
void BPY_context_update(struct bContext *C) {};
+/* Freestyle */
+void FRS_add_freestyle_config(struct SceneRenderLayer* srl) {}
+void FRS_free_freestyle_config(struct SceneRenderLayer* srl) {}
+struct FreestyleLineSet *FRS_get_active_lineset(struct FreestyleConfig *config) { return NULL; }
+short FRS_get_active_lineset_index(struct FreestyleConfig *config) { return 0; }
+void FRS_set_active_lineset_index(struct FreestyleConfig *config, short index) {}
+void FRS_unlink_target_object(struct FreestyleConfig *config, struct Object *ob) {}
/* intern/dualcon */
struct DualConMesh;
struct DualConMesh *dualcon(const struct DualConMesh *input_mesh,
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 3356091b97f..5236f928581 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -36,6 +36,7 @@ blender_include_dirs(
../blender/render/extern/include
../blender/makesdna
../blender/gpu
+ ../blender/freestyle
../blender/windowmanager
)
@@ -646,13 +647,19 @@ elseif(WIN32)
endif()
if(WITH_OPENCOLORIO)
+ set_lib_path(OCIOBIN "opencolorio/bin")
if(NOT MINGW)
- set_lib_path(OCIOBIN "opencolorio/bin")
install(
FILES
${OCIOBIN}/OpenColorIO.dll
DESTINATION ${TARGETDIR}
)
+ else()
+ install(
+ FILES
+ ${OCIOBIN}/libOpenColorIO.dll
+ DESTINATION ${TARGETDIR}
+ )
endif()
endif()
@@ -866,6 +873,7 @@ endif()
bf_python_ext
bf_python_mathutils
bf_python_bmesh
+ bf_freestyle
bf_ikplugin
bf_modifiers
bf_bmesh
diff --git a/source/creator/creator.c b/source/creator/creator.c
index ab9541cf299..f25ff305c14 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -102,6 +102,8 @@
#include "BLI_scanfill.h" /* for BLI_setErrorCallBack, TODO, move elsewhere */
+#include "FRS_freestyle.h"
+
#ifdef WITH_BUILDINFO_HEADER
# define BUILD_DATE
#endif
@@ -1305,7 +1307,7 @@ int main(int argc, const char **argv)
/* for all platforms, even windos has it! */
if (G.background) signal(SIGINT, blender_esc); /* ctrl c out bg render */
#endif
-
+
/* background render uses this font too */
BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);
@@ -1356,6 +1358,10 @@ int main(int argc, const char **argv)
CTX_py_init_set(C, 1);
WM_keymap_init(C);
+ /* initialize Freestyle */
+ FRS_initialize();
+ FRS_set_context(C);
+
/* OK we are ready for it */
#ifndef WITH_PYTHON_MODULE
BLI_argsParse(ba, 4, load_file, C);
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 3a06fe979e1..5cfa97e2e7e 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -125,8 +125,8 @@ static BlendFileData *load_game_data(char *filename)
return bfd;
}
-int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWindow *win, Scene *scene, ARegion *ar,
- KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox)
+static int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWindow *win, Scene *scene, ARegion *ar,
+ KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox)
{
int exitrequested;
@@ -143,7 +143,7 @@ int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWindow *win
// itself is unaware of the extra space, so we clear the whole region for it.
glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
glViewport(ar->winrct.xmin, ar->winrct.ymin,
- BLI_RCT_SIZE_X(&ar->winrct), BLI_RCT_SIZE_Y(&ar->winrct));
+ BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
glClear(GL_COLOR_BUFFER_BIT);
}
@@ -198,7 +198,7 @@ struct BL_KetsjiNextFrameState {
int draw_letterbox;
} ketsjinextframestate;
-int BL_KetsjiPyNextFrame(void *state0)
+static int BL_KetsjiPyNextFrame(void *state0)
{
BL_KetsjiNextFrameState *state = (BL_KetsjiNextFrameState *) state0;
return BL_KetsjiNextFrame(
@@ -552,7 +552,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
ketsjinextframestate.draw_letterbox = draw_letterbox;
pynextframestate.state = &ketsjinextframestate;
- pynextframestate.func = &BL_KetsjiPyNextFrame;
+ pynextframestate.func = &BL_KetsjiPyNextFrame;
printf("Yielding control to Python script '%s'...\n", python_main);
PyRun_SimpleString(python_code);
printf("Exit Python script '%s'\n", python_main);
@@ -590,7 +590,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
const Py_ssize_t numitems= PyList_GET_SIZE(gameLogic_keys_new);
Py_ssize_t listIndex;
for (listIndex=0; listIndex < numitems; listIndex++) {
- PyObject* item = PyList_GET_ITEM(gameLogic_keys_new, listIndex);
+ PyObject *item = PyList_GET_ITEM(gameLogic_keys_new, listIndex);
if (!PySequence_Contains(gameLogic_keys, item)) {
PyDict_DelItem( PyModule_GetDict(gameLogic), item);
}
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
index 6236923d973..4f450bcd668 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
@@ -53,7 +53,7 @@ KX_BlenderCanvas::~KX_BlenderCanvas()
void KX_BlenderCanvas::Init()
{
glDepthFunc(GL_LEQUAL);
-}
+}
void KX_BlenderCanvas::SwapBuffers()
@@ -143,7 +143,7 @@ KX_BlenderCanvas::
GetWindowArea(
) {
return m_area_rect;
-}
+}
void
KX_BlenderCanvas::
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
index 19a84acf027..7c4c759e361 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
@@ -91,7 +91,7 @@ void BL_SwapBuffers(wmWindow *win)
wm_window_swap_buffers(win);
}
-void DisableForText()
+static void DisableForText()
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts otherwise they render as wireframe */
@@ -153,7 +153,7 @@ void BL_print_game_line(int fontid, const char* text, int size, int dpi, float*
}
void BL_print_gamedebug_line(const char* text, int xco, int yco, int width, int height)
-{
+{
/* gl prepping */
DisableForText();
glDisable(GL_DEPTH_TEST);
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
index c4daecc9958..85b76d7c676 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
@@ -344,7 +344,7 @@ void KX_BlenderRenderTools::PopMatrix()
int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& viewmat)
{
- // taken from blender source, incompatibility between Blender Object / GameObject
+ // taken from blender source, incompatibility between Blender Object / GameObject
KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo;
float glviewmat[16];
unsigned int count;
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
index a229c9f34e6..54ff4dde947 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
@@ -62,7 +62,7 @@ class KX_BlenderRenderTools : public RAS_IRenderTools
public:
KX_BlenderRenderTools();
- virtual ~KX_BlenderRenderTools();
+ virtual ~KX_BlenderRenderTools();
void EndFrame(RAS_IRasterizer* rasty);
void BeginFrame(RAS_IRasterizer* rasty);
diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt
index a205ccbdc12..aae7e93cc91 100644
--- a/source/gameengine/CMakeLists.txt
+++ b/source/gameengine/CMakeLists.txt
@@ -25,7 +25,7 @@
# there are too many inter-includes so best define here
if(WITH_PYTHON)
- blender_include_dirs("${PYTHON_INCLUDE_DIRS}")
+ blender_include_dirs_sys("${PYTHON_INCLUDE_DIRS}")
add_definitions(-DWITH_PYTHON)
endif()
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index 92d04115f10..fcf09588791 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -96,7 +96,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject* gameobj,
m_userpose(NULL),
m_action(action),
m_propname(propname),
- m_framepropname(framepropname)
+ m_framepropname(framepropname)
{
if (!end_reset)
m_flag |= ACT_FLAG_CONTINUE;
@@ -299,7 +299,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
m_flag |= ACT_FLAG_ATTEMPT_PLAY;
}
else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent)
- {
+ {
m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
m_localtime = obj->GetActionFrame(m_layer);
bAction *curr_action = obj->GetCurrentAction(m_layer);
@@ -347,7 +347,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
/* Python functions */
/* ------------------------------------------------------------------------- */
-PyObject* BL_ActionActuator::PyGetChannel(PyObject* value)
+PyObject *BL_ActionActuator::PyGetChannel(PyObject *value)
{
PyErr_SetString(PyExc_NotImplementedError, "BL_ActionActuator.getChannel() no longer works, please use BL_ArmatureObject.channels instead");
return NULL;
@@ -555,7 +555,7 @@ PyAttributeDef BL_ActionActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
@@ -589,7 +589,7 @@ int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF
}
-PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
PyErr_SetString(PyExc_NotImplementedError, "BL_ActionActuator.channelNames no longer works, please use BL_ArmatureObject.channels instead");
return NULL;
@@ -620,7 +620,7 @@ PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYA
#endif
}
-PyObject* BL_ActionActuator::pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ActionActuator::pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
return PyBool_FromLong(self->m_flag & ACT_FLAG_CONTINUE);
@@ -638,7 +638,7 @@ int BL_ActionActuator::pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUT
return PY_SET_ATTR_SUCCESS;
}
-PyObject* BL_ActionActuator::pyattr_get_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ActionActuator::pyattr_get_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
return PyFloat_FromDouble(((KX_GameObject*)self->m_gameobj)->GetActionFrame(self->m_layer));
diff --git a/source/gameengine/Converter/BL_ArmatureActuator.cpp b/source/gameengine/Converter/BL_ArmatureActuator.cpp
index 3f4a261a972..f0c4b3d32bb 100644
--- a/source/gameengine/Converter/BL_ArmatureActuator.cpp
+++ b/source/gameengine/Converter/BL_ArmatureActuator.cpp
@@ -146,7 +146,7 @@ void BL_ArmatureActuator::FindConstraint()
bool BL_ArmatureActuator::Update(double curtime, bool frame)
{
// the only role of this actuator is to ensure that the armature pose will be evaluated
- bool result = false;
+ bool result = false;
bool bNegativeEvent = IsNegativeEvent();
RemoveAllEvents();
@@ -227,11 +227,11 @@ PyAttributeDef BL_ArmatureActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* BL_ArmatureActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ArmatureActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ArmatureActuator* actuator = static_cast<BL_ArmatureActuator*>(self);
KX_GameObject *target = (!strcmp(attrdef->m_name, "target")) ? actuator->m_gametarget : actuator->m_gamesubtarget;
- if (!target)
+ if (!target)
Py_RETURN_NONE;
else
return target->GetProxy();
@@ -247,7 +247,7 @@ int BL_ArmatureActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBU
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
if (target != NULL)
- target->UnregisterActuator(actuator);
+ target->UnregisterActuator(actuator);
target = gameobj;
@@ -257,11 +257,11 @@ int BL_ArmatureActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBU
return PY_SET_ATTR_SUCCESS;
}
-PyObject* BL_ArmatureActuator::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ArmatureActuator::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ArmatureActuator* actuator = static_cast<BL_ArmatureActuator*>(self);
BL_ArmatureConstraint* constraint = actuator->m_constraint;
- if (!constraint)
+ if (!constraint)
Py_RETURN_NONE;
else
return constraint->GetProxy();
diff --git a/source/gameengine/Converter/BL_ArmatureActuator.h b/source/gameengine/Converter/BL_ArmatureActuator.h
index 638640c27ce..0c88dccb6f3 100644
--- a/source/gameengine/Converter/BL_ArmatureActuator.h
+++ b/source/gameengine/Converter/BL_ArmatureActuator.h
@@ -73,8 +73,8 @@ public:
#ifdef WITH_PYTHON
/* These are used to get and set m_target */
- static PyObject* pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp
index 7344aa9378e..e588d1d310c 100644
--- a/source/gameengine/Converter/BL_ArmatureChannel.cpp
+++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp
@@ -62,7 +62,7 @@ PyTypeObject BL_ArmatureChannel::Type = {
py_base_new
};
-PyObject* BL_ArmatureChannel::py_repr(void)
+PyObject *BL_ArmatureChannel::py_repr(void)
{
return PyUnicode_FromString(m_posechannel->name);
}
@@ -104,8 +104,8 @@ PyMethodDef BL_ArmatureChannel::Methods[] = {
PyAttributeDef BL_ArmatureChannel::Attributes[] = {
// Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
- KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr),
- KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr),
{ NULL } //Sentinel
};
@@ -147,7 +147,7 @@ PyAttributeDef BL_ArmatureChannel::AttributesPtr[] = {
{ NULL } //Sentinel
};
-PyObject* BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
bPoseChannel* channel = self->m_posechannel;
@@ -200,7 +200,7 @@ int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUT
return PY_SET_ATTR_FAIL;
}
-PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
bPoseChannel* pchan = static_cast<bPoseChannel*>(self_v);
// decompose the pose matrix in euler rotation
@@ -223,7 +223,7 @@ PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const str
}
// remove the rest pose to get the joint movement
transpose_m3(rest_mat);
- mul_m3_m3m3(joint_mat, rest_mat, pose_mat);
+ mul_m3_m3m3(joint_mat, rest_mat, pose_mat);
joints[0] = joints[1] = joints[2] = 0.f;
// returns a 3 element list that gives corresponding joint
int flag = 0;
@@ -458,7 +458,7 @@ PyObject *BL_ArmatureBone::py_bone_get_children(void *self, const struct KX_PYAT
for (child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next)
count++;
- PyObject* childrenlist = PyList_New(count);
+ PyObject *childrenlist = PyList_New(count);
for (count = 0, child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next, ++count)
PyList_SET_ITEM(childrenlist,count,NewProxyPlus_Ext(NULL,&Type,child,false));
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.h b/source/gameengine/Converter/BL_ArmatureChannel.h
index cd38ee2d531..b764d32e8a7 100644
--- a/source/gameengine/Converter/BL_ArmatureChannel.h
+++ b/source/gameengine/Converter/BL_ArmatureChannel.h
@@ -62,11 +62,11 @@ public:
#ifdef WITH_PYTHON
// Python access
- virtual PyObject* py_repr(void);
+ virtual PyObject *py_repr(void);
- static PyObject* py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int py_attr_setattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- static PyObject* py_attr_get_joint_rotation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *py_attr_get_joint_rotation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int py_attr_set_joint_rotation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif // WITH_PYTHON
};
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
index 7939d6e9235..169205d79e7 100644
--- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
@@ -61,7 +61,7 @@ PyTypeObject BL_ArmatureConstraint::Type = {
py_base_new
};
-PyObject* BL_ArmatureConstraint::py_repr(void)
+PyObject *BL_ArmatureConstraint::py_repr(void)
{
return PyUnicode_FromString(m_name);
}
@@ -267,8 +267,8 @@ PyMethodDef BL_ArmatureConstraint::Methods[] = {
PyAttributeDef BL_ArmatureConstraint::Attributes[] = {
// Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
- KX_PYATTRIBUTE_RO_FUNCTION("type",BL_ArmatureConstraint,py_attr_getattr),
- KX_PYATTRIBUTE_RO_FUNCTION("name",BL_ArmatureConstraint,py_attr_getattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("type",BL_ArmatureConstraint,py_attr_getattr),
+ KX_PYATTRIBUTE_RO_FUNCTION("name",BL_ArmatureConstraint,py_attr_getattr),
KX_PYATTRIBUTE_RW_FUNCTION("enforce",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
KX_PYATTRIBUTE_RW_FUNCTION("headtail",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
KX_PYATTRIBUTE_RO_FUNCTION("lin_error",BL_ArmatureConstraint,py_attr_getattr),
@@ -286,7 +286,7 @@ PyAttributeDef BL_ArmatureConstraint::Attributes[] = {
};
-PyObject* BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ArmatureConstraint* self= static_cast<BL_ArmatureConstraint*>(self_v);
bConstraint* constraint = self->m_constraint;
@@ -312,12 +312,12 @@ PyObject* BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_P
case BCA_ROTERROR:
return PyFloat_FromDouble(constraint->rot_error);
case BCA_TARGET:
- if (!self->m_target)
+ if (!self->m_target)
Py_RETURN_NONE;
else
return self->m_target->GetProxy();
case BCA_SUBTARGET:
- if (!self->m_subtarget)
+ if (!self->m_subtarget)
Py_RETURN_NONE;
else
return self->m_subtarget->GetProxy();
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.h b/source/gameengine/Converter/BL_ArmatureConstraint.h
index 0d79bb1cfa7..579153a2e79 100644
--- a/source/gameengine/Converter/BL_ArmatureConstraint.h
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.h
@@ -115,9 +115,9 @@ public:
#ifdef WITH_PYTHON
// Python access
- virtual PyObject* py_repr(void);
+ virtual PyObject *py_repr(void);
- static PyObject* py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int py_attr_setattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif // WITH_PYTHON
};
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 7174a563efa..da73d7a762a 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -430,7 +430,7 @@ void BL_ArmatureObject::ProcessReplica()
m_pose = NULL;
m_framePose = NULL;
- game_copy_pose(&m_pose, pose, 1);
+ game_copy_pose(&m_pose, pose, 1);
}
void BL_ArmatureObject::ReParentLogic()
@@ -521,7 +521,7 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority,
SetPose(m_framePose);
if (m_activeAct && (m_activeAct!=act))
/* Reset the blend timer since this new action cancels the old one */
- m_activeAct->SetBlendTime(0.0);
+ m_activeAct->SetBlendTime(0.0);
}
m_activeAct = act;
m_activePriority = priority;
@@ -648,12 +648,12 @@ PyAttributeDef BL_ArmatureObject::Attributes[] = {
{NULL} //Sentinel
};
-PyObject* BL_ArmatureObject::pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ArmatureObject::pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
return KX_PythonSeq_CreatePyObject((static_cast<BL_ArmatureObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONSTRAINTS);
}
-PyObject* BL_ArmatureObject::pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ArmatureObject::pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ArmatureObject* self = static_cast<BL_ArmatureObject*>(self_v);
self->LoadChannels(); // make sure we have the channels
diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h
index 6274e770409..4e7dc3df2f3 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.h
+++ b/source/gameengine/Converter/BL_ArmatureObject.h
@@ -116,8 +116,8 @@ public:
#ifdef WITH_PYTHON
// PYTHON
- static PyObject* pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
KX_PYMETHOD_DOC_NOARGS(BL_ArmatureObject, update);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 84ad12477d0..6ffdea9f90e 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -216,7 +216,7 @@ static std::map<int, SCA_IInputDevice::KX_EnumInputs> create_translate_table()
// SYSTEM
-#if 0
+#if 0
/* **** XXX **** */
m[KEYBD ] = SCA_IInputDevice::KX_KEYBD;
m[RAWKEYBD ] = SCA_IInputDevice::KX_RAWKEYBD;
@@ -229,7 +229,7 @@ static std::map<int, SCA_IInputDevice::KX_EnumInputs> create_translate_table()
m[WINQUIT ] = SCA_IInputDevice::KX_WINQUIT;
m[Q_FIRSTTIME ] = SCA_IInputDevice::KX_Q_FIRSTTIME;
/* **** XXX **** */
-#endif
+#endif
// standard keyboard
@@ -447,7 +447,7 @@ static void GetRGB(short type,
else { // backup white
c0 = KX_rgbaint2uint_new(color);
c1 = KX_rgbaint2uint_new(color);
- c2 = KX_rgbaint2uint_new(color);
+ c2 = KX_rgbaint2uint_new(color);
if (mface->v4)
c3 = KX_rgbaint2uint_new( color );
}
@@ -469,7 +469,7 @@ static void GetRGB(short type,
}
c0 = KX_rgbaint2uint_new(color);
c1 = KX_rgbaint2uint_new(color);
- c2 = KX_rgbaint2uint_new(color);
+ c2 = KX_rgbaint2uint_new(color);
if (mface->v4)
c3 = KX_rgbaint2uint_new(color);
} break;
@@ -478,7 +478,7 @@ static void GetRGB(short type,
{
c0 = KX_rgbaint2uint_new(color);
c1 = KX_rgbaint2uint_new(color);
- c2 = KX_rgbaint2uint_new(color);
+ c2 = KX_rgbaint2uint_new(color);
if (mface->v4)
c3 = KX_rgbaint2uint_new(color);
} break;
@@ -491,7 +491,7 @@ typedef struct MTF_localLayer {
} MTF_localLayer;
// ------------------------------------
-bool ConvertMaterial(
+static bool ConvertMaterial(
BL_Material *material,
Material *mat,
MTFace* tface,
@@ -1150,7 +1150,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
rgb0 = KX_rgbaint2uint_new(color);
rgb1 = KX_rgbaint2uint_new(color);
- rgb2 = KX_rgbaint2uint_new(color);
+ rgb2 = KX_rgbaint2uint_new(color);
if (mface->v4)
rgb3 = KX_rgbaint2uint_new(color);
@@ -1535,14 +1535,14 @@ static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, floa
//////////////////////////////////////////////////////
-void BL_CreateGraphicObjectNew(KX_GameObject* gameobj,
- const MT_Point3& localAabbMin,
- const MT_Point3& localAabbMax,
- KX_Scene* kxscene,
- bool isActive,
- e_PhysicsEngine physics_engine)
+static void BL_CreateGraphicObjectNew(KX_GameObject* gameobj,
+ const MT_Point3& localAabbMin,
+ const MT_Point3& localAabbMax,
+ KX_Scene* kxscene,
+ bool isActive,
+ e_PhysicsEngine physics_engine)
{
- if (gameobj->GetMeshCount() > 0)
+ if (gameobj->GetMeshCount() > 0)
{
switch (physics_engine)
{
@@ -1574,16 +1574,16 @@ void BL_CreateGraphicObjectNew(KX_GameObject* gameobj,
}
}
-void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
- struct Object* blenderobject,
- RAS_MeshObject* meshobj,
- KX_Scene* kxscene,
- int activeLayerBitInfo,
- e_PhysicsEngine physics_engine,
- KX_BlenderSceneConverter *converter,
- bool processCompoundChildren
- )
-
+static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
+ struct Object* blenderobject,
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ int activeLayerBitInfo,
+ e_PhysicsEngine physics_engine,
+ KX_BlenderSceneConverter *converter,
+ bool processCompoundChildren
+ )
+
{
//SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/
//int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0);
@@ -1694,7 +1694,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
objprop.m_soft_numclusteriterations= blenderobject->bsoft->numclusteriterations; /* number of iterations to refine collision clusters*/
//objprop.m_soft_welding = blenderobject->bsoft->welding; /* welding */
/* disable welding: it doesn't bring any additional stability and it breaks the relation between soft body collision shape and graphic mesh */
- objprop.m_soft_welding = 0.f;
+ objprop.m_soft_welding = 0.f;
objprop.m_margin = blenderobject->bsoft->margin;
objprop.m_contactProcessingThreshold = 0.f;
} else
@@ -2086,7 +2086,7 @@ struct parentChildLink {
#include "DNA_constraint_types.h"
//XXX #include "BIF_editconstraint.h"
-bPoseChannel *get_active_posechannel2 (Object *ob)
+static bPoseChannel *get_active_posechannel2 (Object *ob)
{
bArmature *arm= (bArmature*)ob->data;
bPoseChannel *pchan;
@@ -2100,7 +2100,7 @@ bPoseChannel *get_active_posechannel2 (Object *ob)
return NULL;
}
-ListBase *get_active_constraints2(Object *ob)
+static ListBase *get_active_constraints2(Object *ob)
{
if (!ob)
return NULL;
@@ -2119,8 +2119,7 @@ ListBase *get_active_constraints2(Object *ob)
return NULL;
}
-
-void RBJconstraints(Object *ob)//not used
+static void UNUSED_FUNCTION(RBJconstraints)(Object *ob)//not used
{
ListBase *conlist;
bConstraint *curcon;
@@ -2141,7 +2140,8 @@ void RBJconstraints(Object *ob)//not used
#include "KX_IPhysicsController.h"
#include "PHY_DynamicTypes.h"
-KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc) {//not used
+#if 0 /* UNUSED */
+static KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc) {//not used
for (int j=0;j<sumolist->GetCount();j++)
{
@@ -2151,10 +2151,10 @@ KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc) {//not used
}
return 0;
-
}
+#endif
-KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist)
+static KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist)
{
for (int j=0;j<sumolist->GetCount();j++)
@@ -2617,7 +2617,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
KX_SlowParentRelation * slow_parent_relation = KX_SlowParentRelation::New(blenderchild->sf);
pcit->m_gamechildnode->SetParentRelation(slow_parent_relation);
break;
- }
+ }
case PARBONE:
{
// parent this to a bone
@@ -2741,7 +2741,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
}
- }
+ }
// create physics joints
for (i=0;i<sumolist->GetCount();i++)
@@ -2825,7 +2825,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
kxscene->GetPhysicsEnvironment()->setConstraintParam(constraintId,dof,1,-1);
}
dofbit<<=1;
- }
+ }
}
else if (dat->type == PHY_LINEHINGE_CONSTRAINT)
{
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h
index 61477fb1cac..d14160d39a3 100644
--- a/source/gameengine/Converter/BL_DeformableGameObject.h
+++ b/source/gameengine/Converter/BL_DeformableGameObject.h
@@ -89,7 +89,7 @@ public:
public:
-protected:
+protected:
RAS_Deformer *m_pDeformer;
diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp
index c9371b9df50..b8002d05f18 100644
--- a/source/gameengine/Converter/BL_MeshDeformer.cpp
+++ b/source/gameengine/Converter/BL_MeshDeformer.cpp
@@ -84,7 +84,7 @@ bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*)
}
BL_MeshDeformer::~BL_MeshDeformer()
-{
+{
if (m_transverts)
delete [] m_transverts;
if (m_transnors)
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp
index c1c94c25108..eafed8497ba 100644
--- a/source/gameengine/Converter/BL_ModifierDeformer.cpp
+++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp
@@ -175,7 +175,7 @@ bool BL_ModifierDeformer::Update(void)
* It may not be the case here because of replace mesh actuator */
Mesh *oldmesh = (Mesh*)blendobj->data;
blendobj->data = m_bmesh;
- /* execute the modifiers */
+ /* execute the modifiers */
DerivedMesh *dm = mesh_create_derived_no_virtual(m_scene, blendobj, m_transverts, CD_MASK_MESH);
/* restore object data */
blendobj->data = oldmesh;
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.h b/source/gameengine/Converter/BL_ModifierDeformer.h
index b4827b1bee4..5d0c3bc1317 100644
--- a/source/gameengine/Converter/BL_ModifierDeformer.h
+++ b/source/gameengine/Converter/BL_ModifierDeformer.h
@@ -54,7 +54,7 @@ public:
Scene *scene,
Object *bmeshobj,
RAS_MeshObject *mesh)
- :
+ :
BL_ShapeDeformer(gameobj,bmeshobj, mesh),
m_lastModifierUpdate(-1),
m_scene(scene),
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
index c339e10f673..8325e80db78 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
@@ -83,7 +83,7 @@ BL_ShapeActionActuator::BL_ShapeActionActuator(SCA_IObject* gameobj,
m_playtype(playtype),
m_priority(priority),
m_action(action),
- m_framepropname(framepropname),
+ m_framepropname(framepropname),
m_propname(propname)
{
m_idptr = new PointerRNA();
@@ -526,7 +526,7 @@ PyAttributeDef BL_ShapeActionActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v);
return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp
index b93d731c5e6..f8941e16ed2 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.cpp
+++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp
@@ -173,7 +173,7 @@ bool BL_ShapeDeformer::Update(void)
/* store verts locally */
VerifyStorage();
- do_rel_key(0, m_bmesh->totvert, m_bmesh->totvert, (char *)(float *)m_transverts, m_bmesh->key, NULL, 0); /* last arg is ignored */
+ BKE_key_evaluate_relative(0, m_bmesh->totvert, m_bmesh->totvert, (char *)(float *)m_transverts, m_bmesh->key, NULL, 0); /* last arg is ignored */
m_bDynamic = true;
}
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h
index efc1b546666..ecf501d9a91 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.h
+++ b/source/gameengine/Converter/BL_ShapeDeformer.h
@@ -73,7 +73,7 @@ public:
};
protected:
- bool m_useShapeDrivers;
+ bool m_useShapeDrivers;
double m_lastShapeUpdate;
struct Key* m_key;
diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp
index 47cba81798d..c175c1e3b7b 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.cpp
+++ b/source/gameengine/Converter/BL_SkinDeformer.cpp
@@ -67,7 +67,7 @@ extern "C"{
#define __NLA_DEFNORMALS
//#undef __NLA_DEFNORMALS
-short get_deformflags(struct Object *bmeshobj)
+static short get_deformflags(struct Object *bmeshobj)
{
short flags = ARM_DEF_VGROUP;
@@ -85,9 +85,9 @@ short get_deformflags(struct Object *bmeshobj)
}
BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj,
- struct Object *bmeshobj,
- class RAS_MeshObject *mesh,
- BL_ArmatureObject* arma)
+ struct Object *bmeshobj,
+ class RAS_MeshObject *mesh,
+ BL_ArmatureObject* arma)
: //
BL_MeshDeformer(gameobj, bmeshobj, mesh),
m_armobj(arma),
@@ -110,7 +110,7 @@ BL_SkinDeformer::BL_SkinDeformer(
class RAS_MeshObject *mesh,
bool release_object,
bool recalc_normal,
- BL_ArmatureObject* arma) :
+ BL_ArmatureObject* arma) :
BL_MeshDeformer(gameobj, bmeshobj_old, mesh),
m_armobj(arma),
m_lastArmaUpdate(-1),
@@ -327,7 +327,7 @@ void BL_SkinDeformer::BGEDeformVerts()
bool BL_SkinDeformer::UpdateInternal(bool shape_applied)
{
/* See if the armature has been updated for this frame */
- if (PoseUpdated()) {
+ if (PoseUpdated()) {
if (!shape_applied) {
/* store verts locally */
diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp
index fc3b75c49ad..25da8155867 100644
--- a/source/gameengine/Converter/BlenderWorldInfo.cpp
+++ b/source/gameengine/Converter/BlenderWorldInfo.cpp
@@ -199,7 +199,7 @@ void BlenderWorldInfo::setBackColor(float r, float g, float b)
m_backgroundcolor[2] = b;
}
- void
+ void
BlenderWorldInfo::setMistStart(
float d
) {
@@ -215,7 +215,7 @@ BlenderWorldInfo::setMistDistance(
}
- void
+ void
BlenderWorldInfo::setMistColorRed(
float d
) {
@@ -231,7 +231,7 @@ BlenderWorldInfo::setMistColorGreen(
}
- void
+ void
BlenderWorldInfo::setMistColorBlue(
float d
) {
diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h
index e00eb99e73f..2cf706a3089 100644
--- a/source/gameengine/Converter/BlenderWorldInfo.h
+++ b/source/gameengine/Converter/BlenderWorldInfo.h
@@ -73,27 +73,27 @@ public:
float g,
float b
);
- void
+ void
setMistStart(
float d
);
- void
+ void
setMistDistance(
float d
);
- void
+ void
setMistColorRed(
float d
);
- void
+ void
setMistColorGreen(
float d
);
- void
+ void
setMistColorBlue(
float d
);
diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
index f020aab4d50..72212581d4b 100644
--- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
+++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
@@ -78,5 +78,5 @@ KX_IScalarInterpolator *BL_InterpolatorList::GetScalarInterpolator(const char *r
return *i;
}
return NULL;
-}
+}
diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h
index bc5a6eeef85..980aeef7e60 100644
--- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h
+++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h
@@ -65,7 +65,7 @@ public:
BL_InterpolatorList(struct bAction *action);
~BL_InterpolatorList();
- KX_IScalarInterpolator *GetScalarInterpolator(const char *rna_path, int array_index);
+ KX_IScalarInterpolator *GetScalarInterpolator(const char *rna_path, int array_index);
#ifdef WITH_CXX_GUARDEDALLOC
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 1c3352454a2..9020720eaeb 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -160,7 +160,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
while (itmat != m_materials.end()) {
delete (*itmat).second;
itmat++;
- }
+ }
vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin();
@@ -201,7 +201,7 @@ bool KX_BlenderSceneConverter::TryAndLoadNewFile()
// if not, clear the newfilename
else
{
- m_newfilename = "";
+ m_newfilename = "";
}
*/
return result;
@@ -335,7 +335,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
ccdPhysEnv->setDebugMode(btIDebugDraw::DBG_DrawWireframe|btIDebugDraw::DBG_DrawAabb|btIDebugDraw::DBG_DrawContactPoints|btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_DrawConstraintLimits|btIDebugDraw::DBG_DrawConstraints);
//todo: get a button in blender ?
- //disable / enable debug drawing (contact points, aabb's etc)
+ //disable / enable debug drawing (contact points, aabb's etc)
//ccdPhysEnv->setDebugMode(1);
destinationscene->SetPhysicsEnvironment(ccdPhysEnv);
break;
@@ -689,7 +689,7 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo()
{
- if (addInitFromFrame) {
+ if (addInitFromFrame) {
KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
if (numScenes>=0) {
@@ -704,7 +704,7 @@ void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo()
if (blenderobject->type==OB_ARMATURE)
continue;
float eu[3];
- mat4_to_eul(eu,blenderobject->obmat);
+ mat4_to_eul(eu,blenderobject->obmat);
MT_Point3 pos = MT_Point3(
blenderobject->obmat[3][0],
blenderobject->obmat[3][1],
@@ -779,8 +779,8 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
//const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
- float eulerAngles[3];
- float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f};
+ float eulerAngles[3];
+ float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f};
float tmat[3][3];
// XXX animato
@@ -984,7 +984,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
}
main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain");
- BKE_reports_init(&reports, RPT_STORE);
+ BKE_reports_init(&reports, RPT_STORE);
load_datablocks(main_newlib, bpy_openlib, path, idcode);
@@ -1000,11 +1000,11 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
BLO_blendhandle_close(bpy_openlib);
BKE_reports_clear(&reports);
- /* done linking */
+ /* done linking */
/* needed for lookups*/
GetMainDynamic().push_back(main_newlib);
- strncpy(main_newlib->name, path, sizeof(main_newlib->name));
+ strncpy(main_newlib->name, path, sizeof(main_newlib->name));
if (idcode==ID_ME) {
@@ -1028,7 +1028,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action);
}
}
- else if (idcode==ID_SCE) {
+ else if (idcode==ID_SCE) {
/* Merge all new linked in scene into the existing one */
ID *scene;
for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
@@ -1117,7 +1117,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
{
RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i);
if (meshobj && IS_TAGGED(meshobj->GetMesh()))
- {
+ {
STR_HashedString mn = meshobj->GetName();
mapStringToMeshes.remove(mn);
m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh()));
@@ -1255,7 +1255,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
RAS_IPolyMaterial *mat= (*polymit).second;
Material *bmat= NULL;
- /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
+ /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject *)? - Campbell */
if (mat->GetFlag() & RAS_BLENDERMAT) {
KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
bmat= bl_mat->GetBlenderMaterial();
@@ -1280,7 +1280,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
RAS_IPolyMaterial *mat= (*polymit).second;
Material *bmat= NULL;
- /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
+ /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject *)? - Campbell */
if (mat->GetFlag() & RAS_BLENDERMAT) {
KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
bmat= bl_mat->GetBlenderMaterial();
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 9caa6bbf579..287be3b8359 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -903,7 +903,7 @@ void BL_ConvertActuators(const char* maggiename,
modeArg = SCA_RandomActuator::KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL;
break;
default:
- ; /* error */
+ ; /* error */
}
tmprandomact = new SCA_RandomActuator(gameobj,
seedArg,
diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp
index 81778928c2e..3a6aa228957 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.cpp
+++ b/source/gameengine/Converter/KX_ConvertControllers.cpp
@@ -69,7 +69,7 @@
static void
LinkControllerToActuators(
SCA_IController *game_controller,
- bController* bcontr,
+ bController* bcontr,
SCA_LogicManager* logicmgr,
KX_BlenderSceneConverter* converter
) {
diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp
index faa7780bac0..a63f4c38fb6 100644
--- a/source/gameengine/Converter/KX_ConvertProperties.cpp
+++ b/source/gameengine/Converter/KX_ConvertProperties.cpp
@@ -67,7 +67,7 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan
{
bProperty* prop = (bProperty*)object->prop.first;
- CValue* propval;
+ CValue* propval;
bool show_debug_info;
while(prop)
{
@@ -177,7 +177,7 @@ void BL_ConvertTextProperty(Object* object, KX_FontObject* fontobj,SCA_TimeEvent
{
CValue* tprop = fontobj->GetProperty("Text");
if (!tprop) return;
- bProperty* prop = get_ob_property(object, "Text");
+ bProperty* prop = BKE_bproperty_object_get(object, "Text");
if (!prop) return;
Curve *curve = static_cast<Curve *>(object->data);
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index 9f155a6ebc3..3d4f3ae08f2 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -183,7 +183,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
if (gameobj->GetPhysicsController())
- {
+ {
gamesensor = new KX_TouchSensor(eventmgr,
gameobj,
bFindMaterial,
@@ -209,7 +209,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
}
bool bFindMaterial = true;
if (gameobj->GetPhysicsController())
- {
+ {
gamesensor = new KX_TouchSensor(eventmgr,
gameobj,
bFindMaterial,
@@ -224,7 +224,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*)
logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR);
if (eventmgr) {
- bMessageSensor* msgSens = (bMessageSensor*) sens->data;
+ bMessageSensor* msgSens = (bMessageSensor*) sens->data;
/* Get our NetworkScene */
NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene();
@@ -247,7 +247,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
if (eventmgr)
{
- STR_String nearpropertyname;
+ STR_String nearpropertyname;
bNearSensor* blendernearsensor = (bNearSensor*)sens->data;
if (blendernearsensor->name)
{
@@ -311,7 +311,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
}
case SENS_MOUSE:
{
- int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF;
+ int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF;
int trackfocus = 0;
bMouseSensor *bmouse = (bMouseSensor *)sens->data;
@@ -639,7 +639,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
gamesensor->SetInvert(invert);
gamesensor->SetLevel(level);
gamesensor->SetTap(tap);
- gamesensor->SetName(sens->name);
+ gamesensor->SetName(sens->name);
gameobj->AddSensor(gamesensor);
diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp
index 309959b4324..12f88251805 100644
--- a/source/gameengine/Converter/KX_IpoConvert.cpp
+++ b/source/gameengine/Converter/KX_IpoConvert.cpp
@@ -76,12 +76,12 @@ static BL_InterpolatorList *GetAdtList(struct bAction *for_act, KX_BlenderSceneC
{
BL_InterpolatorList *adtList= converter->FindInterpolatorList(for_act);
- if (!adtList) {
+ if (!adtList) {
adtList = new BL_InterpolatorList(for_act);
converter->RegisterInterpolatorList(adtList, for_act);
}
- return adtList;
+ return adtList;
}
SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter)
@@ -441,7 +441,7 @@ static void ConvertMaterialIpos(
}
interpolator= new KX_ScalarInterpolator(&ipocontr->m_ref, sinterp);
ipocontr->AddInterpolator(interpolator);
- }
+ }
if ((sinterp = adtList->GetScalarInterpolator("emit", 0))) {
if (!ipocontr) {
@@ -452,7 +452,7 @@ static void ConvertMaterialIpos(
interpolator= new KX_ScalarInterpolator(&ipocontr->m_emit, sinterp);
ipocontr->AddInterpolator(interpolator);
}
- }
+ }
}
void BL_ConvertMaterialIpos(
diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp
index 40997a25be1..e640923129a 100644
--- a/source/gameengine/Expressions/BoolValue.cpp
+++ b/source/gameengine/Expressions/BoolValue.cpp
@@ -205,7 +205,7 @@ CValue* CBoolValue::GetReplica()
}
#ifdef WITH_PYTHON
-PyObject* CBoolValue::ConvertValueToPython()
+PyObject *CBoolValue::ConvertValueToPython()
{
return PyBool_FromLong(m_bool != 0);
}
diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/BoolValue.h
index 09e931ea661..64ac0266baf 100644
--- a/source/gameengine/Expressions/BoolValue.h
+++ b/source/gameengine/Expressions/BoolValue.h
@@ -29,7 +29,7 @@
class CBoolValue : public CPropValue
{
- //PLUGIN_DECLARE_SERIAL(CBoolValue,CValue)
+ //PLUGIN_DECLARE_SERIAL(CBoolValue,CValue)
public:
static const STR_String sTrueString;
diff --git a/source/gameengine/Expressions/EXP_C-Api.cpp b/source/gameengine/Expressions/EXP_C-Api.cpp
index 763d115a840..2822fd8f6de 100644
--- a/source/gameengine/Expressions/EXP_C-Api.cpp
+++ b/source/gameengine/Expressions/EXP_C-Api.cpp
@@ -102,8 +102,8 @@ int EXP_IsValid(EXP_ValueHandle inval)
/* assign property 'propval' to 'destinationval' */
void EXP_SetProperty(EXP_ValueHandle destinationval,
- const char* propname,
- EXP_ValueHandle propval)
+ const char *propname,
+ EXP_ValueHandle propval)
{
((CValue*) destinationval)->SetProperty(propname,(CValue*)propval);
}
diff --git a/source/gameengine/Expressions/EXP_C-Api.h b/source/gameengine/Expressions/EXP_C-Api.h
index 6be1e57481c..4d43695f9b9 100644
--- a/source/gameengine/Expressions/EXP_C-Api.h
+++ b/source/gameengine/Expressions/EXP_C-Api.h
@@ -53,7 +53,7 @@ extern void EXP_ReleaseValue(EXP_ValueHandle);
extern int EXP_IsValid(EXP_ValueHandle);
/* assign property 'propval' to 'destinationval' */
-extern void EXP_SetProperty(EXP_ValueHandle propval,EXP_ValueHandle destinationval);
+extern void EXP_SetProperty(EXP_ValueHandle destinationval, const char *propname, EXP_ValueHandle propval);
/* returns NULL if property doesn't exist */
extern EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname);
diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp
index 403338573e2..c9b59e52ee8 100644
--- a/source/gameengine/Expressions/FloatValue.cpp
+++ b/source/gameengine/Expressions/FloatValue.cpp
@@ -314,7 +314,7 @@ CValue* CFloatValue::GetReplica()
#ifdef WITH_PYTHON
-PyObject* CFloatValue::ConvertValueToPython()
+PyObject *CFloatValue::ConvertValueToPython()
{
return PyFloat_FromDouble(m_float);
}
diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp
index 58837235d30..bdf4ee4605b 100644
--- a/source/gameengine/Expressions/InputParser.cpp
+++ b/source/gameengine/Expressions/InputParser.cpp
@@ -543,7 +543,7 @@ CExpression *CParser::Ex(int i)
}
e1 = Error(errtext);
- break;
+ break;
}
default:
NextSym();
@@ -573,7 +573,7 @@ CExpression* CParser::ProcessText
text = intext;
- chcount = 0;
+ chcount = 0;
if (text.Length() == 0) {
return NULL;
}
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp
index 2d427440620..12d6e258ddf 100644
--- a/source/gameengine/Expressions/IntValue.cpp
+++ b/source/gameengine/Expressions/IntValue.cpp
@@ -326,7 +326,7 @@ void CIntValue::SetValue(CValue* newval)
#ifdef WITH_PYTHON
-PyObject* CIntValue::ConvertValueToPython()
+PyObject *CIntValue::ConvertValueToPython()
{
if ((m_int > INT_MIN) && (m_int < INT_MAX))
return PyLong_FromSsize_t(m_int);
diff --git a/source/gameengine/Expressions/KX_HashedPtr.h b/source/gameengine/Expressions/KX_HashedPtr.h
index ffc6ff647d5..866689ed203 100644
--- a/source/gameengine/Expressions/KX_HashedPtr.h
+++ b/source/gameengine/Expressions/KX_HashedPtr.h
@@ -50,7 +50,7 @@ public:
inline friend bool operator ==( const CHashedPtr & rhs,const CHashedPtr & lhs)
{
return rhs.m_valptr == lhs.m_valptr;
- }
+ }
#ifdef WITH_CXX_GUARDEDALLOC
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
index f43625a7821..88b0a986a05 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -278,7 +278,7 @@ bool CListValue::IsModified()
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
-Py_ssize_t listvalue_bufferlen(PyObject* self)
+static Py_ssize_t listvalue_bufferlen(PyObject *self)
{
CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
if (list==NULL)
@@ -287,7 +287,7 @@ Py_ssize_t listvalue_bufferlen(PyObject* self)
return (Py_ssize_t)list->GetCount();
}
-PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index)
+static PyObject *listvalue_buffer_item(PyObject *self, Py_ssize_t index)
{
CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
CValue *cval;
@@ -309,14 +309,14 @@ PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index)
cval= list->GetValue(index);
- PyObject* pyobj = cval->ConvertValueToPython();
+ PyObject *pyobj = cval->ConvertValueToPython();
if (pyobj)
return pyobj;
else
return cval->GetProxy();
}
-PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex)
+static PyObject *listvalue_mapping_subscript(PyObject *self, PyObject *pyindex)
{
CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
if (list==NULL) {
@@ -328,7 +328,7 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex)
{
CValue *item = ((CListValue*) list)->FindValue(_PyUnicode_AsString(pyindex));
if (item) {
- PyObject* pyobj = item->ConvertValueToPython();
+ PyObject *pyobj = item->ConvertValueToPython();
if (pyobj)
return pyobj;
else
@@ -348,7 +348,7 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex)
/* just slice it into a python list... */
-PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihigh)
+static PyObject *listvalue_buffer_slice(PyObject *self,Py_ssize_t ilow, Py_ssize_t ihigh)
{
CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
if (list==NULL) {
@@ -374,17 +374,17 @@ PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihig
for (i = ilow, j = 0; i < ihigh; i++, j++)
{
- PyObject* pyobj = list->GetValue(i)->ConvertValueToPython();
+ PyObject *pyobj = list->GetValue(i)->ConvertValueToPython();
if (!pyobj)
pyobj = list->GetValue(i)->GetProxy();
PyList_SET_ITEM(newlist, i, pyobj);
- }
+ }
return newlist;
}
/* clist + list, return a list that python owns */
-static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other)
+static PyObject *listvalue_buffer_concat(PyObject *self, PyObject *other)
{
CListValue *listval= static_cast<CListValue *>(BGE_PROXY_REF(self));
Py_ssize_t i, numitems, numitems_orig;
@@ -560,7 +560,7 @@ PyAttributeDef CListValue::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* CListValue::Pyappend(PyObject* value)
+PyObject *CListValue::Pyappend(PyObject *value)
{
CValue* objval = ConvertPythonToValue(value, "CList.append(i): CValueList, ");
@@ -577,15 +577,15 @@ PyObject* CListValue::Pyappend(PyObject* value)
Py_RETURN_NONE;
}
-PyObject* CListValue::Pyreverse()
+PyObject *CListValue::Pyreverse()
{
std::reverse(m_pValueArray.begin(),m_pValueArray.end());
Py_RETURN_NONE;
}
-PyObject* CListValue::Pyindex(PyObject *value)
+PyObject *CListValue::Pyindex(PyObject *value)
{
- PyObject* result = NULL;
+ PyObject *result = NULL;
CValue* checkobj = ConvertPythonToValue(value, "val = cList[i]: CValueList, ");
if (checkobj==NULL)
@@ -612,7 +612,7 @@ PyObject* CListValue::Pyindex(PyObject *value)
-PyObject* CListValue::Pycount(PyObject* value)
+PyObject *CListValue::Pycount(PyObject *value)
{
int numfound = 0;
@@ -638,17 +638,17 @@ PyObject* CListValue::Pycount(PyObject* value)
}
/* Matches python dict.get(key, [default]) */
-PyObject* CListValue::Pyget(PyObject *args)
+PyObject *CListValue::Pyget(PyObject *args)
{
char *key;
- PyObject* def = Py_None;
+ PyObject *def = Py_None;
if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
return NULL;
CValue *item = FindValue((const char *)key);
if (item) {
- PyObject* pyobj = item->ConvertValueToPython();
+ PyObject *pyobj = item->ConvertValueToPython();
if (pyobj)
return pyobj;
else
@@ -659,7 +659,7 @@ PyObject* CListValue::Pyget(PyObject *args)
}
-PyObject* CListValue::Pyfrom_id(PyObject* value)
+PyObject *CListValue::Pyfrom_id(PyObject *value)
{
uintptr_t id= (uintptr_t)PyLong_AsVoidPtr(value);
diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h
index 4d104a4bd3a..20005088310 100644
--- a/source/gameengine/Expressions/ListValue.h
+++ b/source/gameengine/Expressions/ListValue.h
@@ -64,7 +64,7 @@ public:
bool CheckEqual(CValue* first,CValue* second);
#ifdef WITH_PYTHON
- virtual PyObject* py_repr(void) {
+ virtual PyObject *py_repr(void) {
PyObject *py_proxy= this->GetProxy();
PyObject *py_list= PySequence_List(py_proxy);
PyObject *py_string= PyObject_Repr(py_list);
diff --git a/source/gameengine/Expressions/Operator2Expr.cpp b/source/gameengine/Expressions/Operator2Expr.cpp
index 2224b0ff5e8..d0240b5ec75 100644
--- a/source/gameengine/Expressions/Operator2Expr.cpp
+++ b/source/gameengine/Expressions/Operator2Expr.cpp
@@ -102,7 +102,7 @@ and m_rhs
m_cached_calculate = ffleft->Calc(m_op,ffright);
- //if (m_cached_calculate)
+ //if (m_cached_calculate)
// m_cached_calculate->Action(CValue::SETOWNEREXPR,&CVoidValue(this,false,CValue::STACKVALUE));
ffleft->Release();
@@ -163,7 +163,7 @@ bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude)
}
}
- return inside;
+ return inside;
}
@@ -241,7 +241,7 @@ CExpression* COperator2Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlink
if (m_rhs)
return Release(m_rhs->AddRef());
-/
+/
*/
return Release();
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index a35cb4f9f69..6bb2f039b5c 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -145,7 +145,7 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent
}
-PyObject * PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyTypeObject *base_type;
PyObjectPlus_Proxy *base = NULL;
@@ -270,7 +270,7 @@ PyAttributeDef PyObjectPlus::Attributes[] = {
-PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
return PyBool_FromLong(self_v ? 0:1);
}
@@ -303,7 +303,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
ptr += attrdef->m_offset;
if (attrdef->m_length > 1)
{
- PyObject* resultlist = PyList_New(attrdef->m_length);
+ PyObject *resultlist = PyList_New(attrdef->m_length);
for (unsigned int i=0; i<attrdef->m_length; i++)
{
switch (attrdef->m_type) {
@@ -420,7 +420,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
#ifdef USE_MATHUTILS
return Vector_CreatePyObject(val, attrdef->m_imax, Py_NEW, NULL);
#else
- PyObject* resultlist = PyList_New(attrdef->m_imax);
+ PyObject *resultlist = PyList_New(attrdef->m_imax);
for (unsigned int i=0; i<attrdef->m_imax; i++)
{
PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(val[i]));
@@ -437,10 +437,10 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
#ifdef USE_MATHUTILS
return Matrix_CreatePyObject(val, attrdef->m_imin, attrdef->m_imax, Py_WRAP, NULL);
#else
- PyObject* collist = PyList_New(attrdef->m_imin);
+ PyObject *collist = PyList_New(attrdef->m_imin);
for (unsigned int i=0; i<attrdef->m_imin; i++)
{
- PyObject* col = PyList_New(attrdef->m_imax);
+ PyObject *col = PyList_New(attrdef->m_imax);
for (unsigned int j=0; j<attrdef->m_imax; j++)
{
PyList_SET_ITEM(col,j,PyFloat_FromDouble(val[j]));
@@ -460,7 +460,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
val->getValue(fval);
return Vector_CreatePyObject(fval, 3, Py_NEW, NULL);
#else
- PyObject* resultlist = PyList_New(3);
+ PyObject *resultlist = PyList_New(3);
for (unsigned int i=0; i<3; i++)
{
PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i]));
@@ -1100,7 +1100,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
}
if (undoBuffer)
free(undoBuffer);
- return 0;
+ return 0;
}
@@ -1139,7 +1139,7 @@ PyObject *PyObjectPlus::NewProxyPlus_Ext(PyObjectPlus *self, PyTypeObject *tp, v
if (!self)
{
// in case of proxy without reference to game object
- PyObject* proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp);
+ PyObject *proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp);
BGE_PROXY_PYREF(proxy) = false;
BGE_PROXY_PYOWNS(proxy) = py_owns;
BGE_PROXY_REF(proxy) = NULL;
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index f74ed7db8f7..005bf2f6cb2 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -190,9 +190,9 @@ public: \
* macro is one that also requires a documentation string
*/
#define KX_PYMETHOD(class_name, method_name) \
- PyObject* Py##method_name(PyObject* args, PyObject* kwds); \
- static PyObject* \
- sPy##method_name(PyObject* self, PyObject* args, PyObject* kwds) { \
+ PyObject *Py##method_name(PyObject *args, PyObject *kwds); \
+ static PyObject * \
+ sPy##method_name(PyObject *self, PyObject *args, PyObject *kwds) { \
if(BGE_PROXY_REF(self)==NULL) { \
PyErr_SetString(PyExc_RuntimeError, \
#class_name "." #method_name "() - " \
@@ -203,9 +203,9 @@ public: \
} \
#define KX_PYMETHOD_VARARGS(class_name, method_name) \
- PyObject* Py##method_name(PyObject* args); \
+ PyObject *Py##method_name(PyObject *args); \
static PyObject* \
- sPy##method_name(PyObject* self, PyObject* args) { \
+ sPy##method_name(PyObject *self, PyObject *args) { \
if(BGE_PROXY_REF(self)==NULL) { \
PyErr_SetString(PyExc_RuntimeError, \
#class_name "." #method_name "() - " \
@@ -215,9 +215,9 @@ public: \
} \
#define KX_PYMETHOD_NOARGS(class_name, method_name) \
- PyObject* Py##method_name(); \
+ PyObject *Py##method_name(); \
static PyObject* \
- sPy##method_name(PyObject* self) { \
+ sPy##method_name(PyObject *self) { \
if(BGE_PROXY_REF(self)==NULL) { \
PyErr_SetString(PyExc_RuntimeError, \
#class_name "." #method_name "() - " \
@@ -227,9 +227,9 @@ public: \
} \
#define KX_PYMETHOD_O(class_name, method_name) \
- PyObject* Py##method_name(PyObject* value); \
+ PyObject *Py##method_name(PyObject *value); \
static PyObject* \
- sPy##method_name(PyObject* self, PyObject* value) { \
+ sPy##method_name(PyObject *self, PyObject *value) { \
if(BGE_PROXY_REF(self)==NULL) { \
PyErr_SetString(PyExc_RuntimeError, \
#class_name "." #method_name "(value) - " \
@@ -239,9 +239,9 @@ public: \
} \
#define KX_PYMETHOD_DOC(class_name, method_name) \
- PyObject* Py##method_name(PyObject* args, PyObject* kwds); \
+ PyObject *Py##method_name(PyObject *args, PyObject *kwds); \
static PyObject* \
- sPy##method_name(PyObject* self, PyObject* args, PyObject* kwds) { \
+ sPy##method_name(PyObject *self, PyObject *args, PyObject *kwds) { \
if(BGE_PROXY_REF(self)==NULL) { \
PyErr_SetString(PyExc_RuntimeError, \
#class_name "." #method_name "(...) - " \
@@ -252,9 +252,9 @@ public: \
static const char method_name##_doc[]; \
#define KX_PYMETHOD_DOC_VARARGS(class_name, method_name) \
- PyObject* Py##method_name(PyObject* args); \
+ PyObject *Py##method_name(PyObject *args); \
static PyObject* \
- sPy##method_name(PyObject* self, PyObject* args) { \
+ sPy##method_name(PyObject *self, PyObject *args) { \
if(BGE_PROXY_REF(self)==NULL) { \
PyErr_SetString(PyExc_RuntimeError, \
#class_name "." #method_name "(...) - " \
@@ -266,9 +266,9 @@ public: \
static const char method_name##_doc[]; \
#define KX_PYMETHOD_DOC_O(class_name, method_name) \
- PyObject* Py##method_name(PyObject* value); \
- static PyObject* \
- sPy##method_name(PyObject* self, PyObject* value) { \
+ PyObject *Py##method_name(PyObject *value); \
+ static PyObject * \
+ sPy##method_name(PyObject *self, PyObject *value) { \
if(BGE_PROXY_REF(self)==NULL) { \
PyErr_SetString(PyExc_RuntimeError, \
#class_name "." #method_name "(value) - " \
@@ -280,9 +280,9 @@ public: \
static const char method_name##_doc[]; \
#define KX_PYMETHOD_DOC_NOARGS(class_name, method_name) \
- PyObject* Py##method_name(); \
- static PyObject* \
- sPy##method_name(PyObject* self) { \
+ PyObject *Py##method_name(); \
+ static PyObject * \
+ sPy##method_name(PyObject *self) { \
if(BGE_PROXY_REF(self)==NULL) { \
PyErr_SetString(PyExc_RuntimeError, \
#class_name "." #method_name "() - " \
@@ -315,19 +315,19 @@ public: \
*/
#define KX_PYMETHODDEF_DOC(class_name, method_name, doc_string) \
const char class_name::method_name##_doc[] = doc_string; \
-PyObject* class_name::Py##method_name(PyObject* args, PyObject* kwds)
+PyObject *class_name::Py##method_name(PyObject *args, PyObject *kwds)
#define KX_PYMETHODDEF_DOC_VARARGS(class_name, method_name, doc_string) \
const char class_name::method_name##_doc[] = doc_string; \
-PyObject* class_name::Py##method_name(PyObject* args)
+PyObject *class_name::Py##method_name(PyObject *args)
#define KX_PYMETHODDEF_DOC_O(class_name, method_name, doc_string) \
const char class_name::method_name##_doc[] = doc_string; \
-PyObject* class_name::Py##method_name(PyObject* value)
+PyObject *class_name::Py##method_name(PyObject *value)
#define KX_PYMETHODDEF_DOC_NOARGS(class_name, method_name, doc_string) \
const char class_name::method_name##_doc[] = doc_string; \
-PyObject* class_name::Py##method_name()
+PyObject *class_name::Py##method_name()
/**
* Attribute management
@@ -354,7 +354,7 @@ enum KX_PYATTRIBUTE_ACCESS {
struct KX_PYATTRIBUTE_DEF;
typedef int (*KX_PYATTRIBUTE_CHECK_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
typedef int (*KX_PYATTRIBUTE_SET_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-typedef PyObject* (*KX_PYATTRIBUTE_GET_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+typedef PyObject *(*KX_PYATTRIBUTE_GET_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
typedef struct KX_PYATTRIBUTE_DEF {
const char *m_name; // name of the python attribute
diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h
index e37b4638a1e..bc102c6e203 100644
--- a/source/gameengine/Expressions/StringValue.h
+++ b/source/gameengine/Expressions/StringValue.h
@@ -25,7 +25,7 @@ class CStringValue : public CPropValue
{
- //PLUGIN_DECLARE_SERIAL(CStringValue,CValue)
+ //PLUGIN_DECLARE_SERIAL(CStringValue,CValue)
public:
/// Construction / destruction
CStringValue();
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index 6507cc32cf1..bcfb7e92d71 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -340,7 +340,7 @@ vector<STR_String> CValue::GetPropertyNames()
// Clear all properties
//
void CValue::ClearProperties()
-{
+{
// Check if we have any properties
if (m_pNamedPropertyArray == NULL)
return;
@@ -530,13 +530,13 @@ PyAttributeDef CValue::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef)
+PyObject *CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
CValue * self = static_cast<CValue *> (self_v);
return PyUnicode_From_STR_String(self->GetName());
}
-CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
+CValue* CValue::ConvertPythonToValue(PyObject *pyobj, const char *error_prefix)
{
CValue* vallie = NULL;
@@ -551,7 +551,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
Py_ssize_t numitems = PyList_GET_SIZE(pyobj);
for (i=0;i<numitems;i++)
{
- PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
+ PyObject *listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
CValue* listitemval = ConvertPythonToValue(listitem, error_prefix);
if (listitemval)
{
@@ -597,7 +597,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
}
-PyObject* CValue::ConvertKeysToPython(void)
+PyObject *CValue::ConvertKeysToPython(void)
{
if (m_pNamedPropertyArray)
{
@@ -636,5 +636,5 @@ void CValue::SetColorOperator(VALUE_OPERATOR op)
void CValue::SetValue(CValue* newval)
{
// no one should get here
- assertd(newval->GetNumber() == 10121969);
+ assertd(newval->GetNumber() == 10121969);
}
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index e3b52e80ba6..e0c4daeccd0 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -218,21 +218,21 @@ public:
CValue();
#ifdef WITH_PYTHON
- //static PyObject* PyMake(PyObject*,PyObject*);
+ //static PyObject *PyMake(PyObject *, PyObject *);
virtual PyObject *py_repr(void)
{
return PyUnicode_From_STR_String(GetText());
}
- virtual PyObject* ConvertValueToPython() {
+ virtual PyObject *ConvertValueToPython() {
return NULL;
}
- virtual CValue* ConvertPythonToValue(PyObject* pyobj, const char *error_prefix);
+ virtual CValue *ConvertPythonToValue(PyObject *pyobj, const char *error_prefix);
- static PyObject * pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
+ static PyObject *pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
- virtual PyObject* ConvertKeysToPython( void );
+ virtual PyObject *ConvertKeysToPython( void );
#endif // WITH_PYTHON
@@ -250,13 +250,13 @@ public:
};
/// Reference Counting
- int GetRefCount()
+ int GetRefCount()
{
return m_refcount;
}
// Add a reference to this value
- CValue* AddRef()
+ CValue *AddRef()
{
// Increase global reference count, used to see at the end of the program
// if all CValue-derived classes have been dereferenced to 0
@@ -269,7 +269,7 @@ public:
}
// Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
- int Release()
+ int Release()
{
// Decrease global reference count, used to see at the end of the program
// if all CValue-derived classes have been dereferenced to 0
@@ -354,16 +354,16 @@ public:
virtual void SetCustomFlag2(bool bCustomFlag) { m_ValFlags.CustomFlag2 = bCustomFlag;}
virtual bool IsCustomFlag2() { return m_ValFlags.CustomFlag2;}
-protected:
+protected:
virtual void DisableRefCount(); // Disable reference counting for this value
- //virtual void AddDataToReplica(CValue* replica);
+ //virtual void AddDataToReplica(CValue* replica);
virtual ~CValue();
private:
- // Member variables
+ // Member variables
std::map<STR_String,CValue*>* m_pNamedPropertyArray; // Properties for user/game etc
ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage)
- int m_refcount; // Reference Counter
- static double m_sZeroVec[3];
+ int m_refcount; // Reference Counter
+ static double m_sZeroVec[3];
};
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
index 685cc3fcc48..912484a2fe5 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
@@ -65,7 +65,7 @@ class SCA_Joystick
/**
*support for JOYHAT_MAX hats (each is a direction)
*/
- int m_hat_array[JOYHAT_MAX];
+ int m_hat_array[JOYHAT_MAX];
/**
* Precision or range of the axes
diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp
index 3fda542410a..6d76f122163 100644
--- a/source/gameengine/GameLogic/SCA_IController.cpp
+++ b/source/gameengine/GameLogic/SCA_IController.cpp
@@ -238,19 +238,19 @@ PyAttributeDef SCA_IController::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_IController* self= static_cast<SCA_IController*>(self_v);
return PyLong_FromSsize_t(self->m_statemask);
}
-PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_SENSORS);
+ return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_SENSORS);
}
-PyObject* SCA_IController::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_IController::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_ACTUATORS);
+ return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_ACTUATORS);
}
#endif // WITH_PYTHON
diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.cpp b/source/gameengine/GameLogic/SCA_IInputDevice.cpp
index 16626b05526..f4fce034c87 100644
--- a/source/gameengine/GameLogic/SCA_IInputDevice.cpp
+++ b/source/gameengine/GameLogic/SCA_IInputDevice.cpp
@@ -45,7 +45,7 @@ SCA_IInputDevice::SCA_IInputDevice()
SCA_IInputDevice::~SCA_IInputDevice()
{
-}
+}
void SCA_IInputDevice::HookEscape()
{
@@ -134,6 +134,6 @@ void SCA_IInputDevice::NextFrame()
break;
default:
; /* error */
- }
+ }
}
}
diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.h b/source/gameengine/GameLogic/SCA_IInputDevice.h
index 0382a2efd21..66a1209751d 100644
--- a/source/gameengine/GameLogic/SCA_IInputDevice.h
+++ b/source/gameengine/GameLogic/SCA_IInputDevice.h
@@ -69,7 +69,7 @@ class SCA_IInputDevice
public:
SCA_IInputDevice();
- virtual ~SCA_IInputDevice();
+ virtual ~SCA_IInputDevice();
enum KX_EnumInputs {
@@ -120,17 +120,17 @@ public:
KX_RETKEY = 13,
KX_SPACEKEY = 32,
KX_PADASTERKEY = 42,
- KX_COMMAKEY = 44,
- KX_MINUSKEY = 45,
+ KX_COMMAKEY = 44,
+ KX_MINUSKEY = 45,
KX_PERIODKEY = 46,
KX_ZEROKEY = 48,
KX_ONEKEY, // =49
- KX_TWOKEY,
+ KX_TWOKEY,
KX_THREEKEY,
- KX_FOURKEY,
- KX_FIVEKEY,
- KX_SIXKEY,
+ KX_FOURKEY,
+ KX_FIVEKEY,
+ KX_SIXKEY,
KX_SEVENKEY,
KX_EIGHTKEY,
KX_NINEKEY, // = 57
@@ -170,14 +170,14 @@ public:
KX_LEFTALTKEY,
KX_RIGHTALTKEY,
KX_RIGHTCTRLKEY,
- KX_RIGHTSHIFTKEY,
+ KX_RIGHTSHIFTKEY,
KX_LEFTSHIFTKEY,// 129
KX_ESCKEY, // 130
KX_TABKEY, //131
- KX_LINEFEEDKEY, // 132
+ KX_LINEFEEDKEY, // 132
KX_BACKSPACEKEY,
KX_DELKEY,
KX_SEMICOLONKEY, // 135
@@ -188,13 +188,13 @@ public:
KX_SLASHKEY, //138
KX_BACKSLASHKEY,
- KX_EQUALKEY,
- KX_LEFTBRACKETKEY,
+ KX_EQUALKEY,
+ KX_LEFTBRACKETKEY,
KX_RIGHTBRACKETKEY, // 142
KX_LEFTARROWKEY, // 145
KX_DOWNARROWKEY,
- KX_RIGHTARROWKEY,
+ KX_RIGHTARROWKEY,
KX_UPARROWKEY, // 148
KX_PAD2 ,
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
index 018a939f68d..cfbdc1e750f 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
@@ -231,7 +231,7 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef)
}
/*Attribute functions */
-PyObject* SCA_ILogicBrick::pyattr_get_owner(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_ILogicBrick::pyattr_get_owner(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_ILogicBrick* self= static_cast<SCA_ILogicBrick*>(self_v);
CValue* parent = self->GetParent();
@@ -254,9 +254,9 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg)
}
}
-PyObject* SCA_ILogicBrick::BoolToPyArg(bool boolarg)
+PyObject *SCA_ILogicBrick::BoolToPyArg(bool boolarg)
{
- return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE);
+ return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE);
}
#endif // WITH_PYTHON
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h
index b505353c7cd..c5fa9399ab7 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.h
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h
@@ -157,7 +157,7 @@ protected:
bool PyArgToBool(int boolArg);
/** Convert a a c++ value to KX_TRUE, KX_FALSE in Python. */
- PyObject* BoolToPyArg(bool);
+ PyObject *BoolToPyArg(bool);
#endif // WITH_PYTHON
diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp
index b90952b2092..ab9e2781001 100644
--- a/source/gameengine/GameLogic/SCA_IObject.cpp
+++ b/source/gameengine/GameLogic/SCA_IObject.cpp
@@ -224,7 +224,7 @@ SCA_IController* SCA_IObject::FindController(const STR_String& controllername)
{
foundcontroller = (*itc);
break;
- }
+ }
}
return foundcontroller;
}
diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h
index 0e657794195..a850d23babf 100644
--- a/source/gameengine/GameLogic/SCA_IObject.h
+++ b/source/gameengine/GameLogic/SCA_IObject.h
@@ -43,7 +43,7 @@ class SCA_IController;
class SCA_IActuator;
#ifdef WITH_PYTHON
-template<class T> T PyVecTo(PyObject*);
+template<class T> T PyVecTo(PyObject *);
#endif
typedef std::vector<SCA_ISensor *> SCA_SensorList;
@@ -213,7 +213,7 @@ public:
*/
unsigned int GetState(void) { return m_state; }
-// const class MT_Point3& ConvertPythonPylist(PyObject* pylist);
+// const class MT_Point3& ConvertPythonPylist(PyObject *pylist);
virtual int GetGameObjectType() {return -1;}
diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp
index 76b9a8df00f..7cf0b18c3b5 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ISensor.cpp
@@ -248,7 +248,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr)
if (result) {
// the sensor triggered this frame
if (m_state || !m_tap) {
- ActivateControllers(logicmgr);
+ ActivateControllers(logicmgr);
// reset these counters so that pulse are synchronized with transition
m_pos_ticks = 0;
m_neg_ticks = 0;
@@ -380,7 +380,7 @@ PyAttributeDef SCA_ISensor::Attributes[] = {
};
-PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
int retval = 0;
@@ -389,13 +389,13 @@ PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_D
return PyLong_FromSsize_t(retval);
}
-PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
return PyLong_FromSsize_t(self->GetState());
}
-PyObject* SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
int status = 0;
@@ -417,13 +417,13 @@ PyObject* SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF
return PyLong_FromSsize_t(status);
}
-PyObject* SCA_ISensor::pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_ISensor::pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
return PyLong_FromLong(self->GetPosTicks());
}
-PyObject* SCA_ISensor::pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_ISensor::pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
return PyLong_FromLong(self->GetNegTicks());
diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
index 2c6beb79fd3..7e9a4bc903c 100644
--- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
@@ -60,7 +60,7 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
m_joymode(joymode),
m_joyindex(joyindex),
m_bAllEvents(allevents)
-{
+{
/*
std::cout << " axis " << m_axis << std::endl;
std::cout << " axis flag " << m_axisf << std::endl;
@@ -308,7 +308,7 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = {
const char SCA_JoystickSensor::GetButtonActiveList_doc[] =
"getButtonActiveList\n"
"\tReturns a list containing the indices of the button currently pressed.\n";
-PyObject* SCA_JoystickSensor::PyGetButtonActiveList( )
+PyObject *SCA_JoystickSensor::PyGetButtonActiveList( )
{
SCA_Joystick *joy = ((SCA_JoystickManager *)m_eventmgr)->GetJoystickDevice(m_joyindex);
PyObject *ls = PyList_New(0);
@@ -331,7 +331,7 @@ PyObject* SCA_JoystickSensor::PyGetButtonActiveList( )
const char SCA_JoystickSensor::GetButtonStatus_doc[] =
"getButtonStatus(buttonIndex)\n"
"\tReturns a bool of the current pressed state of the specified button.\n";
-PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* args )
+PyObject *SCA_JoystickSensor::PyGetButtonStatus( PyObject *args )
{
SCA_Joystick *joy = ((SCA_JoystickManager *)m_eventmgr)->GetJoystickDevice(m_joyindex);
int index;
@@ -345,7 +345,7 @@ PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* args )
return PyBool_FromLong(0);
}
-PyObject* SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
@@ -360,7 +360,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYAT
return list;
}
-PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
@@ -373,7 +373,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT
return PyLong_FromSsize_t(joy->GetAxisPosition(self->m_axis-1));
}
-PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
@@ -388,7 +388,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATT
return list;
}
-PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
@@ -396,28 +396,28 @@ PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATT
return PyLong_FromSsize_t(joy->GetHat(self->m_hat-1));
}
-PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 );
}
-PyObject* SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 );
}
-PyObject* SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 );
}
-PyObject* SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.h b/source/gameengine/GameLogic/SCA_KeyboardManager.h
index 2d9ad45833f..fd3c0706fa7 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardManager.h
+++ b/source/gameengine/GameLogic/SCA_KeyboardManager.h
@@ -54,7 +54,7 @@ public:
bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode);
- virtual void NextFrame();
+ virtual void NextFrame();
SCA_IInputDevice* GetInputDevice();
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
index 5208252ceae..9a2dd9bdd57 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -351,12 +351,12 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
GetParent()->SetProperty(m_targetprop, newstringprop);
newstringprop->Release();
- }
+ }
} else {
/* append */
char pchar = ToCharacter(keyIndex, IsShifted());
STR_String newprop = tprop->GetText() + pchar;
- CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
+ CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
GetParent()->SetProperty(m_targetprop, newstringprop);
newstringprop->Release();
}
@@ -365,7 +365,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
/* Make a new property. Deletes can be ignored. */
char pchar = ToCharacter(keyIndex, IsShifted());
STR_String newprop = pchar;
- CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
+ CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
GetParent()->SetProperty(m_targetprop, newstringprop);
newstringprop->Release();
}
@@ -376,7 +376,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
/**
* Tests whether shift is pressed
- */
+ */
bool SCA_KeyboardSensor::IsShifted(void)
{
SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
@@ -391,9 +391,10 @@ bool SCA_KeyboardSensor::IsShifted(void)
== SCA_InputEvent::KX_JUSTACTIVATED)
) {
return true;
- } else {
+ }
+ else {
return false;
- }
+ }
}
void SCA_KeyboardSensor::LogKeystrokes(void)
@@ -494,25 +495,25 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = {
};
-PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_KeyboardSensor* self= static_cast<SCA_KeyboardSensor*>(self_v);
SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)self->m_eventmgr)->GetInputDevice();
- PyObject* resultlist = PyList_New(0);
+ PyObject *resultlist = PyList_New(0);
for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
{
const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
{
- PyObject* keypair = PyList_New(2);
+ PyObject *keypair = PyList_New(2);
PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i));
PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status));
PyList_Append(resultlist,keypair);
}
- }
+ }
return resultlist;
}
@@ -655,7 +656,7 @@ bool IsPrintable(int keyIndex)
/**
* Tests whether this is a delete key.
- */
+ */
bool IsDelete(int keyIndex)
{
if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
index c059aba305b..caa141e48f2 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
@@ -134,7 +134,7 @@ bool IsPrintable(int keyIndex);
/**
* Tests whether this is a delete key.
- */
+ */
bool IsDelete(int keyIndex);
diff --git a/source/gameengine/GameLogic/SCA_MouseManager.h b/source/gameengine/GameLogic/SCA_MouseManager.h
index 60edb2816cb..02c28807566 100644
--- a/source/gameengine/GameLogic/SCA_MouseManager.h
+++ b/source/gameengine/GameLogic/SCA_MouseManager.h
@@ -63,7 +63,7 @@ public:
* mouse related events. Can also flag mouse movement.
*/
bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode);
- virtual void NextFrame();
+ virtual void NextFrame();
SCA_IInputDevice* GetInputDevice();
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
index f4ee54c56a6..51e0bc6550b 100644
--- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
@@ -156,7 +156,7 @@ bool SCA_MouseSensor::Evaluate()
case KX_MOUSESENSORMODE_WHEELDOWN:
{
const SCA_InputEvent& mevent = mousedev->GetEventValue(m_hotkey);
- switch (mevent.m_status) {
+ switch (mevent.m_status) {
case SCA_InputEvent::KX_JUSTACTIVATED:
m_val = 1;
result = true;
@@ -189,15 +189,15 @@ bool SCA_MouseSensor::Evaluate()
const SCA_InputEvent& eventY = mousedev->GetEventValue(SCA_IInputDevice::KX_MOUSEY);
if (eventX.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
- eventY.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
- eventX.m_status == SCA_InputEvent::KX_ACTIVE ||
- eventY.m_status == SCA_InputEvent::KX_ACTIVE)
+ eventY.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
+ eventX.m_status == SCA_InputEvent::KX_ACTIVE ||
+ eventY.m_status == SCA_InputEvent::KX_ACTIVE)
{
m_val = 1;
result = true;
}
else if (eventX.m_status == SCA_InputEvent::KX_JUSTRELEASED ||
- eventY.m_status == SCA_InputEvent::KX_JUSTRELEASED )
+ eventY.m_status == SCA_InputEvent::KX_JUSTRELEASED )
{
m_val = 0;
result = true;
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
index 31f988fe4b9..0eab6187d07 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
@@ -173,7 +173,7 @@ isValid(
SCA_PropertyActuator::KX_ACT_PROP_MODE mode
) {
- bool res = false;
+ bool res = false;
res = ((mode > KX_ACT_PROP_NODEF) && (mode < KX_ACT_PROP_MAX));
return res;
}
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index ab7f57a5454..7dbbbb2a0d9 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -179,7 +179,7 @@ int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor)
#ifdef WITH_PYTHON
/* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */
-PyObject* SCA_PythonController::sPyGetCurrentController(PyObject *self)
+PyObject *SCA_PythonController::sPyGetCurrentController(PyObject *self)
{
if (m_sCurrentController==NULL)
{
@@ -271,7 +271,7 @@ void SCA_PythonController::ErrorPrint(const char *error_msg)
}
bool SCA_PythonController::Compile()
-{
+{
//printf("py script modified '%s'\n", m_scriptName.Ptr());
m_bModified= false;
@@ -374,7 +374,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
m_sCurrentLogicManager = logicmgr;
PyObject *excdict= NULL;
- PyObject* resultobj= NULL;
+ PyObject *resultobj= NULL;
switch(m_mode) {
case SCA_PYEXEC_SCRIPT:
@@ -447,13 +447,13 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
// This doesn't appear to be needed anymore
//PyDict_Clear(excdict);
Py_DECREF(excdict);
- }
+ }
m_triggeredSensors.clear();
m_sCurrentController = NULL;
}
-PyObject* SCA_PythonController::PyActivate(PyObject *value)
+PyObject *SCA_PythonController::PyActivate(PyObject *value)
{
if (m_sCurrentController != this) {
PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller");
@@ -468,7 +468,7 @@ PyObject* SCA_PythonController::PyActivate(PyObject *value)
Py_RETURN_NONE;
}
-PyObject* SCA_PythonController::PyDeActivate(PyObject *value)
+PyObject *SCA_PythonController::PyDeActivate(PyObject *value)
{
if (m_sCurrentController != this) {
PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller");
@@ -483,7 +483,7 @@ PyObject* SCA_PythonController::PyDeActivate(PyObject *value)
Py_RETURN_NONE;
}
-PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
//SCA_PythonController* self= static_cast<SCA_PythonController*>(static_cast<SCA_IController*>(static_cast<SCA_ILogicBrick*>(static_cast<CValue*>(static_cast<PyObjectPlus*>(self_v)))));
// static_cast<void *>(dynamic_cast<Derived *>(obj)) - static_cast<void *>(obj)
diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h
index ccdb82aa722..8a72ce6bad9 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.h
+++ b/source/gameengine/GameLogic/SCA_PythonController.h
@@ -74,7 +74,7 @@ class SCA_PythonController : public SCA_IController
//for debugging
//virtual CValue* AddRef();
- //virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+ //virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
SCA_PythonController(SCA_IObject* gameobj, int mode);
virtual ~SCA_PythonController();
@@ -96,11 +96,11 @@ class SCA_PythonController : public SCA_IController
void ErrorPrint(const char *error_msg);
#ifdef WITH_PYTHON
- static const char* sPyGetCurrentController__doc__;
- static PyObject* sPyGetCurrentController(PyObject* self);
- static const char* sPyAddActiveActuator__doc__;
- static PyObject* sPyAddActiveActuator(PyObject* self,
- PyObject* args);
+ static const char *sPyGetCurrentController__doc__;
+ static PyObject *sPyGetCurrentController(PyObject *self);
+ static const char *sPyAddActiveActuator__doc__;
+ static PyObject *sPyAddActiveActuator(PyObject *self,
+ PyObject *args);
static SCA_IActuator* LinkedActuatorFromPy(PyObject *value);
diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
index f83b23f510c..42cda9433b8 100644
--- a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
@@ -58,13 +58,13 @@ SCA_PythonKeyboard::~SCA_PythonKeyboard()
/* ------------------------------------------------------------------------- */
/* clipboard */
-static PyObject* gPyGetClipboard(PyObject* args, PyObject* kwds)
+static PyObject *gPyGetClipboard(PyObject *args, PyObject *kwds)
{
char *buf = (char *)GHOST_getClipboard(0);
return PyUnicode_FromString(buf?buf:"");
}
-static PyObject* gPySetClipboard(PyObject* args, PyObject* value)
+static PyObject *gPySetClipboard(PyObject *args, PyObject *value)
{
char* buf;
if (!PyArg_ParseTuple(value,"s:setClipboard",&buf))
@@ -109,7 +109,7 @@ PyAttributeDef SCA_PythonKeyboard::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_PythonKeyboard* self = static_cast<SCA_PythonKeyboard*>(self_v);
@@ -123,7 +123,7 @@ PyObject* SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBU
return self->m_event_dict;
}
-PyObject* SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_PythonKeyboard* self = static_cast<SCA_PythonKeyboard*>(self_v);
diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.h b/source/gameengine/GameLogic/SCA_PythonKeyboard.h
index df5e46f8c28..aab49bcb83b 100644
--- a/source/gameengine/GameLogic/SCA_PythonKeyboard.h
+++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.h
@@ -35,7 +35,7 @@ class SCA_PythonKeyboard : public PyObjectPlus
private:
class SCA_IInputDevice *m_keyboard;
#ifdef WITH_PYTHON
- PyObject* m_event_dict;
+ PyObject *m_event_dict;
#endif
public:
SCA_PythonKeyboard(class SCA_IInputDevice* keyboard);
diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.cpp b/source/gameengine/GameLogic/SCA_PythonMouse.cpp
index cdbeaba2235..0806bda072b 100644
--- a/source/gameengine/GameLogic/SCA_PythonMouse.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonMouse.cpp
@@ -90,9 +90,9 @@ PyAttributeDef SCA_PythonMouse::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("position", SCA_PythonMouse, pyattr_get_position, pyattr_set_position),
KX_PYATTRIBUTE_RW_FUNCTION("visible", SCA_PythonMouse, pyattr_get_visible, pyattr_set_visible),
{ NULL } //Sentinel
-};
+};
-PyObject* SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_PythonMouse* self = static_cast<SCA_PythonMouse*>(self_v);
@@ -106,7 +106,7 @@ PyObject* SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_
return self->m_event_dict;
}
-PyObject* SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_PythonMouse* self = static_cast<SCA_PythonMouse*>(self_v);
@@ -123,7 +123,7 @@ PyObject* SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATT
return self->m_event_dict;
}
-PyObject* SCA_PythonMouse::pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_PythonMouse::pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_PythonMouse* self = static_cast<SCA_PythonMouse*>(self_v);
const SCA_InputEvent & xevent = self->m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEX);
@@ -134,7 +134,7 @@ PyObject* SCA_PythonMouse::pyattr_get_position(void *self_v, const KX_PYATTRIBUT
x_coord = self->m_canvas->GetMouseNormalizedX(xevent.m_eventval);
y_coord = self->m_canvas->GetMouseNormalizedY(yevent.m_eventval);
- PyObject* ret = PyTuple_New(2);
+ PyObject *ret = PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(x_coord));
PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(y_coord));
@@ -158,7 +158,7 @@ int SCA_PythonMouse::pyattr_set_position(void *self_v, const KX_PYATTRIBUTE_DEF
return PY_SET_ATTR_SUCCESS;
}
-PyObject* SCA_PythonMouse::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_PythonMouse::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_PythonMouse* self = static_cast<SCA_PythonMouse*>(self_v);
diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.h b/source/gameengine/GameLogic/SCA_PythonMouse.h
index 1313d55005f..f770a54d6e6 100644
--- a/source/gameengine/GameLogic/SCA_PythonMouse.h
+++ b/source/gameengine/GameLogic/SCA_PythonMouse.h
@@ -36,7 +36,7 @@ private:
class SCA_IInputDevice *m_mouse;
class RAS_ICanvas *m_canvas;
#ifdef WITH_PYTHON
- PyObject* m_event_dict;
+ PyObject *m_event_dict;
#endif
public:
SCA_PythonMouse(class SCA_IInputDevice* mouse, class RAS_ICanvas* canvas);
@@ -47,12 +47,12 @@ public:
#ifdef WITH_PYTHON
KX_PYMETHOD_DOC(SCA_PythonMouse, show);
- static PyObject* pyattr_get_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_active_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value);
- static PyObject* pyattr_get_visible(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_visible(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value);
+ static PyObject *pyattr_get_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_active_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_visible(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_visible(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif
};
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
index c727eebd015..9a54c76ed4e 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
@@ -161,7 +161,7 @@ bool SCA_RandomActuator::Update()
while (b >= a) {
b = b * m_base->DrawFloat();
res++;
- };
+ };
tmpval = new CIntValue(res);
}
break;
@@ -361,9 +361,9 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = {
KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,MAX_PROP_NAME,false,SCA_RandomActuator,m_propname,CheckProperty),
KX_PYATTRIBUTE_RW_FUNCTION("seed",SCA_RandomActuator,pyattr_get_seed,pyattr_set_seed),
{ NULL } //Sentinel
-};
+};
-PyObject* SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_RandomActuator* act = static_cast<SCA_RandomActuator*>(self);
return PyLong_FromSsize_t(act->m_base->GetSeed());
@@ -420,7 +420,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setBoolBernouilli,
}
m_distribution = KX_RANDOMACT_BOOL_BERNOUILLI;
- m_parameter1 = paraArg;
+ m_parameter1 = paraArg;
enforceConstraints();
Py_RETURN_NONE;
}
@@ -473,7 +473,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setIntPoisson,
}
m_distribution = KX_RANDOMACT_INT_POISSON;
- m_parameter1 = paraArg;
+ m_parameter1 = paraArg;
enforceConstraints();
Py_RETURN_NONE;
}
@@ -489,7 +489,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatConst,
}
m_distribution = KX_RANDOMACT_FLOAT_CONST;
- m_parameter1 = paraArg;
+ m_parameter1 = paraArg;
enforceConstraints();
Py_RETURN_NONE;
}
@@ -544,7 +544,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatNegativeExponential,
}
m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL;
- m_parameter1 = paraArg;
+ m_parameter1 = paraArg;
enforceConstraints();
Py_RETURN_NONE;
}
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h
index 522663651e0..f61de24c0cc 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.h
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.h
@@ -67,10 +67,10 @@ class SCA_RandomActuator : public SCA_IActuator
KX_RANDOMACT_NODEF,
KX_RANDOMACT_BOOL_CONST,
KX_RANDOMACT_BOOL_UNIFORM,
- KX_RANDOMACT_BOOL_BERNOUILLI,
+ KX_RANDOMACT_BOOL_BERNOUILLI,
KX_RANDOMACT_INT_CONST,
KX_RANDOMACT_INT_UNIFORM,
- KX_RANDOMACT_INT_POISSON,
+ KX_RANDOMACT_INT_POISSON,
KX_RANDOMACT_FLOAT_CONST,
KX_RANDOMACT_FLOAT_UNIFORM,
KX_RANDOMACT_FLOAT_NORMAL,
@@ -98,7 +98,7 @@ class SCA_RandomActuator : public SCA_IActuator
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
- static PyObject* pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
KX_PYMETHOD_DOC_VARARGS(SCA_RandomActuator, setBoolConst);
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
index 3b37507dcf3..17784755421 100644
--- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
@@ -165,7 +165,7 @@ PyAttributeDef SCA_RandomSensor::Attributes[] = {
{NULL} //Sentinel
};
-PyObject* SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
SCA_RandomSensor* self= static_cast<SCA_RandomSensor*>(self_v);
return PyLong_FromSsize_t(self->m_basegenerator->GetSeed());
diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
index e28f00abba2..e8a6289a98e 100644
--- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
@@ -54,7 +54,7 @@ SCA_TimeEventManager::~SCA_TimeEventManager()
!(it == m_timevalues.end()); ++it)
{
(*it)->Release();
- }
+ }
}
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
index f4224b9e255..7581484a41f 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
@@ -99,7 +99,7 @@ void GPC_Canvas::Resize(int width, int height)
void GPC_Canvas::EndFrame()
{
if (m_bannersEnabled)
- DrawAllBanners();
+ DrawAllBanners();
}
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h
index 25a50fbcac3..453b9505183 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.h
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h
@@ -163,7 +163,7 @@ public:
void SetMouseState(RAS_MouseState mousestate)
{
- // not yet
+ // not yet
}
void SetMousePosition(int x, int y)
@@ -250,7 +250,7 @@ protected:
int oldWriteMask;
};
- void
+ void
PushRenderState(
CanvasRenderState & render_state
);
diff --git a/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp b/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp
index a38bba7788b..e38a9e3d6cb 100644
--- a/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp
@@ -67,7 +67,8 @@ void GPC_MouseDevice::NextFrame()
for (int mouseevent= KX_BEGINMOUSE; mouseevent< KX_ENDMOUSEBUTTONS; mouseevent++) {
SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][mouseevent];
if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
- oldevent.m_status == SCA_InputEvent::KX_ACTIVE) {
+ oldevent.m_status == SCA_InputEvent::KX_ACTIVE)
+ {
m_eventStatusTables[m_currentTable][mouseevent] = oldevent;
m_eventStatusTables[m_currentTable][mouseevent].m_status = SCA_InputEvent::KX_ACTIVE;
}
@@ -76,7 +77,8 @@ void GPC_MouseDevice::NextFrame()
SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][mousemove];
m_eventStatusTables[m_currentTable][mousemove] = oldevent;
if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
- oldevent.m_status == SCA_InputEvent::KX_ACTIVE) {
+ oldevent.m_status == SCA_InputEvent::KX_ACTIVE)
+ {
m_eventStatusTables[m_currentTable][mousemove].m_status = SCA_InputEvent::KX_JUSTRELEASED;
}
else {
diff --git a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
index 9f129c1cdfb..c0d66541800 100644
--- a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
@@ -89,7 +89,7 @@ bool GPC_RawImage::Load(
// Put original in upper left corner
// Add vertical offset
- dst += offsetY * dstBytesWidth;
+ dst += offsetY * dstBytesWidth;
// Add horizontal offset
dst += offsetX * 4;
for (int row = 0; row < numRows; row++)
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
index 749e7748e19..9cd6715f3d2 100644
--- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
@@ -442,7 +442,7 @@ void GPC_RenderTools::PopMatrix()
int GPC_RenderTools::applyLights(int objectlayer, const MT_Transform& viewmat)
{
- // taken from blender source, incompatibility between Blender Object / GameObject
+ // taken from blender source, incompatibility between Blender Object / GameObject
KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo;
float glviewmat[16];
unsigned int count;
diff --git a/source/gameengine/GamePlayer/common/bmfont.cpp b/source/gameengine/GamePlayer/common/bmfont.cpp
index 4c1c6ae5604..6f40d13fe7a 100644
--- a/source/gameengine/GamePlayer/common/bmfont.cpp
+++ b/source/gameengine/GamePlayer/common/bmfont.cpp
@@ -110,7 +110,7 @@ void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step)
buffer = (unsigned char*)MEM_mallocN(bytes, "readBitmapFontVersion0:buffer");
- index = 0;
+ index = 0;
for (i = 0; i < bytes; i++) {
buffer[i] = rect[index];
index += step;
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 21de7011eda..40b52c3212a 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -479,7 +479,7 @@ bool GPG_Application::processEvent(GHOST_IEvent* event)
// // first check if we want to exit
// m_exitRequested = m_ketsjiengine->GetExitCode();
- //
+ //
// // kick the engine
// bool renderFrame = m_ketsjiengine->NextFrame();
// if (renderFrame)
@@ -546,7 +546,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
return false;
// SYS_WriteCommandLineInt(syshandle, "fixedtime", 0);
- // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1);
+ // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1);
GameData *gm= &m_startScene->gm;
bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
@@ -576,7 +576,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
m_canvas->Init();
if (gm->flag & GAME_SHOW_MOUSE)
- m_canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
+ m_canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
m_rendertools = new GPC_RenderTools();
if (!m_rendertools)
@@ -681,7 +681,7 @@ bool GPG_Application::startEngine(void)
// Temporary hack to disable banner display for NaN approved content.
/*
- m_canvas->SetBannerDisplayEnabled(true);
+ m_canvas->SetBannerDisplayEnabled(true);
Camera* cam;
cam = (Camera*)scene->camera->data;
if (cam) {
@@ -730,7 +730,7 @@ bool GPG_Application::startEngine(void)
// Set the GameLogic.globalDict from marshal'd data, so we can
// load new blend files and keep data in GameLogic.globalDict
loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length);
-#endif
+#endif
m_sceneconverter->ConvertScene(
startscene,
m_rendertools,
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index d8b07fd50d9..7500a55a059 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -57,10 +57,10 @@ extern "C"
{
#endif // __cplusplus
#include "MEM_guardedalloc.h"
-#include "BKE_blender.h"
-#include "BKE_global.h"
-#include "BKE_icons.h"
-#include "BKE_node.h"
+#include "BKE_blender.h"
+#include "BKE_global.h"
+#include "BKE_icons.h"
+#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_library.h"
#include "BLI_threads.h"
@@ -223,7 +223,7 @@ void usage(const char* program, bool isBlenderPlayer)
printf(" --Optional parameters--\n");
printf(" angle = field of view in degrees\n");
printf(" tilt = tilt angle in degrees\n");
- printf(" warpdata = a file to use for warping the image (absolute path)\n");
+ printf(" warpdata = a file to use for warping the image (absolute path)\n");
printf(" mode: fisheye (Fisheye)\n");
printf(" truncatedfront (Front-Truncated)\n");
printf(" truncatedrear (Rear-Truncated)\n");
@@ -1016,12 +1016,12 @@ int main(int argc, char** argv)
gpg_nextframestate.app = &app;
gpg_nextframestate.gs = &gs;
pynextframestate.state = &gpg_nextframestate;
- pynextframestate.func = &GPG_PyNextFrame;
+ pynextframestate.func = &GPG_PyNextFrame;
printf("Yielding control to Python script '%s'...\n", python_main);
PyRun_SimpleString(python_code);
printf("Exit Python script '%s'\n", python_main);
-#endif // WITH_PYTHON
+#endif // WITH_PYTHON
MEM_freeN(python_code);
}
else {
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index c0fca88c426..e0ad1539b4a 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -431,7 +431,7 @@ void BL_Shader::SetProg(bool enable)
glUseProgramObjectARB(mShader);
}
else {
- glUseProgramObjectARB(0);
+ glUseProgramObjectARB(0);
}
}
}
@@ -613,7 +613,7 @@ void BL_Shader::SetUniform(int uniform, const MT_Tuple3& vec)
GLEW_ARB_vertex_shader &&
GLEW_ARB_shader_objects
)
- {
+ {
float value[3];
vec.getValue(value);
glUniform3fvARB(uniform, 1, value);
@@ -931,7 +931,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
{
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float));
-#else
+#else
SetUniform( loc, (float)value );
#endif
}
@@ -1142,7 +1142,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv, "setUniformfv( float (list2 or list
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float)*2);
#else
- SetUniform(loc, array2, 2);
+ SetUniform(loc, array2, 2);
#endif
Py_RETURN_NONE;
} break;
@@ -1152,7 +1152,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv, "setUniformfv( float (list2 or list
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float)*3);
#else
- SetUniform(loc, array3, 3);
+ SetUniform(loc, array3, 3);
#endif
Py_RETURN_NONE;
}break;
@@ -1162,7 +1162,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv, "setUniformfv( float (list2 or list
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float)*4);
#else
- SetUniform(loc, array4, 4);
+ SetUniform(loc, array4, 4);
#endif
Py_RETURN_NONE;
}break;
@@ -1226,7 +1226,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
#else
- SetUniform(loc, array2, 2);
+ SetUniform(loc, array2, 2);
#endif
Py_RETURN_NONE;
} break;
@@ -1237,7 +1237,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2
SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
#else
- SetUniform(loc, array3, 3);
+ SetUniform(loc, array3, 3);
#endif
Py_RETURN_NONE;
}break;
@@ -1248,7 +1248,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2
SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
#else
- SetUniform(loc, array4, 4);
+ SetUniform(loc, array4, 4);
#endif
Py_RETURN_NONE;
}break;
diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h
index 2bb094f12ee..b577a1849a0 100644
--- a/source/gameengine/Ketsji/BL_Shader.h
+++ b/source/gameengine/Ketsji/BL_Shader.h
@@ -222,7 +222,7 @@ public:
// Python interface
#ifdef WITH_PYTHON
- virtual PyObject* py_repr(void) { return PyUnicode_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); }
+ virtual PyObject *py_repr(void) { return PyUnicode_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); }
// -----------------------------------
KX_PYMETHOD_DOC(BL_Shader, setSource);
diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp
index b8cc4ebeff9..7196c1ec664 100644
--- a/source/gameengine/Ketsji/BL_Texture.cpp
+++ b/source/gameengine/Ketsji/BL_Texture.cpp
@@ -47,7 +47,7 @@ static int power_of_2_min_i(int num)
{
while (!is_power_of_2_i(num))
num= num&(num-1);
- return num;
+ return num;
}
// Place holder for a full texture manager
@@ -427,7 +427,7 @@ void BL_Texture::DisableAllTextures()
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
- glDisable(GL_TEXTURE_2D);
+ glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
@@ -447,14 +447,14 @@ void BL_Texture::ActivateTexture()
if (mType == GL_TEXTURE_CUBE_MAP_ARB && GLEW_ARB_texture_cube_map)
{
- glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTexture );
+ glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTexture );
glEnable(GL_TEXTURE_CUBE_MAP_ARB);
}
else {
if (GLEW_ARB_texture_cube_map )
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
- glBindTexture( GL_TEXTURE_2D, mTexture );
+ glBindTexture( GL_TEXTURE_2D, mTexture );
glEnable(GL_TEXTURE_2D);
}
}
@@ -659,7 +659,7 @@ void my_envmap_split_ima(EnvMap *env, ImBuf *ibuf)
{
int dx, part;
- my_free_envmapdata(env);
+ my_free_envmapdata(env);
dx= ibuf->y;
dx/= 2;
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
index a69f02baa57..6260596159d 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
@@ -38,7 +38,7 @@
#include "NG_NetworkMessage.h"
#include "NG_NetworkScene.h"
#include "NG_NetworkObject.h"
-#include "SCA_IObject.h"
+#include "SCA_IObject.h"
#include "InputParser.h"
#include "ListValue.h"
#include "StringValue.h"
@@ -201,7 +201,7 @@ PyAttributeDef KX_NetworkMessageSensor::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v);
if (self->m_BodyList) {
@@ -211,7 +211,7 @@ PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYAT
}
}
-PyObject* KX_NetworkMessageSensor::pyattr_get_subjects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_NetworkMessageSensor::pyattr_get_subjects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v);
if (self->m_SubjectList) {
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
index 66f723d072c..6b9779de6e3 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
@@ -80,7 +80,7 @@ public:
/* ------------------------------------------------------------- */
/* attributes */
- static PyObject* pyattr_get_bodies(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_bodies(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_subjects(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_ArmatureSensor.cpp b/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
index f72d9c1dee6..523f3ceeaea 100644
--- a/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
+++ b/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
@@ -86,7 +86,7 @@ void KX_ArmatureSensor::FindConstraint()
/* this constraint is not valid, can't use it */
break;
m_constraint = pcon;
- break;
+ break;
}
}
break;
@@ -193,13 +193,13 @@ PyAttributeDef KX_ArmatureSensor::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_ArmatureSensor::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ArmatureSensor::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ArmatureSensor* sensor = static_cast<KX_ArmatureSensor*>(self);
if (sensor->m_gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) {
BL_ArmatureObject* armobj = (BL_ArmatureObject*)sensor->m_gameobj;
BL_ArmatureConstraint* constraint = armobj->GetConstraint(sensor->m_posechannel, sensor->m_constraintname);
- if (constraint)
+ if (constraint)
return constraint->GetProxy();
}
Py_RETURN_NONE;
diff --git a/source/gameengine/Ketsji/KX_ArmatureSensor.h b/source/gameengine/Ketsji/KX_ArmatureSensor.h
index 9c3faa355a6..74603b3ff01 100644
--- a/source/gameengine/Ketsji/KX_ArmatureSensor.h
+++ b/source/gameengine/Ketsji/KX_ArmatureSensor.h
@@ -72,7 +72,7 @@ public:
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
- static PyObject* pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index b602ba447ad..2337e9569f3 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -412,7 +412,7 @@ KX_BlenderMaterial::ActivatShaders(
if ((mMaterial->ras_mode &WIRE) ||
(rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
- {
+ {
if (mMaterial->ras_mode &WIRE)
rasty->SetCullFace(false);
rasty->SetLines(true);
@@ -457,7 +457,7 @@ KX_BlenderMaterial::ActivateBlenderShaders(
if ((mMaterial->ras_mode &WIRE) ||
(rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
- {
+ {
if (mMaterial->ras_mode &WIRE)
rasty->SetCullFace(false);
rasty->SetLines(true);
@@ -506,7 +506,7 @@ KX_BlenderMaterial::ActivateMat(
if ((mMaterial->ras_mode &WIRE) ||
(rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
- {
+ {
if (mMaterial->ras_mode &WIRE)
rasty->SetCullFace(false);
rasty->SetLines(true);
@@ -614,7 +614,7 @@ void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const
mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
1.0f);
- rasty->SetEmissive(
+ rasty->SetEmissive(
mMaterial->matcolor[0]*mMaterial->emit,
mMaterial->matcolor[1]*mMaterial->emit,
mMaterial->matcolor[2]*mMaterial->emit,
@@ -835,19 +835,19 @@ PyTypeObject KX_BlenderMaterial::Type = {
py_base_new
};
-PyObject* KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
return self->PygetShader(NULL, NULL);
}
-PyObject* KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
return PyLong_FromSsize_t(self->GetMaterialIndex());
}
-PyObject* KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
unsigned int* bfunc = self->getBlendFunc();
@@ -857,7 +857,7 @@ PyObject* KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRI
int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v);
- PyObject* obj = self->PysetBlending(value, NULL);
+ PyObject *obj = self->PysetBlending(value, NULL);
if (obj)
{
Py_DECREF(obj);
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index 8fc86ef9cf2..a69f5c92d19 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -106,11 +106,11 @@ public:
#ifdef WITH_PYTHON
// --------------------------------
- virtual PyObject* py_repr(void) { return PyUnicode_From_STR_String(mMaterial->matname); }
+ virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(mMaterial->matname); }
- static PyObject* pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
KX_PYMETHOD_DOC(KX_BlenderMaterial, getShader);
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
index b974886f60a..20c41b95dd3 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
@@ -269,7 +269,7 @@ void KX_BulletPhysicsController::AddCompoundChild(KX_IPhysicsController* chil
rootScale[2] = 1.0/rootScale[2];
// relative scale = child_scale/parent_scale
btVector3 relativeScale = childShape->getLocalScaling()*rootScale;
- btMatrix3x3 rootRotInverse = rootTrans.getBasis().transpose();
+ btMatrix3x3 rootRotInverse = rootTrans.getBasis().transpose();
// relative pos = parent_rot^-1 * ((parent_pos-child_pos)/parent_scale)
btVector3 relativePos = rootRotInverse*((childTrans.getOrigin()-rootTrans.getOrigin())*rootScale);
// relative rot = parent_rot^-1 * child_rot
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index ac17adaf052..c0071ab22f6 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -67,7 +67,7 @@ KX_Camera::~KX_Camera()
delete m_pSGNode;
m_pSGNode = NULL;
}
-}
+}
CValue* KX_Camera::GetReplica()
@@ -119,7 +119,7 @@ const MT_Point3 KX_Camera::GetCameraLocation() const
//MT_Transform trans;
//trans.setBasis(NodeGetWorldOrientation());
- return NodeGetWorldPosition();
+ return NodeGetWorldPosition();
}
@@ -712,7 +712,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop,
Py_RETURN_NONE;
}
-PyObject* KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyBool_FromLong(self->m_camdata.m_perspective);
@@ -732,7 +732,7 @@ int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *at
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyFloat_FromDouble(self->m_camdata.m_lens);
@@ -752,7 +752,7 @@ int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef,
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_Camera::pyattr_get_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyFloat_FromDouble(self->m_camdata.m_scale);
@@ -772,7 +772,7 @@ int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *at
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyFloat_FromDouble(self->m_camdata.m_clipstart);
@@ -792,7 +792,7 @@ int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef,
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyFloat_FromDouble(self->m_camdata.m_clipend);
@@ -813,7 +813,7 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
}
-PyObject* KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyBool_FromLong(self->GetViewport());
@@ -832,7 +832,7 @@ int KX_Camera::pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *a
}
-PyObject* KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyObjectFrom(self->GetProjectionMatrix());
@@ -849,34 +849,34 @@ int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_D
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyObjectFrom(self->GetModelviewMatrix());
}
-PyObject* KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyObjectFrom(self->GetCameraToWorld());
}
-PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Camera* self= static_cast<KX_Camera*>(self_v);
return PyObjectFrom(self->GetWorldToCamera());
}
-PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{ return PyLong_FromSsize_t(INSIDE); }
-PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{ return PyLong_FromSsize_t(OUTSIDE); }
-PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{ return PyLong_FromSsize_t(INTERSECT); }
-bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix)
+bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix)
{
if (value==NULL) {
PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
@@ -976,7 +976,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition,
vect[1] = 1.0 - vect[1]; //to follow Blender window coordinate system (Top-Down)
- PyObject* ret = PyTuple_New(2);
+ PyObject *ret = PyTuple_New(2);
if (ret) {
PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(vect[0]));
PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(vect[1]));
@@ -1040,7 +1040,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay,
if (!PyArg_ParseTuple(args,"ddd|s:getScreenRay",&x,&y,&dist,&propName))
return NULL;
- PyObject* argValue = PyTuple_New(2);
+ PyObject *argValue = PyTuple_New(2);
PyTuple_SET_ITEM(argValue, 0, PyFloat_FromDouble(x));
PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(y));
@@ -1065,7 +1065,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay,
if (propName)
PyTuple_SET_ITEM(argValue, 2, PyUnicode_FromString(propName));
- PyObject* ret= this->PyrayCastTo(argValue,NULL);
+ PyObject *ret= this->PyrayCastTo(argValue,NULL);
Py_DECREF(argValue);
return ret;
}
diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h
index 7481b2eb7f0..d95d10e8384 100644
--- a/source/gameengine/Ketsji/KX_Camera.h
+++ b/source/gameengine/Ketsji/KX_Camera.h
@@ -45,7 +45,7 @@
#ifdef WITH_PYTHON
/* utility conversion function */
-bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix);
+bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix);
#endif
class KX_Camera : public KX_GameObject
@@ -156,7 +156,7 @@ public:
* instance allocated on the heap. Ownership of the new
* object belongs with the caller.
*/
- virtual CValue*
+ virtual CValue*
GetReplica(
);
virtual void ProcessReplica();
@@ -286,8 +286,8 @@ public:
KX_PYMETHOD_DOC_NOARGS(KX_Camera, getCameraToWorld);
KX_PYMETHOD_DOC_NOARGS(KX_Camera, getWorldToCamera);
- KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport);
- KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop);
+ KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport);
+ KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop);
KX_PYMETHOD_DOC_O(KX_Camera, getScreenPosition);
KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenVect);
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
index 4c63afa7f3e..9ca1ec59a0b 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -394,7 +394,7 @@ PyAttributeDef KX_CameraActuator::Attributes[] = {
{NULL}
};
-PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_CameraActuator* self= static_cast<KX_CameraActuator*>(self_v);
if (self->m_ob==NULL)
@@ -412,7 +412,7 @@ int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
if (self->m_ob)
- self->m_ob->UnregisterActuator(self);
+ self->m_ob->UnregisterActuator(self);
if ((self->m_ob = (SCA_IObject*)gameobj))
self->m_ob->RegisterActuator(self);
diff --git a/source/gameengine/Ketsji/KX_CameraIpoSGController.h b/source/gameengine/Ketsji/KX_CameraIpoSGController.h
index 06058760332..9b7c1eddf00 100644
--- a/source/gameengine/Ketsji/KX_CameraIpoSGController.h
+++ b/source/gameengine/Ketsji/KX_CameraIpoSGController.h
@@ -77,13 +77,13 @@ public:
m_ipotime = time;
m_modified = true;
}
- void SetModifyLens(bool modify) {
+ void SetModifyLens(bool modify) {
m_modify_lens = modify;
}
- void SetModifyClipEnd(bool modify) {
+ void SetModifyClipEnd(bool modify) {
m_modify_clipend = modify;
}
- void SetModifyClipStart(bool modify) {
+ void SetModifyClipStart(bool modify) {
m_modify_clipstart = modify;
}
void AddInterpolator(KX_IInterpolator* interp);
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
index 322d6e60071..3caa4d35565 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -166,7 +166,7 @@ bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo* client)
bool KX_ConstraintActuator::Update(double curtime, bool frame)
{
- bool result = false;
+ bool result = false;
bool bNegativeEvent = IsNegativeEvent();
RemoveAllEvents();
@@ -462,7 +462,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
// we expect a hit object
if (!m_hitObject)
result = false;
- if (result)
+ if (result)
{
MT_Vector3 newnormal = callback.m_hitNormal;
// compute new position & orientation
@@ -619,7 +619,7 @@ int KX_ConstraintActuator::pyattr_check_direction(void *self, const struct KX_PY
return 1;
}
act->m_refDirVector = dir/len;
- return 0;
+ return 0;
}
#endif
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h
index f491aedba74..786e4ff53d2 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.h
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h
@@ -43,7 +43,7 @@ class KX_GameObject;
class KX_ConstraintActuator : public SCA_IActuator
{
Py_Header
-protected:
+protected:
// Damp time (int),
int m_posDampTime;
int m_rotDampTime;
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
index df6b08974dd..5727ed29e67 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
@@ -50,13 +50,13 @@ KX_ConstraintWrapper::~KX_ConstraintWrapper()
#ifdef WITH_PYTHON
-PyObject* KX_ConstraintWrapper::PyGetConstraintId()
+PyObject *KX_ConstraintWrapper::PyGetConstraintId()
{
return PyLong_FromSsize_t(m_constraintId);
}
-PyObject* KX_ConstraintWrapper::PyGetParam(PyObject* args, PyObject* kwds)
+PyObject *KX_ConstraintWrapper::PyGetParam(PyObject *args, PyObject *kwds)
{
int dof;
float value;
@@ -69,7 +69,7 @@ PyObject* KX_ConstraintWrapper::PyGetParam(PyObject* args, PyObject* kwds)
}
-PyObject* KX_ConstraintWrapper::PySetParam(PyObject* args, PyObject* kwds)
+PyObject *KX_ConstraintWrapper::PySetParam(PyObject *args, PyObject *kwds)
{
int dof;
float minLimit,maxLimit;
@@ -117,7 +117,7 @@ PyAttributeDef KX_ConstraintWrapper::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_ConstraintWrapper::pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ConstraintWrapper::pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ConstraintWrapper* self= static_cast<KX_ConstraintWrapper*>(self_v);
return self->PyGetConstraintId();
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
index a92ae83e7f0..dbc3571cad6 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
@@ -48,7 +48,7 @@ public:
KX_PYMETHOD(KX_ConstraintWrapper,SetParam);
KX_PYMETHOD(KX_ConstraintWrapper,GetParam);
- static PyObject* pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
#endif
private:
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index f1038c04499..776953206fe 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -282,7 +282,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
relativeRot.getValue(rot);
shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot);
- parentShapeInfo->AddShape(shapeInfo);
+ parentShapeInfo->AddShape(shapeInfo);
compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
//do some recalc?
//recalc inertia for rigidbody
@@ -439,7 +439,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
{
env->addCcdPhysicsController( physicscontroller);
}
- physicscontroller->setNewClientInfo(gameobj->getClientInfo());
+ physicscontroller->setNewClientInfo(gameobj->getClientInfo());
{
btRigidBody* rbody = physicscontroller->GetRigidBody();
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index 44c9cb1dab8..fd3a18a9d2a 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -592,7 +592,7 @@ void KX_Dome::CreateMeshDome180(void)
cubebottom[0].u[2] = 0.0;
cubebottom[0].v[2] = 0.0;
- nfacesbottom = 1;
+ nfacesbottom = 1;
/* Left face - two triangles */
@@ -682,12 +682,12 @@ void KX_Dome::CreateMeshDome180(void)
cubetop.resize(4*nfacestop);
SplitFace(cubetop,&nfacestop);
cubebottom.resize(4*nfacesbottom);
- SplitFace(cubebottom,&nfacesbottom);
+ SplitFace(cubebottom,&nfacesbottom);
cubeleft.resize(4*nfacesleft);
SplitFace(cubeleft,&nfacesleft);
cuberight.resize(4*nfacesright);
SplitFace(cuberight,&nfacesright);
- }
+ }
// Turn into a hemisphere
for (j=0;j<3;j++) {
@@ -763,13 +763,13 @@ void KX_Dome::CreateMeshDome250(void)
cubefront[0].verts[1][0] = 1.0;
cubefront[0].verts[1][1] = 1.0;
- cubefront[0].verts[1][2] = 1.0;
+ cubefront[0].verts[1][2] = 1.0;
cubefront[0].u[1] = uv_ratio;
cubefront[0].v[1] = uv_ratio;
cubefront[0].verts[2][0] =-1.0;
cubefront[0].verts[2][1] = 1.0;
- cubefront[0].verts[2][2] = 1.0;
+ cubefront[0].verts[2][2] = 1.0;
cubefront[0].u[2] = 0.0;
cubefront[0].v[2] = uv_ratio;
@@ -782,13 +782,13 @@ void KX_Dome::CreateMeshDome250(void)
cubefront[1].verts[1][0] =-1.0;
cubefront[1].verts[1][1] = 1.0;
- cubefront[1].verts[1][2] =-1.0;
+ cubefront[1].verts[1][2] =-1.0;
cubefront[1].u[1] = 0.0;
cubefront[1].v[1] = 0.0;
cubefront[1].verts[2][0] = 1.0;
cubefront[1].verts[2][1] = 1.0;
- cubefront[1].verts[2][2] =-1.0;
+ cubefront[1].verts[2][2] =-1.0;
cubefront[1].u[2] = uv_ratio;
cubefront[1].v[2] = 0.0;
@@ -803,13 +803,13 @@ void KX_Dome::CreateMeshDome250(void)
cubeleft[0].verts[1][0] =-1.0;
cubeleft[0].verts[1][1] =-verts_height;
- cubeleft[0].verts[1][2] = 1.0;
+ cubeleft[0].verts[1][2] = 1.0;
cubeleft[0].u[1] = uv_base;
cubeleft[0].v[1] = uv_ratio;
cubeleft[0].verts[2][0] =-1.0;
cubeleft[0].verts[2][1] =-verts_height;
- cubeleft[0].verts[2][2] =-1.0;
+ cubeleft[0].verts[2][2] =-1.0;
cubeleft[0].u[2] = uv_base;
cubeleft[0].v[2] = 0.0;
@@ -822,13 +822,13 @@ void KX_Dome::CreateMeshDome250(void)
cubeleft[1].verts[1][0] =-1.0;
cubeleft[1].verts[1][1] = 1.0;
- cubeleft[1].verts[1][2] =-1.0;
+ cubeleft[1].verts[1][2] =-1.0;
cubeleft[1].u[1] = uv_ratio;
cubeleft[1].v[1] = 0.0;
cubeleft[1].verts[2][0] =-1.0;
cubeleft[1].verts[2][1] = 1.0;
- cubeleft[1].verts[2][2] = 1.0;
+ cubeleft[1].verts[2][2] = 1.0;
cubeleft[1].u[2] = uv_ratio;
cubeleft[1].v[2] = uv_ratio;
@@ -843,13 +843,13 @@ void KX_Dome::CreateMeshDome250(void)
cuberight[0].verts[1][0] = 1.0;
cuberight[0].verts[1][1] =-verts_height;
- cuberight[0].verts[1][2] =-1.0;
+ cuberight[0].verts[1][2] =-1.0;
cuberight[0].u[1] = uv_height;
cuberight[0].v[1] = 0.0;
cuberight[0].verts[2][0] = 1.0;
cuberight[0].verts[2][1] =-verts_height;
- cuberight[0].verts[2][2] = 1.0;
+ cuberight[0].verts[2][2] = 1.0;
cuberight[0].u[2] = uv_height;
cuberight[0].v[2] = uv_ratio;
@@ -862,13 +862,13 @@ void KX_Dome::CreateMeshDome250(void)
cuberight[1].verts[1][0] = 1.0;
cuberight[1].verts[1][1] = 1.0;
- cuberight[1].verts[1][2] = 1.0;
+ cuberight[1].verts[1][2] = 1.0;
cuberight[1].u[1] = 0.0;
cuberight[1].v[1] = uv_ratio;
cuberight[1].verts[2][0] = 1.0;
cuberight[1].verts[2][1] = 1.0;
- cuberight[1].verts[2][2] =-1.0;
+ cuberight[1].verts[2][2] =-1.0;
cuberight[1].u[2] = 0.0;
cuberight[1].v[2] = 0.0;
@@ -883,13 +883,13 @@ void KX_Dome::CreateMeshDome250(void)
cubetop[0].verts[1][0] = 1.0;
cubetop[0].verts[1][1] =-verts_height;
- cubetop[0].verts[1][2] = 1.0;
+ cubetop[0].verts[1][2] = 1.0;
cubetop[0].u[1] = uv_ratio;
cubetop[0].v[1] = uv_height;
cubetop[0].verts[2][0] =-1.0;
cubetop[0].verts[2][1] =-verts_height;
- cubetop[0].verts[2][2] = 1.0;
+ cubetop[0].verts[2][2] = 1.0;
cubetop[0].u[2] = 0.0;
cubetop[0].v[2] = uv_height;
@@ -902,13 +902,13 @@ void KX_Dome::CreateMeshDome250(void)
cubetop[1].verts[1][0] =-1.0;
cubetop[1].verts[1][1] = 1.0;
- cubetop[1].verts[1][2] = 1.0;
+ cubetop[1].verts[1][2] = 1.0;
cubetop[1].u[1] = 0.0;
cubetop[1].v[1] = 0.0;
cubetop[1].verts[2][0] = 1.0;
cubetop[1].verts[2][1] = 1.0;
- cubetop[1].verts[2][2] = 1.0;
+ cubetop[1].verts[2][2] = 1.0;
cubetop[1].u[2] = uv_ratio;
cubetop[1].v[2] = 0.0;
@@ -923,13 +923,13 @@ void KX_Dome::CreateMeshDome250(void)
cubebottom[0].verts[1][0] = 1.0;
cubebottom[0].verts[1][1] = 1.0;
- cubebottom[0].verts[1][2] =-1.0;
+ cubebottom[0].verts[1][2] =-1.0;
cubebottom[0].u[1] = uv_ratio;
cubebottom[0].v[1] = uv_ratio;
cubebottom[0].verts[2][0] =-1.0;
cubebottom[0].verts[2][1] = 1.0;
- cubebottom[0].verts[2][2] =-1.0;
+ cubebottom[0].verts[2][2] =-1.0;
cubebottom[0].u[2] = 0.0;
cubebottom[0].v[2] = uv_ratio;
@@ -942,13 +942,13 @@ void KX_Dome::CreateMeshDome250(void)
cubebottom[1].verts[1][0] =-1.0;
cubebottom[1].verts[1][1] =-verts_height;
- cubebottom[1].verts[1][2] =-1.0;
+ cubebottom[1].verts[1][2] =-1.0;
cubebottom[1].u[1] = 0.0;
cubebottom[1].v[1] = uv_base;
cubebottom[1].verts[2][0] = 1.0;
cubebottom[1].verts[2][1] =-verts_height;
- cubebottom[1].verts[2][2] =-1.0;
+ cubebottom[1].verts[2][2] =-1.0;
cubebottom[1].u[2] = uv_ratio;
cubebottom[1].v[2] = uv_base;
@@ -963,7 +963,7 @@ void KX_Dome::CreateMeshDome250(void)
cubetop.resize(4*nfacestop);
SplitFace(cubetop,&nfacestop);
cubebottom.resize(4*nfacesbottom);
- SplitFace(cubebottom,&nfacesbottom);
+ SplitFace(cubebottom,&nfacesbottom);
cubeleft.resize(4*nfacesleft);
SplitFace(cubeleft,&nfacesleft);
cuberight.resize(4*nfacesright);
@@ -986,13 +986,13 @@ void KX_Dome::CreateMeshDome250(void)
//flatten onto xz plane
for (i=0;i<nfacesfront;i++)
- FlattenDome(cubefront[i].verts);
+ FlattenDome(cubefront[i].verts);
for (i=0;i<nfacestop;i++)
FlattenDome(cubetop[i].verts);
for (i=0;i<nfacesbottom;i++)
FlattenDome(cubebottom[i].verts);
for (i=0;i<nfacesleft;i++)
- FlattenDome(cubeleft[i].verts);
+ FlattenDome(cubeleft[i].verts);
for (i=0;i<nfacesright;i++)
FlattenDome(cuberight[i].verts);
}
@@ -1417,7 +1417,7 @@ void KX_Dome::SplitFace(vector <DomeFace>& face, int *nfaces)
face[n2+2].u[2] = (face[i].u[2] + face[i].u[0]) /2;
face[n2+2].v[0] = (face[i].v[0] + face[i].v[1]) /2;
face[n2+2].v[1] = (face[i].v[1] + face[i].v[2]) /2;
- face[n2+2].v[2] = (face[i].v[2] + face[i].v[0]) /2;
+ face[n2+2].v[2] = (face[i].v[2] + face[i].v[0]) /2;
//face[i].verts[0] = face[i].verts[0];
face[i].verts[1] = (face[i].verts[0] + face[i].verts[1]) /2;
@@ -1427,7 +1427,7 @@ void KX_Dome::SplitFace(vector <DomeFace>& face, int *nfaces)
face[i].u[2] = (face[i].u[0] + face[i].u[2]) /2;
//face[i].v[0] = face[i].v[0];
face[i].v[1] = (face[i].v[0] + face[i].v[1]) /2;
- face[i].v[2] = (face[i].v[0] + face[i].v[2]) /2;
+ face[i].v[2] = (face[i].v[0] + face[i].v[2]) /2;
n2 += 3; // number of faces
}
@@ -1858,7 +1858,7 @@ void KX_Dome::DrawDomeFisheye(void)
glBindTexture(GL_TEXTURE_2D, domefacesId[0]);
GLDrawTriangles(cubetop, nfacestop);
- // bottom triangle
+ // bottom triangle
glBindTexture(GL_TEXTURE_2D, domefacesId[1]);
GLDrawTriangles(cubebottom, nfacesbottom);
diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp
index 931eac7a974..9f6ef894f12 100644
--- a/source/gameengine/Ketsji/KX_FontObject.cpp
+++ b/source/gameengine/Ketsji/KX_FontObject.cpp
@@ -52,7 +52,7 @@ extern "C" {
/* proptotype */
int GetFontId(VFont *font);
-std::vector<STR_String> split_string(STR_String str)
+static std::vector<STR_String> split_string(STR_String str)
{
std::vector<STR_String> text = std::vector<STR_String>();
@@ -73,10 +73,10 @@ std::vector<STR_String> split_string(STR_String str)
return text;
}
-KX_FontObject::KX_FontObject( void* sgReplicationInfo,
- SG_Callbacks callbacks,
- RAS_IRenderTools* rendertools,
- Object *ob):
+KX_FontObject::KX_FontObject(void* sgReplicationInfo,
+ SG_Callbacks callbacks,
+ RAS_IRenderTools* rendertools,
+ Object *ob):
KX_GameObject(sgReplicationInfo, callbacks),
m_object(ob),
m_dpi(72),
@@ -252,7 +252,7 @@ PyAttributeDef KX_FontObject::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_FontObject::pyattr_get_text(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_FontObject::pyattr_get_text(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_FontObject* self= static_cast<KX_FontObject*>(self_v);
STR_String str = STR_String();
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 3818cef7d6e..fe8419d5343 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -362,7 +362,7 @@ BL_ActionManager* KX_GameObject::GetActionManager()
{
// We only want to create an action manager if we need it
if (!m_actionManager)
- {
+ {
KX_GetActiveScene()->AddAnimatedObject(this);
m_actionManager = new BL_ActionManager(this);
}
@@ -690,7 +690,7 @@ void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, vo
void KX_GameObject::SetDebugColor(unsigned int bgra)
{
for (size_t i=0;i<m_meshes.size();i++)
- m_meshes[i]->DebugColor(bgra);
+ m_meshes[i]->DebugColor(bgra);
}
@@ -701,8 +701,8 @@ void KX_GameObject::ResetDebugColor()
}
void KX_GameObject::InitIPO(bool ipo_as_force,
- bool ipo_add,
- bool ipo_local)
+ bool ipo_add,
+ bool ipo_local)
{
SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
@@ -939,7 +939,7 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
vect /= len;
orimat = GetSGNode()->GetWorldOrientation();
switch (axis)
- {
+ {
case 0: //x axis
ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector parallel to the pivot?
@@ -1041,7 +1041,7 @@ MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
return locvel;
}
}
- return velocity;
+ return velocity;
}
MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
@@ -1060,7 +1060,7 @@ MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
return locvel;
}
}
- return velocity;
+ return velocity;
}
MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point)
@@ -1668,7 +1668,7 @@ PyAttributeDef KX_GameObject::Attributes[] = {
{NULL} //Sentinel
};
-PyObject* KX_GameObject::PyReplaceMesh(PyObject* args)
+PyObject *KX_GameObject::PyReplaceMesh(PyObject *args)
{
KX_Scene *scene = KX_GetActiveScene();
@@ -1686,7 +1686,7 @@ PyObject* KX_GameObject::PyReplaceMesh(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_GameObject::PyEndObject()
+PyObject *KX_GameObject::PyEndObject()
{
SG_Node* node = this->GetSGNode();
KX_Scene* scene = static_cast<KX_Scene*>(node->GetSGClientInfo());
@@ -1697,7 +1697,7 @@ PyObject* KX_GameObject::PyEndObject()
}
-PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args)
+PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args)
{
KX_GameObject *gameobj= NULL;
RAS_MeshObject *mesh= NULL;
@@ -1724,7 +1724,7 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
const char *attr_str= _PyUnicode_AsString(item);
CValue* resultattr;
- PyObject* pyconvert;
+ PyObject *pyconvert;
if (self==NULL) {
PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, "BGE_PROXY_ERROR_MSG);
@@ -1733,7 +1733,7 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
/* first see if the attributes a string and try get the cvalue attribute */
if (attr_str && (resultattr=self->GetProperty(attr_str))) {
- pyconvert = resultattr->ConvertValueToPython();
+ pyconvert = resultattr->ConvertValueToPython();
return pyconvert ? pyconvert:resultattr->GetProxy();
}
/* no CValue attribute, try get the python only m_attr_dict attribute */
@@ -1907,13 +1907,13 @@ PyTypeObject KX_GameObject::Type = {
py_base_new
};
-PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
return PyUnicode_From_STR_String(self->GetName());
}
-PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
KX_GameObject* parent = self->GetParent();
@@ -1924,7 +1924,7 @@ PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE
Py_RETURN_NONE;
}
-PyObject* KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
@@ -1937,7 +1937,7 @@ PyObject* KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF
Py_RETURN_NONE;
}
-PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
KX_IPhysicsController *spc = self->GetPhysicsController();
@@ -1960,7 +1960,7 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
KX_IPhysicsController *spc = self->GetPhysicsController();
@@ -1983,7 +1983,7 @@ int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
KX_IPhysicsController *spc = self->GetPhysicsController();
@@ -2007,7 +2007,7 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF
}
-PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
return PyBool_FromLong(self->GetVisible());
@@ -2027,7 +2027,7 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
@@ -2049,11 +2049,11 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
-#ifdef USE_MATHUTILS
+#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
-#else
+#else
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetLocalPosition());
#endif
@@ -2071,7 +2071,7 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
@@ -2083,7 +2083,7 @@ PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIB
#endif
}
-PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
@@ -2108,7 +2108,7 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
@@ -2132,7 +2132,7 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
@@ -2154,7 +2154,7 @@ int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DE
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
@@ -2176,7 +2176,7 @@ int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DE
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_localTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_localTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
@@ -2222,7 +2222,7 @@ int KX_GameObject::pyattr_set_localTransform(void *self_v, const KX_PYATTRIBUTE_
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_worldTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_worldTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
@@ -2256,7 +2256,7 @@ int KX_GameObject::pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL);
@@ -2278,7 +2278,7 @@ int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRI
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL);
@@ -2300,7 +2300,7 @@ int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRI
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL);
@@ -2322,7 +2322,7 @@ int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTR
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL);
@@ -2345,7 +2345,7 @@ int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTR
}
-PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
SG_Node* sg_parent;
@@ -2372,7 +2372,7 @@ int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
int state = 0;
@@ -2400,7 +2400,7 @@ int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attr
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
PyObject *meshes= PyList_New(self->m_meshes.size());
@@ -2415,7 +2415,7 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE
return meshes;
}
-PyObject* KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR);
@@ -2437,35 +2437,35 @@ int KX_GameObject::pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *at
}
/* These are experimental! */
-PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
}
-PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS);
}
-PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
}
/* End experimental */
-PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
return self->GetChildren()->NewProxy(true);
}
-PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
return self->GetChildrenRecursive()->NewProxy(true);
}
-PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
@@ -2476,10 +2476,10 @@ PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_
return self->m_attr_dict;
}
-PyObject* KX_GameObject::PyApplyForce(PyObject* args)
+PyObject *KX_GameObject::PyApplyForce(PyObject *args)
{
int local = 0;
- PyObject* pyvect;
+ PyObject *pyvect;
if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) {
MT_Vector3 force;
@@ -2491,10 +2491,10 @@ PyObject* KX_GameObject::PyApplyForce(PyObject* args)
return NULL;
}
-PyObject* KX_GameObject::PyApplyTorque(PyObject* args)
+PyObject *KX_GameObject::PyApplyTorque(PyObject *args)
{
int local = 0;
- PyObject* pyvect;
+ PyObject *pyvect;
if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) {
MT_Vector3 torque;
@@ -2506,10 +2506,10 @@ PyObject* KX_GameObject::PyApplyTorque(PyObject* args)
return NULL;
}
-PyObject* KX_GameObject::PyApplyRotation(PyObject* args)
+PyObject *KX_GameObject::PyApplyRotation(PyObject *args)
{
int local = 0;
- PyObject* pyvect;
+ PyObject *pyvect;
if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) {
MT_Vector3 rotation;
@@ -2521,10 +2521,10 @@ PyObject* KX_GameObject::PyApplyRotation(PyObject* args)
return NULL;
}
-PyObject* KX_GameObject::PyApplyMovement(PyObject* args)
+PyObject *KX_GameObject::PyApplyMovement(PyObject *args)
{
int local = 0;
- PyObject* pyvect;
+ PyObject *pyvect;
if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) {
MT_Vector3 movement;
@@ -2536,7 +2536,7 @@ PyObject* KX_GameObject::PyApplyMovement(PyObject* args)
return NULL;
}
-PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args)
+PyObject *KX_GameObject::PyGetLinearVelocity(PyObject *args)
{
// only can get the velocity if we have a physics object connected to us...
int local = 0;
@@ -2550,10 +2550,10 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args)
}
}
-PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args)
+PyObject *KX_GameObject::PySetLinearVelocity(PyObject *args)
{
int local = 0;
- PyObject* pyvect;
+ PyObject *pyvect;
if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) {
MT_Vector3 velocity;
@@ -2565,7 +2565,7 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args)
return NULL;
}
-PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args)
+PyObject *KX_GameObject::PyGetAngularVelocity(PyObject *args)
{
// only can get the velocity if we have a physics object connected to us...
int local = 0;
@@ -2579,10 +2579,10 @@ PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args)
}
}
-PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args)
+PyObject *KX_GameObject::PySetAngularVelocity(PyObject *args)
{
int local = 0;
- PyObject* pyvect;
+ PyObject *pyvect;
if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) {
MT_Vector3 velocity;
@@ -2594,7 +2594,7 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args)
return NULL;
}
-PyObject* KX_GameObject::PySetVisible(PyObject* args)
+PyObject *KX_GameObject::PySetVisible(PyObject *args)
{
int visible, recursive = 0;
if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive))
@@ -2606,7 +2606,7 @@ PyObject* KX_GameObject::PySetVisible(PyObject* args)
}
-PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
+PyObject *KX_GameObject::PySetOcclusion(PyObject *args)
{
int occlusion, recursive = 0;
if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive))
@@ -2616,11 +2616,11 @@ PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
+PyObject *KX_GameObject::PyGetVelocity(PyObject *args)
{
// only can get the velocity if we have a physics object connected to us...
MT_Point3 point(0.0,0.0,0.0);
- PyObject* pypos = NULL;
+ PyObject *pypos = NULL;
if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point)))
return NULL;
@@ -2634,7 +2634,7 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
}
}
-PyObject* KX_GameObject::PyGetReactionForce()
+PyObject *KX_GameObject::PyGetReactionForce()
{
// only can get the velocity if we have a physics object connected to us...
@@ -2651,7 +2651,7 @@ PyObject* KX_GameObject::PyGetReactionForce()
-PyObject* KX_GameObject::PyEnableRigidBody()
+PyObject *KX_GameObject::PyEnableRigidBody()
{
if (GetPhysicsController())
GetPhysicsController()->setRigidBody(true);
@@ -2661,7 +2661,7 @@ PyObject* KX_GameObject::PyEnableRigidBody()
-PyObject* KX_GameObject::PyDisableRigidBody()
+PyObject *KX_GameObject::PyDisableRigidBody()
{
if (GetPhysicsController())
GetPhysicsController()->setRigidBody(false);
@@ -2670,10 +2670,10 @@ PyObject* KX_GameObject::PyDisableRigidBody()
}
-PyObject* KX_GameObject::PySetParent(PyObject* args)
+PyObject *KX_GameObject::PySetParent(PyObject *args)
{
KX_Scene *scene = KX_GetActiveScene();
- PyObject* pyobj;
+ PyObject *pyobj;
KX_GameObject *obj;
int addToCompound=1, ghost=1;
@@ -2687,7 +2687,7 @@ PyObject* KX_GameObject::PySetParent(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_GameObject::PyRemoveParent()
+PyObject *KX_GameObject::PyRemoveParent()
{
KX_Scene *scene = KX_GetActiveScene();
@@ -2696,7 +2696,7 @@ PyObject* KX_GameObject::PyRemoveParent()
}
-PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value)
+PyObject *KX_GameObject::PySetCollisionMargin(PyObject *value)
{
float collisionMargin = PyFloat_AsDouble(value);
@@ -2716,10 +2716,10 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value)
-PyObject* KX_GameObject::PyApplyImpulse(PyObject* args)
+PyObject *KX_GameObject::PyApplyImpulse(PyObject *args)
{
- PyObject* pyattach;
- PyObject* pyimpulse;
+ PyObject *pyattach;
+ PyObject *pyimpulse;
if (!m_pPhysicsController1) {
PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
@@ -2743,7 +2743,7 @@ PyObject* KX_GameObject::PyApplyImpulse(PyObject* args)
-PyObject* KX_GameObject::PySuspendDynamics()
+PyObject *KX_GameObject::PySuspendDynamics()
{
SuspendDynamics();
Py_RETURN_NONE;
@@ -2751,16 +2751,16 @@ PyObject* KX_GameObject::PySuspendDynamics()
-PyObject* KX_GameObject::PyRestoreDynamics()
+PyObject *KX_GameObject::PyRestoreDynamics()
{
RestoreDynamics();
Py_RETURN_NONE;
}
-PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
+PyObject *KX_GameObject::PyAlignAxisToVect(PyObject *args)
{
- PyObject* pyvect;
+ PyObject *pyvect;
int axis = 2; //z axis is the default
float fac = 1.0f;
@@ -2780,7 +2780,7 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
return NULL;
}
-PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
+PyObject *KX_GameObject::PyGetAxisVect(PyObject *value)
{
MT_Vector3 vect;
if (PyVecTo(value, vect))
@@ -2791,7 +2791,7 @@ PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
}
-PyObject* KX_GameObject::PyGetPhysicsId()
+PyObject *KX_GameObject::PyGetPhysicsId()
{
KX_IPhysicsController* ctrl = GetPhysicsController();
uint_ptr physid=0;
@@ -2802,7 +2802,7 @@ PyObject* KX_GameObject::PyGetPhysicsId()
return PyLong_FromSsize_t((long)physid);
}
-PyObject* KX_GameObject::PyGetPropertyNames()
+PyObject *KX_GameObject::PyGetPropertyNames()
{
PyObject *list= ConvertKeysToPython();
@@ -2932,7 +2932,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
" other = 3-tuple or object reference")
{
MT_Point3 toPoint;
- PyObject* pyarg;
+ PyObject *pyarg;
float dist = 0.0f;
char *propName = NULL;
@@ -3050,8 +3050,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
{
MT_Point3 toPoint;
MT_Point3 fromPoint;
- PyObject* pyto;
- PyObject* pyfrom = NULL;
+ PyObject *pyto;
+ PyObject *pyfrom = NULL;
float dist = 0.0f;
char *propName = NULL;
KX_GameObject *other;
@@ -3125,7 +3125,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
if (m_pHitObject)
{
- PyObject* returnValue = (poly==2) ? PyTuple_New(5) : (poly) ? PyTuple_New(4) : PyTuple_New(3);
+ PyObject *returnValue = (poly == 2) ? PyTuple_New(5) : (poly) ? PyTuple_New(4) : PyTuple_New(3);
if (returnValue) { // unlikely this would ever fail, if it does python sets an error
PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy());
PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
@@ -3301,11 +3301,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, isPlayingAction,
/* Matches python dict.get(key, [default]) */
-PyObject* KX_GameObject::Pyget(PyObject *args)
+PyObject *KX_GameObject::Pyget(PyObject *args)
{
PyObject *key;
- PyObject* def = Py_None;
- PyObject* ret;
+ PyObject *def = Py_None;
+ PyObject *ret;
if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
return NULL;
@@ -3331,7 +3331,7 @@ PyObject* KX_GameObject::Pyget(PyObject *args)
return def;
}
-bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
+bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
{
if (value==NULL) {
PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 2b0d13ff2f7..ea75ca4a917 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -68,7 +68,7 @@ struct bAction;
#ifdef WITH_PYTHON
/* utility conversion function */
-bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix);
+bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_none_ok, const char *error_prefix);
#endif
#ifdef USE_MATHUTILS
@@ -159,7 +159,7 @@ public:
* side effect of storing the result internally. The
* memory for the matrix remains the property of this class.
*/
- double*
+ double *
GetOpenGLMatrix(
);
@@ -170,7 +170,7 @@ public:
* memory for the returned matrix.
*/
- MT_CmMatrix4x4*
+ MT_CmMatrix4x4 *
GetOpenGLMatrixPtr(
) {
return &m_OpenGL_4x4Matrix;
@@ -193,18 +193,18 @@ public:
* object. It is the responsibility of the caller to decrement
* the reference count when you have finished with it.
*/
- KX_GameObject*
+ KX_GameObject*
GetParent(
);
/**
* Sets the parent of this object to a game object
- */
+ */
void SetParent(KX_Scene *scene, KX_GameObject *obj, bool addToCompound=true, bool ghost=true);
/**
* Removes the parent of this object to a game object
- */
+ */
void RemoveParent(KX_Scene *scene);
/*********************************
@@ -292,7 +292,7 @@ public:
/**
* Inherited from CValue -- does nothing!
*/
- CValue*
+ CValue*
Calc(
VALUE_OPERATOR op,
CValue *val
@@ -301,7 +301,7 @@ public:
/**
* Inherited from CValue -- does nothing!
*/
- CValue*
+ CValue*
CalcFinal(
VALUE_DATA_TYPE dtype,
VALUE_OPERATOR op,
@@ -312,7 +312,7 @@ public:
* Inherited from CValue -- does nothing!
*/
const
- STR_String &
+ STR_String &
GetText(
);
@@ -331,14 +331,14 @@ public:
/**
* Inherited from CValue -- returns the name of this object.
*/
- STR_String&
+ STR_String&
GetName(
);
/**
* Inherited from CValue -- set the name of this object.
*/
- void
+ void
SetName(
const char *name
);
@@ -348,7 +348,7 @@ public:
* instance allocated on the heap. Ownership of the new
* object belongs with the caller.
*/
- virtual CValue*
+ virtual CValue*
GetReplica(
);
@@ -356,7 +356,7 @@ public:
* Inherited from CValue -- Makes sure any internal
* data owned by this class is deep copied. Called internally
*/
- virtual void
+ virtual void
ProcessReplica();
/**
@@ -379,7 +379,7 @@ public:
/**
* Return the mass of the object
*/
- MT_Scalar
+ MT_Scalar
GetMass();
/**
@@ -410,7 +410,7 @@ public:
* Quick'n'dirty obcolor ipo stuff
*/
- void
+ void
SetObjectColor(
const MT_Vector4& rgbavec
);
@@ -482,7 +482,7 @@ public:
// adapt local position so that world position is set to desired position
void NodeSetWorldPosition(const MT_Point3& trans);
- void
+ void
NodeUpdateGS(
double time
);
@@ -504,7 +504,7 @@ public:
return m_pSGNode;
}
- const SG_Node* GetSGNode( ) const
+ const SG_Node* GetSGNode( ) const
{
return m_pSGNode;
}
@@ -581,48 +581,48 @@ public:
* place.
*/
- void
+ void
ApplyForce(
const MT_Vector3& force, bool local
);
- void
+ void
ApplyTorque(
const MT_Vector3& torque,
bool local
);
- void
+ void
ApplyRotation(
const MT_Vector3& drot,
bool local
);
- void
+ void
ApplyMovement(
const MT_Vector3& dloc,
bool local
);
- void
+ void
addLinearVelocity(
const MT_Vector3& lin_vel,
bool local
);
- void
+ void
setLinearVelocity(
const MT_Vector3& lin_vel,
bool local
);
- void
+ void
setAngularVelocity(
const MT_Vector3& ang_vel,
bool local
);
- /**
+ /**
* Update the physics object transform based upon the current SG_Node
* position.
*/
@@ -642,7 +642,7 @@ public:
/**
* Function to set IPO option at start of IPO
*/
- void
+ void
InitIPO(
bool ipo_as_force,
bool ipo_add,
@@ -652,7 +652,7 @@ public:
/**
* Odd function to update an ipo. ???
*/
- void
+ void
UpdateIPO(
float curframetime,
bool recurse
@@ -676,20 +676,20 @@ public:
* \section Mesh accessor functions.
*/
- /**
+ /**
* Update buckets to indicate that there is a new
* user of this object's meshes.
*/
- void
+ void
AddMeshUser(
);
- /**
+ /**
* Update buckets with data about the mesh after
* creating or duplicating the object, changing
* visibility, object color, .. .
*/
- void
+ void
UpdateBuckets(
bool recursive
);
@@ -699,7 +699,7 @@ public:
* and remove from the bucketing system.
* Don't think this actually deletes any of the meshes.
*/
- void
+ void
RemoveMeshes(
);
@@ -709,7 +709,7 @@ public:
* Make sure you call RemoveMeshes() before deleting the
* mesh though,
*/
- void
+ void
AddMesh(
RAS_MeshObject* mesh
) {
@@ -719,7 +719,7 @@ public:
/**
* Pick out a mesh associated with the integer 'num'.
*/
- RAS_MeshObject*
+ RAS_MeshObject*
GetMesh(
int num
) const {
@@ -730,17 +730,17 @@ public:
* Return the number of meshes currently associated with this
* game object.
*/
- int
+ int
GetMeshCount(
) const {
return m_meshes.size();
}
- /**
+ /**
* Set the debug color of the meshes associated with this
* class. Does this still work?
*/
- void
+ void
SetDebugColor(
unsigned int bgra
);
@@ -748,7 +748,7 @@ public:
/**
* Reset the debug color of meshes associated with this class.
*/
- void
+ void
ResetDebugColor(
);
@@ -855,7 +855,7 @@ public:
m_bSuspendDynamics = true;
}
- void RestoreDynamics(void) {
+ void RestoreDynamics(void) {
if (!m_bSuspendDynamics)
{
return;
@@ -887,7 +887,7 @@ public:
/**
* \section Python interface functions.
*/
- virtual PyObject* py_repr(void)
+ virtual PyObject *py_repr(void)
{
return PyUnicode_From_STR_String(GetName());
}
@@ -983,7 +983,7 @@ public:
static PyObject* pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static int pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_IInterpolator.h b/source/gameengine/Ketsji/KX_IInterpolator.h
index 6ca44e1f6e5..6c0bf2d85cc 100644
--- a/source/gameengine/Ketsji/KX_IInterpolator.h
+++ b/source/gameengine/Ketsji/KX_IInterpolator.h
@@ -38,7 +38,7 @@
#include "MEM_guardedalloc.h"
#endif
-class KX_IInterpolator {
+class KX_IInterpolator {
public:
virtual ~KX_IInterpolator() {}
diff --git a/source/gameengine/Ketsji/KX_IScalarInterpolator.h b/source/gameengine/Ketsji/KX_IScalarInterpolator.h
index 2b5aefccfe7..1e822c49c6d 100644
--- a/source/gameengine/Ketsji/KX_IScalarInterpolator.h
+++ b/source/gameengine/Ketsji/KX_IScalarInterpolator.h
@@ -36,7 +36,7 @@
#include "MEM_guardedalloc.h"
#endif
-class KX_IScalarInterpolator {
+class KX_IScalarInterpolator {
public:
virtual ~KX_IScalarInterpolator() {}
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
index 5599f3e31c6..5ea7a2e7394 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.cpp
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -182,7 +182,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
m_bIpoPlaying = true;
bIpoStart = true;
}
- }
+ }
switch ((IpoActType)m_type)
{
@@ -254,7 +254,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
result = false;
if (bIpoStart)
- ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
+ ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
break;
}
@@ -309,7 +309,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
bIpoStart = true;
}
else
- {
+ {
/* Perform clamping */
m_localtime=m_endframe;
result = false;
@@ -453,7 +453,7 @@ PyAttributeDef KX_IpoActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_IpoActuator::pyattr_get_frame_start(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_IpoActuator::pyattr_get_frame_start(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_IpoActuator* self= static_cast<KX_IpoActuator*>(self_v);
return PyFloat_FromDouble(self->m_startframe);
@@ -474,7 +474,7 @@ int KX_IpoActuator::pyattr_set_frame_start(void *self_v, const KX_PYATTRIBUTE_DE
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_IpoActuator::pyattr_get_frame_end(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_IpoActuator::pyattr_get_frame_end(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_IpoActuator* self= static_cast<KX_IpoActuator*>(self_v);
return PyFloat_FromDouble(self->m_endframe);
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index a560b606f5b..c2857141058 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -253,7 +253,7 @@ void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer)
* At the moment the bge.logic module is imported into 'pythondictionary' after this function is called.
* if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand.
*/
-void KX_KetsjiEngine::SetPyNamespace(PyObject* pythondictionary)
+void KX_KetsjiEngine::SetPyNamespace(PyObject *pythondictionary)
{
MT_assert(pythondictionary);
m_pythondictionary = pythondictionary;
@@ -361,7 +361,7 @@ void KX_KetsjiEngine::RenderDome()
// no FlushDebugLines
}
m_dome->BindImages(i);
- }
+ }
m_canvas->EndFrame();//XXX do we really need that?
@@ -391,7 +391,7 @@ void KX_KetsjiEngine::RenderDome()
// Draw Callback for the last scene
#ifdef WITH_PYTHON
scene->RunDrawingCallbacks(scene->GetPostDrawCB());
-#endif
+#endif
EndFrame();
}
@@ -477,7 +477,7 @@ void KX_KetsjiEngine::ClearFrame()
SetBackGround(firstscene->GetWorldInfo());
m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(),
- clearvp.GetRight(), clearvp.GetTop());
+ clearvp.GetRight(), clearvp.GetTop());
m_rasterizer->ClearColorBuffer();
}
}
@@ -498,7 +498,7 @@ bool KX_KetsjiEngine::BeginFrame()
}
return false;
-}
+}
void KX_KetsjiEngine::EndFrame()
@@ -641,7 +641,7 @@ else
scene->GetPhysicsEnvironment()->endFrame();
// Update scenegraph after physics step. This maps physics calculations
- // into node positions.
+ // into node positions.
//m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
//SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE);
//scene->UpdateParents(m_frameTime);
@@ -692,7 +692,7 @@ else
if (m_animation_record)
- {
+ {
m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame);
}
@@ -725,7 +725,7 @@ else
bool bUseAsyncLogicBricks= false;//true;
if (bUseAsyncLogicBricks)
- {
+ {
// Logic update sub frame: this will let some logic bricks run at the
// full frame rate.
for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
@@ -756,7 +756,7 @@ else
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep);
// Update scenegraph after physics step. This maps physics calculations
- // into node positions.
+ // into node positions.
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_PHYSICS2);
scene->UpdateParents(m_clockTime);
@@ -938,7 +938,7 @@ void KX_KetsjiEngine::Render()
//RenderFrame(scene);
RenderFrame(scene, cam);
- list<class KX_Camera*>* cameras = scene->GetCameras();
+ list<class KX_Camera*>* cameras = scene->GetCameras();
// Draw the scene once for each camera with an enabled viewport
list<KX_Camera*>::iterator it = cameras->begin();
@@ -1013,7 +1013,7 @@ void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
if (wi->hasWorld())
{
if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
- {
+ {
m_rasterizer->SetBackColor(
wi->getBackColorRed(),
wi->getBackColorGreen(),
@@ -1038,7 +1038,7 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
);
if (m_drawingmode >= RAS_IRasterizer::KX_SOLID)
- {
+ {
if (wi->hasMist())
{
m_rasterizer->SetFog(
@@ -1203,11 +1203,11 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
GetSceneViewport(scene, cam, area, viewport);
// store the computed viewport in the scene
- scene->SetSceneViewport(viewport);
+ scene->SetSceneViewport(viewport);
// set the viewport for this frame and scene
m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(),
- viewport.GetRight(), viewport.GetTop());
+ viewport.GetRight(), viewport.GetTop());
// see KX_BlenderMaterial::Activate
//m_rasterizer->SetAmbient();
@@ -1348,7 +1348,7 @@ void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene)
m_rasterizer->FlushDebugShapes();
scene->Render2DFilters(m_canvas);
#ifdef WITH_PYTHON
- scene->RunDrawingCallbacks(scene->GetPostDrawCB());
+ scene->RunDrawingCallbacks(scene->GetPostDrawCB());
#endif
}
@@ -1368,10 +1368,10 @@ void KX_KetsjiEngine::StopEngine()
{
KX_Scene* scene = *sceneit;
m_sceneconverter->RemoveScene(scene);
- }
+ }
m_scenes.clear();
- // cleanup all the stuff
+ // cleanup all the stuff
m_rasterizer->Exit();
}
}
@@ -1469,7 +1469,7 @@ void KX_KetsjiEngine::RenderDebugProperties()
/* Profile and framerate display */
if (m_show_profile)
- {
+ {
for (int j = tc_first; j < tc_numCategories; j++)
{
debugtxt.Format(m_profileLabels[j]);
@@ -1556,7 +1556,7 @@ void KX_KetsjiEngine::RenderDebugProperties()
KX_SceneList* KX_KetsjiEngine::CurrentScenes()
{
- return &m_scenes;
+ return &m_scenes;
}
@@ -1572,7 +1572,7 @@ KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename)
sceneit++;
}
- return ((sceneit == m_scenes.end()) ? NULL : *sceneit);
+ return ((sceneit == m_scenes.end()) ? NULL : *sceneit);
}
@@ -1635,7 +1635,7 @@ void KX_KetsjiEngine::RemoveScheduledScenes()
m_scenes.erase(sceneit);
break;
}
- }
+ }
}
m_removingScenes.clear();
}
@@ -1737,7 +1737,7 @@ void KX_KetsjiEngine::ReplaceScheduledScenes()
}
}
m_replace_scenes.clear();
- }
+ }
}
@@ -1910,7 +1910,7 @@ void KX_KetsjiEngine::SceneListsChanged(void)
while ((sceneit != m_scenes.end()) && (!m_propertiesPresent))
{
KX_Scene* scene = *sceneit;
- vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
+ vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
m_propertiesPresent = !debugproplist.empty();
sceneit++;
}
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index b3bef016b0f..e05ba652bbe 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -98,7 +98,7 @@ private:
/* The current list of scenes. */
KX_SceneList m_scenes;
/* State variable recording the presence of object debug info in the current scene list. */
- bool m_propertiesPresent;
+ bool m_propertiesPresent;
bool m_bInitialized;
int m_activecam;
@@ -136,7 +136,7 @@ private:
int m_drawingmode;
float m_cameraZoom;
- bool m_overrideCam;
+ bool m_overrideCam;
STR_String m_overrideSceneName;
bool m_overrideCamUseOrtho;
@@ -220,7 +220,7 @@ public:
void SetRenderTools(RAS_IRenderTools* rendertools);
void SetRasterizer(RAS_IRasterizer* rasterizer);
#ifdef WITH_PYTHON
- void SetPyNamespace(PyObject* pythondictionary);
+ void SetPyNamespace(PyObject *pythondictionary);
PyObject* GetPyNamespace() { return m_pythondictionary; }
#endif
void SetSceneConverter(KX_ISceneConverter* sceneconverter);
@@ -415,7 +415,7 @@ public:
KX_Scene* CreateScene(const STR_String& scenename);
KX_Scene* CreateScene(Scene *scene);
- GlobalSettings* GetGlobalSettings(void);
+ GlobalSettings* GetGlobalSettings(void);
void SetGlobalSettings(GlobalSettings* gs);
protected:
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index f5aa1bb3c75..8b80daa75d3 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -344,7 +344,7 @@ PyAttributeDef KX_LightObject::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return Py_BuildValue("[fff]", self->m_lightobj.m_red, self->m_lightobj.m_green, self->m_lightobj.m_blue);
@@ -365,9 +365,9 @@ int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *att
return PY_SET_ATTR_FAIL;
}
-PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- PyObject* retvalue;
+ PyObject *retvalue;
const char* type = attrdef->m_name;
@@ -387,13 +387,13 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT
return retvalue;
}
-PyObject* KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyLong_FromSsize_t(self->m_lightobj.m_type);
}
-int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value)
+int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
int val = PyLong_AsSsize_t(value);
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 9fe13f471ba..7426896a92a 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -76,10 +76,10 @@ public:
#ifdef WITH_PYTHON
/* attributes */
static PyObject* pyattr_get_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value);
+ static int pyattr_set_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_typeconst(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value);
+ static int pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif
};
diff --git a/source/gameengine/Ketsji/KX_LightIpoSGController.h b/source/gameengine/Ketsji/KX_LightIpoSGController.h
index 3a3a9677b04..4a1ceba0963 100644
--- a/source/gameengine/Ketsji/KX_LightIpoSGController.h
+++ b/source/gameengine/Ketsji/KX_LightIpoSGController.h
@@ -74,15 +74,15 @@ public:
m_modified = true;
}
- void SetModifyEnergy(bool modify) {
+ void SetModifyEnergy(bool modify) {
m_modify_energy = modify;
}
- void SetModifyColor(bool modify) {
+ void SetModifyColor(bool modify) {
m_modify_color = modify;
}
- void SetModifyDist(bool modify) {
+ void SetModifyDist(bool modify) {
m_modify_dist = modify;
}
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
index f1a9a93c2db..8451dc3497d 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.cpp
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -105,7 +105,7 @@ KX_MeshProxy::~KX_MeshProxy()
// stuff for cvalue related things
CValue* KX_MeshProxy::Calc(VALUE_OPERATOR op, CValue *val) { return NULL;}
-CValue* KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;}
+CValue* KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;}
const STR_String & KX_MeshProxy::GetText() {return m_meshobj->GetName();};
double KX_MeshProxy::GetNumber() { return -1;}
@@ -116,7 +116,7 @@ CValue* KX_MeshProxy::GetReplica() { return NULL;}
// stuff for python integration
-PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds)
+PyObject *KX_MeshProxy::PyGetMaterialName(PyObject *args, PyObject *kwds)
{
int matid= 1;
STR_String matname;
@@ -134,7 +134,7 @@ PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds)
}
-PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds)
+PyObject *KX_MeshProxy::PyGetTextureName(PyObject *args, PyObject *kwds)
{
int matid= 1;
STR_String matname;
@@ -151,7 +151,7 @@ PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds)
}
-PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds)
+PyObject *KX_MeshProxy::PyGetVertexArrayLength(PyObject *args, PyObject *kwds)
{
int matid= 0;
int length = 0;
@@ -174,7 +174,7 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds)
}
-PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds)
+PyObject *KX_MeshProxy::PyGetVertex(PyObject *args, PyObject *kwds)
{
int vertexindex;
int matindex;
@@ -192,10 +192,10 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds)
return (new KX_VertexProxy(this, vertex))->NewProxy(true);
}
-PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds)
+PyObject *KX_MeshProxy::PyGetPolygon(PyObject *args, PyObject *kwds)
{
int polyindex= 1;
- PyObject* polyob = NULL;
+ PyObject *polyob = NULL;
if (!PyArg_ParseTuple(args,"i:getPolygon",&polyindex))
return NULL;
@@ -218,7 +218,7 @@ PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds)
return polyob;
}
-PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MeshProxy* self= static_cast<KX_MeshProxy*>(self_v);
@@ -233,7 +233,7 @@ PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_
for (i=0; i<tot; mit++, i++) {
RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial();
- /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
+ /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject *)? - Campbell */
if (polymat->GetFlag() & RAS_BLENDERMAT)
{
KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat);
@@ -243,7 +243,7 @@ PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_
KX_PolygonMaterial *mat = static_cast<KX_PolygonMaterial*>(polymat);
PyList_SET_ITEM(materials, i, mat->GetProxy());
}
- }
+ }
return materials;
}
@@ -260,7 +260,7 @@ PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBU
}
/* a close copy of ConvertPythonToGameObject but for meshes */
-bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix)
+bool ConvertPythonToMesh(PyObject *value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix)
{
if (value==NULL) {
PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
@@ -297,7 +297,7 @@ bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none
if (kx_mesh==NULL) {
PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
return false;
- }
+ }
*object = kx_mesh->GetMesh();
return true;
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h
index 58b5c87e494..a05ef6ab2e7 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.h
+++ b/source/gameengine/Ketsji/KX_MeshProxy.h
@@ -37,7 +37,7 @@
#include "SCA_IObject.h"
/* utility conversion function */
-bool ConvertPythonToMesh(PyObject * value, class RAS_MeshObject **object, bool py_none_ok, const char *error_prefix);
+bool ConvertPythonToMesh(PyObject *value, class RAS_MeshObject **object, bool py_none_ok, const char *error_prefix);
class KX_MeshProxy : public CValue
{
@@ -73,8 +73,8 @@ public:
KX_PYMETHOD(KX_MeshProxy,GetPolygon);
static PyObject* pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject * pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
- static PyObject * pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
+ static PyObject *pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
+ static PyObject *pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
};
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index bfee124d443..3251cc4af46 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -239,7 +239,7 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
/* build the from and to point in normalized device coordinates
* Normalized device coordinates are [-1,1] in x, y, z
- *
+ *
* The actual z coordinates used don't have to be exact just infront and
* behind of the near and far clip planes.
*/
@@ -392,19 +392,19 @@ PyAttributeDef KX_MouseFocusSensor::Attributes[] = {
};
/* Attributes */
-PyObject* KX_MouseFocusSensor::pyattr_get_ray_source(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_MouseFocusSensor::pyattr_get_ray_source(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
return PyObjectFrom(self->RaySource());
}
-PyObject* KX_MouseFocusSensor::pyattr_get_ray_target(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_MouseFocusSensor::pyattr_get_ray_target(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
return PyObjectFrom(self->RayTarget());
}
-PyObject* KX_MouseFocusSensor::pyattr_get_ray_direction(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_MouseFocusSensor::pyattr_get_ray_direction(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
MT_Vector3 dir = self->RayTarget() - self->RaySource();
@@ -413,7 +413,7 @@ PyObject* KX_MouseFocusSensor::pyattr_get_ray_direction(void *self_v, const KX_P
return PyObjectFrom(dir);
}
-PyObject* KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
@@ -423,19 +423,19 @@ PyObject* KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYAT
Py_RETURN_NONE;
}
-PyObject* KX_MouseFocusSensor::pyattr_get_hit_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_MouseFocusSensor::pyattr_get_hit_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
return PyObjectFrom(self->HitPosition());
}
-PyObject* KX_MouseFocusSensor::pyattr_get_hit_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_MouseFocusSensor::pyattr_get_hit_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
return PyObjectFrom(self->HitNormal());
}
-PyObject* KX_MouseFocusSensor::pyattr_get_hit_uv(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_MouseFocusSensor::pyattr_get_hit_uv(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
return PyObjectFrom(self->HitUV());
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
index 35058e5fe5d..a05292f268a 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
@@ -210,7 +210,7 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
{
//detailed mesh vertex
memcpy(dvertices+3*(newIdx-nverts), allVerts+3*vi, 3*sizeof(float));
- }
+ }
}
}
@@ -245,7 +245,7 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
{
memset(vert, 0, 3*sizeof(float)); //vertex isn't in any poly, set dummy zero coordinates
}
- vert+=3;
+ vert+=3;
}
//create tris
@@ -294,7 +294,7 @@ bool KX_NavMeshObject::BuildNavMesh()
float *vertices = NULL, *dvertices = NULL;
unsigned short *polys = NULL, *dtris = NULL, *dmeshes = NULL;
- int nverts = 0, npolys = 0, ndvertsuniq = 0, ndtris = 0;
+ int nverts = 0, npolys = 0, ndvertsuniq = 0, ndtris = 0;
int vertsPerPoly = 0;
if (!BuildVertIndArrays(vertices, nverts, polys, npolys,
dmeshes, dvertices, ndvertsuniq, dtris, ndtris, vertsPerPoly )
@@ -446,11 +446,11 @@ bool KX_NavMeshObject::BuildNavMesh()
dtl.nverts = dmeshes[i*4+1];
dtl.tbase = dmeshes[i*4+2];
dtl.ntris = dmeshes[i*4+3];
- }
+ }
}
m_navMesh = new dtStatNavMesh;
- m_navMesh->init(data, dataSize, true);
+ m_navMesh->init(data, dataSize, true);
delete [] vertices;
@@ -487,7 +487,7 @@ void KX_NavMeshObject::DrawNavMesh(NavMeshRenderMode renderMode)
const dtStatPoly* poly = m_navMesh->getPoly(pi);
for (int i = 0, j = (int)poly->nv-1; i < (int)poly->nv; j = i++)
- {
+ {
if (poly->n[j] && renderMode==RM_WALLS)
continue;
const float* vif = m_navMesh->getVertex(poly->v[i]);
@@ -564,7 +564,7 @@ int KX_NavMeshObject::FindPath(const MT_Point3& from, const MT_Point3& to, float
if (!m_navMesh)
return 0;
MT_Point3 localfrom = TransformToLocalCoords(from);
- MT_Point3 localto = TransformToLocalCoords(to);
+ MT_Point3 localto = TransformToLocalCoords(to);
float spos[3], epos[3];
localfrom.getValue(spos); flipAxes(spos);
localto.getValue(epos); flipAxes(epos);
@@ -598,7 +598,7 @@ float KX_NavMeshObject::Raycast(const MT_Point3& from, const MT_Point3& to)
if (!m_navMesh)
return 0.f;
MT_Point3 localfrom = TransformToLocalCoords(from);
- MT_Point3 localto = TransformToLocalCoords(to);
+ MT_Point3 localto = TransformToLocalCoords(to);
float spos[3], epos[3];
localfrom.getValue(spos); flipAxes(spos);
localto.getValue(epos); flipAxes(epos);
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
index a3f098c3b1f..f35090f9e9b 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -460,7 +460,7 @@ Mathutils_Callback mathutils_obactu_vector_cb = {
mathutils_obactu_vector_set_index
};
-PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
}
@@ -476,7 +476,7 @@ int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *a
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
}
@@ -501,7 +501,7 @@ void KX_ObjectActuator_Mathutils_Callback_Init(void)
#endif // USE_MATHUTILS
-PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
PyObject *retVal = PyList_New(3);
@@ -517,7 +517,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE
{
KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
- PyObject* seq = PySequence_Fast(value, "");
+ PyObject *seq = PySequence_Fast(value, "");
if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
{
self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
@@ -537,7 +537,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE
return PY_SET_ATTR_FAIL;
}
-PyObject* KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
PyObject *retVal = PyList_New(3);
@@ -553,7 +553,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE
{
KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
- PyObject* seq = PySequence_Fast(value, "");
+ PyObject *seq = PySequence_Fast(value, "");
if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
{
self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
@@ -573,7 +573,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE
return PY_SET_ATTR_FAIL;
}
-PyObject* KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
PyObject *retVal = PyList_New(3);
@@ -589,7 +589,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE
{
KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
- PyObject* seq = PySequence_Fast(value, "");
+ PyObject *seq = PySequence_Fast(value, "");
if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
{
self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
@@ -609,7 +609,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE
return PY_SET_ATTR_FAIL;
}
-PyObject* KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
if (!actuator->m_reference)
@@ -632,7 +632,7 @@ int KX_ObjectActuator::pyattr_set_reference(void *self, const struct KX_PYATTRIB
if (refOb==NULL) {
actuator->m_reference= NULL;
}
- else {
+ else {
actuator->m_reference = refOb;
actuator->m_reference->RegisterActuator(actuator);
}
diff --git a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp
index a942f87856c..99d9fc7f9ee 100644
--- a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp
+++ b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp
@@ -257,7 +257,7 @@ void KX_ObstacleSimulation::AddObstacleForObj(KX_GameObject* gameobj)
}
void KX_ObstacleSimulation::AddObstaclesForNavMesh(KX_NavMeshObject* navmeshobj)
-{
+{
dtStatNavMesh* navmesh = navmeshobj->GetNavMesh();
if (navmesh)
{
@@ -267,7 +267,7 @@ void KX_ObstacleSimulation::AddObstaclesForNavMesh(KX_NavMeshObject* navmeshobj)
const dtStatPoly* poly = navmesh->getPoly(pi);
for (int i = 0, j = (int)poly->nv-1; i < (int)poly->nv; j = i++)
- {
+ {
if (poly->n[j]) continue;
const float* vj = navmesh->getVertex(poly->v[j]);
const float* vi = navmesh->getVertex(poly->v[i]);
@@ -364,9 +364,9 @@ void KX_ObstacleSimulation::DrawObstacles()
else if (m_obstacles[i]->m_shape==KX_OBSTACLE_CIRCLE)
{
KX_RasterizerDrawDebugCircle(m_obstacles[i]->m_pos, m_obstacles[i]->m_rad, bluecolor,
- normal, SECTORS_NUM);
+ normal, SECTORS_NUM);
}
- }
+ }
}
static MT_Point3 nearestPointToObstacle(MT_Point3& pos ,KX_Obstacle* obstacle)
@@ -424,7 +424,7 @@ KX_ObstacleSimulationTOI::KX_ObstacleSimulationTOI(MT_Scalar levelHeight, bool e
void KX_ObstacleSimulationTOI::AdjustObstacleVelocity(KX_Obstacle* activeObst, KX_NavMeshObject* activeNavMeshObj,
- MT_Vector3& velocity, MT_Scalar maxDeltaSpeed, MT_Scalar maxDeltaAngle)
+ MT_Vector3& velocity, MT_Scalar maxDeltaSpeed, MT_Scalar maxDeltaAngle)
{
int nobs = m_obstacles.size();
int obstidx = std::find(m_obstacles.begin(), m_obstacles.end(), activeObst) - m_obstacles.begin();
@@ -446,7 +446,7 @@ void KX_ObstacleSimulationTOI::AdjustObstacleVelocity(KX_Obstacle* activeObst, K
vadd(vel, activeObst->vel, dv);
velocity.x() = vel[0];
- velocity.y() = vel[1];
+ velocity.y() = vel[1];
}
///////////*********TOI_rays**********/////////////////
@@ -642,7 +642,7 @@ static void processSamples(KX_Obstacle* activeObst, KX_NavMeshObject* activeNavM
for (int n = 0; n < nspos; ++n)
{
float vcand[2];
- vcpy(vcand, &spos[n*2]);
+ vcpy(vcand, &spos[n*2]);
// Find min time of impact and exit amongst all obstacles.
float tmin = maxToi;
diff --git a/source/gameengine/Ketsji/KX_ObstacleSimulation.h b/source/gameengine/Ketsji/KX_ObstacleSimulation.h
index 5b359fc031e..50589b5bc69 100644
--- a/source/gameengine/Ketsji/KX_ObstacleSimulation.h
+++ b/source/gameengine/Ketsji/KX_ObstacleSimulation.h
@@ -34,13 +34,13 @@ class KX_GameObject;
class KX_NavMeshObject;
enum KX_OBSTACLE_TYPE
-{
+{
KX_OBSTACLE_OBJ,
KX_OBSTACLE_NAV_MESH,
};
enum KX_OBSTACLE_SHAPE
-{
+{
KX_OBSTACLE_CIRCLE,
KX_OBSTACLE_SEGMENT,
};
@@ -86,9 +86,9 @@ public:
void DestroyObstacleForObj(KX_GameObject* gameobj);
void AddObstaclesForNavMesh(KX_NavMeshObject* navmesh);
KX_Obstacle* GetObstacle(KX_GameObject* gameobj);
- void UpdateObstacles();
+ void UpdateObstacles();
virtual void AdjustObstacleVelocity(KX_Obstacle* activeObst, KX_NavMeshObject* activeNavMeshObj,
- MT_Vector3& velocity, MT_Scalar maxDeltaSpeed,MT_Scalar maxDeltaAngle);
+ MT_Vector3& velocity, MT_Scalar maxDeltaSpeed,MT_Scalar maxDeltaAngle);
};
class KX_ObstacleSimulationTOI: public KX_ObstacleSimulation
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp
index 5058af18d15..6926fdb1d4c 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp
@@ -172,10 +172,10 @@ PyAttributeDef KX_ParentActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_ParentActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_ParentActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_ParentActuator* actuator = static_cast<KX_ParentActuator*>(self);
- if (!actuator->m_ob)
+ if (!actuator->m_ob)
Py_RETURN_NONE;
else
return actuator->m_ob->GetProxy();
@@ -190,7 +190,7 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
if (actuator->m_ob != NULL)
- actuator->m_ob->UnregisterActuator(actuator);
+ actuator->m_ob->UnregisterActuator(actuator);
actuator->m_ob = (SCA_IObject*) gameobj;
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h
index 6191b889da3..f2f5acd3dfb 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.h
+++ b/source/gameengine/Ketsji/KX_ParentActuator.h
@@ -81,7 +81,7 @@ public:
/* --------------------------------------------------------------------- */
/* These are used to get and set m_ob */
- static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
index 225a1628b3b..f18c35c0c78 100644
--- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
@@ -51,7 +51,7 @@ KX_PhysicsObjectWrapper::~KX_PhysicsObjectWrapper()
#ifdef WITH_PYTHON
-PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* args)
+PyObject *KX_PhysicsObjectWrapper::PySetPosition(PyObject *args)
{
float x,y,z;
if (PyArg_ParseTuple(args,"fff:setPosition",&x,&y,&z))
@@ -65,7 +65,7 @@ PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* args)
}
-PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* args)
+PyObject *KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject *args)
{
float x,y,z;
int local;
@@ -79,7 +79,7 @@ PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* args)
+PyObject *KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject *args)
{
float x,y,z;
int local;
@@ -93,7 +93,7 @@ PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject* args)
+PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject *args)
{
int active;
if (PyArg_ParseTuple(args,"i:setActive",&active))
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp
index 85c88337d60..13b6bda4ebc 100644
--- a/source/gameengine/Ketsji/KX_PolyProxy.cpp
+++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp
@@ -102,7 +102,7 @@ KX_PolyProxy::~KX_PolyProxy()
// stuff for cvalue related things
CValue* KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
-CValue* KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}
+CValue* KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}
STR_String sPolyName="polygone";
const STR_String & KX_PolyProxy::GetText() {return sPolyName;};
double KX_PolyProxy::GetNumber() { return -1;}
@@ -112,52 +112,52 @@ CValue* KX_PolyProxy::GetReplica() { return NULL;}
// stuff for python integration
-PyObject* KX_PolyProxy::pyattr_get_material_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_material_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return self->PygetMaterialName();
}
-PyObject* KX_PolyProxy::pyattr_get_texture_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_texture_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return self->PygetTextureName();
}
-PyObject* KX_PolyProxy::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return self->PygetMaterial();
}
-PyObject* KX_PolyProxy::pyattr_get_material_id(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_material_id(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return self->PygetMaterialIndex();
}
-PyObject* KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 0));
}
-PyObject* KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 1));
}
-PyObject* KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 2));
}
-PyObject* KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
@@ -168,13 +168,13 @@ PyObject* KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *at
return PyLong_FromSsize_t(0);
}
-PyObject* KX_PolyProxy::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return self->PyisVisible();
}
-PyObject* KX_PolyProxy::pyattr_get_collide(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolyProxy::pyattr_get_collide(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self= static_cast<KX_PolyProxy*>(self_v);
return self->PyisCollider();
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h
index 83c3bff0ee2..9e3556a03f8 100644
--- a/source/gameengine/Ketsji/KX_PolyProxy.h
+++ b/source/gameengine/Ketsji/KX_PolyProxy.h
@@ -57,16 +57,16 @@ public:
// stuff for python integration
- static PyObject* pyattr_get_material_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_texture_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_material_id(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_collide(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_material_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_texture_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_material_id(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_collide(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex)
KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex)
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
index 2e39190f4f9..3b58a8abd83 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
@@ -143,7 +143,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI
{
PyObject *pyRasty = PyCapsule_New((void*)rasty, KX_POLYGONMATERIAL_CAPSULE_ID, NULL); /* new reference */
PyObject *pyCachingInfo = PyCapsule_New((void*) &cachingInfo, KX_POLYGONMATERIAL_CAPSULE_ID, NULL); /* new reference */
- PyObject *ret = PyObject_CallMethod(m_pymaterial, (char *)"activate", (char *)"(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy);
+ PyObject *ret = PyObject_CallMethod(m_pymaterial, (char *)"activate", (char *)"(NNO)", pyRasty, pyCachingInfo, (PyObject *) this->m_proxy);
if (ret)
{
bool value = PyLong_AsSsize_t(ret);
@@ -252,7 +252,7 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = {
KX_PYATTRIBUTE_INT_RW("tile", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tile),
KX_PYATTRIBUTE_INT_RW("tilexrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tilexrep),
KX_PYATTRIBUTE_INT_RW("tileyrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tileyrep),
- KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode),
+ KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode),
//KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer),
KX_PYATTRIBUTE_BOOL_RW("transparent", KX_PolygonMaterial, m_alpha),
@@ -262,7 +262,7 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = {
KX_PYATTRIBUTE_FLOAT_RW("specularity", 0.0f, 1000.0f, KX_PolygonMaterial, m_specularity),
KX_PYATTRIBUTE_RW_FUNCTION("diffuse", KX_PolygonMaterial, pyattr_get_diffuse, pyattr_set_diffuse),
- KX_PYATTRIBUTE_RW_FUNCTION("specular",KX_PolygonMaterial, pyattr_get_specular, pyattr_set_specular),
+ KX_PYATTRIBUTE_RW_FUNCTION("specular",KX_PolygonMaterial, pyattr_get_specular, pyattr_set_specular),
KX_PYATTRIBUTE_RO_FUNCTION("tface", KX_PolygonMaterial, pyattr_get_tface), /* How the heck is this even useful??? - Campbell */
KX_PYATTRIBUTE_RO_FUNCTION("gl_texture", KX_PolygonMaterial, pyattr_get_gl_texture), /* could be called 'bindcode' */
@@ -355,26 +355,26 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)")
return NULL;
}
-PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
return PyUnicode_From_STR_String(self->m_texturename);
}
-PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
return PyUnicode_From_STR_String(self->m_materialname);
}
/* this does not seem useful */
-PyObject* KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
return PyCapsule_New(&self->m_tface, KX_POLYGONMATERIAL_CAPSULE_ID, NULL);
}
-PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
int bindcode= 0;
@@ -385,7 +385,7 @@ PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATT
}
-PyObject* KX_PolygonMaterial::pyattr_get_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolygonMaterial::pyattr_get_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
return PyObjectFrom(self->m_diffuse);
@@ -403,7 +403,7 @@ int KX_PolygonMaterial::pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DE
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
return PyObjectFrom(self->m_specular);
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h
index f7ad3973212..6384008fb7d 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.h
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h
@@ -137,7 +137,7 @@ public:
KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial);
KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram);
- virtual PyObject* py_repr(void) { return PyUnicode_FromString(m_material ? ((ID *)m_material)->name+2 : ""); }
+ virtual PyObject *py_repr(void) { return PyUnicode_FromString(m_material ? ((ID *)m_material)->name+2 : ""); }
static PyObject* pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
@@ -145,9 +145,9 @@ public:
static PyObject* pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_diffuse(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_diffuse(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- static PyObject* pyattr_get_specular(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_specular(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index 556d451cf66..5f3a4879150 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -89,9 +89,9 @@ static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)
-static PyObject* gPySetGravity(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetGravity(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float x,y,z;
if (PyArg_ParseTuple(args,"fff",&x,&y,&z))
@@ -106,9 +106,9 @@ static PyObject* gPySetGravity(PyObject* self,
Py_RETURN_NONE;
}
-static PyObject* gPySetDebugMode(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetDebugMode(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
int mode;
if (PyArg_ParseTuple(args,"i",&mode))
@@ -129,9 +129,9 @@ static PyObject* gPySetDebugMode(PyObject* self,
-static PyObject* gPySetNumTimeSubSteps(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetNumTimeSubSteps(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
int substep;
if (PyArg_ParseTuple(args,"i",&substep))
@@ -148,9 +148,9 @@ static PyObject* gPySetNumTimeSubSteps(PyObject* self,
}
-static PyObject* gPySetNumIterations(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetNumIterations(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
int iter;
if (PyArg_ParseTuple(args,"i",&iter))
@@ -167,9 +167,9 @@ static PyObject* gPySetNumIterations(PyObject* self,
}
-static PyObject* gPySetDeactivationTime(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetDeactivationTime(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float deactive_time;
if (PyArg_ParseTuple(args,"f",&deactive_time))
@@ -186,9 +186,9 @@ static PyObject* gPySetDeactivationTime(PyObject* self,
}
-static PyObject* gPySetDeactivationLinearTreshold(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetDeactivationLinearTreshold(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float linearDeactivationTreshold;
if (PyArg_ParseTuple(args,"f",&linearDeactivationTreshold))
@@ -205,9 +205,9 @@ static PyObject* gPySetDeactivationLinearTreshold(PyObject* self,
}
-static PyObject* gPySetDeactivationAngularTreshold(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetDeactivationAngularTreshold(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float angularDeactivationTreshold;
if (PyArg_ParseTuple(args,"f",&angularDeactivationTreshold))
@@ -223,9 +223,9 @@ static PyObject* gPySetDeactivationAngularTreshold(PyObject* self,
Py_RETURN_NONE;
}
-static PyObject* gPySetContactBreakingTreshold(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetContactBreakingTreshold(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float contactBreakingTreshold;
if (PyArg_ParseTuple(args,"f",&contactBreakingTreshold))
@@ -242,9 +242,9 @@ static PyObject* gPySetContactBreakingTreshold(PyObject* self,
}
-static PyObject* gPySetCcdMode(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetCcdMode(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float ccdMode;
if (PyArg_ParseTuple(args,"f",&ccdMode))
@@ -260,9 +260,9 @@ static PyObject* gPySetCcdMode(PyObject* self,
Py_RETURN_NONE;
}
-static PyObject* gPySetSorConstant(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetSorConstant(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float sor;
if (PyArg_ParseTuple(args,"f",&sor))
@@ -278,9 +278,9 @@ static PyObject* gPySetSorConstant(PyObject* self,
Py_RETURN_NONE;
}
-static PyObject* gPySetSolverTau(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetSolverTau(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float tau;
if (PyArg_ParseTuple(args,"f",&tau))
@@ -297,9 +297,9 @@ static PyObject* gPySetSolverTau(PyObject* self,
}
-static PyObject* gPySetSolverDamping(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetSolverDamping(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float damping;
if (PyArg_ParseTuple(args,"f",&damping))
@@ -315,9 +315,9 @@ static PyObject* gPySetSolverDamping(PyObject* self,
Py_RETURN_NONE;
}
-static PyObject* gPySetLinearAirDamping(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetLinearAirDamping(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float damping;
if (PyArg_ParseTuple(args,"f",&damping))
@@ -334,9 +334,9 @@ static PyObject* gPySetLinearAirDamping(PyObject* self,
}
-static PyObject* gPySetUseEpa(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetUseEpa(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
int epa;
if (PyArg_ParseTuple(args,"i",&epa))
@@ -351,9 +351,9 @@ static PyObject* gPySetUseEpa(PyObject* self,
}
Py_RETURN_NONE;
}
-static PyObject* gPySetSolverType(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPySetSolverType(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
int solverType;
if (PyArg_ParseTuple(args,"i",&solverType))
@@ -371,9 +371,9 @@ static PyObject* gPySetSolverType(PyObject* self,
-static PyObject* gPyGetVehicleConstraint(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPyGetVehicleConstraint(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
#if defined(_WIN64)
__int64 constraintid;
@@ -403,9 +403,9 @@ static PyObject* gPyGetVehicleConstraint(PyObject* self,
}
-static PyObject* gPyCreateConstraint(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPyCreateConstraint(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
/* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */
#if defined(_WIN64)
@@ -435,7 +435,7 @@ static PyObject* gPyCreateConstraint(PyObject* self,
#else
success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype,
&pivotX,&pivotY,&pivotZ);
-#endif
+#endif
}
else if (len == 9)
{
@@ -521,9 +521,9 @@ static PyObject* gPyCreateConstraint(PyObject* self,
-static PyObject* gPyGetAppliedImpulse(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPyGetAppliedImpulse(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
float appliedImpulse = 0.f;
@@ -548,9 +548,9 @@ static PyObject* gPyGetAppliedImpulse(PyObject* self,
}
-static PyObject* gPyRemoveConstraint(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+static PyObject *gPyRemoveConstraint(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
#if defined(_WIN64)
__int64 constraintid;
@@ -572,7 +572,7 @@ static PyObject* gPyRemoveConstraint(PyObject* self,
Py_RETURN_NONE;
}
-static PyObject* gPyExportBulletFile(PyObject*, PyObject* args)
+static PyObject *gPyExportBulletFile(PyObject *, PyObject *args)
{
char* filename;
if (!PyArg_ParseTuple(args,"s:exportBulletFile",&filename))
@@ -655,13 +655,13 @@ static struct PyModuleDef PhysicsConstraints_module_def = {
0, /* m_free */
};
-PyObject* initPythonConstraintBinding()
+PyObject *initPythonConstraintBinding()
{
- PyObject* ErrorObject;
- PyObject* m;
- PyObject* d;
- PyObject* item;
+ PyObject *ErrorObject;
+ PyObject *m;
+ PyObject *d;
+ PyObject *item;
/* Use existing module where possible
* be careful not to init any runtime vars after this */
@@ -716,10 +716,11 @@ PyObject* initPythonConstraintBinding()
return d;
}
-
-void KX_RemovePythonConstraintBinding()
+#if 0
+static void KX_RemovePythonConstraintBinding()
{
}
+#endif
void PHY_SetActiveEnvironment(class PHY_IPhysicsEnvironment* env)
{
diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp
index f459b806d2f..bc324c3b140 100644
--- a/source/gameengine/Ketsji/KX_PyMath.cpp
+++ b/source/gameengine/Ketsji/KX_PyMath.cpp
@@ -47,7 +47,7 @@
#include "KX_Python.h"
#include "KX_PyMath.h"
-bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefix)
+bool PyOrientationTo(PyObject *pyval, MT_Matrix3x3 &rot, const char *error_prefix)
{
int size= PySequence_Size(pyval);
@@ -80,7 +80,7 @@ bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefi
return false;
}
-bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot)
+bool PyQuatTo(PyObject *pyval, MT_Quaternion &qrot)
{
if (!PyVecTo(pyval, qrot))
return false;
@@ -95,7 +95,7 @@ bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot)
return true;
}
-PyObject* PyObjectFrom(const MT_Matrix4x4 &mat)
+PyObject *PyObjectFrom(const MT_Matrix4x4 &mat)
{
#ifdef USE_MATHUTILS
float fmat[16];
@@ -119,7 +119,7 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat)
#endif
}
-PyObject* PyObjectFrom(const MT_Matrix3x3 &mat)
+PyObject *PyObjectFrom(const MT_Matrix3x3 &mat)
{
#ifdef USE_MATHUTILS
float fmat[9];
@@ -143,7 +143,7 @@ PyObject* PyObjectFrom(const MT_Matrix3x3 &mat)
}
#ifdef USE_MATHUTILS
-PyObject* PyObjectFrom(const MT_Quaternion &qrot)
+PyObject *PyObjectFrom(const MT_Quaternion &qrot)
{
/* NOTE, were re-ordering here for Mathutils compat */
float fvec[4];
@@ -152,7 +152,7 @@ PyObject* PyObjectFrom(const MT_Quaternion &qrot)
}
#endif
-PyObject* PyObjectFrom(const MT_Tuple4 &vec)
+PyObject *PyObjectFrom(const MT_Tuple4 &vec)
{
#ifdef USE_MATHUTILS
float fvec[4];
@@ -168,7 +168,7 @@ PyObject* PyObjectFrom(const MT_Tuple4 &vec)
#endif
}
-PyObject* PyObjectFrom(const MT_Tuple3 &vec)
+PyObject *PyObjectFrom(const MT_Tuple3 &vec)
{
#ifdef USE_MATHUTILS
float fvec[3];
@@ -180,10 +180,10 @@ PyObject* PyObjectFrom(const MT_Tuple3 &vec)
PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1]));
PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2]));
return list;
-#endif
+#endif
}
-PyObject* PyObjectFrom(const MT_Tuple2 &vec)
+PyObject *PyObjectFrom(const MT_Tuple2 &vec)
{
#ifdef USE_MATHUTILS
float fvec[2];
diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h
index aec871d7700..d79397ed807 100644
--- a/source/gameengine/Ketsji/KX_PyMath.h
+++ b/source/gameengine/Ketsji/KX_PyMath.h
@@ -61,7 +61,7 @@ inline unsigned int Size(const MT_Tuple4&) { return 4; }
* Converts the given python matrix (column-major) to an MT class (row-major).
*/
template<class T>
-bool PyMatTo(PyObject* pymat, T& mat)
+bool PyMatTo(PyObject *pymat, T& mat)
{
bool noerror = true;
mat.setIdentity();
@@ -133,7 +133,7 @@ bool PyMatTo(PyObject* pymat, T& mat)
* Converts a python sequence to a MT class.
*/
template<class T>
-bool PyVecTo(PyObject* pyval, T& vec)
+bool PyVecTo(PyObject *pyval, T& vec)
{
#ifdef USE_MATHUTILS
/* no need for BaseMath_ReadCallback() here, reading the sequences will do this */
@@ -235,41 +235,41 @@ bool PyVecTo(PyObject* pyval, T& vec)
}
-bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot);
+bool PyQuatTo(PyObject *pyval, MT_Quaternion &qrot);
-bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix);
+bool PyOrientationTo(PyObject *pyval, MT_Matrix3x3 &mat, const char *error_prefix);
/**
* Converts an MT_Matrix4x4 to a python object.
*/
-PyObject* PyObjectFrom(const MT_Matrix4x4 &mat);
+PyObject *PyObjectFrom(const MT_Matrix4x4 &mat);
/**
* Converts an MT_Matrix3x3 to a python object.
*/
-PyObject* PyObjectFrom(const MT_Matrix3x3 &mat);
+PyObject *PyObjectFrom(const MT_Matrix3x3 &mat);
/**
* Converts an MT_Tuple2 to a python object.
*/
-PyObject* PyObjectFrom(const MT_Tuple2 &vec);
+PyObject *PyObjectFrom(const MT_Tuple2 &vec);
/**
* Converts an MT_Tuple3 to a python object
*/
-PyObject* PyObjectFrom(const MT_Tuple3 &vec);
+PyObject *PyObjectFrom(const MT_Tuple3 &vec);
#ifdef USE_MATHUTILS
/**
* Converts an MT_Quaternion to a python object.
*/
-PyObject* PyObjectFrom(const MT_Quaternion &qrot);
+PyObject *PyObjectFrom(const MT_Quaternion &qrot);
#endif
/**
* Converts an MT_Tuple4 to a python object.
*/
-PyObject* PyObjectFrom(const MT_Tuple4 &pos);
+PyObject *PyObjectFrom(const MT_Tuple4 &pos);
#endif
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 7d29a20d1a2..43fca40f2da 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -210,15 +210,15 @@ static PyObject *gp_OrigPythonSysModules= NULL;
#include "SCA_PythonController.h"
// List of methods defined in the module
-static PyObject* ErrorObject;
+static PyObject *ErrorObject;
static const char *gPyGetRandomFloat_doc="getRandomFloat returns a random floating point value in the range [0..1]";
-static PyObject* gPyGetRandomFloat(PyObject*)
+static PyObject *gPyGetRandomFloat(PyObject *)
{
return PyFloat_FromDouble(MT_random());
}
-static PyObject* gPySetGravity(PyObject*, PyObject* value)
+static PyObject *gPySetGravity(PyObject *, PyObject *value)
{
MT_Vector3 vec;
if (!PyVecTo(value, vec))
@@ -240,7 +240,7 @@ file to make a full path name (doesn't change during the game, even if you load\
other .blend).\n\
The function also converts the directory separator to the local file system format.";
-static PyObject* gPyExpandPath(PyObject*, PyObject* args)
+static PyObject *gPyExpandPath(PyObject *, PyObject *args)
{
char expanded[FILE_MAX];
char* filename;
@@ -257,7 +257,7 @@ static char gPyStartGame_doc[] =
"startGame(blend)\n\
Loads the blend file";
-static PyObject* gPyStartGame(PyObject*, PyObject* args)
+static PyObject *gPyStartGame(PyObject *, PyObject *args)
{
char* blendfile;
@@ -274,7 +274,7 @@ static char gPyEndGame_doc[] =
"endGame()\n\
Ends the current game";
-static PyObject* gPyEndGame(PyObject*)
+static PyObject *gPyEndGame(PyObject *)
{
gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_QUIT_GAME);
@@ -287,7 +287,7 @@ static char gPyRestartGame_doc[] =
"restartGame()\n\
Restarts the current game by reloading the .blend file";
-static PyObject* gPyRestartGame(PyObject*)
+static PyObject *gPyRestartGame(PyObject *)
{
gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_RESTART_GAME);
gp_KetsjiEngine->SetNameNextGame(gp_GamePythonPath);
@@ -299,7 +299,7 @@ static char gPySaveGlobalDict_doc[] =
"saveGlobalDict()\n"
"Saves bge.logic.globalDict to a file";
-static PyObject* gPySaveGlobalDict(PyObject*)
+static PyObject *gPySaveGlobalDict(PyObject *)
{
char marshal_path[512];
char *marshal_buffer = NULL;
@@ -336,7 +336,7 @@ static char gPyLoadGlobalDict_doc[] =
"LoadGlobalDict()\n"
"Loads bge.logic.globalDict from a file";
-static PyObject* gPyLoadGlobalDict(PyObject*)
+static PyObject *gPyLoadGlobalDict(PyObject *)
{
char marshal_path[512];
char *marshal_buffer = NULL;
@@ -381,7 +381,7 @@ body = Message body\
to = Name of object to send the message to\
from = Name of object to send the string from";
-static PyObject* gPySendMessage(PyObject*, PyObject* args)
+static PyObject *gPySendMessage(PyObject *, PyObject *args)
{
char* subject;
char* body = (char *)"";
@@ -397,9 +397,9 @@ static PyObject* gPySendMessage(PyObject*, PyObject* args)
}
// this gets a pointer to an array filled with floats
-static PyObject* gPyGetSpectrum(PyObject*)
+static PyObject *gPyGetSpectrum(PyObject *)
{
- PyObject* resultlist = PyList_New(512);
+ PyObject *resultlist = PyList_New(512);
for (int index = 0; index < 512; index++)
{
@@ -409,7 +409,7 @@ static PyObject* gPyGetSpectrum(PyObject*)
return resultlist;
}
-static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args)
+static PyObject *gPySetLogicTicRate(PyObject *, PyObject *args)
{
float ticrate;
if (!PyArg_ParseTuple(args, "f:setLogicTicRate", &ticrate))
@@ -419,12 +419,12 @@ static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyGetLogicTicRate(PyObject*)
+static PyObject *gPyGetLogicTicRate(PyObject *)
{
return PyFloat_FromDouble(KX_KetsjiEngine::GetTicRate());
}
-static PyObject* gPySetExitKey(PyObject*, PyObject* args)
+static PyObject *gPySetExitKey(PyObject *, PyObject *args)
{
short exitkey;
if (!PyArg_ParseTuple(args, "h:setExitKey", &exitkey))
@@ -433,12 +433,12 @@ static PyObject* gPySetExitKey(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyGetExitKey(PyObject*)
+static PyObject *gPyGetExitKey(PyObject *)
{
return PyLong_FromSsize_t(KX_KetsjiEngine::GetExitKey());
}
-static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args)
+static PyObject *gPySetMaxLogicFrame(PyObject *, PyObject *args)
{
int frame;
if (!PyArg_ParseTuple(args, "i:setMaxLogicFrame", &frame))
@@ -448,12 +448,12 @@ static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyGetMaxLogicFrame(PyObject*)
+static PyObject *gPyGetMaxLogicFrame(PyObject *)
{
return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxLogicFrame());
}
-static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args)
+static PyObject *gPySetMaxPhysicsFrame(PyObject *, PyObject *args)
{
int frame;
if (!PyArg_ParseTuple(args, "i:setMaxPhysicsFrame", &frame))
@@ -463,12 +463,12 @@ static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyGetMaxPhysicsFrame(PyObject*)
+static PyObject *gPyGetMaxPhysicsFrame(PyObject *)
{
return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxPhysicsFrame());
}
-static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args)
+static PyObject *gPySetPhysicsTicRate(PyObject *, PyObject *args)
{
float ticrate;
if (!PyArg_ParseTuple(args, "f:setPhysicsTicRate", &ticrate))
@@ -478,7 +478,7 @@ static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
#if 0 // unused
-static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args)
+static PyObject *gPySetPhysicsDebug(PyObject *, PyObject *args)
{
int debugMode;
if (!PyArg_ParseTuple(args, "i:setPhysicsDebug", &debugMode))
@@ -490,21 +490,21 @@ static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args)
#endif
-static PyObject* gPyGetPhysicsTicRate(PyObject*)
+static PyObject *gPyGetPhysicsTicRate(PyObject *)
{
return PyFloat_FromDouble(PHY_GetActiveEnvironment()->getFixedTimeStep());
}
-static PyObject* gPyGetAverageFrameRate(PyObject*)
+static PyObject *gPyGetAverageFrameRate(PyObject *)
{
return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate());
}
-static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args)
+static PyObject *gPyGetBlendFileList(PyObject *, PyObject *args)
{
char cpath[sizeof(gp_GamePythonPath)];
char *searchpath = NULL;
- PyObject* list, *value;
+ PyObject *list, *value;
DIR *dp;
struct dirent *dirp;
@@ -545,7 +545,7 @@ static char gPyAddScene_doc[] =
adds a scene to the game engine\n\
name = Name of the scene\n\
overlay = Overlay or underlay";
-static PyObject* gPyAddScene(PyObject*, PyObject* args)
+static PyObject *gPyAddScene(PyObject *, PyObject *args)
{
char* name;
int overlay = 1;
@@ -561,7 +561,7 @@ static PyObject* gPyAddScene(PyObject*, PyObject* args)
static const char *gPyGetCurrentScene_doc =
"getCurrentScene()\n"
"Gets a reference to the current scene.\n";
-static PyObject* gPyGetCurrentScene(PyObject* self)
+static PyObject *gPyGetCurrentScene(PyObject *self)
{
return gp_KetsjiScene->GetProxy();
}
@@ -569,10 +569,10 @@ static PyObject* gPyGetCurrentScene(PyObject* self)
static const char *gPyGetSceneList_doc =
"getSceneList()\n"
"Return a list of converted scenes.\n";
-static PyObject* gPyGetSceneList(PyObject* self)
+static PyObject *gPyGetSceneList(PyObject *self)
{
KX_KetsjiEngine* m_engine = KX_GetActiveEngine();
- PyObject* list;
+ PyObject *list;
KX_SceneList* scenes = m_engine->CurrentScenes();
int numScenes = scenes->size();
int i;
@@ -665,7 +665,7 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *)
Py_RETURN_NONE;
}
-static PyObject *gLibLoad(PyObject*, PyObject* args, PyObject* kwds)
+static PyObject *gLibLoad(PyObject *, PyObject *args, PyObject *kwds)
{
KX_Scene *kx_scene= gp_KetsjiScene;
char *path;
@@ -721,7 +721,7 @@ static PyObject *gLibLoad(PyObject*, PyObject* args, PyObject* kwds)
Py_RETURN_FALSE;
}
-static PyObject *gLibNew(PyObject*, PyObject* args)
+static PyObject *gLibNew(PyObject *, PyObject *args)
{
KX_Scene *kx_scene= gp_KetsjiScene;
char *path;
@@ -779,7 +779,7 @@ static PyObject *gLibNew(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject *gLibFree(PyObject*, PyObject* args)
+static PyObject *gLibFree(PyObject *, PyObject *args)
{
KX_Scene *kx_scene= gp_KetsjiScene;
char *path;
@@ -796,7 +796,7 @@ static PyObject *gLibFree(PyObject*, PyObject* args)
}
}
-static PyObject *gLibList(PyObject*, PyObject* args)
+static PyObject *gLibList(PyObject *, PyObject *args)
{
vector<Main*> &dynMaggie = gp_KetsjiScene->GetSceneConverter()->GetMainDynamic();
int i= 0;
@@ -866,14 +866,14 @@ static struct PyMethodDef game_methods[] = {
{NULL, (PyCFunction) NULL, 0, NULL }
};
-static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args)
+static PyObject *gPyGetWindowHeight(PyObject *, PyObject *args)
{
return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetHeight() : 0));
}
-static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args)
+static PyObject *gPyGetWindowWidth(PyObject *, PyObject *args)
{
return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetWidth() : 0));
}
@@ -883,7 +883,7 @@ static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args)
// temporarility visibility thing, will be moved to rasterizer/renderer later
bool gUseVisibilityTemp = false;
-static PyObject* gPyEnableVisibility(PyObject*, PyObject* args)
+static PyObject *gPyEnableVisibility(PyObject *, PyObject *args)
{
int visible;
if (!PyArg_ParseTuple(args,"i:enableVisibility",&visible))
@@ -895,7 +895,7 @@ static PyObject* gPyEnableVisibility(PyObject*, PyObject* args)
-static PyObject* gPyShowMouse(PyObject*, PyObject* args)
+static PyObject *gPyShowMouse(PyObject *, PyObject *args)
{
int visible;
if (!PyArg_ParseTuple(args,"i:showMouse",&visible))
@@ -916,7 +916,7 @@ static PyObject* gPyShowMouse(PyObject*, PyObject* args)
-static PyObject* gPySetMousePosition(PyObject*, PyObject* args)
+static PyObject *gPySetMousePosition(PyObject *, PyObject *args)
{
int x,y;
if (!PyArg_ParseTuple(args,"ii:setMousePosition",&x,&y))
@@ -928,7 +928,7 @@ static PyObject* gPySetMousePosition(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args)
+static PyObject *gPySetEyeSeparation(PyObject *, PyObject *args)
{
float sep;
if (!PyArg_ParseTuple(args, "f:setEyeSeparation", &sep))
@@ -944,7 +944,7 @@ static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyGetEyeSeparation(PyObject*)
+static PyObject *gPyGetEyeSeparation(PyObject *)
{
if (!gp_Rasterizer) {
PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getEyeSeparation(), Rasterizer not available");
@@ -954,7 +954,7 @@ static PyObject* gPyGetEyeSeparation(PyObject*)
return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation());
}
-static PyObject* gPySetFocalLength(PyObject*, PyObject* args)
+static PyObject *gPySetFocalLength(PyObject *, PyObject *args)
{
float focus;
if (!PyArg_ParseTuple(args, "f:setFocalLength", &focus))
@@ -970,7 +970,7 @@ static PyObject* gPySetFocalLength(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*)
+static PyObject *gPyGetFocalLength(PyObject *, PyObject *, PyObject *)
{
if (!gp_Rasterizer) {
PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getFocalLength(), Rasterizer not available");
@@ -982,7 +982,7 @@ static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*)
Py_RETURN_NONE;
}
-static PyObject* gPySetBackgroundColor(PyObject*, PyObject* value)
+static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value)
{
MT_Vector4 vec;
@@ -1003,7 +1003,7 @@ static PyObject* gPySetBackgroundColor(PyObject*, PyObject* value)
-static PyObject* gPySetMistColor(PyObject*, PyObject* value)
+static PyObject *gPySetMistColor(PyObject *, PyObject *value)
{
MT_Vector3 vec;
@@ -1013,25 +1013,25 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* value)
if (!gp_Rasterizer) {
PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available");
return NULL;
- }
+ }
gp_Rasterizer->SetFogColor((float)vec[0], (float)vec[1], (float)vec[2]);
Py_RETURN_NONE;
}
-static PyObject* gPyDisableMist(PyObject*)
+static PyObject *gPyDisableMist(PyObject *)
{
if (!gp_Rasterizer) {
PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available");
return NULL;
- }
+ }
gp_Rasterizer->DisableFog();
Py_RETURN_NONE;
}
-static PyObject* gPySetMistStart(PyObject*, PyObject* args)
+static PyObject *gPySetMistStart(PyObject *, PyObject *args)
{
float miststart;
@@ -1050,7 +1050,7 @@ static PyObject* gPySetMistStart(PyObject*, PyObject* args)
-static PyObject* gPySetMistEnd(PyObject*, PyObject* args)
+static PyObject *gPySetMistEnd(PyObject *, PyObject *args)
{
float mistend;
@@ -1068,7 +1068,7 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args)
}
-static PyObject* gPySetAmbientColor(PyObject*, PyObject* value)
+static PyObject *gPySetAmbientColor(PyObject *, PyObject *value)
{
MT_Vector3 vec;
@@ -1078,7 +1078,7 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* value)
if (!gp_Rasterizer) {
PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available");
return NULL;
- }
+ }
gp_Rasterizer->SetAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]);
Py_RETURN_NONE;
@@ -1087,7 +1087,7 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* value)
-static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args)
+static PyObject *gPyMakeScreenshot(PyObject *, PyObject *args)
{
char* filename;
if (!PyArg_ParseTuple(args,"s:makeScreenshot",&filename))
@@ -1101,7 +1101,7 @@ static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args)
+static PyObject *gPyEnableMotionBlur(PyObject *, PyObject *args)
{
float motionblurvalue;
if (!PyArg_ParseTuple(args,"f:enableMotionBlur",&motionblurvalue))
@@ -1117,7 +1117,7 @@ static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyDisableMotionBlur(PyObject*)
+static PyObject *gPyDisableMotionBlur(PyObject *)
{
if (!gp_Rasterizer) {
PyErr_SetString(PyExc_RuntimeError, "Rasterizer.disableMotionBlur(), Rasterizer not available");
@@ -1147,9 +1147,9 @@ static int getGLSLSettingFlag(const char *setting)
return -1;
}
-static PyObject* gPySetGLSLMaterialSetting(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject *gPySetGLSLMaterialSetting(PyObject *,
+ PyObject *args,
+ PyObject *)
{
GlobalSettings *gs= gp_KetsjiEngine->GetGlobalSettings();
char *setting;
@@ -1190,9 +1190,9 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*,
Py_RETURN_NONE;
}
-static PyObject* gPyGetGLSLMaterialSetting(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject *gPyGetGLSLMaterialSetting(PyObject *,
+ PyObject *args,
+ PyObject *)
{
GlobalSettings *gs= gp_KetsjiEngine->GetGlobalSettings();
char *setting;
@@ -1216,9 +1216,9 @@ static PyObject* gPyGetGLSLMaterialSetting(PyObject*,
#define KX_BLENDER_MULTITEX_MATERIAL 1
#define KX_BLENDER_GLSL_MATERIAL 2
-static PyObject* gPySetMaterialType(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject *gPySetMaterialType(PyObject *,
+ PyObject *args,
+ PyObject *)
{
GlobalSettings *gs= gp_KetsjiEngine->GetGlobalSettings();
int type;
@@ -1240,7 +1240,7 @@ static PyObject* gPySetMaterialType(PyObject*,
Py_RETURN_NONE;
}
-static PyObject* gPyGetMaterialType(PyObject*)
+static PyObject *gPyGetMaterialType(PyObject *)
{
GlobalSettings *gs= gp_KetsjiEngine->GetGlobalSettings();
int flag;
@@ -1255,7 +1255,7 @@ static PyObject* gPyGetMaterialType(PyObject*)
return PyLong_FromSsize_t(flag);
}
-static PyObject* gPySetAnisotropicFiltering(PyObject*, PyObject* args)
+static PyObject *gPySetAnisotropicFiltering(PyObject *, PyObject *args)
{
short level;
@@ -1272,16 +1272,16 @@ static PyObject* gPySetAnisotropicFiltering(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPyGetAnisotropicFiltering(PyObject*, PyObject* args)
+static PyObject *gPyGetAnisotropicFiltering(PyObject *, PyObject *args)
{
return PyLong_FromLong(gp_Rasterizer->GetAnisotropicFiltering());
}
-static PyObject* gPyDrawLine(PyObject*, PyObject* args)
+static PyObject *gPyDrawLine(PyObject *, PyObject *args)
{
- PyObject* ob_from;
- PyObject* ob_to;
- PyObject* ob_color;
+ PyObject *ob_from;
+ PyObject *ob_to;
+ PyObject *ob_color;
if (!gp_Rasterizer) {
PyErr_SetString(PyExc_RuntimeError, "Rasterizer.drawLine(obFrom, obTo, color): Rasterizer not available");
@@ -1306,7 +1306,7 @@ static PyObject* gPyDrawLine(PyObject*, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject* gPySetWindowSize(PyObject*, PyObject* args)
+static PyObject *gPySetWindowSize(PyObject *, PyObject *args)
{
int width, height;
if (!PyArg_ParseTuple(args, "ii:resize", &width, &height))
@@ -1383,11 +1383,11 @@ static struct PyModuleDef GameLogic_module_def = {
0, /* m_free */
};
-PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook
+PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook
{
- PyObject* m;
- PyObject* d;
- PyObject* item; /* temp PyObject* storage */
+ PyObject *m;
+ PyObject *d;
+ PyObject *item; /* temp PyObject *storage */
gp_KetsjiEngine = engine;
gp_KetsjiScene = scene;
@@ -1405,7 +1405,7 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
}
else {
PyErr_Clear();
- // Create the module and add the functions
+ // Create the module and add the functions
m = PyModule_Create(&GameLogic_module_def);
PyDict_SetItemString(PySys_GetObject("modules"), GameLogic_module_def.m_name, m);
}
@@ -1832,7 +1832,7 @@ static void restorePySysObjects(void)
PyDict_Clear(sys_mods);
PyDict_Update(sys_mods, gp_OrigPythonSysModules);
Py_DECREF(gp_OrigPythonSysModules);
- gp_OrigPythonSysModules= NULL;
+ gp_OrigPythonSysModules= NULL;
// fprintf(stderr, "\nRestore Path: %d ", PyList_GET_SIZE(sys_path));
@@ -1862,7 +1862,7 @@ static struct _inittab bge_internal_modules[]= {
* Python is not initialized.
* see bpy_interface.c's BPY_python_start() which shares the same functionality in blender.
*/
-PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv)
+PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv)
{
/* Yet another gotcha in the py api
* Cant run PySys_SetArgv more then once because this adds the
@@ -1935,7 +1935,7 @@ PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
}
void exitGamePlayerPythonScripting()
-{
+{
/* Clean up the Python mouse and keyboard */
delete gp_PythonKeyboard;
gp_PythonKeyboard = NULL;
@@ -1956,7 +1956,7 @@ void exitGamePlayerPythonScripting()
/**
* Python is already initialized.
*/
-PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie)
+PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie)
{
#if 0 // XXX TODO Py3
STR_String pname = progname;
@@ -1998,9 +1998,10 @@ void exitGamePythonScripting()
/* similar to the above functions except it sets up the namespace
* and other more general things */
-void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene* startscene, Main *blenderdata, PyObject * pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv)
+void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene *startscene, Main *blenderdata,
+ PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv)
{
- PyObject* dictionaryobject;
+ PyObject *dictionaryobject;
if (argv) /* player only */
dictionaryobject= initGamePlayerPythonScripting("Ketsji", psl_Lowest, blenderdata, argc, argv);
@@ -2053,15 +2054,15 @@ static struct PyModuleDef Rasterizer_module_def = {
0, /* m_free */
};
-PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
+PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
{
gp_Canvas = canvas;
gp_Rasterizer = rasty;
- PyObject* m;
- PyObject* d;
- PyObject* item;
+ PyObject *m;
+ PyObject *d;
+ PyObject *item;
/* Use existing module where possible
* be careful not to init any runtime vars after this */
@@ -2114,9 +2115,9 @@ static char gPyEventToString_doc[] =
"EventToString(event) - Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
;
-static PyObject* gPyEventToString(PyObject*, PyObject* value)
+static PyObject *gPyEventToString(PyObject *, PyObject *value)
{
- PyObject* mod, *dict, *key, *val, *ret = NULL;
+ PyObject *mod, *dict, *key, *val, *ret = NULL;
Py_ssize_t pos = 0;
mod = PyImport_ImportModule( "GameKeys" );
@@ -2144,7 +2145,7 @@ static char gPyEventToCharacter_doc[] =
"EventToCharacter(event, is_shift) - Take a valid event from the GameKeys module or Keyboard Sensor and return a character"
;
-static PyObject* gPyEventToCharacter(PyObject*, PyObject* args)
+static PyObject *gPyEventToCharacter(PyObject *, PyObject *args)
{
int event, shift;
if (!PyArg_ParseTuple(args,"ii:EventToCharacter", &event, &shift))
@@ -2179,11 +2180,11 @@ static struct PyModuleDef GameKeys_module_def = {
0, /* m_free */
};
-PyObject* initGameKeys()
+PyObject *initGameKeys()
{
- PyObject* m;
- PyObject* d;
- PyObject* item;
+ PyObject *m;
+ PyObject *d;
+ PyObject *item;
/* Use existing module where possible */
m = PyImport_ImportModule( "GameKeys" );
@@ -2231,24 +2232,24 @@ PyObject* initGameKeys()
KX_MACRO_addTypesToDict(d, YKEY, SCA_IInputDevice::KX_YKEY);
KX_MACRO_addTypesToDict(d, ZKEY, SCA_IInputDevice::KX_ZKEY);
- KX_MACRO_addTypesToDict(d, ZEROKEY, SCA_IInputDevice::KX_ZEROKEY);
- KX_MACRO_addTypesToDict(d, ONEKEY, SCA_IInputDevice::KX_ONEKEY);
- KX_MACRO_addTypesToDict(d, TWOKEY, SCA_IInputDevice::KX_TWOKEY);
+ KX_MACRO_addTypesToDict(d, ZEROKEY, SCA_IInputDevice::KX_ZEROKEY);
+ KX_MACRO_addTypesToDict(d, ONEKEY, SCA_IInputDevice::KX_ONEKEY);
+ KX_MACRO_addTypesToDict(d, TWOKEY, SCA_IInputDevice::KX_TWOKEY);
KX_MACRO_addTypesToDict(d, THREEKEY, SCA_IInputDevice::KX_THREEKEY);
- KX_MACRO_addTypesToDict(d, FOURKEY, SCA_IInputDevice::KX_FOURKEY);
- KX_MACRO_addTypesToDict(d, FIVEKEY, SCA_IInputDevice::KX_FIVEKEY);
- KX_MACRO_addTypesToDict(d, SIXKEY, SCA_IInputDevice::KX_SIXKEY);
+ KX_MACRO_addTypesToDict(d, FOURKEY, SCA_IInputDevice::KX_FOURKEY);
+ KX_MACRO_addTypesToDict(d, FIVEKEY, SCA_IInputDevice::KX_FIVEKEY);
+ KX_MACRO_addTypesToDict(d, SIXKEY, SCA_IInputDevice::KX_SIXKEY);
KX_MACRO_addTypesToDict(d, SEVENKEY, SCA_IInputDevice::KX_SEVENKEY);
KX_MACRO_addTypesToDict(d, EIGHTKEY, SCA_IInputDevice::KX_EIGHTKEY);
- KX_MACRO_addTypesToDict(d, NINEKEY, SCA_IInputDevice::KX_NINEKEY);
+ KX_MACRO_addTypesToDict(d, NINEKEY, SCA_IInputDevice::KX_NINEKEY);
KX_MACRO_addTypesToDict(d, CAPSLOCKKEY, SCA_IInputDevice::KX_CAPSLOCKKEY);
- KX_MACRO_addTypesToDict(d, LEFTCTRLKEY, SCA_IInputDevice::KX_LEFTCTRLKEY);
+ KX_MACRO_addTypesToDict(d, LEFTCTRLKEY, SCA_IInputDevice::KX_LEFTCTRLKEY);
KX_MACRO_addTypesToDict(d, LEFTALTKEY, SCA_IInputDevice::KX_LEFTALTKEY);
KX_MACRO_addTypesToDict(d, RIGHTALTKEY, SCA_IInputDevice::KX_RIGHTALTKEY);
KX_MACRO_addTypesToDict(d, RIGHTCTRLKEY, SCA_IInputDevice::KX_RIGHTCTRLKEY);
- KX_MACRO_addTypesToDict(d, RIGHTSHIFTKEY, SCA_IInputDevice::KX_RIGHTSHIFTKEY);
+ KX_MACRO_addTypesToDict(d, RIGHTSHIFTKEY, SCA_IInputDevice::KX_RIGHTSHIFTKEY);
KX_MACRO_addTypesToDict(d, LEFTSHIFTKEY, SCA_IInputDevice::KX_LEFTSHIFTKEY);
KX_MACRO_addTypesToDict(d, ESCKEY, SCA_IInputDevice::KX_ESCKEY);
@@ -2256,25 +2257,25 @@ PyObject* initGameKeys()
KX_MACRO_addTypesToDict(d, RETKEY, SCA_IInputDevice::KX_RETKEY);
KX_MACRO_addTypesToDict(d, ENTERKEY, SCA_IInputDevice::KX_RETKEY);
KX_MACRO_addTypesToDict(d, SPACEKEY, SCA_IInputDevice::KX_SPACEKEY);
- KX_MACRO_addTypesToDict(d, LINEFEEDKEY, SCA_IInputDevice::KX_LINEFEEDKEY);
+ KX_MACRO_addTypesToDict(d, LINEFEEDKEY, SCA_IInputDevice::KX_LINEFEEDKEY);
KX_MACRO_addTypesToDict(d, BACKSPACEKEY, SCA_IInputDevice::KX_BACKSPACEKEY);
KX_MACRO_addTypesToDict(d, DELKEY, SCA_IInputDevice::KX_DELKEY);
KX_MACRO_addTypesToDict(d, SEMICOLONKEY, SCA_IInputDevice::KX_SEMICOLONKEY);
- KX_MACRO_addTypesToDict(d, PERIODKEY, SCA_IInputDevice::KX_PERIODKEY);
- KX_MACRO_addTypesToDict(d, COMMAKEY, SCA_IInputDevice::KX_COMMAKEY);
- KX_MACRO_addTypesToDict(d, QUOTEKEY, SCA_IInputDevice::KX_QUOTEKEY);
- KX_MACRO_addTypesToDict(d, ACCENTGRAVEKEY, SCA_IInputDevice::KX_ACCENTGRAVEKEY);
- KX_MACRO_addTypesToDict(d, MINUSKEY, SCA_IInputDevice::KX_MINUSKEY);
- KX_MACRO_addTypesToDict(d, SLASHKEY, SCA_IInputDevice::KX_SLASHKEY);
+ KX_MACRO_addTypesToDict(d, PERIODKEY, SCA_IInputDevice::KX_PERIODKEY);
+ KX_MACRO_addTypesToDict(d, COMMAKEY, SCA_IInputDevice::KX_COMMAKEY);
+ KX_MACRO_addTypesToDict(d, QUOTEKEY, SCA_IInputDevice::KX_QUOTEKEY);
+ KX_MACRO_addTypesToDict(d, ACCENTGRAVEKEY, SCA_IInputDevice::KX_ACCENTGRAVEKEY);
+ KX_MACRO_addTypesToDict(d, MINUSKEY, SCA_IInputDevice::KX_MINUSKEY);
+ KX_MACRO_addTypesToDict(d, SLASHKEY, SCA_IInputDevice::KX_SLASHKEY);
KX_MACRO_addTypesToDict(d, BACKSLASHKEY, SCA_IInputDevice::KX_BACKSLASHKEY);
- KX_MACRO_addTypesToDict(d, EQUALKEY, SCA_IInputDevice::KX_EQUALKEY);
- KX_MACRO_addTypesToDict(d, LEFTBRACKETKEY, SCA_IInputDevice::KX_LEFTBRACKETKEY);
- KX_MACRO_addTypesToDict(d, RIGHTBRACKETKEY, SCA_IInputDevice::KX_RIGHTBRACKETKEY);
+ KX_MACRO_addTypesToDict(d, EQUALKEY, SCA_IInputDevice::KX_EQUALKEY);
+ KX_MACRO_addTypesToDict(d, LEFTBRACKETKEY, SCA_IInputDevice::KX_LEFTBRACKETKEY);
+ KX_MACRO_addTypesToDict(d, RIGHTBRACKETKEY, SCA_IInputDevice::KX_RIGHTBRACKETKEY);
KX_MACRO_addTypesToDict(d, LEFTARROWKEY, SCA_IInputDevice::KX_LEFTARROWKEY);
KX_MACRO_addTypesToDict(d, DOWNARROWKEY, SCA_IInputDevice::KX_DOWNARROWKEY);
- KX_MACRO_addTypesToDict(d, RIGHTARROWKEY, SCA_IInputDevice::KX_RIGHTARROWKEY);
- KX_MACRO_addTypesToDict(d, UPARROWKEY, SCA_IInputDevice::KX_UPARROWKEY);
+ KX_MACRO_addTypesToDict(d, RIGHTARROWKEY, SCA_IInputDevice::KX_RIGHTARROWKEY);
+ KX_MACRO_addTypesToDict(d, UPARROWKEY, SCA_IInputDevice::KX_UPARROWKEY);
KX_MACRO_addTypesToDict(d, PAD2 , SCA_IInputDevice::KX_PAD2);
KX_MACRO_addTypesToDict(d, PAD4 , SCA_IInputDevice::KX_PAD4);
@@ -2347,14 +2348,14 @@ PyObject* initGameKeys()
int saveGamePythonConfig( char **marshal_buffer)
{
int marshal_length = 0;
- PyObject* gameLogic = PyImport_ImportModule("GameLogic");
+ PyObject *gameLogic = PyImport_ImportModule("GameLogic");
if (gameLogic) {
- PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module
+ PyObject *pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module
if (pyGlobalDict) {
-#ifdef Py_MARSHAL_VERSION
- PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5
+#ifdef Py_MARSHAL_VERSION
+ PyObject *pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5
#else
- PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict );
+ PyObject *pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict );
#endif
if (pyGlobalDictMarshal) {
// for testing only
@@ -2384,12 +2385,12 @@ int loadGamePythonConfig(char *marshal_buffer, int marshal_length)
{
/* Restore the dict */
if (marshal_buffer) {
- PyObject* gameLogic = PyImport_ImportModule("GameLogic");
+ PyObject *gameLogic = PyImport_ImportModule("GameLogic");
if (gameLogic) {
- PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length);
+ PyObject *pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length);
if (pyGlobalDict) {
- PyObject* pyGlobalDict_orig = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module.
+ PyObject *pyGlobalDict_orig = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module.
if (pyGlobalDict_orig) {
PyDict_Clear(pyGlobalDict_orig);
PyDict_Update(pyGlobalDict_orig, pyGlobalDict);
@@ -2405,10 +2406,11 @@ int loadGamePythonConfig(char *marshal_buffer, int marshal_length)
PyErr_Clear();
printf("Error could not marshall string\n");
}
- } else {
+ }
+ else {
PyErr_Clear();
printf("Error, bge.logic failed to import bge.logic.globalDict will be lost\n");
- }
+ }
}
return 0;
}
diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h
index 1500dd97ae1..69517b2b1e9 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.h
+++ b/source/gameengine/Ketsji/KX_PythonInit.h
@@ -52,7 +52,8 @@ void exitGamePlayerPythonScripting();
PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie);
void exitGamePythonScripting();
-void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene* startscene, Main *blenderdata, PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv);
+void setupGamePython(KX_KetsjiEngine *ketsjiengine, KX_Scene *startscene, Main *blenderdata,
+ PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv);
void setGamePythonPath(const char *path);
void resetGamePythonPath();
@@ -72,11 +73,12 @@ class KX_Scene* KX_GetActiveScene();
class KX_KetsjiEngine* KX_GetActiveEngine();
typedef int (*PyNextFrameFunc)(void *);
+
struct PyNextFrameState {
- //state: can be either a GPG_NextFrameState or a BL_KetsjiNextFrameState
- void *state;
- //func: can be either GPG_PyNextFrame or BL_KetsjiPyNextFrame
- PyNextFrameFunc func;
+ /** can be either a GPG_NextFrameState or a BL_KetsjiNextFrameState */
+ void *state;
+ /** can be either GPG_PyNextFrame or BL_KetsjiPyNextFrame */
+ PyNextFrameFunc func;
};
extern struct PyNextFrameState pynextframestate;
@@ -84,7 +86,7 @@ extern struct PyNextFrameState pynextframestate;
void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color);
void KX_RasterizerDrawDebugCircle(const MT_Vector3& center, const MT_Scalar radius, const MT_Vector3& color,
- const MT_Vector3& normal, int nsector);
+ const MT_Vector3& normal, int nsector);
#endif //__KX_PYTHONINIT_H__
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
index 3033c534e84..d0e3d26f61b 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
@@ -29,14 +29,10 @@
* \ingroup ketsji
*/
-
-
-
-#ifndef _adr_py_init_types_h_ // only process once,
-#define _adr_py_init_types_h_ // even if multiply included
-
#ifdef WITH_PYTHON
+#include "KX_PythonInitTypes.h"
+
/* Only for Class::Parents */
#include "BL_BlenderShader.h"
#include "BL_ShapeActionActuator.h"
@@ -166,7 +162,7 @@ static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *a
void initPyTypes(void)
{
-
+
/*
* initPyObjectPlusType(BL_ActionActuator::Parents);
* .....
@@ -266,5 +262,3 @@ void initPyTypes(void)
}
#endif // WITH_PYTHON
-
-#endif
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.h b/source/gameengine/Ketsji/KX_PythonInitTypes.h
index a06fe46a0ea..d8ee4f75fdd 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.h
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.h
@@ -29,11 +29,11 @@
* \ingroup ketsji
*/
-#ifndef _adr_py_init_types_h_ // only process once,
-#define _adr_py_init_types_h_ // even if multiply included
+#ifndef __KX_PYTHON_INIT_TYPES__
+#define __KX_PYTHON_INIT_TYPES__
#ifdef WITH_PYTHON
void initPyTypes(void);
#endif
-#endif
+#endif /* __KX_PYTHON_INIT_TYPES__ */
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp
index 6eadc0cbef3..5ab3de15fb3 100644
--- a/source/gameengine/Ketsji/KX_PythonSeq.cpp
+++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp
@@ -69,7 +69,7 @@ static void KX_PythonSeq_dealloc(KX_PythonSeq * self)
PyObject_GC_Del(self);
}
-static Py_ssize_t KX_PythonSeq_len( PyObject * self )
+static Py_ssize_t KX_PythonSeq_len( PyObject *self )
{
PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
@@ -100,7 +100,7 @@ static Py_ssize_t KX_PythonSeq_len( PyObject * self )
}
}
-static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index)
+static PyObject *KX_PythonSeq_getIndex(PyObject *self, int index)
{
PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
@@ -264,7 +264,7 @@ static PyObjectPlus * KX_PythonSeq_subscript__internal(PyObject *self, const cha
}
-static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key)
+static PyObject * KX_PythonSeq_subscript(PyObject *self, PyObject *key)
{
PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
@@ -314,10 +314,10 @@ static int KX_PythonSeq_contains(PyObject *self, PyObject *key)
}
/* Matches python dict.get(key, [default]) */
-PyObject* KX_PythonSeq_get(PyObject * self, PyObject *args)
+static PyObject *KX_PythonSeq_get(PyObject *self, PyObject *args)
{
char *key;
- PyObject* def = Py_None;
+ PyObject *def = Py_None;
PyObjectPlus* ret_plus;
if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
@@ -396,7 +396,7 @@ static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self)
static int KX_PythonSeq_compare( KX_PythonSeq * a, KX_PythonSeq * b )
{
- return ( a->type == b->type && a->base == b->base) ? 0 : -1;
+ return ( a->type == b->type && a->base == b->base) ? 0 : -1;
}
static PyObject *KX_PythonSeq_richcmp(PyObject *a, PyObject *b, int op)
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp
index 74009f51078..fb949fffa8a 100644
--- a/source/gameengine/Ketsji/KX_RadarSensor.cpp
+++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp
@@ -217,7 +217,7 @@ PyAttributeDef KX_RadarSensor::Attributes[] = {
{NULL} //Sentinel
};
-PyObject* KX_RadarSensor::pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_RadarSensor::pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_RadarSensor* self= static_cast<KX_RadarSensor*>(self_v);
diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp
index 58ca847b617..14786e8429e 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.cpp
+++ b/source/gameengine/Ketsji/KX_RaySensor.cpp
@@ -361,7 +361,7 @@ PyAttributeDef KX_RaySensor::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_RaySensor::pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_RaySensor::pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_RaySensor* self = static_cast<KX_RaySensor*>(self_v);
if (self->m_hitObject)
diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h
index f5d1c72d098..27aaa442dcd 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.h
+++ b/source/gameengine/Ketsji/KX_RaySensor.h
@@ -94,7 +94,7 @@ public:
#ifdef WITH_PYTHON
/* Attributes */
- static PyObject* pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
index 841feda5237..d850168afdf 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -203,10 +203,10 @@ PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
- if (!actuator->m_OriginalObject)
+ if (!actuator->m_OriginalObject)
Py_RETURN_NONE;
else
return actuator->m_OriginalObject->GetProxy();
@@ -221,7 +221,7 @@ int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYAT
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
if (actuator->m_OriginalObject != NULL)
- actuator->m_OriginalObject->UnregisterActuator(actuator);
+ actuator->m_OriginalObject->UnregisterActuator(actuator);
actuator->m_OriginalObject = (SCA_IObject*)gameobj;
@@ -231,7 +231,7 @@ int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYAT
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
if (!actuator->m_lastCreatedObject)
@@ -240,7 +240,7 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, con
return actuator->m_lastCreatedObject->GetProxy();
}
-PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject()
+PyObject *KX_SCA_AddObjectActuator::PyInstantAddObject()
{
InstantAddObject();
@@ -253,7 +253,7 @@ void KX_SCA_AddObjectActuator::InstantAddObject()
{
if (m_OriginalObject)
{
- // Add an identical object, with properties inherited from the original object
+ // Add an identical object, with properties inherited from the original object
// Now it needs to be added to the current scene.
SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp );
KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica);
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
index f49f2473036..9c8cbfa3d09 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
@@ -112,7 +112,7 @@ public:
virtual bool
Update();
- SCA_IObject*
+ SCA_IObject *
GetLastCreatedObject(
) const;
@@ -122,9 +122,9 @@ public:
KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,InstantAddObject);
- static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- static PyObject* pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
index f408b2cd7c9..5dc67a4cff3 100644
--- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
@@ -119,14 +119,14 @@ bool KX_SCA_DynamicActuator::Update()
switch (m_dyn_operation)
{
- case 0:
- obj->RestoreDynamics();
+ case 0:
+ obj->RestoreDynamics();
break;
case 1:
obj->SuspendDynamics();
break;
case 2:
- controller->setRigidBody(true);
+ controller->setRigidBody(true);
break;
case 3:
controller->setRigidBody(false);
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
index ffe5556cfe6..b105256836b 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
@@ -87,7 +87,7 @@ PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SCA_ReplaceMeshActuator* actuator = static_cast<KX_SCA_ReplaceMeshActuator*>(self);
if (!actuator->m_mesh)
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
index 6db16a0e1b6..52a20142442 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
@@ -84,7 +84,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator
m_scene= val;
};
- static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,instantReplaceMesh);
diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
index 13200696ffb..19b9d13087d 100644
--- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
+++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
@@ -51,14 +51,14 @@ KX_BoneParentRelation::
New(Bone* bone
) {
return new KX_BoneParentRelation(bone);
-}
+}
bool
KX_BoneParentRelation::
UpdateChildCoordinates(
SG_Spatial * child,
const SG_Spatial * parent,
- bool& parentUpdated
+ bool& parentUpdated
) {
MT_assert(child != NULL);
@@ -71,7 +71,7 @@ UpdateChildCoordinates(
// we don't know if the armature has been updated or not, assume yes
parentUpdated = true;
- // the childs world locations which we will update.
+ // the childs world locations which we will update.
MT_Vector3 child_w_scale;
MT_Point3 child_w_pos;
diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
index 76fefdebe08..6f4fd482198 100644
--- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
+++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
@@ -57,7 +57,7 @@ public :
static
KX_BoneParentRelation *
New(Bone* bone
- );
+ );
/**
* Updates the childs world coordinates relative to the parent's
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
index 699b267496d..e80de76861e 100644
--- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
@@ -45,14 +45,14 @@ KX_NormalParentRelation::
New(
) {
return new KX_NormalParentRelation();
-}
+}
bool
KX_NormalParentRelation::
UpdateChildCoordinates(
SG_Spatial * child,
const SG_Spatial * parent,
- bool& parentUpdated
+ bool& parentUpdated
) {
MT_assert(child != NULL);
@@ -67,7 +67,7 @@ UpdateChildCoordinates(
return true; //false;
}
else {
- // the childs world locations which we will update.
+ // the childs world locations which we will update.
const MT_Vector3 & p_world_scale = parent->GetWorldScaling();
const MT_Point3 & p_world_pos = parent->GetWorldPosition();
const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation();
@@ -121,7 +121,7 @@ KX_VertexParentRelation::
UpdateChildCoordinates(
SG_Spatial * child,
const SG_Spatial * parent,
- bool& parentUpdated
+ bool& parentUpdated
) {
MT_assert(child != NULL);
@@ -176,7 +176,7 @@ New(
MT_Scalar relaxation
) {
return new KX_SlowParentRelation(relaxation);
-}
+}
/**
* Method inherited from KX_ParentRelation
@@ -187,7 +187,7 @@ KX_SlowParentRelation::
UpdateChildCoordinates(
SG_Spatial * child,
const SG_Spatial * parent,
- bool& parentUpdated
+ bool& parentUpdated
) {
MT_assert(child != NULL);
@@ -198,7 +198,7 @@ UpdateChildCoordinates(
const MT_Point3 & child_pos = child->GetLocalPosition();
const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
- // the childs world locations which we will update.
+ // the childs world locations which we will update.
MT_Vector3 child_w_scale;
MT_Point3 child_w_pos;
@@ -230,7 +230,7 @@ UpdateChildCoordinates(
child_w_scale = child->GetWorldScaling();
child_w_pos = child->GetWorldPosition();
- child_w_rotation = child->GetWorldOrientation();
+ child_w_rotation = child->GetWorldOrientation();
// now 'interpolate' the normal coordinates with the last
// world coordinates to get the new world coordinates.
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
index b5ab5302910..5d777f5028f 100644
--- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
@@ -57,7 +57,7 @@ public :
static
KX_NormalParentRelation *
New(
- );
+ );
/**
* Method inherited from KX_ParentRelation
@@ -67,7 +67,7 @@ public :
UpdateChildCoordinates(
SG_Spatial * child,
const SG_Spatial * parent,
- bool& parentUpdated
+ bool& parentUpdated
);
/**
@@ -106,7 +106,7 @@ public :
static
KX_VertexParentRelation *
New(
- );
+ );
/**
* Method inherited from KX_ParentRelation
@@ -116,7 +116,7 @@ public :
UpdateChildCoordinates(
SG_Spatial * child,
const SG_Spatial * parent,
- bool& parentUpdated
+ bool& parentUpdated
);
/**
@@ -162,7 +162,7 @@ public :
KX_SlowParentRelation *
New(
MT_Scalar relaxation
- );
+ );
/**
* Method inherited from KX_ParentRelation
@@ -172,7 +172,7 @@ public :
UpdateChildCoordinates(
SG_Spatial * child,
const SG_Spatial * parent,
- bool& parentUpdated
+ bool& parentUpdated
);
/**
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index c1afed82b02..652ed2ab2dd 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -98,7 +98,7 @@
#include <stdio.h>
-void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
+static void *KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
{
KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj);
@@ -108,7 +108,7 @@ void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
return (void*)replica;
}
-void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene)
+static void *KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene)
{
((KX_Scene*)scene)->RemoveNodeDestructObject(node,(KX_GameObject*)gameobj);
@@ -368,7 +368,7 @@ void KX_Scene::SetFramingType(RAS_FrameSettings & frame_settings)
const RAS_FrameSettings& KX_Scene::GetFramingType() const
{
return m_frame_settings;
-};
+};
@@ -441,7 +441,7 @@ void KX_Scene::EnableZBufferClearing(bool isclearingZbuffer)
void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gameobj)
{
- KX_GameObject* orgobj = (KX_GameObject*)gameobj;
+ KX_GameObject* orgobj = (KX_GameObject*)gameobj;
if (NewRemoveObject(orgobj) != 0)
{
// object is not yet deleted because a reference is hanging somewhere.
@@ -1072,7 +1072,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u
}
if (use_gfx && mesh != NULL)
- {
+ {
gameobj->RemoveMeshes();
gameobj->AddMesh(mesh);
@@ -1278,7 +1278,7 @@ void KX_Scene::AddCamera(KX_Camera* cam)
KX_Camera* KX_Scene::GetActiveCamera()
-{
+{
// NULL if not defined
return m_active_camera;
}
@@ -1634,16 +1634,17 @@ void KX_Scene::UpdateObjectActivity(void)
* Manhattan distance. */
MT_Point3 obpos = ob->NodeGetWorldPosition();
- if ( (fabs(camloc[0] - obpos[0]) > m_activity_box_radius)
- || (fabs(camloc[1] - obpos[1]) > m_activity_box_radius)
- || (fabs(camloc[2] - obpos[2]) > m_activity_box_radius) )
- {
+ if ((fabs(camloc[0] - obpos[0]) > m_activity_box_radius) ||
+ (fabs(camloc[1] - obpos[1]) > m_activity_box_radius) ||
+ (fabs(camloc[2] - obpos[2]) > m_activity_box_radius) )
+ {
ob->Suspend();
- } else {
+ }
+ else {
ob->Resume();
}
}
- }
+ }
}
}
@@ -1944,15 +1945,15 @@ void KX_Scene::Render2DFilters(RAS_ICanvas* canvas)
#ifdef WITH_PYTHON
-void KX_Scene::RunDrawingCallbacks(PyObject* cb_list)
+void KX_Scene::RunDrawingCallbacks(PyObject *cb_list)
{
Py_ssize_t len;
if (cb_list && (len=PyList_GET_SIZE(cb_list)))
{
- PyObject* args= PyTuple_New(0); // save python creating each call
- PyObject* func;
- PyObject* ret;
+ PyObject *args = PyTuple_New(0); // save python creating each call
+ PyObject *func;
+ PyObject *ret;
// Iterate the list and run the callbacks
for (Py_ssize_t pos=0; pos < len; pos++)
@@ -2019,7 +2020,7 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
{
KX_Scene* self= static_cast<KX_Scene*>BGE_PROXY_REF(self_v);
const char *attr_str= _PyUnicode_AsString(item);
- PyObject* pyconvert;
+ PyObject *pyconvert;
if (self==NULL) {
PyErr_SetString(PyExc_SystemError, "val = scene[key]: KX_Scene, "BGE_PROXY_ERROR_MSG);
@@ -2122,31 +2123,31 @@ PySequenceMethods KX_Scene::Sequence = {
(ssizeargfunc) NULL, /* sq_inplace_repeat */
};
-PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self= static_cast<KX_Scene*>(self_v);
return PyUnicode_From_STR_String(self->GetName());
}
-PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self= static_cast<KX_Scene*>(self_v);
return self->GetObjectList()->GetProxy();
}
-PyObject* KX_Scene::pyattr_get_objects_inactive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Scene::pyattr_get_objects_inactive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self= static_cast<KX_Scene*>(self_v);
return self->GetInactiveList()->GetProxy();
}
-PyObject* KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self= static_cast<KX_Scene*>(self_v);
return self->GetLightList()->GetProxy();
}
-PyObject* KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
/* With refcounts in this case...
* the new CListValue is owned by python, so its possible python holds onto it longer then the BGE
@@ -2167,7 +2168,7 @@ PyObject* KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *a
return clist->NewProxy(true);
}
-PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self= static_cast<KX_Scene*>(self_v);
KX_Camera* cam= self->GetActiveCamera();
@@ -2190,7 +2191,7 @@ int KX_Scene::pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *a
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_Scene::pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Scene::pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self = static_cast<KX_Scene*>(self_v);
@@ -2200,7 +2201,7 @@ PyObject* KX_Scene::pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATT
return self->m_draw_call_pre;
}
-PyObject* KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self = static_cast<KX_Scene*>(self_v);
@@ -2354,8 +2355,8 @@ KX_PYMETHODDEF_DOC(KX_Scene, drawObstacleSimulation,
KX_PYMETHODDEF_DOC(KX_Scene, get, "")
{
PyObject *key;
- PyObject* def = Py_None;
- PyObject* ret;
+ PyObject *def = Py_None;
+ PyObject *ret;
if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
return NULL;
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index f8480753395..bb329da99de 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -237,7 +237,7 @@ protected:
/**
* The execution priority of replicated object actuators?
- */
+ */
int m_ueberExecutionPriority;
/**
@@ -295,7 +295,7 @@ protected:
KX_ObstacleSimulation* m_obstacleSimulation;
-public:
+public:
KX_Scene(class SCA_IInputDevice* keyboarddevice,
class SCA_IInputDevice* mousedevice,
class NG_NetworkDeviceInterface* ndi,
@@ -303,7 +303,7 @@ public:
struct Scene* scene,
class RAS_ICanvas* canvas);
- virtual
+ virtual
~KX_Scene();
RAS_BucketManager* GetBucketManager();
@@ -349,11 +349,11 @@ public:
void LogicUpdateFrame(double curtime, bool frame);
void UpdateAnimations(double curtime);
- void
+ void
LogicEndFrame(
);
- CListValue*
+ CListValue*
GetTempObjectList(
);
@@ -361,23 +361,23 @@ public:
GetObjectList(
);
- CListValue*
+ CListValue*
GetInactiveList(
);
- CListValue*
+ CListValue*
GetRootParentList(
);
- CListValue*
+ CListValue*
GetLightList(
);
- SCA_LogicManager*
+ SCA_LogicManager *
GetLogicManager(
);
- SCA_TimeEventManager*
+ SCA_TimeEventManager *
GetTimeEventManager(
);
@@ -426,7 +426,7 @@ public:
);
/** Find the currently active camera. */
- KX_Camera*
+ KX_Camera*
GetActiveCamera(
);
@@ -435,7 +435,7 @@ public:
* camera is not present in the camera list, it will be added
*/
- void
+ void
SetActiveCamera(
class KX_Camera*
);
@@ -453,7 +453,7 @@ public:
* Activates new desired canvas width set at design time.
* \param width The new desired width.
*/
- void
+ void
SetCanvasDesignWidth(
unsigned int width
);
@@ -461,7 +461,7 @@ public:
* Activates new desired canvas height set at design time.
* \param width The new desired height.
*/
- void
+ void
SetCanvasDesignHeight(
unsigned int height
);
@@ -469,7 +469,7 @@ public:
* Returns the current desired canvas width set at design time.
* \return The desired width.
*/
- unsigned int
+ unsigned int
GetCanvasDesignWidth(
void
) const;
@@ -478,7 +478,7 @@ public:
* Returns the current desired canvas height set at design time.
* \return The desired height.
*/
- unsigned int
+ unsigned int
GetCanvasDesignHeight(
void
) const;
@@ -617,7 +617,7 @@ public:
static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- virtual PyObject* py_repr(void) { return PyUnicode_From_STR_String(GetName()); }
+ virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(GetName()); }
/* getitem/setitem */
static PyMappingMethods Mapping;
@@ -626,10 +626,10 @@ public:
/**
* Run the registered python drawing functions.
*/
- void RunDrawingCallbacks(PyObject* cb_list);
+ void RunDrawingCallbacks(PyObject *cb_list);
- PyObject* GetPreDrawCB() { return m_draw_call_pre; }
- PyObject* GetPostDrawCB() { return m_draw_call_post; }
+ PyObject *GetPreDrawCB() { return m_draw_call_pre; }
+ PyObject *GetPostDrawCB() { return m_draw_call_post; }
#endif
/**
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp
index 781c1fdab87..83b57dee7c1 100644
--- a/source/gameengine/Ketsji/KX_SceneActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp
@@ -256,7 +256,7 @@ PyAttributeDef KX_SceneActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self);
if (!actuator->m_camera)
@@ -279,7 +279,7 @@ int KX_SceneActuator::pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_
if (camOb==NULL) {
actuator->m_camera= NULL;
}
- else {
+ else {
actuator->m_camera = camOb;
actuator->m_camera->RegisterActuator(actuator);
}
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h
index 8e157544e2e..0b633334cce 100644
--- a/source/gameengine/Ketsji/KX_SceneActuator.h
+++ b/source/gameengine/Ketsji/KX_SceneActuator.h
@@ -99,7 +99,7 @@ class KX_SceneActuator : public SCA_IActuator
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
- static PyObject* pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index db91cea9074..c0191db640a 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -358,7 +358,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound,
}
/* Atribute setting and getting -------------------------------------------- */
-PyObject* KX_SoundActuator::pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SoundActuator::pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
const char* prop = attrdef->m_name;
@@ -392,11 +392,11 @@ PyObject* KX_SoundActuator::pyattr_get_3d_property(void *self, const struct KX_P
Py_RETURN_NONE;
}
- PyObject* result = PyFloat_FromDouble(result_value);
+ PyObject *result = PyFloat_FromDouble(result_value);
return result;
}
-PyObject* KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
float position = 0.0;
@@ -404,32 +404,32 @@ PyObject* KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_P
if (!actuator->m_handle.isNull())
position = actuator->m_handle->getPosition();
- PyObject* result = PyFloat_FromDouble(position);
+ PyObject *result = PyFloat_FromDouble(position);
return result;
}
-PyObject* KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
float gain = actuator->m_volume;
- PyObject* result = PyFloat_FromDouble(gain);
+ PyObject *result = PyFloat_FromDouble(gain);
return result;
}
-PyObject* KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
float pitch = actuator->m_pitch;
- PyObject* result = PyFloat_FromDouble(pitch);
+ PyObject *result = PyFloat_FromDouble(pitch);
return result;
}
-PyObject* KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
if (!actuator->m_sound.isNull())
@@ -542,7 +542,7 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D
int KX_SoundActuator::pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
- PyObject* sound = NULL;
+ PyObject *sound = NULL;
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
if (!PyArg_Parse(value, "O", &sound))
return PY_SET_ATTR_FAIL;
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h
index dbdb17d0da5..fcaf214dd90 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.h
+++ b/source/gameengine/Ketsji/KX_SoundActuator.h
@@ -115,12 +115,12 @@ public:
static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- static PyObject* pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
index 16b9285386a..2fa72c04a20 100644
--- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
@@ -253,7 +253,7 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
static const MT_Vector3 PATH_COLOR(1,0,0);
m_navmesh->DrawPath(m_path, m_pathLen, PATH_COLOR);
}
- }
+ }
}
break;
@@ -285,7 +285,7 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
//temporary solution: set 2D steering velocity directly to obj
//correct way is to apply physical force
MT_Vector3 curvel = obj->GetLinearVelocity();
- newvel.z() = curvel.z();
+ newvel.z() = curvel.z();
obj->setLinearVelocity(newvel, false);
}
else
@@ -356,8 +356,8 @@ static bool getNavmeshNormal(dtStatNavMesh* navmesh, const MT_Vector3& pos, MT_V
{
static const float polyPickExt[3] = {2, 4, 2};
float spos[3];
- pos.getValue(spos);
- flipAxes(spos);
+ pos.getValue(spos);
+ flipAxes(spos);
dtStatPolyRef sPolyRef = navmesh->findNearestPoly(spos, polyPickExt);
if (sPolyRef == 0)
return false;
@@ -382,7 +382,7 @@ static bool getNavmeshNormal(dtStatNavMesh* navmesh, const MT_Vector3& pos, MT_V
{
distMin = dist;
idxMin = i;
- }
+ }
}
if (idxMin>=0)
@@ -416,7 +416,7 @@ void KX_SteeringActuator::HandleActorFace(MT_Vector3& velocity)
KX_GameObject* curobj = (KX_GameObject*) GetParent();
MT_Vector3 dir = m_facingMode==0 ? curobj->NodeGetLocalOrientation().getColumn(1) : velocity;
if (dir.fuzzyZero())
- return;
+ return;
dir.normalize();
MT_Vector3 up(0,0,1);
MT_Vector3 left;
@@ -431,7 +431,7 @@ void KX_SteeringActuator::HandleActorFace(MT_Vector3& velocity)
{
left = (dir.cross(up)).safe_normalized();
- dir = (-left.cross(normal)).safe_normalized();
+ dir = (-left.cross(normal)).safe_normalized();
up = normal;
}
}
@@ -495,7 +495,7 @@ void KX_SteeringActuator::HandleActorFace(MT_Vector3& velocity)
MT_Point3 localpos;
localpos = curobj->GetSGNode()->GetLocalPosition();
MT_Matrix3x3 parentmatinv;
- parentmatinv = parentObject->NodeGetWorldOrientation ().inverse ();
+ parentmatinv = parentObject->NodeGetWorldOrientation ().inverse ();
mat = parentmatinv * mat;
mat = m_parentlocalmat * mat;
curobj->NodeSetLocalOrientation(mat);
@@ -551,16 +551,16 @@ PyAttributeDef KX_SteeringActuator::Attributes[] = {
KX_PYATTRIBUTE_FLOAT_RW("turnspeed", 0.0f, 720.0f, KX_SteeringActuator, m_turnspeed),
KX_PYATTRIBUTE_BOOL_RW("selfterminated", KX_SteeringActuator, m_isSelfTerminated),
KX_PYATTRIBUTE_BOOL_RW("enableVisualization", KX_SteeringActuator, m_enableVisualization),
- KX_PYATTRIBUTE_RO_FUNCTION("steeringVec", KX_SteeringActuator, pyattr_get_steeringVec),
+ KX_PYATTRIBUTE_RO_FUNCTION("steeringVec", KX_SteeringActuator, pyattr_get_steeringVec),
KX_PYATTRIBUTE_SHORT_RW("facingMode", 0, 6, true, KX_SteeringActuator, m_facingMode),
KX_PYATTRIBUTE_INT_RW("pathUpdatePeriod", -1, 100000, true, KX_SteeringActuator, m_pathUpdatePeriod),
{ NULL } //Sentinel
};
-PyObject* KX_SteeringActuator::pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SteeringActuator::pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SteeringActuator* actuator = static_cast<KX_SteeringActuator*>(self);
- if (!actuator->m_target)
+ if (!actuator->m_target)
Py_RETURN_NONE;
else
return actuator->m_target->GetProxy();
@@ -575,7 +575,7 @@ int KX_SteeringActuator::pyattr_set_target(void *self, const struct KX_PYATTRIBU
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
if (actuator->m_target != NULL)
- actuator->m_target->UnregisterActuator(actuator);
+ actuator->m_target->UnregisterActuator(actuator);
actuator->m_target = (KX_GameObject*) gameobj;
@@ -585,10 +585,10 @@ int KX_SteeringActuator::pyattr_set_target(void *self, const struct KX_PYATTRIBU
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_SteeringActuator::pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SteeringActuator::pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SteeringActuator* actuator = static_cast<KX_SteeringActuator*>(self);
- if (!actuator->m_navmesh)
+ if (!actuator->m_navmesh)
Py_RETURN_NONE;
else
return actuator->m_navmesh->GetProxy();
@@ -609,7 +609,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB
}
if (actuator->m_navmesh != NULL)
- actuator->m_navmesh->UnregisterActuator(actuator);
+ actuator->m_navmesh->UnregisterActuator(actuator);
actuator->m_navmesh = static_cast<KX_NavMeshObject*>(gameobj);
@@ -619,7 +619,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB
return PY_SET_ATTR_SUCCESS;
}
-PyObject* KX_SteeringActuator::pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_SteeringActuator::pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SteeringActuator* actuator = static_cast<KX_SteeringActuator*>(self);
const MT_Vector3& steeringVec = actuator->GetSteeringVec();
diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.h b/source/gameengine/Ketsji/KX_SteeringActuator.h
index c22a636cd95..341421d8948 100644
--- a/source/gameengine/Ketsji/KX_SteeringActuator.h
+++ b/source/gameengine/Ketsji/KX_SteeringActuator.h
@@ -82,7 +82,7 @@ public:
KX_GameObject *navmesh,
float distance,
float velocity,
- float acceleration,
+ float acceleration,
float turnspeed,
bool isSelfTerminated,
int pathUpdatePeriod,
@@ -107,11 +107,11 @@ public:
/* --------------------------------------------------------------------- */
/* These are used to get and set m_target */
- static PyObject* pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- static PyObject* pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
- static PyObject* pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp
index d7bcf1306a1..885ac70061e 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.cpp
+++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp
@@ -331,7 +331,7 @@ PyAttributeDef KX_TouchSensor::Attributes[] = {
/* Python API */
-PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v);
@@ -341,7 +341,7 @@ PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBU
Py_RETURN_NONE;
}
-PyObject* KX_TouchSensor::pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_TouchSensor::pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v);
return self->m_colliders->GetProxy();
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h
index d739144d70d..c80b8598e43 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.h
+++ b/source/gameengine/Ketsji/KX_TouchSensor.h
@@ -56,7 +56,7 @@ protected:
/**
* The sensor should only look for objects with this property.
*/
- STR_String m_touchedpropname;
+ STR_String m_touchedpropname;
bool m_bFindMaterial;
bool m_bTouchPulse; /* changes in the colliding objects trigger pulses */
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index 99732130f83..1597948bafe 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -90,7 +90,7 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj,
/* old function from Blender */
-MT_Matrix3x3 EulToMat3(float *eul)
+static MT_Matrix3x3 EulToMat3(float eul[3])
{
MT_Matrix3x3 mat;
float ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
@@ -122,7 +122,7 @@ MT_Matrix3x3 EulToMat3(float *eul)
/* old function from Blender */
-void Mat3ToEulOld(MT_Matrix3x3 mat, float eul[3])
+static void Mat3ToEulOld(MT_Matrix3x3 mat, float eul[3])
{
const float cy = sqrtf(mat[0][0] * mat[0][0] + mat[0][1] * mat[0][1]);
@@ -141,7 +141,7 @@ void Mat3ToEulOld(MT_Matrix3x3 mat, float eul[3])
/* old function from Blender */
-void compatible_eulFast(float *eul, float *oldrot)
+static void compatible_eulFast(float *eul, float *oldrot)
{
float dx, dy, dz;
@@ -164,9 +164,9 @@ void compatible_eulFast(float *eul, float *oldrot)
-MT_Matrix3x3 matrix3x3_interpol(MT_Matrix3x3 oldmat, MT_Matrix3x3 mat, int m_time)
+static MT_Matrix3x3 matrix3x3_interpol(MT_Matrix3x3 oldmat, MT_Matrix3x3 mat, int m_time)
{
- float eul[3], oldeul[3];
+ float eul[3], oldeul[3];
Mat3ToEulOld(oldmat, oldeul);
Mat3ToEulOld(mat, eul);
@@ -238,7 +238,7 @@ void KX_TrackToActuator::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map)
bool KX_TrackToActuator::Update(double curtime, bool frame)
{
- bool result = false;
+ bool result = false;
bool bNegativeEvent = IsNegativeEvent();
RemoveAllEvents();
@@ -395,7 +395,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
localpos = curobj->GetSGNode()->GetLocalPosition();
// Get the inverse of the parent matrix
MT_Matrix3x3 parentmatinv;
- parentmatinv = m_parentobj->NodeGetWorldOrientation ().inverse ();
+ parentmatinv = m_parentobj->NodeGetWorldOrientation ().inverse ();
// transform the local coordinate system into the parents system
mat = parentmatinv * mat;
// append the initial parent local rotation matrix
@@ -458,10 +458,10 @@ PyAttributeDef KX_TrackToActuator::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_TrackToActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_TrackToActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_TrackToActuator* actuator = static_cast<KX_TrackToActuator*>(self);
- if (!actuator->m_object)
+ if (!actuator->m_object)
Py_RETURN_NONE;
else
return actuator->m_object->GetProxy();
@@ -476,7 +476,7 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
if (actuator->m_object != NULL)
- actuator->m_object->UnregisterActuator(actuator);
+ actuator->m_object->UnregisterActuator(actuator);
actuator->m_object = (SCA_IObject*) gameobj;
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h
index fb2ced2a415..6329c7b34d9 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.h
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.h
@@ -74,8 +74,8 @@ class KX_TrackToActuator : public SCA_IActuator
/* Python part */
/* These are used to get and set m_ob */
- static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
- static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
index 1c03df80dc1..b5d6f11a2d5 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
@@ -34,11 +34,11 @@ KX_VehicleWrapper::~KX_VehicleWrapper()
#ifdef WITH_PYTHON
-PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* args)
+PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
{
- PyObject* pylistPos,*pylistDir,*pylistAxleDir;
- PyObject* wheelGameObject;
+ PyObject *pylistPos,*pylistDir,*pylistAxleDir;
+ PyObject *wheelGameObject;
float suspensionRestLength,wheelRadius;
int hasSteering;
@@ -83,7 +83,7 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* args)
-PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* args)
+PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args)
{
int wheelIndex;
@@ -98,7 +98,7 @@ PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* args)
return NULL;
}
-PyObject* KX_VehicleWrapper::PyGetWheelRotation(PyObject* args)
+PyObject *KX_VehicleWrapper::PyGetWheelRotation(PyObject *args)
{
int wheelIndex;
if (PyArg_ParseTuple(args,"i:getWheelRotation",&wheelIndex))
@@ -108,7 +108,7 @@ PyObject* KX_VehicleWrapper::PyGetWheelRotation(PyObject* args)
return NULL;
}
-PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args)
+PyObject *KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject *args)
{
int wheelIndex;
if (PyArg_ParseTuple(args,"i:getWheelOrientationQuaternion",&wheelIndex))
@@ -124,20 +124,20 @@ PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args)
}
-PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* args)
+PyObject *KX_VehicleWrapper::PyGetNumWheels(PyObject *args)
{
return PyLong_FromSsize_t(m_vehicle->GetNumWheels());
}
-PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* args)
+PyObject *KX_VehicleWrapper::PyGetConstraintId(PyObject *args)
{
return PyLong_FromSsize_t(m_vehicle->GetUserConstraintId());
}
-PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* args)
+PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args)
{
float force;
int wheelIndex;
@@ -153,7 +153,7 @@ PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* args)
+PyObject *KX_VehicleWrapper::PySetTyreFriction(PyObject *args)
{
float wheelFriction;
int wheelIndex;
@@ -168,7 +168,7 @@ PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* args)
+PyObject *KX_VehicleWrapper::PySetSuspensionStiffness(PyObject *args)
{
float suspensionStiffness;
int wheelIndex;
@@ -183,7 +183,7 @@ PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* args)
+PyObject *KX_VehicleWrapper::PySetSuspensionDamping(PyObject *args)
{
float suspensionDamping;
int wheelIndex;
@@ -197,7 +197,7 @@ PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* args)
+PyObject *KX_VehicleWrapper::PySetSuspensionCompression(PyObject *args)
{
float suspensionCompression;
int wheelIndex;
@@ -211,7 +211,7 @@ PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* args)
Py_RETURN_NONE;
}
-PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* args)
+PyObject *KX_VehicleWrapper::PySetRollInfluence(PyObject *args)
{
float rollInfluence;
int wheelIndex;
@@ -227,7 +227,7 @@ PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* args)
}
-PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* args)
+PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args)
{
float braking;
int wheelIndex;
@@ -245,7 +245,7 @@ PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* args)
-PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args)
+PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args)
{
float steeringValue;
int wheelIndex;
@@ -261,7 +261,7 @@ PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args)
}
-PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* args)
+PyObject *KX_VehicleWrapper::PyGetConstraintType(PyObject *args)
{
return PyLong_FromSsize_t(m_vehicle->GetUserConstraintType());
}
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp
index d489c015273..461563d4512 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.cpp
+++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp
@@ -101,85 +101,85 @@ PyAttributeDef KX_VertexProxy::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* KX_VertexProxy::pyattr_get_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getXYZ()[0]);
}
-PyObject* KX_VertexProxy::pyattr_get_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getXYZ()[1]);
}
-PyObject* KX_VertexProxy::pyattr_get_z(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_z(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getXYZ()[2]);
}
-PyObject* KX_VertexProxy::pyattr_get_r(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_r(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getRGBA()[0]/255.0);
}
-PyObject* KX_VertexProxy::pyattr_get_g(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_g(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getRGBA()[1]/255.0);
}
-PyObject* KX_VertexProxy::pyattr_get_b(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_b(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getRGBA()[2]/255.0);
}
-PyObject* KX_VertexProxy::pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getRGBA()[3]/255.0);
}
-PyObject* KX_VertexProxy::pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getUV1()[0]);
}
-PyObject* KX_VertexProxy::pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getUV1()[1]);
}
-PyObject* KX_VertexProxy::pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getUV2()[0]);
}
-PyObject* KX_VertexProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyFloat_FromDouble(self->m_vertex->getUV2()[1]);
}
-PyObject* KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyObjectFrom(MT_Vector3(self->m_vertex->getXYZ()));
}
-PyObject* KX_VertexProxy::pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyObjectFrom(MT_Point2(self->m_vertex->getUV1()));
}
-PyObject* KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
const unsigned char *colp = self->m_vertex->getRGBA();
@@ -188,7 +188,7 @@ PyObject* KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DE
return PyObjectFrom(color);
}
-PyObject* KX_VertexProxy::pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject *KX_VertexProxy::pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
return PyObjectFrom(MT_Vector3(self->m_vertex->getNormal()));
@@ -459,12 +459,12 @@ CValue* KX_VertexProxy::GetReplica() { return NULL;}
// stuff for python integration
-PyObject* KX_VertexProxy::PyGetXYZ()
+PyObject *KX_VertexProxy::PyGetXYZ()
{
return PyObjectFrom(MT_Point3(m_vertex->getXYZ()));
}
-PyObject* KX_VertexProxy::PySetXYZ(PyObject* value)
+PyObject *KX_VertexProxy::PySetXYZ(PyObject *value)
{
MT_Point3 vec;
if (!PyVecTo(value, vec))
@@ -475,12 +475,12 @@ PyObject* KX_VertexProxy::PySetXYZ(PyObject* value)
Py_RETURN_NONE;
}
-PyObject* KX_VertexProxy::PyGetNormal()
+PyObject *KX_VertexProxy::PyGetNormal()
{
return PyObjectFrom(MT_Vector3(m_vertex->getNormal()));
}
-PyObject* KX_VertexProxy::PySetNormal(PyObject* value)
+PyObject *KX_VertexProxy::PySetNormal(PyObject *value)
{
MT_Vector3 vec;
if (!PyVecTo(value, vec))
@@ -492,13 +492,13 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject* value)
}
-PyObject* KX_VertexProxy::PyGetRGBA()
+PyObject *KX_VertexProxy::PyGetRGBA()
{
int *rgba = (int *) m_vertex->getRGBA();
return PyLong_FromSsize_t(*rgba);
}
-PyObject* KX_VertexProxy::PySetRGBA(PyObject* value)
+PyObject *KX_VertexProxy::PySetRGBA(PyObject *value)
{
if (PyLong_Check(value)) {
int rgba = PyLong_AsSsize_t(value);
@@ -521,12 +521,12 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject* value)
}
-PyObject* KX_VertexProxy::PyGetUV()
+PyObject *KX_VertexProxy::PyGetUV()
{
return PyObjectFrom(MT_Vector2(m_vertex->getUV1()));
}
-PyObject* KX_VertexProxy::PySetUV(PyObject* value)
+PyObject *KX_VertexProxy::PySetUV(PyObject *value)
{
MT_Point2 vec;
if (!PyVecTo(value, vec))
@@ -537,17 +537,17 @@ PyObject* KX_VertexProxy::PySetUV(PyObject* value)
Py_RETURN_NONE;
}
-PyObject* KX_VertexProxy::PyGetUV2()
+PyObject *KX_VertexProxy::PyGetUV2()
{
return PyObjectFrom(MT_Vector2(m_vertex->getUV2()));
}
-PyObject* KX_VertexProxy::PySetUV2(PyObject* args)
+PyObject *KX_VertexProxy::PySetUV2(PyObject *args)
{
MT_Point2 vec;
unsigned int unit= RAS_TexVert::SECOND_UV;
- PyObject* list= NULL;
+ PyObject *list = NULL;
if (!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit))
return NULL;
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h
index 3084e5fac93..f56e2be26a3 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.h
+++ b/source/gameengine/Ketsji/KX_VertexProxy.h
@@ -59,21 +59,21 @@ public:
// stuff for python integration
- static PyObject* pyattr_get_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_z(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_r(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_g(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_b(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
- static PyObject* pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_z(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_r(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_g(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_b(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_x(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_y(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_z(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h
index 409b1fec321..575d4e72f14 100644
--- a/source/gameengine/Ketsji/KX_WorldIpoController.h
+++ b/source/gameengine/Ketsji/KX_WorldIpoController.h
@@ -72,15 +72,15 @@ public:
m_modified = true;
}
- void SetModifyMistStart(bool modify) {
+ void SetModifyMistStart(bool modify) {
m_modify_mist_start = modify;
}
- void SetModifyMistColor(bool modify) {
+ void SetModifyMistColor(bool modify) {
m_modify_mist_color = modify;
}
- void SetModifyMistDist(bool modify) {
+ void SetModifyMistDist(bool modify) {
m_modify_mist_dist = modify;
}
diff --git a/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h
index 92ba6100359..f9d2146a766 100644
--- a/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h
+++ b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h
@@ -36,7 +36,7 @@
#include "NG_NetworkDeviceInterface.h"
class NG_LoopBackNetworkDeviceInterface : public NG_NetworkDeviceInterface
-{
+{
std::deque<NG_NetworkMessage*> m_messages[2];
int m_currentQueue;
diff --git a/source/gameengine/Network/NG_NetworkScene.h b/source/gameengine/Network/NG_NetworkScene.h
index 41ac8ead5e4..381b71da0d7 100644
--- a/source/gameengine/Network/NG_NetworkScene.h
+++ b/source/gameengine/Network/NG_NetworkScene.h
@@ -51,7 +51,7 @@ class NG_NetworkDeviceInterface;
class NG_NetworkScene
{
- class NG_NetworkDeviceInterface *m_networkdevice;
+ class NG_NetworkDeviceInterface *m_networkdevice;
CTR_Map<STR_HashedString, class NG_NetworkObject *> m_networkObjects;
// CTR_Maps used as a 'Bloom' filter
@@ -107,7 +107,7 @@ protected:
* Releases messages for the given message map.
* \param map Message map with messages.
*/
- void ClearMessageMap(TMessageMap& map);
+ void ClearMessageMap(TMessageMap& map);
#ifdef WITH_CXX_GUARDEDALLOC
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.h b/source/gameengine/Physics/Bullet/CcdGraphicController.h
index 60ff475832b..15edfeb5759 100644
--- a/source/gameengine/Physics/Bullet/CcdGraphicController.h
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.h
@@ -33,7 +33,7 @@ class CcdPhysicsEnvironment;
class btCollisionObject;
///CcdGraphicController is a graphic object that supports view frustrum culling and occlusion
-class CcdGraphicController : public PHY_IGraphicController
+class CcdGraphicController : public PHY_IGraphicController
{
public:
CcdGraphicController(CcdPhysicsEnvironment* phyEnv, PHY_IMotionState* motionState);
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index ed2b9cfcb0b..81bf66d9536 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -787,7 +787,7 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
if (oldbody->getActivationState() == DISABLE_DEACTIVATION)
body->setActivationState(DISABLE_DEACTIVATION);
}
- }
+ }
// sensor object are added when needed
if (!m_cci.m_bSensor)
m_cci.m_physicsEnv->addCcdPhysicsController(this);
@@ -806,7 +806,7 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
m_sumoObj = new SM_Object(
orgsumoobject->getShapeHandle(),
- orgsumoobject->getMaterialProps(),
+ orgsumoobject->getMaterialProps(),
orgsumoobject->getShapeProps(),
dynaparent);
@@ -1142,7 +1142,7 @@ void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bo
btTransform xform = m_object->getWorldTransform();
if (local)
- {
+ {
force = xform.getBasis()*force;
}
btRigidBody* body = GetRigidBody();
@@ -1661,7 +1661,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
}
if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */
vert_tag_array[mf->v3]= false;
- *bt++ = v3->co[0];
+ *bt++ = v3->co[0];
*bt++ = v3->co[1];
*bt++ = v3->co[2];
}
@@ -1693,7 +1693,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
if (vert_tag_array[mf->v4]==true) { /* *** v4 *** */
vert_tag_array[mf->v4]= false;
*bt++ = v4->co[0];
- *bt++ = v4->co[1];
+ *bt++ = v4->co[1];
*bt++ = v4->co[2];
}
}
@@ -2089,7 +2089,7 @@ bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo)
btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, bool useGimpact, bool useBvh)
{
btCollisionShape* collisionShape = 0;
- btCompoundShape* compoundShape = 0;
+ btCompoundShape* compoundShape = 0;
if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL)
return m_shapeProxy->CreateBulletShape(margin, useGimpact, useBvh);
@@ -2138,7 +2138,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b
// One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1
// and btScaledBvhTriangleMeshShape otherwise.
if (useGimpact)
- {
+ {
btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(
m_polygonIndexArray.size(),
&m_triFaceArray[0],
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 94dc796df23..2204f224e7d 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -171,7 +171,7 @@ public:
btVector3 m_halfExtend;
btTransform m_childTrans;
btVector3 m_childScale;
- void* m_userData;
+ void* m_userData;
btAlignedObjectArray<btScalar> m_vertexArray; // Contains both vertex array for polytope shape and
// triangle array for concave mesh shape. Each vertex is 3 consecutive values
// In this case a triangle is made of 3 consecutive points
@@ -397,7 +397,7 @@ class btCollisionObject;
class btSoftBody;
///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution.
-class CcdPhysicsController : public PHY_IPhysicsController
+class CcdPhysicsController : public PHY_IPhysicsController
{
protected:
btCollisionObject* m_object;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index 5d28bf47401..55bbc0d33b9 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -303,13 +303,13 @@ static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVec
{
for (j=0;j<3;j++)
{
- pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
+ pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
edgecoord[2]*halfExtents[2]);
pa+=center;
int othercoord = j%3;
edgecoord[othercoord]*=-1.f;
- pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
+ pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
edgecoord[2]*halfExtents[2]);
pb+=center;
@@ -484,9 +484,8 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr
body->getCollisionShape()->calculateLocalInertia(newMass, inertia);
body->setMassProps(newMass, inertia);
m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask);
- }
- else
- {
+ }
+ else {
m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask);
}
}
@@ -605,7 +604,7 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float
float subStep = timeStep / float(m_numTimeSubSteps);
i = m_dynamicsWorld->stepSimulation(interval,25,subStep);//perform always a full simulation step
-//uncomment next line to see where Bullet spend its time (printf in console)
+//uncomment next line to see where Bullet spend its time (printf in console)
//CProfileManager::dumpAll();
processFhSprings(curTime,i*subStep);
@@ -1084,7 +1083,7 @@ static bool GetHitTriangle(btCollisionShape* shape, CcdShapeConstructionInfo* sh
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
- triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
}
meshInterface->unLockReadOnlyVertexBase(0);
return true;
@@ -1248,7 +1247,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY();
result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ();
filterCallback.reportHit(&result);
- }
+ }
return result.m_controller;
@@ -1391,7 +1390,7 @@ struct OcclusionBuffer
static bool project(btVector4* p,int n)
{
for (int i=0;i<n;++i)
- {
+ {
p[i][2]=1/p[i][3];
p[i][0]*=p[i][2];
p[i][1]*=p[i][2];
@@ -1611,7 +1610,7 @@ struct OcclusionBuffer
const int a=x[2]*y[0]+x[0]*y[1]-x[2]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0];
const btScalar ia=1/(btScalar)a;
const btScalar dzx=ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1]));
- const btScalar dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width);
+ const btScalar dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width);
int c[]={ miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0],
miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1],
miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]};
@@ -1674,7 +1673,7 @@ struct OcclusionBuffer
const float* c,
const float* d,
const float face)
- {
+ {
btVector4 p[4];
transformM(a,p[0]);
transformM(b,p[1]);
@@ -1744,7 +1743,7 @@ struct DbvtCullingCallback : btDbvt::ICollide
Process(node);
}
void Process(const btDbvtNode* leaf)
- {
+ {
btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data;
// the client object is a graphic controller
CcdGraphicController* ctrl = static_cast<CcdGraphicController*>(proxy->m_clientObject);
@@ -1817,11 +1816,11 @@ bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* user
dispatcher.m_ocb = &gOcb;
// occlusion culling, the direction of the view is taken from the first plan which MUST be the near plane
btDbvt::collideOCL(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);
- btDbvt::collideOCL(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);
+ btDbvt::collideOCL(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);
}
else {
btDbvt::collideKDOP(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,nplanes,dispatcher);
- btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher);
+ btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher);
}
return true;
}
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
index 69bbc7745e0..6994706ce2d 100644
--- a/source/gameengine/Physics/common/PHY_DynamicTypes.h
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -32,11 +32,11 @@ struct PHY__Vector2
operator const float* () const
{
return &m_vec[0];
- }
+ }
operator float* ()
{
return &m_vec[0];
- }
+ }
};
struct PHY__Vector3
@@ -46,11 +46,11 @@ struct PHY__Vector3
operator const float* () const
{
return &m_vec[0];
- }
+ }
operator float* ()
{
return &m_vec[0];
- }
+ }
};
struct PHY__Vector4
@@ -75,11 +75,11 @@ struct PHY__Vector4
operator const float* () const
{
return &m_vec[0];
- }
+ }
operator float* ()
{
return &m_vec[0];
- }
+ }
};
//typedef float PHY__Vector3[4];
diff --git a/source/gameengine/Physics/common/PHY_IController.h b/source/gameengine/Physics/common/PHY_IController.h
index 239ac3366e1..729abd8ec04 100644
--- a/source/gameengine/Physics/common/PHY_IController.h
+++ b/source/gameengine/Physics/common/PHY_IController.h
@@ -45,7 +45,7 @@ class PHY_IPhysicsEnvironment;
controlled by the physics engine. This includes the physics objects
and the graphics object for view frustrum and occlusion culling.
*/
-class PHY_IController
+class PHY_IController
{
public:
virtual ~PHY_IController();
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h
index 2eb2a9f39cf..72ff37468ee 100644
--- a/source/gameengine/Physics/common/PHY_IMotionState.h
+++ b/source/gameengine/Physics/common/PHY_IMotionState.h
@@ -43,7 +43,7 @@
class PHY_IMotionState
{
- public:
+ public:
virtual ~PHY_IMotionState();
virtual void getWorldPosition(float& posX,float& posY,float& posZ)=0;
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index 30d63e6695d..3f8699d25d2 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -48,7 +48,7 @@ class PHY_IPhysicsController;
*/
struct PHY_RayCastResult
{
- PHY_IPhysicsController* m_controller;
+ PHY_IPhysicsController* m_controller;
PHY__Vector3 m_hitPoint;
PHY__Vector3 m_hitNormal;
const RAS_MeshObject* m_meshObject; // !=NULL for mesh object (only for Bullet controllers)
diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index 06251cd2282..7312b521788 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -110,7 +110,7 @@ void RAS_2DFilterManager::PrintShaderErrors(unsigned int shader, const char *tas
unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource)
{
- GLuint program = 0;
+ GLuint program = 0;
GLuint fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
GLint success;
@@ -469,7 +469,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
glEnable(GL_DEPTH_TEST);
glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);
- EndShaderProgram();
+ EndShaderProgram();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
index 90587bb9739..457fd0ad90c 100644
--- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
@@ -232,8 +232,8 @@ void RAS_BucketManager::Renderbuckets(
/* beginning each frame, clear (texture/material) caching information */
rasty->ClearCachingInfo();
- RenderSolidBuckets(cameratrans, rasty, rendertools);
- RenderAlphaBuckets(cameratrans, rasty, rendertools);
+ RenderSolidBuckets(cameratrans, rasty, rendertools);
+ RenderAlphaBuckets(cameratrans, rasty, rendertools);
rendertools->SetClientObject(rasty, NULL);
}
diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h
index 51c4da3c49d..d70e56dc285 100644
--- a/source/gameengine/Rasterizer/RAS_Deformer.h
+++ b/source/gameengine/Rasterizer/RAS_Deformer.h
@@ -91,7 +91,7 @@ public:
protected:
class RAS_MeshObject *m_pMesh;
- bool m_bDynamic;
+ bool m_bDynamic;
#ifdef WITH_CXX_GUARDEDALLOC
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.cpp b/source/gameengine/Rasterizer/RAS_FramingManager.cpp
index 1cd110f8cc6..53d9b64ab0e 100644
--- a/source/gameengine/Rasterizer/RAS_FramingManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.cpp
@@ -43,7 +43,7 @@ ComputeDefaultFrustum(
const short sensor_fit,
const float design_aspect_ratio,
RAS_FrameFrustum & frustum
-) {
+) {
float halfSize;
float sizeX;
float sizeY;
@@ -202,7 +202,7 @@ ComputeViewport(
{
ComputeBestFitViewRect(
availableViewport,
- design_aspect_ratio,
+ design_aspect_ratio,
viewport
);
@@ -260,7 +260,7 @@ ComputeFrustum(
RAS_Rect vt;
ComputeBestFitViewRect(
availableViewport,
- design_aspect_ratio,
+ design_aspect_ratio,
vt
);
@@ -277,13 +277,13 @@ ComputeFrustum(
frustum.y2 *= y_scale;
break;
- }
+ }
case RAS_FrameSettings::e_frame_scale :
case RAS_FrameSettings::e_frame_bars:
default :
break;
}
-}
+}
void
RAS_FramingManager::
@@ -330,7 +330,7 @@ RAS_FramingManager::
RAS_Rect vt;
ComputeBestFitViewRect(
availableViewport,
- design_aspect_ratio,
+ design_aspect_ratio,
vt
);
@@ -347,7 +347,7 @@ RAS_FramingManager::
frustum.y2 *= y_scale;
break;
- }
+ }
case RAS_FrameSettings::e_frame_scale :
case RAS_FrameSettings::e_frame_bars:
default :
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h
index dd640bc6839..122f0ca46ec 100644
--- a/source/gameengine/Rasterizer/RAS_FramingManager.h
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.h
@@ -109,7 +109,7 @@ public :
*/
const
- RAS_FrameType &
+ RAS_FrameType &
FrameType(
) const {
return m_frame_type;
@@ -143,13 +143,13 @@ public :
unsigned int
DesignAspectWidth(
) const {
- return m_design_aspect_width;
+ return m_design_aspect_width;
};
unsigned int
DesignAspectHeight(
) const {
- return m_design_aspect_height;
+ return m_design_aspect_height;
};
private :
@@ -262,7 +262,7 @@ public :
const short sensor_fit,
const float design_aspect_ratio,
RAS_FrameFrustum & frustum
- );
+ );
static
void
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
index 7749c4af9d6..8efc10f2118 100644
--- a/source/gameengine/Rasterizer/RAS_IRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -301,7 +301,7 @@ public:
virtual int GetDrawingMode()=0;
/**
* Sets face culling
- */
+ */
virtual void SetCullFace(bool enable)=0;
/**
* Sets wireframe mode.
diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h
index c02bc5e7a44..ca6f20b71ad 100644
--- a/source/gameengine/Rasterizer/RAS_IRenderTools.h
+++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h
@@ -72,18 +72,18 @@ public:
{
};
- virtual
+ virtual
~RAS_IRenderTools(
) {};
virtual
- void
+ void
BeginFrame(
RAS_IRasterizer* rasty
)=0;
virtual
- void
+ void
EndFrame(
RAS_IRasterizer* rasty
)=0;
@@ -94,7 +94,7 @@ public:
// so must be renamed to 'applyTransform' or something
virtual
- void
+ void
applyTransform(
class RAS_IRasterizer* rasty,
double* oglmatrix,
@@ -112,7 +112,7 @@ public:
* \param aspect A scaling factor to compensate for the size.
*/
virtual
- void
+ void
RenderText3D(int fontid,
const char* text,
int size,
@@ -133,7 +133,7 @@ public:
* \param height Height of the canvas to draw to.
*/
virtual
- void
+ void
RenderText2D(
RAS_TEXT_RENDER_MODE mode,
const char* text,
@@ -145,7 +145,7 @@ public:
// 3d text, mapped on polygon
virtual
- void
+ void
RenderText(
int mode,
RAS_IPolyMaterial* polymat,
@@ -156,8 +156,8 @@ public:
int glattrib
)=0;
- virtual
- void
+ virtual
+ void
ProcessLighting(
RAS_IRasterizer *rasty,
bool uselights,
@@ -165,35 +165,35 @@ public:
)=0;
virtual
- void
+ void
SetClientObject(
RAS_IRasterizer* rasty,
void* obj
);
- void
+ void
SetAuxilaryClientInfo(
void* inf
);
virtual
- void
+ void
PushMatrix(
)=0;
virtual
- void
+ void
PopMatrix(
)=0;
virtual
- void
+ void
AddLight(
struct RAS_LightObject* lightobject
);
virtual
- void
+ void
RemoveLight(
struct RAS_LightObject* lightobject
);
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
index a18adfd8986..183da9d252e 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
@@ -489,7 +489,7 @@ bool RAS_MeshSlot::Split(bool force)
}
-#ifdef USE_SPLIT
+#ifdef USE_SPLIT
bool RAS_MeshSlot::IsCulled()
{
if (m_joinSlot)
@@ -502,7 +502,7 @@ bool RAS_MeshSlot::IsCulled()
return false;
return true;
}
-#endif
+#endif
/* material bucket sorting */
@@ -531,12 +531,12 @@ RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const
}
bool RAS_MaterialBucket::IsAlpha() const
-{
+{
return (m_material->IsAlpha());
}
bool RAS_MaterialBucket::IsZSort() const
-{
+{
return (m_material->IsZSort());
}
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
index 25afefbcc5a..c50aa28e9fc 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
@@ -173,7 +173,7 @@ const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid)
RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid)
{
- if (m_materials.size() > 0 && (matid < m_materials.size()))
+ if ((m_materials.empty() == false) && (matid < m_materials.size()))
{
list<RAS_MeshMaterial>::iterator it = m_materials.begin();
while (matid--) ++it;
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index b769fc4b703..67423123a7a 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -438,7 +438,7 @@ void RAS_OpenGLRasterizer::EndFrame()
glDisable(GL_MULTISAMPLE_ARB);
m_2DCanvas->EndFrame();
-}
+}
void RAS_OpenGLRasterizer::SetRenderArea()
{
@@ -975,7 +975,7 @@ void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
/* Get into argument. Looks a bit dodgy, but it's ok. */
mat.getValue(matrix);
/* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
- glLoadMatrixd(matrix);
+ glLoadMatrixd(matrix);
m_camortho= (mat[3][3] != 0.0);
}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
index e5eba249175..8b54f507ee0 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
@@ -278,7 +278,7 @@ public:
line.m_type = OglDebugShape::CIRCLE;
line.m_pos= center;
line.m_param = normal;
- line.m_color = color;
+ line.m_color = color;
line.m_param2.x() = radius;
line.m_param2.y() = (float) nsector;
m_debugShapes.push_back(line);
diff --git a/source/gameengine/SceneGraph/SG_Controller.h b/source/gameengine/SceneGraph/SG_Controller.h
index d82738dbb86..455aaf90d6d 100644
--- a/source/gameengine/SceneGraph/SG_Controller.h
+++ b/source/gameengine/SceneGraph/SG_Controller.h
@@ -53,7 +53,7 @@ public:
) {};
virtual
- bool
+ bool
Update(
double time
)=0;
@@ -69,13 +69,13 @@ public:
);
virtual
- void
+ void
SetSimulatedTime(
double time
)=0;
- virtual
- SG_Controller*
+ virtual
+ SG_Controller*
GetReplica(
class SG_Node* destnode
)=0;
diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp
index afd647c2a2a..9ae32a89ff8 100644
--- a/source/gameengine/SceneGraph/SG_IObject.cpp
+++ b/source/gameengine/SceneGraph/SG_IObject.cpp
@@ -70,7 +70,7 @@ AddSGController(
m_SGcontrollers.push_back(cont);
}
- void
+ void
SG_IObject::
RemoveSGController(
SG_Controller* cont
diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h
index c36c984f3d3..53b51507e97 100644
--- a/source/gameengine/SceneGraph/SG_IObject.h
+++ b/source/gameengine/SceneGraph/SG_IObject.h
@@ -174,7 +174,7 @@ public:
* this object is deleted.
*/
- void
+ void
AddSGController(
SG_Controller* cont
);
@@ -196,7 +196,7 @@ public:
* leaks.
*/
- void
+ void
RemoveAllControllers(
);
@@ -233,7 +233,7 @@ public:
* This may be NULL.
*/
- inline const void* GetSGClientObject() const
+ inline const void* GetSGClientObject() const
{
return m_SGclientObject;
}
@@ -280,7 +280,7 @@ public:
void SetControllerTime(double time);
virtual
- void
+ void
Destruct(
) = 0;
diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp
index 33af9f16d7c..04d9a306fc4 100644
--- a/source/gameengine/SceneGraph/SG_Node.cpp
+++ b/source/gameengine/SceneGraph/SG_Node.cpp
@@ -143,7 +143,7 @@ Destruct()
}
const
- SG_Node*
+ SG_Node *
SG_Node::
GetRootSGParent(
) const {
diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h
index 1d0c0e592e6..063eeaab01d 100644
--- a/source/gameengine/SceneGraph/SG_Node.h
+++ b/source/gameengine/SceneGraph/SG_Node.h
@@ -63,7 +63,7 @@ public:
* make a deep copy.
*/
- void
+ void
AddChild(
SG_Node* child
);
@@ -75,7 +75,7 @@ public:
* If the node was not a child of this object no action is performed.
*/
- void
+ void
RemoveChild(
SG_Node* child
);
@@ -149,7 +149,7 @@ public:
* Disconnect this node from it's parent
*/
- void
+ void
DisconnectFromParent(
);
@@ -182,12 +182,12 @@ public:
- /**
+ /**
* Update the spatial data of this node. Iterate through
* the children of this node and update their world data.
*/
- void
+ void
UpdateWorldData(
double time,
bool parentUpdated=false
@@ -198,7 +198,7 @@ public:
* the children nodes and update their simulated time.
*/
- void
+ void
SetSimulatedTime(
double time,
bool recurse
@@ -244,17 +244,17 @@ public:
* Node replication functions.
*/
- SG_Node*
+ SG_Node*
GetSGReplica(
);
- void
+ void
Destruct(
);
private:
- void
+ void
ProcessSGReplica(
SG_Node** replica
);
diff --git a/source/gameengine/SceneGraph/SG_ParentRelation.h b/source/gameengine/SceneGraph/SG_ParentRelation.h
index 4478ed11bc1..6e314996456 100644
--- a/source/gameengine/SceneGraph/SG_ParentRelation.h
+++ b/source/gameengine/SceneGraph/SG_ParentRelation.h
@@ -118,7 +118,7 @@ protected :
*/
SG_ParentRelation(
- ) {
+ ) {
};
/**
diff --git a/source/gameengine/SceneGraph/SG_Spatial.cpp b/source/gameengine/SceneGraph/SG_Spatial.cpp
index f8c4b5165ee..8c0d2b88c63 100644
--- a/source/gameengine/SceneGraph/SG_Spatial.cpp
+++ b/source/gameengine/SceneGraph/SG_Spatial.cpp
@@ -161,8 +161,8 @@ RelativeTranslate(
}
}
SetModified();
-}
-
+}
+
/**
* Scaling methods.
diff --git a/source/gameengine/SceneGraph/SG_Spatial.h b/source/gameengine/SceneGraph/SG_Spatial.h
index e456851d183..7630af51781 100644
--- a/source/gameengine/SceneGraph/SG_Spatial.h
+++ b/source/gameengine/SceneGraph/SG_Spatial.h
@@ -137,7 +137,7 @@ public:
}
- void
+ void
RelativeRotate(
const MT_Matrix3x3& rot,
bool local
@@ -178,12 +178,12 @@ public:
m_worldScaling = scale;
}
- const MT_Point3& GetLocalPosition() const
+ const MT_Point3& GetLocalPosition() const
{
return m_localPosition;
}
- const MT_Matrix3x3& GetLocalOrientation() const
+ const MT_Matrix3x3& GetLocalOrientation() const
{
return m_localRotation;
}
@@ -193,17 +193,17 @@ public:
return m_localScaling;
}
- const MT_Point3& GetWorldPosition() const
+ const MT_Point3& GetWorldPosition() const
{
return m_worldPosition;
}
- const MT_Matrix3x3& GetWorldOrientation() const
+ const MT_Matrix3x3& GetWorldOrientation() const
{
return m_worldRotation;
}
- const MT_Vector3& GetWorldScaling() const
+ const MT_Vector3& GetWorldScaling() const
{
return m_worldScaling;
}
diff --git a/source/gameengine/SceneGraph/SG_Tree.cpp b/source/gameengine/SceneGraph/SG_Tree.cpp
index 0f8264985de..99f68ef625a 100644
--- a/source/gameengine/SceneGraph/SG_Tree.cpp
+++ b/source/gameengine/SceneGraph/SG_Tree.cpp
@@ -236,7 +236,7 @@ void SG_TreeFactory::Add(SG_Tree* tree)
SG_Tree* SG_TreeFactory::MakeTreeDown(SG_BBox &bbox)
{
- if (m_objects.size() == 0)
+ if (m_objects.empty())
return NULL;
if (m_objects.size() == 1)
return *m_objects.begin();
diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h
index 0131cc61c44..e19aadc49d2 100644
--- a/source/gameengine/VideoTexture/BlendType.h
+++ b/source/gameengine/VideoTexture/BlendType.h
@@ -37,7 +37,7 @@ public:
BlendType (const char * name) : m_name(name) {}
/// check blender type and return pointer to contained object or NULL (if type is not valid)
- PyObj * checkType (PyObject * obj)
+ PyObj *checkType(PyObject *obj)
{
// if pointer to type isn't set
if (m_objType == NULL)
@@ -55,17 +55,18 @@ public:
return NULL;
// return pointer to object, this class can only be used for KX object =>
// the Py object is actually a proxy
- return (PyObj*)BGE_PROXY_REF(obj);
+ return (PyObj *)BGE_PROXY_REF(obj);
}
/// parse arguments to get object
- PyObj * parseArg (PyObject * args)
+ PyObj *parseArg(PyObject *args)
{
// parse arguments
- PyObject * obj;
- if (PyArg_ParseTuple(args, "O", &obj))
+ PyObject *obj;
+ if (PyArg_ParseTuple(args, "O", &obj)) {
// if successfully parsed, return pointer to object
return checkType(obj);
+ }
// otherwise return NULL
return NULL;
}
@@ -74,7 +75,7 @@ protected:
/// name of Python type
const char * m_name;
/// pointer to Python type
- PyTypeObject * m_objType;
+ PyTypeObject *m_objType;
};
diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp
index 90ea8436ffe..6ec5e237ac2 100644
--- a/source/gameengine/VideoTexture/FilterBase.cpp
+++ b/source/gameengine/VideoTexture/FilterBase.cpp
@@ -90,10 +90,10 @@ PyTypeList pyFilterTypes;
// object allocation
-PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
+PyObject *Filter_allocNew (PyTypeObject *type, PyObject *args, PyObject *kwds)
{
// allocate object
- PyFilter * self = reinterpret_cast<PyFilter*>(type->tp_alloc(type, 0));
+ PyFilter *self = reinterpret_cast<PyFilter*>(type->tp_alloc(type, 0));
// initialize object structure
self->m_filter = NULL;
// return allocated object
@@ -101,7 +101,7 @@ PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwd
}
// object deallocation
-void Filter_dealloc (PyFilter * self)
+void Filter_dealloc (PyFilter *self)
{
// release object attributes
if (self->m_filter != NULL)
@@ -114,7 +114,7 @@ void Filter_dealloc (PyFilter * self)
// get previous pixel filter object
-PyObject * Filter_getPrevious (PyFilter * self, void * closure)
+PyObject *Filter_getPrevious (PyFilter *self, void *closure)
{
// if filter object is available
if (self->m_filter != NULL)
@@ -135,7 +135,7 @@ PyObject * Filter_getPrevious (PyFilter * self, void * closure)
// set previous pixel filter object
-int Filter_setPrevious (PyFilter * self, PyObject * value, void * closure)
+int Filter_setPrevious (PyFilter *self, PyObject *value, void *closure)
{
// if filter object is available
if (self->m_filter != NULL)
diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h
index 63561c25ffa..422cf86f23e 100644
--- a/source/gameengine/VideoTexture/FilterBase.h
+++ b/source/gameengine/VideoTexture/FilterBase.h
@@ -118,9 +118,9 @@ extern PyTypeList pyFilterTypes;
// functions for python interface
// object initialization
-template <class T> static int Filter_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+template <class T> static int Filter_init (PyObject *pySelf, PyObject *args, PyObject *kwds)
{
- PyFilter * self = reinterpret_cast<PyFilter*>(pySelf);
+ PyFilter *self = reinterpret_cast<PyFilter*>(pySelf);
// create filter object
if (self->m_filter != NULL) delete self->m_filter;
self->m_filter = new T();
@@ -129,14 +129,14 @@ template <class T> static int Filter_init (PyObject * pySelf, PyObject * args, P
}
// object allocation
-PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds);
+PyObject *Filter_allocNew(PyTypeObject *type, PyObject *args, PyObject *kwds);
// object deallocation
-void Filter_dealloc (PyFilter * self);
+void Filter_dealloc(PyFilter *self);
// get previous pixel filter object
-PyObject * Filter_getPrevious (PyFilter * self, void * closure);
+PyObject *Filter_getPrevious(PyFilter *self, void *closure);
// set previous pixel filter object
-int Filter_setPrevious (PyFilter * self, PyObject * value, void * closure);
+int Filter_setPrevious(PyFilter *self, PyObject *value, void *closure);
#endif
diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
index 02a6a8f0344..8559e8f87f4 100644
--- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp
+++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
@@ -66,21 +66,21 @@ void FilterBlueScreen::setLimits (unsigned short minLimit, unsigned short maxLim
// cast Filter pointer to FilterBlueScreen
-inline FilterBlueScreen * getFilter (PyFilter * self)
+inline FilterBlueScreen * getFilter (PyFilter *self)
{ return static_cast<FilterBlueScreen*>(self->m_filter); }
// python methods and get/sets
// get color
-static PyObject * getColor (PyFilter * self, void * closure)
+static PyObject *getColor (PyFilter *self, void *closure)
{
return Py_BuildValue("[BBB]", getFilter(self)->getColor()[0],
getFilter(self)->getColor()[1], getFilter(self)->getColor()[2]);
}
// set color
-static int setColor (PyFilter * self, PyObject * value, void * closure)
+static int setColor (PyFilter *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 3
@@ -100,14 +100,14 @@ static int setColor (PyFilter * self, PyObject * value, void * closure)
}
// get limits
-static PyObject * getLimits (PyFilter * self, void * closure)
+static PyObject *getLimits (PyFilter *self, void *closure)
{
return Py_BuildValue("[II]", getFilter(self)->getLimits()[0],
getFilter(self)->getLimits()[1]);
}
// set limit
-static int setLimits (PyFilter * self, PyObject * value, void * closure)
+static int setLimits (PyFilter *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2
diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp
index ed75b4f8da8..35a6414f383 100644
--- a/source/gameengine/VideoTexture/FilterColor.cpp
+++ b/source/gameengine/VideoTexture/FilterColor.cpp
@@ -108,14 +108,14 @@ void FilterColor::setMatrix (ColorMatrix & mat)
// cast Filter pointer to FilterColor
-inline FilterColor * getFilterColor (PyFilter * self)
+inline FilterColor * getFilterColor (PyFilter *self)
{ return static_cast<FilterColor*>(self->m_filter); }
// python methods and get/sets
// get color matrix
-static PyObject * getMatrix (PyFilter * self, void * closure)
+static PyObject *getMatrix (PyFilter *self, void *closure)
{
ColorMatrix & mat = getFilterColor(self)->getMatrix();
return Py_BuildValue("((hhhhh)(hhhhh)(hhhhh)(hhhhh))",
@@ -126,7 +126,7 @@ static PyObject * getMatrix (PyFilter * self, void * closure)
}
// set color matrix
-static int setMatrix (PyFilter * self, PyObject * value, void * closure)
+static int setMatrix (PyFilter *self, PyObject *value, void *closure)
{
// matrix to store items
ColorMatrix mat;
@@ -243,14 +243,14 @@ void FilterLevel::setLevels (ColorLevel & lev)
// cast Filter pointer to FilterLevel
-inline FilterLevel * getFilterLevel (PyFilter * self)
+inline FilterLevel * getFilterLevel (PyFilter *self)
{ return static_cast<FilterLevel*>(self->m_filter); }
// python methods and get/sets
// get color levels
-static PyObject * getLevels (PyFilter * self, void * closure)
+static PyObject *getLevels (PyFilter *self, void *closure)
{
ColorLevel & lev = getFilterLevel(self)->getLevels();
return Py_BuildValue("((HH)(HH)(HH)(HH))",
@@ -259,7 +259,7 @@ static PyObject * getLevels (PyFilter * self, void * closure)
}
// set color levels
-static int setLevels (PyFilter * self, PyObject * value, void * closure)
+static int setLevels (PyFilter *self, PyObject *value, void *closure)
{
// matrix to store items
ColorLevel lev;
diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp
index dda1a493291..03c500a7e14 100644
--- a/source/gameengine/VideoTexture/FilterNormal.cpp
+++ b/source/gameengine/VideoTexture/FilterNormal.cpp
@@ -59,20 +59,20 @@ void FilterNormal::setDepth (float depth)
// cast Filter pointer to FilterNormal
-inline FilterNormal * getFilter (PyFilter * self)
+inline FilterNormal * getFilter (PyFilter *self)
{ return static_cast<FilterNormal*>(self->m_filter); }
// python methods and get/sets
// get index of color used to calculate normal
-static PyObject * getColor (PyFilter * self, void * closure)
+static PyObject *getColor (PyFilter *self, void *closure)
{
return Py_BuildValue("H", getFilter(self)->getColor());
}
// set index of color used to calculate normal
-static int setColor (PyFilter * self, PyObject * value, void * closure)
+static int setColor (PyFilter *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PyLong_Check(value))
@@ -88,13 +88,13 @@ static int setColor (PyFilter * self, PyObject * value, void * closure)
// get depth
-static PyObject * getDepth (PyFilter * self, void * closure)
+static PyObject *getDepth (PyFilter *self, void *closure)
{
return Py_BuildValue("f", getFilter(self)->getDepth());
}
// set depth
-static int setDepth (PyFilter * self, PyObject * value, void * closure)
+static int setDepth (PyFilter *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value)
diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp
index 54c1939ce6b..2de49795681 100644
--- a/source/gameengine/VideoTexture/ImageBase.cpp
+++ b/source/gameengine/VideoTexture/ImageBase.cpp
@@ -128,7 +128,7 @@ PyImage * ImageBase::getSource (const char * id)
// set source object
-bool ImageBase::setSource (const char * id, PyImage * source)
+bool ImageBase::setSource (const char * id, PyImage *source)
{
// find source
ImageSourceList::iterator src = findSource(id);
@@ -315,7 +315,7 @@ bool ImageSource::is (const char * id)
// set source object
-void ImageSource::setSource (PyImage * source)
+void ImageSource::setSource (PyImage *source)
{
// reference new source
if (source != NULL) Py_INCREF(source);
@@ -358,10 +358,10 @@ PyTypeList pyImageTypes;
// functions for python interface
// object allocation
-PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
+PyObject *Image_allocNew (PyTypeObject *type, PyObject *args, PyObject *kwds)
{
// allocate object
- PyImage * self = reinterpret_cast<PyImage*>(type->tp_alloc(type, 0));
+ PyImage *self = reinterpret_cast<PyImage*>(type->tp_alloc(type, 0));
// initialize object structure
self->m_image = NULL;
// return allocated object
@@ -369,7 +369,7 @@ PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds
}
// object deallocation
-void Image_dealloc (PyImage * self)
+void Image_dealloc (PyImage *self)
{
// release object attributes
if (self->m_image != NULL)
@@ -388,7 +388,7 @@ void Image_dealloc (PyImage * self)
}
// get image data
-PyObject * Image_getImage (PyImage * self, char * mode)
+PyObject *Image_getImage (PyImage *self, char * mode)
{
try
{
@@ -463,7 +463,7 @@ PyObject * Image_getImage (PyImage * self, char * mode)
}
}
}
- return (PyObject*)buffer;
+ return (PyObject *)buffer;
}
}
catch (Exception & exp)
@@ -475,28 +475,28 @@ PyObject * Image_getImage (PyImage * self, char * mode)
}
// get image size
-PyObject * Image_getSize (PyImage * self, void * closure)
+PyObject *Image_getSize (PyImage *self, void *closure)
{
return Py_BuildValue("(hh)", self->m_image->getSize()[0],
self->m_image->getSize()[1]);
}
// refresh image
-PyObject * Image_refresh (PyImage * self)
+PyObject *Image_refresh (PyImage *self)
{
self->m_image->refresh();
Py_RETURN_NONE;
}
// get scale
-PyObject * Image_getScale (PyImage * self, void * closure)
+PyObject *Image_getScale (PyImage *self, void *closure)
{
if (self->m_image != NULL && self->m_image->getScale()) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
// set scale
-int Image_setScale (PyImage * self, PyObject * value, void * closure)
+int Image_setScale (PyImage *self, PyObject *value, void *closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
@@ -511,14 +511,14 @@ int Image_setScale (PyImage * self, PyObject * value, void * closure)
}
// get flip
-PyObject * Image_getFlip (PyImage * self, void * closure)
+PyObject *Image_getFlip (PyImage *self, void *closure)
{
if (self->m_image != NULL && self->m_image->getFlip()) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
// set flip
-int Image_setFlip (PyImage * self, PyObject * value, void * closure)
+int Image_setFlip (PyImage *self, PyObject *value, void *closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
@@ -534,7 +534,7 @@ int Image_setFlip (PyImage * self, PyObject * value, void * closure)
// get filter source object
-PyObject * Image_getSource (PyImage * self, PyObject * args)
+PyObject *Image_getSource (PyImage *self, PyObject *args)
{
// get arguments
char * id;
@@ -543,7 +543,7 @@ PyObject * Image_getSource (PyImage * self, PyObject * args)
if (self->m_image != NULL)
{
// get source object
- PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id));
+ PyObject *src = reinterpret_cast<PyObject*>(self->m_image->getSource(id));
// if source is available
if (src != NULL)
{
@@ -558,11 +558,11 @@ PyObject * Image_getSource (PyImage * self, PyObject * args)
// set filter source object
-PyObject * Image_setSource (PyImage * self, PyObject * args)
+PyObject *Image_setSource (PyImage *self, PyObject *args)
{
// get arguments
char * id;
- PyObject * obj;
+ PyObject *obj;
if (!PyArg_ParseTuple(args, "sO:setSource", &id, &obj))
return NULL;
if (self->m_image != NULL)
@@ -593,7 +593,7 @@ PyObject * Image_setSource (PyImage * self, PyObject * args)
// get pixel filter object
-PyObject * Image_getFilter (PyImage * self, void * closure)
+PyObject *Image_getFilter (PyImage *self, void *closure)
{
// if image object is available
if (self->m_image != NULL)
@@ -614,7 +614,7 @@ PyObject * Image_getFilter (PyImage * self, void * closure)
// set pixel filter object
-int Image_setFilter (PyImage * self, PyObject * value, void * closure)
+int Image_setFilter (PyImage *self, PyObject *value, void *closure)
{
// if image object is available
if (self->m_image != NULL)
@@ -632,7 +632,7 @@ int Image_setFilter (PyImage * self, PyObject * value, void * closure)
// return success
return 0;
}
-PyObject * Image_valid(PyImage * self, void * closure)
+PyObject *Image_valid(PyImage *self, void *closure)
{
if (self->m_image->isImageAvailable())
{
@@ -644,7 +644,7 @@ PyObject * Image_valid(PyImage * self, void * closure)
}
}
-int Image_getbuffer(PyImage *self, Py_buffer *view, int flags)
+static int Image_getbuffer(PyImage *self, Py_buffer *view, int flags)
{
unsigned int * image;
int ret;
@@ -674,7 +674,7 @@ int Image_getbuffer(PyImage *self, Py_buffer *view, int flags)
self->m_image->m_exports++;
return 0;
}
- ret = PyBuffer_FillInfo(view, (PyObject*)self, image, self->m_image->getBuffSize(), 0, flags);
+ ret = PyBuffer_FillInfo(view, (PyObject *)self, image, self->m_image->getBuffSize(), 0, flags);
if (ret >= 0)
self->m_image->m_exports++;
return ret;
@@ -684,14 +684,14 @@ error:
// The bug is fixed in Python SVN 77916, as soon as the python revision used by Blender is
// updated, you can simply return -1 and set the error
static char* buf = (char *)"";
- ret = PyBuffer_FillInfo(view, (PyObject*)self, buf, 0, 0, flags);
+ ret = PyBuffer_FillInfo(view, (PyObject *)self, buf, 0, 0, flags);
if (ret >= 0)
self->m_image->m_exports++;
return ret;
}
-void Image_releaseBuffer(PyImage *self, Py_buffer *buffer)
+static void Image_releaseBuffer(PyImage *self, Py_buffer *buffer)
{
self->m_image->m_exports--;
}
diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h
index 6c38b107a4d..bb3f0c19e4b 100644
--- a/source/gameengine/VideoTexture/ImageBase.h
+++ b/source/gameengine/VideoTexture/ImageBase.h
@@ -82,7 +82,7 @@ public:
/// get source object
PyImage * getSource (const char * id);
/// set source object, return true, if source was set
- bool setSource (const char * id, PyImage * source);
+ bool setSource (const char * id, PyImage *source);
/// get pixel filter
PyFilter * getFilter (void) { return m_pyfilter; }
@@ -276,7 +276,7 @@ public:
/// get source object
PyImage * getSource (void) { return m_source; }
/// set source object
- void setSource (PyImage * source);
+ void setSource (PyImage *source);
/// get image from source
unsigned int * getImage (double ts=-1.0);
@@ -312,9 +312,9 @@ extern PyTypeList pyImageTypes;
// functions for python interface
// object initialization
-template <class T> static int Image_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+template <class T> static int Image_init (PyObject *pySelf, PyObject *args, PyObject *kwds)
{
- PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+ PyImage *self = reinterpret_cast<PyImage*>(pySelf);
// create source object
if (self->m_image != NULL) delete self->m_image;
self->m_image = new T();
@@ -323,37 +323,37 @@ template <class T> static int Image_init (PyObject * pySelf, PyObject * args, Py
}
// object allocation
-PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds);
+PyObject *Image_allocNew (PyTypeObject *type, PyObject *args, PyObject *kwds);
// object deallocation
-void Image_dealloc (PyImage * self);
+void Image_dealloc (PyImage *self);
// get image data
-PyObject * Image_getImage (PyImage * self, char * mode);
+PyObject *Image_getImage (PyImage *self, char * mode);
// get image size
-PyObject * Image_getSize (PyImage * self, void * closure);
+PyObject *Image_getSize (PyImage *self, void *closure);
// refresh image - invalidate current content
-PyObject * Image_refresh (PyImage * self);
+PyObject *Image_refresh (PyImage *self);
// get scale
-PyObject * Image_getScale (PyImage * self, void * closure);
+PyObject *Image_getScale (PyImage *self, void *closure);
// set scale
-int Image_setScale (PyImage * self, PyObject * value, void * closure);
+int Image_setScale (PyImage *self, PyObject *value, void *closure);
// get flip
-PyObject * Image_getFlip (PyImage * self, void * closure);
+PyObject *Image_getFlip (PyImage *self, void *closure);
// set flip
-int Image_setFlip (PyImage * self, PyObject * value, void * closure);
+int Image_setFlip (PyImage *self, PyObject *value, void *closure);
// get filter source object
-PyObject * Image_getSource (PyImage * self, PyObject * args);
+PyObject *Image_getSource (PyImage *self, PyObject *args);
// set filter source object
-PyObject * Image_setSource (PyImage * self, PyObject * args);
+PyObject *Image_setSource (PyImage *self, PyObject *args);
// get pixel filter object
-PyObject * Image_getFilter (PyImage * self, void * closure);
+PyObject *Image_getFilter (PyImage *self, void *closure);
// set pixel filter object
-int Image_setFilter (PyImage * self, PyObject * value, void * closure);
+int Image_setFilter (PyImage *self, PyObject *value, void *closure);
// check if a buffer can be extracted
-PyObject * Image_valid(PyImage * self, void * closure);
+PyObject *Image_valid(PyImage *self, void *closure);
// for buffer access to PyImage objects
extern PyBufferProcs imageBufferProcs;
diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp
index 17513d20a39..eec0bccbe56 100644
--- a/source/gameengine/VideoTexture/ImageBuff.cpp
+++ b/source/gameengine/VideoTexture/ImageBuff.cpp
@@ -47,7 +47,7 @@ FilterRGB24 defFilter;
// forward declaration;
extern PyTypeObject ImageBuffType;
-static int ImageBuff_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+static int ImageBuff_init (PyObject *pySelf, PyObject *args, PyObject *kwds)
{
short width = -1;
short height = -1;
@@ -55,7 +55,7 @@ static int ImageBuff_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
PyObject *py_scale = Py_False;
ImageBuff *image;
- PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+ PyImage *self = reinterpret_cast<PyImage*>(pySelf);
// create source object
if (self->m_image != NULL)
delete self->m_image;
@@ -190,7 +190,7 @@ void ImageBuff::plot (ImageBuff* img, short x, short y, short mode)
// cast Image pointer to ImageBuff
-inline ImageBuff * getImageBuff (PyImage * self)
+inline ImageBuff * getImageBuff (PyImage *self)
{ return static_cast<ImageBuff*>(self->m_image); }
@@ -245,7 +245,7 @@ static bool testBGLBuffer(Buffer* buffer, int width, int height, unsigned int pi
// load image
-static PyObject * load (PyImage * self, PyObject * args)
+static PyObject *load(PyImage *self, PyObject *args)
{
// parameters: string image buffer, its size, width, height
Py_buffer buffer;
@@ -306,10 +306,10 @@ static PyObject * load (PyImage * self, PyObject * args)
}
if (PyErr_Occurred())
return NULL;
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
-static PyObject * plot (PyImage * self, PyObject * args)
+static PyObject *plot (PyImage *self, PyObject *args)
{
PyImage * other;
Buffer* bglBuffer;
@@ -332,7 +332,7 @@ static PyObject * plot (PyImage * self, PyObject * args)
PyBuffer_Release(&buffer);
if (PyErr_Occurred())
return NULL;
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
PyErr_Clear();
// try the other format
@@ -354,7 +354,7 @@ static PyObject * plot (PyImage * self, PyObject * args)
}
if (PyErr_Occurred())
return NULL;
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
// methods structure
diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp
index cd8c6683a7f..f09454a517b 100644
--- a/source/gameengine/VideoTexture/ImageMix.cpp
+++ b/source/gameengine/VideoTexture/ImageMix.cpp
@@ -101,14 +101,14 @@ void ImageMix::calcImage (unsigned int texId, double ts)
// cast Image pointer to ImageMix
-inline ImageMix * getImageMix (PyImage * self)
+inline ImageMix * getImageMix (PyImage *self)
{ return static_cast<ImageMix*>(self->m_image); }
// python methods
// get source weight
-PyObject * getWeight (PyImage * self, PyObject * args)
+static PyObject *getWeight (PyImage *self, PyObject *args)
{
// weight
short weight = 0;
@@ -125,7 +125,7 @@ PyObject * getWeight (PyImage * self, PyObject * args)
// set source weight
-PyObject * setWeight (PyImage * self, PyObject * args)
+static PyObject *setWeight (PyImage *self, PyObject *args)
{
// get arguments
char * id;
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index c8763671dd1..2135d0a07eb 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -277,7 +277,7 @@ void ImageRender::Render()
// cast Image pointer to ImageRender
-inline ImageRender * getImageRender (PyImage * self)
+inline ImageRender * getImageRender (PyImage *self)
{ return static_cast<ImageRender*>(self->m_image); }
@@ -290,10 +290,10 @@ BlendType<KX_Camera> cameraType ("KX_Camera");
// object initialization
-static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+static int ImageRender_init (PyObject *pySelf, PyObject *args, PyObject *kwds)
{
// parameters - scene object
- PyObject * scene;
+ PyObject *scene;
// camera object
PyObject * camera;
// parameter keywords
@@ -317,7 +317,7 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds
if (cameraPtr == NULL) THRWEXCP(CameraInvalid, S_OK);
// get pointer to image structure
- PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+ PyImage *self = reinterpret_cast<PyImage*>(pySelf);
// create source object
if (self->m_image != NULL) delete self->m_image;
self->m_image = new ImageRender(scenePtr, cameraPtr);
@@ -333,7 +333,7 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds
// get background color
-PyObject * getBackground (PyImage * self, void * closure)
+static PyObject *getBackground (PyImage *self, void *closure)
{
return Py_BuildValue("[BBBB]",
getImageRender(self)->getBackground(0),
@@ -343,7 +343,7 @@ PyObject * getBackground (PyImage * self, void * closure)
}
// set color
-static int setBackground (PyImage * self, PyObject * value, void * closure)
+static int setBackground (PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 4
@@ -434,14 +434,14 @@ PyTypeObject ImageRenderType =
};
// object initialization
-static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+static int ImageMirror_init (PyObject *pySelf, PyObject *args, PyObject *kwds)
{
// parameters - scene object
- PyObject * scene;
+ PyObject *scene;
// reference object for mirror
- PyObject * observer;
+ PyObject *observer;
// object holding the mirror
- PyObject * mirror;
+ PyObject *mirror;
// material of the mirror
short materialID = 0;
// parameter keywords
@@ -490,7 +490,7 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds
THRWEXCP(MaterialNotAvail, S_OK);
// get pointer to image structure
- PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+ PyImage *self = reinterpret_cast<PyImage*>(pySelf);
// create source object
if (self->m_image != NULL)
@@ -510,13 +510,13 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds
}
// get background color
-PyObject * getClip (PyImage * self, void * closure)
+static PyObject *getClip (PyImage *self, void *closure)
{
return PyFloat_FromDouble(getImageRender(self)->getClip());
}
// set clip
-static int setClip (PyImage * self, PyObject * value, void * closure)
+static int setClip (PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
double clip;
diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp
index a780fdcc38c..9b503efcf39 100644
--- a/source/gameengine/VideoTexture/ImageViewport.cpp
+++ b/source/gameengine/VideoTexture/ImageViewport.cpp
@@ -165,7 +165,7 @@ void ImageViewport::calcImage (unsigned int texId, double ts)
// cast Image pointer to ImageViewport
-inline ImageViewport * getImageViewport (PyImage * self)
+inline ImageViewport * getImageViewport (PyImage *self)
{ return static_cast<ImageViewport*>(self->m_image); }
@@ -173,14 +173,14 @@ inline ImageViewport * getImageViewport (PyImage * self)
// get whole
-PyObject * ImageViewport_getWhole (PyImage * self, void * closure)
+PyObject *ImageViewport_getWhole (PyImage *self, void *closure)
{
if (self->m_image != NULL && getImageViewport(self)->getWhole()) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
// set whole
-int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure)
+int ImageViewport_setWhole (PyImage *self, PyObject *value, void *closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
@@ -203,14 +203,14 @@ int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure)
}
// get alpha
-PyObject * ImageViewport_getAlpha (PyImage * self, void * closure)
+PyObject *ImageViewport_getAlpha (PyImage *self, void *closure)
{
if (self->m_image != NULL && getImageViewport(self)->getAlpha()) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
// set whole
-int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure)
+int ImageViewport_setAlpha (PyImage *self, PyObject *value, void *closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
@@ -226,14 +226,14 @@ int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure)
// get position
-static PyObject * ImageViewport_getPosition (PyImage * self, void * closure)
+static PyObject *ImageViewport_getPosition (PyImage *self, void *closure)
{
return Py_BuildValue("(ii)", getImageViewport(self)->getPosition()[0],
getImageViewport(self)->getPosition()[1]);
}
// set position
-static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * closure)
+static int ImageViewport_setPosition (PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2
@@ -254,14 +254,14 @@ static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * c
}
// get capture size
-PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure)
+PyObject *ImageViewport_getCaptureSize (PyImage *self, void *closure)
{
return Py_BuildValue("(ii)", getImageViewport(self)->getCaptureSize()[0],
getImageViewport(self)->getCaptureSize()[1]);
}
// set capture size
-int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure)
+int ImageViewport_setCaptureSize (PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2
diff --git a/source/gameengine/VideoTexture/ImageViewport.h b/source/gameengine/VideoTexture/ImageViewport.h
index ccc58a41605..198655c6ebf 100644
--- a/source/gameengine/VideoTexture/ImageViewport.h
+++ b/source/gameengine/VideoTexture/ImageViewport.h
@@ -91,12 +91,12 @@ protected:
GLint * getViewportSize (void) { return m_viewport + 2; }
};
-PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure);
-int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure);
-PyObject * ImageViewport_getWhole (PyImage * self, void * closure);
-int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure);
-PyObject * ImageViewport_getAlpha (PyImage * self, void * closure);
-int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure);
+PyObject *ImageViewport_getCaptureSize (PyImage *self, void *closure);
+int ImageViewport_setCaptureSize (PyImage *self, PyObject *value, void *closure);
+PyObject *ImageViewport_getWhole (PyImage *self, void *closure);
+int ImageViewport_setWhole (PyImage *self, PyObject *value, void *closure);
+PyObject *ImageViewport_getAlpha (PyImage *self, void *closure);
+int ImageViewport_setAlpha (PyImage *self, PyObject *value, void *closure);
#endif
diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp
index ed53e8bd1f1..9fe98544961 100644
--- a/source/gameengine/VideoTexture/PyTypeList.cpp
+++ b/source/gameengine/VideoTexture/PyTypeList.cpp
@@ -41,7 +41,7 @@ PyTypeList::~PyTypeList()
}
/// check, if type is in list
-bool PyTypeList::in (PyTypeObject * type)
+bool PyTypeList::in (PyTypeObject *type)
{
// if list exists
if (m_list.get() != NULL)
@@ -54,7 +54,7 @@ bool PyTypeList::in (PyTypeObject * type)
}
/// add type to list
-void PyTypeList::add (PyTypeObject * type, const char * name)
+void PyTypeList::add (PyTypeObject *type, const char * name)
{
// if list doesn't exist, create it
if (m_list.get() == NULL)
@@ -78,7 +78,7 @@ bool PyTypeList::ready (void)
}
/// register types to module
-void PyTypeList::reg (PyObject * module)
+void PyTypeList::reg(PyObject *module)
{
// if list exists
if (m_list.get() != NULL)
@@ -88,6 +88,6 @@ void PyTypeList::reg (PyObject * module)
// increase ref count
Py_INCREF((*it)->getType());
// add type to module
- PyModule_AddObject(module, (char*)(*it)->getName(), (PyObject*)(*it)->getType());
+ PyModule_AddObject(module, (char*)(*it)->getName(), (PyObject *)(*it)->getType());
}
}
diff --git a/source/gameengine/VideoTexture/PyTypeList.h b/source/gameengine/VideoTexture/PyTypeList.h
index aa1df0ce54b..4872b3c3d5c 100644
--- a/source/gameengine/VideoTexture/PyTypeList.h
+++ b/source/gameengine/VideoTexture/PyTypeList.h
@@ -49,16 +49,16 @@ public:
~PyTypeList();
/// check, if type is in list
- bool in (PyTypeObject * type);
+ bool in (PyTypeObject *type);
/// add type to list
- void add (PyTypeObject * type, const char * name);
+ void add (PyTypeObject *type, const char * name);
/// prepare types
bool ready (void);
/// register types to module
- void reg (PyObject * module);
+ void reg(PyObject *module);
protected:
/// pointer to list of types
@@ -71,21 +71,21 @@ class PyTypeListItem
{
public:
/// constructor adds type into list
- PyTypeListItem (PyTypeObject * type, const char * name)
+ PyTypeListItem (PyTypeObject *type, const char * name)
: m_type(type), m_name(name)
{ }
/// does type match
- PyTypeObject * getType (void) { return m_type; }
+ PyTypeObject *getType (void) { return m_type; }
/// get name of type
const char * getName (void) { return m_name; }
protected:
/// pointer to type object
- PyTypeObject * m_type;
+ PyTypeObject *m_type;
/// name of type
- const char * m_name;
+ const char *m_name;
};
diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp
index a21300018eb..f58d17f949c 100644
--- a/source/gameengine/VideoTexture/Texture.cpp
+++ b/source/gameengine/VideoTexture/Texture.cpp
@@ -108,7 +108,7 @@ RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID)
}
// get pointer to a lamp
-KX_LightObject * getLamp(PyObject *obj)
+static KX_LightObject *getLamp(PyObject *obj)
{
// if object is available
if (obj == NULL) return NULL;
@@ -119,7 +119,7 @@ KX_LightObject * getLamp(PyObject *obj)
// get material ID
-short getMaterialID(PyObject * obj, const char *name)
+short getMaterialID(PyObject *obj, const char *name)
{
// search for material
for (short matID = 0;; ++matID)
@@ -147,7 +147,7 @@ short getMaterialID(PyObject * obj, const char *name)
// Texture object allocation
-PyObject * Texture_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
+static PyObject *Texture_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
// allocate object
Texture * self = reinterpret_cast<Texture*>(type->tp_alloc(type, 0));
@@ -167,22 +167,22 @@ PyObject * Texture_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
// forward declaration
-PyObject * Texture_close(Texture * self);
-int Texture_setSource (Texture * self, PyObject * value, void * closure);
+PyObject *Texture_close(Texture * self);
+int Texture_setSource (Texture * self, PyObject *value, void *closure);
// Texture object deallocation
-void Texture_dealloc (Texture * self)
+static void Texture_dealloc(Texture *self)
{
// release renderer
Py_XDECREF(self->m_source);
// close texture
- PyObject* ret = Texture_close(self);
+ PyObject *ret = Texture_close(self);
Py_DECREF(ret);
// release scaled image buffer
delete [] self->m_scaledImg;
// release object
- Py_TYPE((PyObject *)self)->tp_free((PyObject*)self);
+ Py_TYPE((PyObject *)self)->tp_free((PyObject *)self);
}
@@ -190,10 +190,10 @@ ExceptionID MaterialNotAvail;
ExpDesc MaterialNotAvailDesc (MaterialNotAvail, "Texture material is not available");
// Texture object initialization
-int Texture_init (Texture *self, PyObject *args, PyObject *kwds)
+static int Texture_init(Texture *self, PyObject *args, PyObject *kwds)
{
// parameters - game object with video texture
- PyObject * obj = NULL;
+ PyObject *obj = NULL;
// material ID
short matID = 0;
// texture ID
@@ -275,7 +275,7 @@ int Texture_init (Texture *self, PyObject *args, PyObject *kwds)
// close added texture
-PyObject * Texture_close(Texture * self)
+PyObject *Texture_close(Texture * self)
{
// restore texture
if (self->m_orgSaved)
@@ -298,10 +298,10 @@ PyObject * Texture_close(Texture * self)
// refresh texture
-PyObject * Texture_refresh (Texture * self, PyObject * args)
+static PyObject *Texture_refresh(Texture *self, PyObject *args)
{
// get parameter - refresh source
- PyObject * param;
+ PyObject *param;
double ts = -1.0;
if (!PyArg_ParseTuple(args, "O|d:refresh", &param, &ts) || !PyBool_Check(param))
@@ -390,14 +390,14 @@ PyObject * Texture_refresh (Texture * self, PyObject * args)
}
// get OpenGL Bind Id
-PyObject * Texture_getBindId (Texture * self, void * closure)
+static PyObject *Texture_getBindId(Texture *self, void *closure)
{
unsigned int id = self->m_actTex;
return Py_BuildValue("h", id);
}
// get mipmap value
-PyObject * Texture_getMipmap (Texture * self, void * closure)
+static PyObject *Texture_getMipmap(Texture *self, void *closure)
{
// return true if flag is set, otherwise false
if (self->m_mipmap) Py_RETURN_TRUE;
@@ -405,7 +405,7 @@ PyObject * Texture_getMipmap (Texture * self, void * closure)
}
// set mipmap value
-int Texture_setMipmap (Texture * self, PyObject * value, void * closure)
+static int Texture_setMipmap(Texture *self, PyObject *value, void *closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
@@ -421,7 +421,7 @@ int Texture_setMipmap (Texture * self, PyObject * value, void * closure)
// get source object
-PyObject * Texture_getSource (Texture * self, PyObject * value, void * closure)
+static PyObject *Texture_getSource(Texture *self, PyObject *value, void *closure)
{
// if source exists
if (self->m_source != NULL)
@@ -435,7 +435,7 @@ PyObject * Texture_getSource (Texture * self, PyObject * value, void * closure)
// set source object
-int Texture_setSource (Texture * self, PyObject * value, void * closure)
+int Texture_setSource (Texture * self, PyObject *value, void *closure)
{
// check new value
if (value == NULL || !pyImageTypes.in(Py_TYPE(value)))
diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h
index ad5b7b9fb44..cc265725b29 100644
--- a/source/gameengine/VideoTexture/Texture.h
+++ b/source/gameengine/VideoTexture/Texture.h
@@ -78,14 +78,14 @@ struct Texture
extern PyTypeObject TextureType;
// load texture
-void loadTexture (unsigned int texId, unsigned int * texture, short * size,
- bool mipmap = false);
+void loadTexture(unsigned int texId, unsigned int *texture, short *size,
+ bool mipmap = false);
// get material
-RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID);
+RAS_IPolyMaterial *getMaterial(PyObject *obj, short matID);
// get material ID
-short getMaterialID (PyObject * obj, const char *name);
+short getMaterialID(PyObject *obj, const char *name);
// Exceptions
extern ExceptionID MaterialNotAvail;
diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp
index 6662df8d7d1..1eb2e830d37 100644
--- a/source/gameengine/VideoTexture/VideoBase.cpp
+++ b/source/gameengine/VideoTexture/VideoBase.cpp
@@ -116,24 +116,24 @@ void Video_open (VideoBase * self, char * file, short captureID)
// play video
-PyObject * Video_play (PyImage * self)
+PyObject *Video_play(PyImage *self)
{ if (getVideo(self)->play()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
// pause video
-PyObject * Video_pause (PyImage * self)
+PyObject *Video_pause(PyImage *self)
{ if (getVideo(self)->pause()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
-PyObject * Video_stop (PyImage * self)
+PyObject *Video_stop(PyImage *self)
{ if (getVideo(self)->stop()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
// get status
-PyObject * Video_getStatus (PyImage * self, void * closure)
+PyObject *Video_getStatus(PyImage *self, void *closure)
{
return Py_BuildValue("h", getVideo(self)->getStatus());
}
// refresh video
-PyObject * Video_refresh (PyImage * self)
+PyObject *Video_refresh(PyImage *self)
{
getVideo(self)->refresh();
return Video_getStatus(self, NULL);
@@ -141,19 +141,20 @@ PyObject * Video_refresh (PyImage * self)
// get range
-PyObject * Video_getRange (PyImage * self, void * closure)
+PyObject *Video_getRange(PyImage *self, void *closure)
{
return Py_BuildValue("[ff]", getVideo(self)->getRange()[0],
getVideo(self)->getRange()[1]);
}
// set range
-int Video_setRange (PyImage * self, PyObject * value, void * closure)
+int Video_setRange(PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
- if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2
- || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0))
- || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1)))
+ if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 ||
+ /* XXX - this is incorrect if the sequence is not a list/tuple! */
+ !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0)) ||
+ !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 float");
return -1;
@@ -166,11 +167,11 @@ int Video_setRange (PyImage * self, PyObject * value, void * closure)
}
// get repeat
-PyObject * Video_getRepeat (PyImage * self, void * closure)
+PyObject *Video_getRepeat (PyImage *self, void *closure)
{ return Py_BuildValue("h", getVideo(self)->getRepeat()); }
// set repeat
-int Video_setRepeat (PyImage * self, PyObject * value, void * closure)
+int Video_setRepeat(PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PyLong_Check(value))
@@ -185,11 +186,11 @@ int Video_setRepeat (PyImage * self, PyObject * value, void * closure)
}
// get frame rate
-PyObject * Video_getFrameRate (PyImage * self, void * closure)
+PyObject *Video_getFrameRate (PyImage *self, void *closure)
{ return Py_BuildValue("f", double(getVideo(self)->getFrameRate())); }
// set frame rate
-int Video_setFrameRate (PyImage * self, PyObject * value, void * closure)
+int Video_setFrameRate(PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PyFloat_Check(value))
diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h
index e221d876358..4cf913d755d 100644
--- a/source/gameengine/VideoTexture/VideoBase.h
+++ b/source/gameengine/VideoTexture/VideoBase.h
@@ -164,14 +164,14 @@ protected:
// cast Image pointer to Video
-inline VideoBase * getVideo (PyImage * self)
+inline VideoBase *getVideo(PyImage *self)
{ return static_cast<VideoBase*>(self->m_image); }
extern ExceptionID SourceVideoCreation;
// object initialization
-template <class T> void Video_init (PyImage * self)
+template <class T> void Video_init(PyImage *self)
{
// create source video object
if (self->m_image != NULL) delete self->m_image;
@@ -182,18 +182,18 @@ template <class T> void Video_init (PyImage * self)
// video functions
-void Video_open (VideoBase * self, char * file, short captureID);
-PyObject * Video_play (PyImage * self);
-PyObject * Video_pause (PyImage * self);
-PyObject * Video_stop (PyImage * self);
-PyObject * Video_refresh (PyImage * self);
-PyObject * Video_getStatus (PyImage * self, void * closure);
-PyObject * Video_getRange (PyImage * self, void * closure);
-int Video_setRange (PyImage * self, PyObject * value, void * closure);
-PyObject * Video_getRepeat (PyImage * self, void * closure);
-int Video_setRepeat (PyImage * self, PyObject * value, void * closure);
-PyObject * Video_getFrameRate (PyImage * self, void * closure);
-int Video_setFrameRate (PyImage * self, PyObject * value, void * closure);
+void Video_open(VideoBase * self, char * file, short captureID);
+PyObject *Video_play(PyImage *self);
+PyObject *Video_pause(PyImage *self);
+PyObject *Video_stop(PyImage *self);
+PyObject *Video_refresh(PyImage *self);
+PyObject *Video_getStatus(PyImage *self, void *closure);
+PyObject *Video_getRange(PyImage *self, void *closure);
+int Video_setRange(PyImage *self, PyObject *value, void *closure);
+PyObject *Video_getRepeat(PyImage *self, void *closure);
+int Video_setRepeat(PyImage *self, PyObject *value, void *closure);
+PyObject *Video_getFrameRate(PyImage *self, void *closure);
+int Video_setFrameRate(PyImage *self, PyObject *value, void *closure);
#endif
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index 1ba944aa955..cf65362c31d 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -524,7 +524,7 @@ void VideoFFmpeg::openFile (char * filename)
if (m_codecCtx->gop_size)
m_preseek = (m_codecCtx->gop_size < 25) ? m_codecCtx->gop_size+1 : 25;
- else if (m_codecCtx->has_b_frames)
+ else if (m_codecCtx->has_b_frames)
m_preseek = 25; // should determine gopsize
else
m_preseek = 0;
@@ -1076,14 +1076,14 @@ AVFrame *VideoFFmpeg::grabFrame(long position)
// cast Image pointer to VideoFFmpeg
-inline VideoFFmpeg * getVideoFFmpeg (PyImage * self)
+inline VideoFFmpeg * getVideoFFmpeg (PyImage *self)
{ return static_cast<VideoFFmpeg*>(self->m_image); }
// object initialization
-static int VideoFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+static int VideoFFmpeg_init (PyObject *pySelf, PyObject *args, PyObject *kwds)
{
- PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+ PyImage *self = reinterpret_cast<PyImage*>(pySelf);
// parameters - video source
// file name or format type for capture (only for Linux: video4linux or dv1394)
char * file = NULL;
@@ -1123,13 +1123,13 @@ static int VideoFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds
return 0;
}
-PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure)
+static PyObject *VideoFFmpeg_getPreseek(PyImage *self, void *closure)
{
return Py_BuildValue("h", getFFmpeg(self)->getPreseek());
}
// set range
-int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure)
+static int VideoFFmpeg_setPreseek(PyImage *self, PyObject *value, void *closure)
{
// check validity of parameter
if (value == NULL || !PyLong_Check(value))
@@ -1144,7 +1144,7 @@ int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure)
}
// get deinterlace
-PyObject * VideoFFmpeg_getDeinterlace (PyImage * self, void * closure)
+static PyObject *VideoFFmpeg_getDeinterlace(PyImage *self, void *closure)
{
if (getFFmpeg(self)->getDeinterlace())
Py_RETURN_TRUE;
@@ -1153,7 +1153,7 @@ PyObject * VideoFFmpeg_getDeinterlace (PyImage * self, void * closure)
}
// set flip
-int VideoFFmpeg_setDeinterlace (PyImage * self, PyObject * value, void * closure)
+static int VideoFFmpeg_setDeinterlace(PyImage *self, PyObject *value, void *closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
@@ -1239,9 +1239,9 @@ PyTypeObject VideoFFmpegType =
};
// object initialization
-static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+static int ImageFFmpeg_init (PyObject *pySelf, PyObject *args, PyObject *kwds)
{
- PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+ PyImage *self = reinterpret_cast<PyImage*>(pySelf);
// parameters - video source
// file name or format type for capture (only for Linux: video4linux or dv1394)
char * file = NULL;
@@ -1269,7 +1269,7 @@ static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds
return 0;
}
-PyObject * Image_reload (PyImage * self, PyObject *args)
+static PyObject *Image_reload(PyImage *self, PyObject *args)
{
char * newname = NULL;
if (!PyArg_ParseTuple(args, "|s:reload", &newname))
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h
index e63032e0c66..cd0edfc09ef 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.h
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.h
@@ -204,7 +204,7 @@ private:
static void *cacheThread(void *);
};
-inline VideoFFmpeg * getFFmpeg (PyImage * self)
+inline VideoFFmpeg *getFFmpeg(PyImage *self)
{
return static_cast<VideoFFmpeg*>(self->m_image);
}
diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp
index 627da57baac..dd9d83c043f 100644
--- a/source/gameengine/VideoTexture/blendVideoTex.cpp
+++ b/source/gameengine/VideoTexture/blendVideoTex.cpp
@@ -26,6 +26,8 @@ http://www.gnu.org/copyleft/lesser.txt.
#include "PyObjectPlus.h"
+#include "KX_PythonInit.h"
+
#include <RAS_GLExtensionManager.h>
#include <RAS_IPolygonMaterial.h>
@@ -46,10 +48,10 @@ http://www.gnu.org/copyleft/lesser.txt.
// get material id
-static PyObject * getMaterialID (PyObject *self, PyObject *args)
+static PyObject *getMaterialID (PyObject *self, PyObject *args)
{
// parameters - game object with video texture
- PyObject * obj = NULL;
+ PyObject *obj = NULL;
// material name
char * matName;
@@ -70,13 +72,13 @@ static PyObject * getMaterialID (PyObject *self, PyObject *args)
// get last error description
-static PyObject * getLastError (PyObject *self, PyObject *args)
+static PyObject *getLastError (PyObject *self, PyObject *args)
{
return PyUnicode_FromString(Exception::m_lastError.c_str());
}
// set log file
-static PyObject * setLogFile (PyObject *self, PyObject *args)
+static PyObject *setLogFile (PyObject *self, PyObject *args)
{
// get parameters
if (!PyArg_ParseTuple(args, "s:setLogFile", &Exception::m_logFile))
@@ -87,10 +89,10 @@ static PyObject * setLogFile (PyObject *self, PyObject *args)
// image to numpy array
-static PyObject * imageToArray (PyObject * self, PyObject *args)
+static PyObject *imageToArray(PyObject *self, PyObject *args)
{
// parameter is Image object
- PyObject * pyImg;
+ PyObject *pyImg;
char *mode = NULL;
if (!PyArg_ParseTuple(args, "O|s:imageToArray", &pyImg, &mode) || !pyImageTypes.in(Py_TYPE(pyImg)))
{
@@ -168,9 +170,9 @@ static struct PyModuleDef VideoTexture_module_def = {
0, /* m_free */
};
-PyObject* initVideoTexture(void)
+PyObject *initVideoTexture(void)
{
- PyObject * m;
+ PyObject *m;
// initialize GL extensions
//bgl::InitExtensions(0);
@@ -208,7 +210,7 @@ PyObject* initVideoTexture(void)
pyFilterTypes.reg(m);
Py_INCREF(&TextureType);
- PyModule_AddObject(m, (char*)"Texture", (PyObject*)&TextureType);
+ PyModule_AddObject(m, (char*)"Texture", (PyObject *)&TextureType);
PyModule_AddIntConstant(m, (char*)"SOURCE_ERROR", SourceError);
PyModule_AddIntConstant(m, (char*)"SOURCE_EMPTY", SourceEmpty);
PyModule_AddIntConstant(m, (char*)"SOURCE_READY", SourceReady);
diff --git a/source/tests/bl_rna_wiki_reference.py b/source/tests/bl_rna_wiki_reference.py
index 2018c4327a3..a4019214138 100644
--- a/source/tests/bl_rna_wiki_reference.py
+++ b/source/tests/bl_rna_wiki_reference.py
@@ -21,15 +21,30 @@
# Use for validating our wiki interlinking.
# ./blender.bin --background -noaudio --python source/tests/bl_rna_wiki_reference.py
#
-# 1) test_lookup_coverage() -- ensure that we have lookups for _every_ RNA path
-# 2) test_urls() -- ensure all the URL's are correct
-# 3) test_language_coverage() -- ensure language lookup table is complete
+# 1) test_data() -- ensure the data we have is correct format
+# 2) test_lookup_coverage() -- ensure that we have lookups for _every_ RNA path
+# 3) test_urls() -- ensure all the URL's are correct
+# 4) test_language_coverage() -- ensure language lookup table is complete
#
import bpy
-# a stripped down version of api_dump() in rna_info_dump.py
+def test_data():
+ import rna_wiki_reference
+
+ assert(isinstance(rna_wiki_reference.url_manual_mapping, tuple))
+ for i, value in enumerate(rna_wiki_reference.url_manual_mapping):
+ try:
+ assert(len(value) == 2)
+ assert(isinstance(value[0], str))
+ assert(isinstance(value[1], str))
+ except:
+ print("Expected a tuple of 2 strings, instead item %d is a %s: %r" % (i, type(value), value))
+ import traceback
+ traceback.print_exc()
+ raise
+# a stripped down version of api_dump() in rna_info_dump.py
def test_lookup_coverage():
@@ -39,20 +54,37 @@ def test_lookup_coverage():
struct = rna_info.BuildRNAInfo()[0]
for struct_id, v in sorted(struct.items()):
props = [(prop.identifier, prop) for prop in v.properties]
+ struct_path = "bpy.types.%s" % struct_id[1]
for prop_id, prop in props:
- yield "bpy.types.%s.%s" % (struct_id[1], prop_id)
+ yield (struct_path, "%s.%s" % (struct_path, prop_id))
for submod_id in dir(bpy.ops):
+ op_path = "bpy.ops.%s" % submod_id
for op_id in dir(getattr(bpy.ops, submod_id)):
- yield "bpy.ops.%s.%s" % (submod_id, op_id)
+ yield (op_path, "%s.%s" % (op_path, op_id))
# check coverage
from bl_operators import wm
- for rna_id in rna_ids():
+ set_group_all = set()
+ set_group_doc = set()
+
+ for rna_group, rna_id in rna_ids():
url = wm.WM_OT_doc_view_manual._lookup_rna_url(rna_id, verbose=False)
print(rna_id, "->", url)
+ set_group_all.add(rna_group)
+ if url is not None:
+ set_group_doc.add(rna_group)
+
+ # finally report undocumented groups
+ print("")
+ print("---------------------")
+ print("Undocumented Sections")
+
+ for rna_group in sorted(set_group_all):
+ if rna_group not in set_group_doc:
+ print("%s.*" % rna_group)
def test_urls():
pass # TODO
@@ -63,6 +95,7 @@ def test_language_coverage():
def main():
+ test_data()
test_lookup_coverage()
test_language_coverage()
diff --git a/source/tests/bl_run_operators.py b/source/tests/bl_run_operators.py
index 53cc37bc02b..146b60b8f28 100644
--- a/source/tests/bl_run_operators.py
+++ b/source/tests/bl_run_operators.py
@@ -44,7 +44,7 @@ op_blacklist = (
"help.operator_cheat_sheet",
"wm.keyconfig_test", # just annoying - but harmless
"wm.memory_statistics", # another annoying one
- # "mesh.vertex_color_remove", #crashes! fixme
+ "console.*", # just annoying - but harmless
)
@@ -61,7 +61,7 @@ def filter_op_list(operators):
operators[:] = [op for op in operators if is_op_ok(op[0])]
-def run_ops(operators, setup_func=None):
+def run_ops(operators, setup_func=None, reset=True):
print("\ncontext:", setup_func.__name__)
# first invoke
for op_id, op in operators:
@@ -70,7 +70,8 @@ def run_ops(operators, setup_func=None):
sys.stdout.flush() # in case of crash
# disable will get blender in a bad state and crash easy!
- bpy.ops.wm.read_factory_settings()
+ if reset:
+ bpy.ops.wm.read_factory_settings()
setup_func()
@@ -82,6 +83,11 @@ def run_ops(operators, setup_func=None):
#traceback.print_exc()
pass
+ if not operators:
+ # run test
+ if reset:
+ bpy.ops.wm.read_factory_settings()
+ setup_func()
# contexts
def ctx_clear_scene(): # copied from batch_import.py
@@ -99,7 +105,23 @@ def ctx_clear_scene(): # copied from batch_import.py
def ctx_editmode_mesh():
bpy.ops.object.mode_set(mode='EDIT')
+
+
+def ctx_editmode_mesh_extra():
bpy.ops.object.vertex_group_add()
+ bpy.ops.object.shape_key_add(from_mix=False)
+ bpy.ops.object.shape_key_add(from_mix=True)
+ bpy.ops.mesh.uv_texture_add()
+ bpy.ops.mesh.vertex_color_add()
+ bpy.ops.object.material_slot_add()
+ # editmode last!
+ bpy.ops.object.mode_set(mode='EDIT')
+
+
+def ctx_editmode_mesh_empty():
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.delete()
def ctx_editmode_curves():
@@ -107,6 +129,12 @@ def ctx_editmode_curves():
bpy.ops.object.mode_set(mode='EDIT')
+def ctx_editmode_curves_empty():
+ bpy.ops.curve.primitive_nurbs_circle_add()
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.curve.delete(type='ALL')
+
+
def ctx_editmode_surface():
bpy.ops.surface.primitive_nurbs_surface_torus_add()
bpy.ops.object.mode_set(mode='EDIT')
@@ -127,6 +155,13 @@ def ctx_editmode_armature():
bpy.ops.object.mode_set(mode='EDIT')
+def ctx_editmode_armature_empty():
+ bpy.ops.object.armature_add()
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.armature.select_all(action='SELECT')
+ bpy.ops.armature.delete()
+
+
def ctx_editmode_lattice():
bpy.ops.object.add(type='LATTICE')
bpy.ops.object.mode_set(mode='EDIT')
@@ -137,10 +172,28 @@ def ctx_object_empty():
bpy.ops.object.add(type='EMPTY')
-def ctx_weightpaint():
+def ctx_object_pose():
+ bpy.ops.object.armature_add()
+ bpy.ops.object.mode_set(mode='POSE')
+ bpy.ops.pose.select_all(action='SELECT')
+
+
+def ctx_object_paint_weight():
bpy.ops.object.mode_set(mode='WEIGHT_PAINT')
+def ctx_object_paint_vertex():
+ bpy.ops.object.mode_set(mode='VERTEX_PAINT')
+
+
+def ctx_object_paint_sculpt():
+ bpy.ops.object.mode_set(mode='SCULPT')
+
+
+def ctx_object_paint_texture():
+ bpy.ops.object.mode_set(mode='TEXTURE_PAINT')
+
+
def bpy_check_type_duplicates():
# non essential sanity check
bl_types = dir(bpy.types)
@@ -178,21 +231,39 @@ def main():
#import random
#random.shuffle(operators)
-
- # Run the operator tests in different contexts
- run_ops(operators, setup_func=lambda: None)
- run_ops(operators, setup_func=ctx_editmode_surface)
- run_ops(operators, setup_func=ctx_object_empty)
- run_ops(operators, setup_func=ctx_editmode_armature)
- run_ops(operators, setup_func=ctx_editmode_mesh)
- run_ops(operators, setup_func=ctx_clear_scene)
- run_ops(operators, setup_func=ctx_editmode_curves)
- run_ops(operators, setup_func=ctx_editmode_mball)
- run_ops(operators, setup_func=ctx_editmode_text)
- run_ops(operators, setup_func=ctx_weightpaint)
- run_ops(operators, setup_func=ctx_editmode_lattice)
-
- print("finished")
+
+ # 2 passes, first just run setup_func to make sure they are ok
+ for operators_test in ((), operators):
+ # Run the operator tests in different contexts
+ run_ops(operators_test, setup_func=lambda: None)
+ run_ops(operators_test, setup_func=ctx_clear_scene)
+ # object modes
+ run_ops(operators_test, setup_func=ctx_object_empty)
+ run_ops(operators_test, setup_func=ctx_object_pose)
+ run_ops(operators_test, setup_func=ctx_object_paint_weight)
+ run_ops(operators_test, setup_func=ctx_object_paint_vertex)
+ run_ops(operators_test, setup_func=ctx_object_paint_sculpt)
+ run_ops(operators_test, setup_func=ctx_object_paint_texture)
+ # mesh
+ run_ops(operators_test, setup_func=ctx_editmode_mesh)
+ run_ops(operators_test, setup_func=ctx_editmode_mesh_extra)
+ run_ops(operators_test, setup_func=ctx_editmode_mesh_empty)
+ # armature
+ run_ops(operators_test, setup_func=ctx_editmode_armature)
+ run_ops(operators_test, setup_func=ctx_editmode_armature_empty)
+ # curves
+ run_ops(operators_test, setup_func=ctx_editmode_curves)
+ run_ops(operators_test, setup_func=ctx_editmode_curves_empty)
+ run_ops(operators_test, setup_func=ctx_editmode_surface)
+ # other
+ run_ops(operators_test, setup_func=ctx_editmode_mball)
+ run_ops(operators_test, setup_func=ctx_editmode_text)
+ run_ops(operators_test, setup_func=ctx_editmode_lattice)
+
+ if not operators_test:
+ print("All setup functions run fine!")
+
+ print("Finished %r" % __file__)
if __name__ == "__main__":
main()