diff options
author | Julian Eisel <eiseljulian@gmail.com> | 2017-02-12 23:43:13 +0300 |
---|---|---|
committer | Julian Eisel <eiseljulian@gmail.com> | 2017-02-12 23:43:13 +0300 |
commit | 10b24eabbab0193f6944cdf3bec7b386c75d5445 (patch) | |
tree | 28cefb0f056191e09828cb79d2f7f728df4e2ead | |
parent | f754ce1c5e050d1637fe97d78f782d6a68da6c15 (diff) | |
parent | b104057d001d2472cc55c7fa51cff3275e331523 (diff) |
Merge branch 'blender2.8' into transform-manipulators
Conflicts:
source/blender/editors/interface/resources.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/transform/transform_manipulator.c
source/blender/gpu/CMakeLists.txt
source/blender/gpu/intern/gpu_shader.c
422 files changed, 19672 insertions, 7571 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index de01be1d299..a107dd78fbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,6 +242,8 @@ endif() option(WITH_PLAYER "Build Player" OFF) option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO}) +option(WITH_CLAY_ENGINE "Enable New Clay engine (Breaks Mac and Intel compatibility)" ON) + # Compositor option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON) @@ -722,7 +724,7 @@ if(NOT WITH_BOOST) macro(set_and_warn _setting _val) if(${${_setting}}) - message(STATUS "'WITH_BOOST' is disabled: forceing 'set(${_setting} ${_val})'") + message(STATUS "'WITH_BOOST' is disabled: forcing 'set(${_setting} ${_val})'") endif() set(${_setting} ${_val}) endmacro() diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index a8519f54d0a..c167d392100 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -787,7 +787,7 @@ CXXFLAGS_BACK=$CXXFLAGS if [ "$USE_CXX11" = true ]; then WARNING "C++11 is now mandatory for blender2.8, this *should* go smoothly with any very recent distribution. However, if you are experiencing linking errors (also when building Blender itself), please try the following: - * Re-run this script with `--build-all --force-all` options. + * Re-run this script with '--build-all --force-all' options. * Ensure your gcc version is at the very least 4.8, if possible you should really rather use gcc-5.1 or above. Please note that until the transition to C++11-built libraries if completed in your distribution, situation will diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 76d538ad578..860dd1174cf 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -72,10 +72,8 @@ if 'cmake' in builder: # Set up OSX architecture if builder.endswith('x86_64_10_6_cmake'): cmake_extra_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=x86_64') - cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda8-hack/bin/nvcc') cmake_extra_options.append('-DWITH_CODEC_QUICKTIME=OFF') cmake_extra_options.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=10.6') - build_cubins = False elif builder.startswith('win'): diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 09428953a46..fa9c2a28cb5 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -566,6 +566,7 @@ function(SETUP_BLENDER_SORTED_LIBS) bf_editor_space_userpref bf_editor_space_view3d bf_editor_space_clip + bf_editor_space_collections bf_editor_transform bf_editor_util @@ -597,6 +598,7 @@ function(SETUP_BLENDER_SORTED_LIBS) bf_modifiers bf_bmesh bf_gpu + bf_draw bf_blenloader bf_blenkernel bf_physics diff --git a/build_files/cmake/platform/platform_win32_msvc.cmake b/build_files/cmake/platform/platform_win32_msvc.cmake index 1a266df7791..45a44596e61 100644 --- a/build_files/cmake/platform/platform_win32_msvc.cmake +++ b/build_files/cmake/platform/platform_win32_msvc.cmake @@ -453,6 +453,12 @@ if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV) debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib ) + set(OPENSUBDIV_HAS_OPENMP TRUE) + set(OPENSUBDIV_HAS_TBB FALSE) + set(OPENSUBDIV_HAS_OPENCL TRUE) + set(OPENSUBDIV_HAS_CUDA FALSE) + set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE) + set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE) windows_find_package(OpenSubdiv) endif() diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index 9a5476772ab..dd9889c81ba 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -62,7 +62,7 @@ if(WITH_IK_ITASC) add_subdirectory(itasc) endif() -if(WITH_IK_SOLVER OR WITH_GAMEENGINE OR WITH_MOD_BOOLEAN) +if(WITH_GAMEENGINE) add_subdirectory(moto) endif() diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 2c5365c9189..c8c9ef58c52 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -62,7 +62,7 @@ def _parse_command_line(): num_resumable_chunks = None current_resumable_chunk = None - # TODO(sergey): Add some nice error ptins if argument is not used properly. + # TODO(sergey): Add some nice error prints if argument is not used properly. idx = 0 while idx < len(argv) - 1: arg = argv[idx] diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 802b9b76c5d..5c51f9afc28 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -638,6 +638,20 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): items=enum_texture_limit ) + cls.ao_bounces = IntProperty( + name="AO Bounces", + default=0, + description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature", + min=0, max=1024, + ) + + cls.ao_bounces_render = IntProperty( + name="AO Bounces Render", + default=0, + description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature", + min=0, max=1024, + ) + # Various fine-tuning debug flags def devices_update_callback(self, context): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index a1e78623d29..eb89f0b1efa 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1038,10 +1038,11 @@ class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel): layout = self.layout light = context.world.light_settings + scene = context.scene row = layout.row() sub = row.row() - sub.active = light.use_ambient_occlusion + sub.active = light.use_ambient_occlusion or scene.render.use_simplify sub.prop(light, "ao_factor", text="Factor") row.prop(light, "distance", text="Distance") @@ -1613,6 +1614,13 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel): row.active = cscene.use_distance_cull row.prop(cscene, "distance_cull_margin", text="Distance") + split = layout.split() + col = split.column() + col.prop(cscene, "ao_bounces") + + col = split.column() + col.prop(cscene, "ao_bounces_render") + def draw_device(self, context): scene = context.scene layout = self.layout diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 04b5c3fa013..2f30cbd961f 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -1352,6 +1352,9 @@ void BlenderSession::update_resumable_tile_manager(int num_samples) VLOG(1) << "Samples range start is " << range_start_sample << ", " << "number of samples to render is " << range_num_samples; + scene->integrator->start_sample = range_start_sample; + scene->integrator->tag_update(scene); + session->tile_manager.range_start_sample = range_start_sample; session->tile_manager.range_num_samples = range_num_samples; } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index f8f2303ec76..d8043105cd8 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -322,6 +322,15 @@ void BlenderSync::sync_integrator() integrator->volume_samples = volume_samples; } + if(b_scene.render().use_simplify()) { + if(preview) { + integrator->ao_bounces = get_int(cscene, "ao_bounces"); + } + else { + integrator->ao_bounces = get_int(cscene, "ao_bounces_render"); + } + } + if(integrator->modified(previntegrator)) integrator->tag_update(scene); } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 8ce9a4f02ec..f90701a8260 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -109,6 +109,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, /* intersect scene */ Intersection isect; uint visibility = path_state_ray_visibility(kg, state); + if(state->bounce > kernel_data.integrator.ao_bounces) { + visibility = PATH_RAY_SHADOW; + ray->t = kernel_data.background.ao_distance; + } bool hit = scene_intersect(kg, *ray, visibility, @@ -292,6 +296,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, break; } + else if(state->bounce > kernel_data.integrator.ao_bounces) { + break; + } /* setup shading */ shader_setup_from_ray(kg, @@ -627,6 +634,11 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg, lcg_state = lcg_state_init(rng, &state, 0x51633e2d); } + if(state.bounce > kernel_data.integrator.ao_bounces) { + visibility = PATH_RAY_SHADOW; + ray.t = kernel_data.background.ao_distance; + } + bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax); #else bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f); @@ -769,6 +781,9 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg, break; } + else if(state.bounce > kernel_data.integrator.ao_bounces) { + break; + } /* setup shading */ shader_setup_from_ray(kg, &sd, &isect, &ray); diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h index 13597eab287..7b903556bf9 100644 --- a/intern/cycles/kernel/kernel_path_common.h +++ b/intern/cycles/kernel/kernel_path_common.h @@ -30,7 +30,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg, int num_samples = kernel_data.integrator.aa_samples; - if(sample == 0) { + if(sample == kernel_data.integrator.start_sample) { *rng_state = hash_int_2d(x, y); } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index b7af90cd739..8c271c75e44 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1143,6 +1143,8 @@ typedef struct KernelIntegrator { int max_transmission_bounce; int max_volume_bounce; + int ao_bounces; + /* transparent */ int transparent_min_bounce; int transparent_max_bounce; @@ -1186,7 +1188,8 @@ typedef struct KernelIntegrator { float light_inv_rr_threshold; - int pad1; + int start_sample; + int pad1, pad2, pad3; } KernelIntegrator; static_assert_align(KernelIntegrator, 16); diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index 01547b60014..a7f15de7325 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -134,32 +134,37 @@ ccl_device float3 svm_math_blackbody_color(float t) { { 6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f }, }; - if(t >= 12000.0f) + int i; + if(t >= 12000.0f) { return make_float3(0.826270103f, 0.994478524f, 1.56626022f); + } + else if(t >= 6365.0f) { + i = 5; + } + else if(t >= 3315.0f) { + i = 4; + } + else if(t >= 1902.0f) { + i = 3; + } + else if(t >= 1449.0f) { + i = 2; + } + else if(t >= 1167.0f) { + i = 1; + } + else if(t >= 965.0f) { + i = 0; + } + else { + /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */ + return make_float3(4.70366907f, 0.0f, 0.0f); + } - /* Define a macro to reduce stack usage for nvcc */ -#define MAKE_BB_RGB(i) make_float3(\ - rc[i][0] / t + rc[i][1] * t + rc[i][2],\ - gc[i][0] / t + gc[i][1] * t + gc[i][2],\ - ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3]) - - if(t >= 6365.0f) - return MAKE_BB_RGB(5); - if(t >= 3315.0f) - return MAKE_BB_RGB(4); - if(t >= 1902.0f) - return MAKE_BB_RGB(3); - if(t >= 1449.0f) - return MAKE_BB_RGB(2); - if(t >= 1167.0f) - return MAKE_BB_RGB(1); - if(t >= 965.0f) - return MAKE_BB_RGB(0); - -#undef MAKE_BB_RGB - - /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */ - return make_float3(4.70366907f, 0.0f, 0.0f); + const float t_inv = 1.0f / t; + return make_float3(rc[i][0] * t_inv + rc[i][1] * t + rc[i][2], + gc[i][0] * t_inv + gc[i][1] * t + gc[i][2], + ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3]); } ccl_device_inline float3 svm_math_gamma_color(float3 color, float gamma) diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index a9a33d2e789..1ab0f9874f2 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -43,6 +43,8 @@ NODE_DEFINE(Integrator) SOCKET_INT(transparent_max_bounce, "Transparent Max Bounce", 7); SOCKET_BOOLEAN(transparent_shadows, "Transparent Shadows", false); + SOCKET_INT(ao_bounces, "AO Bounces", 0); + SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024); SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f); @@ -62,6 +64,7 @@ NODE_DEFINE(Integrator) SOCKET_INT(mesh_light_samples, "Mesh Light Samples", 1); SOCKET_INT(subsurface_samples, "Subsurface Samples", 1); SOCKET_INT(volume_samples, "Volume Samples", 1); + SOCKET_INT(start_sample, "Start Sample", 0); SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true); SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true); @@ -111,6 +114,13 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene kintegrator->transparent_max_bounce = transparent_max_bounce + 1; kintegrator->transparent_min_bounce = transparent_min_bounce + 1; + if(ao_bounces == 0) { + kintegrator->ao_bounces = INT_MAX; + } + else { + kintegrator->ao_bounces = ao_bounces - 1; + } + /* Transparent Shadows * We only need to enable transparent shadows, if we actually have * transparent shaders in the scene. Otherwise we can disable it @@ -152,6 +162,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene kintegrator->mesh_light_samples = mesh_light_samples; kintegrator->subsurface_samples = subsurface_samples; kintegrator->volume_samples = volume_samples; + kintegrator->start_sample = start_sample; if(method == BRANCHED_PATH) { kintegrator->sample_all_lights_direct = sample_all_lights_direct; diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index 17fdd0ef1db..27fff4831e5 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -43,6 +43,8 @@ public: int transparent_max_bounce; bool transparent_shadows; + int ao_bounces; + int volume_max_steps; float volume_step_size; @@ -64,6 +66,7 @@ public: int mesh_light_samples; int subsurface_samples; int volume_samples; + int start_sample; bool sample_all_lights_direct; bool sample_all_lights_indirect; diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp index 32b4c7265ee..3fc086cbc0c 100644 --- a/intern/cycles/test/render_graph_finalize_test.cpp +++ b/intern/cycles/test/render_graph_finalize_test.cpp @@ -92,7 +92,7 @@ public: template<typename T> ShaderGraphBuilder& add_node(const T& node) { - EXPECT_EQ(NULL, find_node(node.name())); + EXPECT_EQ(find_node(node.name()), (void*)NULL); graph_->add(node.node()); node_map_[node.name()] = node.node(); return *this; @@ -104,8 +104,8 @@ public: vector<string> tokens_from, tokens_to; string_split(tokens_from, from, "::"); string_split(tokens_to, to, "::"); - EXPECT_EQ(2, tokens_from.size()); - EXPECT_EQ(2, tokens_to.size()); + EXPECT_EQ(tokens_from.size(), 2); + EXPECT_EQ(tokens_to.size(), 2); ShaderNode *node_from = find_node(tokens_from[0]), *node_to = find_node(tokens_to[0]); EXPECT_NE((void*)NULL, node_from); diff --git a/intern/cycles/test/util_aligned_malloc_test.cpp b/intern/cycles/test/util_aligned_malloc_test.cpp index 479070f0513..9fb3aad0c3f 100644 --- a/intern/cycles/test/util_aligned_malloc_test.cpp +++ b/intern/cycles/test/util_aligned_malloc_test.cpp @@ -18,7 +18,7 @@ #include "util/util_aligned_malloc.h" -#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ(0, (size_t)ptr % align) +#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ((size_t)ptr % align, 0) CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/test/util_path_test.cpp b/intern/cycles/test/util_path_test.cpp index 92be1dd4cbe..c2f400c105d 100644 --- a/intern/cycles/test/util_path_test.cpp +++ b/intern/cycles/test/util_path_test.cpp @@ -26,63 +26,63 @@ CCL_NAMESPACE_BEGIN TEST(util_path_filename, simple_unix) { string str = path_filename("/tmp/foo.txt"); - EXPECT_EQ("foo.txt", str); + EXPECT_EQ(str, "foo.txt"); } TEST(util_path_filename, root_unix) { string str = path_filename("/"); - EXPECT_EQ("/", str); + EXPECT_EQ(str, "/"); } TEST(util_path_filename, last_slash_unix) { string str = path_filename("/tmp/foo.txt/"); - EXPECT_EQ(".", str); + EXPECT_EQ(str, "."); } TEST(util_path_filename, alternate_slash_unix) { string str = path_filename("/tmp\\foo.txt"); - EXPECT_EQ("tmp\\foo.txt", str); + EXPECT_EQ(str, "tmp\\foo.txt"); } #endif /* !_WIN32 */ TEST(util_path_filename, file_only) { string str = path_filename("foo.txt"); - EXPECT_EQ("foo.txt", str); + EXPECT_EQ(str, "foo.txt"); } TEST(util_path_filename, empty) { string str = path_filename(""); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } #ifdef _WIN32 TEST(util_path_filename, simple_windows) { string str = path_filename("C:\\tmp\\foo.txt"); - EXPECT_EQ("foo.txt", str); + EXPECT_EQ(str, "foo.txt"); } TEST(util_path_filename, root_windows) { string str = path_filename("C:\\"); - EXPECT_EQ("\\", str); + EXPECT_EQ(str, "\\"); } TEST(util_path_filename, last_slash_windows) { string str = path_filename("C:\\tmp\\foo.txt\\"); - EXPECT_EQ(".", str); + EXPECT_EQ(str, "."); } TEST(util_path_filename, alternate_slash_windows) { string str = path_filename("C:\\tmp/foo.txt"); - EXPECT_EQ("foo.txt", str); + EXPECT_EQ(str, "foo.txt"); } #endif /* _WIN32 */ @@ -92,63 +92,63 @@ TEST(util_path_filename, alternate_slash_windows) TEST(util_path_dirname, simple_unix) { string str = path_dirname("/tmp/foo.txt"); - EXPECT_EQ("/tmp", str); + EXPECT_EQ(str, "/tmp"); } TEST(util_path_dirname, root_unix) { string str = path_dirname("/"); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_path_dirname, last_slash_unix) { string str = path_dirname("/tmp/foo.txt/"); - EXPECT_EQ("/tmp/foo.txt", str); + EXPECT_EQ(str, "/tmp/foo.txt"); } TEST(util_path_dirname, alternate_slash_unix) { string str = path_dirname("/tmp\\foo.txt"); - EXPECT_EQ("/", str); + EXPECT_EQ(str, "/"); } #endif /* !_WIN32 */ TEST(util_path_dirname, file_only) { string str = path_dirname("foo.txt"); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_path_dirname, empty) { string str = path_dirname(""); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } #ifdef _WIN32 TEST(util_path_dirname, simple_windows) { string str = path_dirname("C:\\tmp\\foo.txt"); - EXPECT_EQ("C:\\tmp", str); + EXPECT_EQ(str, "C:\\tmp"); } TEST(util_path_dirname, root_windows) { string str = path_dirname("C:\\"); - EXPECT_EQ("C:", str); + EXPECT_EQ(str, "C:"); } TEST(util_path_dirname, last_slash_windows) { string str = path_dirname("C:\\tmp\\foo.txt\\"); - EXPECT_EQ("C:\\tmp\\foo.txt", str); + EXPECT_EQ(str, "C:\\tmp\\foo.txt"); } TEST(util_path_dirname, alternate_slash_windows) { string str = path_dirname("C:\\tmp/foo.txt"); - EXPECT_EQ("C:\\tmp", str); + EXPECT_EQ(str, "C:\\tmp"); } #endif /* _WIN32 */ @@ -157,152 +157,152 @@ TEST(util_path_dirname, alternate_slash_windows) TEST(util_path_join, empty_both) { string str = path_join("", ""); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_path_join, empty_directory) { string str = path_join("", "foo.txt"); - EXPECT_EQ("foo.txt", str); + EXPECT_EQ(str, "foo.txt"); } TEST(util_path_join, empty_filename) { string str = path_join("foo", ""); - EXPECT_EQ("foo", str); + EXPECT_EQ(str, "foo"); } #ifndef _WIN32 TEST(util_path_join, simple_unix) { string str = path_join("foo", "bar"); - EXPECT_EQ("foo/bar", str); + EXPECT_EQ(str, "foo/bar"); } TEST(util_path_join, directory_slash_unix) { string str = path_join("foo/", "bar"); - EXPECT_EQ("foo/bar", str); + EXPECT_EQ(str, "foo/bar"); } TEST(util_path_join, filename_slash_unix) { string str = path_join("foo", "/bar"); - EXPECT_EQ("foo/bar", str); + EXPECT_EQ(str, "foo/bar"); } TEST(util_path_join, both_slash_unix) { string str = path_join("foo/", "/bar"); - EXPECT_EQ("foo//bar", str); + EXPECT_EQ(str, "foo//bar"); } TEST(util_path_join, directory_alternate_slash_unix) { string str = path_join("foo\\", "bar"); - EXPECT_EQ("foo\\/bar", str); + EXPECT_EQ(str, "foo\\/bar"); } TEST(util_path_join, filename_alternate_slash_unix) { string str = path_join("foo", "\\bar"); - EXPECT_EQ("foo/\\bar", str); + EXPECT_EQ(str, "foo/\\bar"); } TEST(util_path_join, both_alternate_slash_unix) { string str = path_join("foo", "\\bar"); - EXPECT_EQ("foo/\\bar", str); + EXPECT_EQ(str, "foo/\\bar"); } TEST(util_path_join, empty_dir_filename_slash_unix) { string str = path_join("", "/foo.txt"); - EXPECT_EQ("/foo.txt", str); + EXPECT_EQ(str, "/foo.txt"); } TEST(util_path_join, empty_dir_filename_alternate_slash_unix) { string str = path_join("", "\\foo.txt"); - EXPECT_EQ("\\foo.txt", str); + EXPECT_EQ(str, "\\foo.txt"); } TEST(util_path_join, empty_filename_dir_slash_unix) { string str = path_join("foo/", ""); - EXPECT_EQ("foo/", str); + EXPECT_EQ(str, "foo/"); } TEST(util_path_join, empty_filename_dir_alternate_slash_unix) { string str = path_join("foo\\", ""); - EXPECT_EQ("foo\\", str); + EXPECT_EQ(str, "foo\\"); } #else /* !_WIN32 */ TEST(util_path_join, simple_windows) { string str = path_join("foo", "bar"); - EXPECT_EQ("foo\\bar", str); + EXPECT_EQ(str, "foo\\bar"); } TEST(util_path_join, directory_slash_windows) { string str = path_join("foo\\", "bar"); - EXPECT_EQ("foo\\bar", str); + EXPECT_EQ(str, "foo\\bar"); } TEST(util_path_join, filename_slash_windows) { string str = path_join("foo", "\\bar"); - EXPECT_EQ("foo\\bar", str); + EXPECT_EQ(str, "foo\\bar"); } TEST(util_path_join, both_slash_windows) { string str = path_join("foo\\", "\\bar"); - EXPECT_EQ("foo\\\\bar", str); + EXPECT_EQ(str, "foo\\\\bar"); } TEST(util_path_join, directory_alternate_slash_windows) { string str = path_join("foo/", "bar"); - EXPECT_EQ("foo/bar", str); + EXPECT_EQ(str, "foo/bar"); } TEST(util_path_join, filename_alternate_slash_windows) { string str = path_join("foo", "/bar"); - EXPECT_EQ("foo/bar", str); + EXPECT_EQ(str, "foo/bar"); } TEST(util_path_join, both_alternate_slash_windows) { string str = path_join("foo/", "/bar"); - EXPECT_EQ("foo//bar", str); + EXPECT_EQ(str, "foo//bar"); } TEST(util_path_join, empty_dir_filename_slash_windows) { string str = path_join("", "\\foo.txt"); - EXPECT_EQ("\\foo.txt", str); + EXPECT_EQ(str, "\\foo.txt"); } TEST(util_path_join, empty_dir_filename_alternate_slash_windows) { string str = path_join("", "/foo.txt"); - EXPECT_EQ("/foo.txt", str); + EXPECT_EQ(str, "/foo.txt"); } TEST(util_path_join, empty_filename_dir_slash_windows) { string str = path_join("foo\\", ""); - EXPECT_EQ("foo\\", str); + EXPECT_EQ(str, "foo\\"); } TEST(util_path_join, empty_filename_dir_alternate_slash_windows) { string str = path_join("foo/", ""); - EXPECT_EQ("foo/", str); + EXPECT_EQ(str, "foo/"); } #endif /* !_WIN32 */ @@ -311,31 +311,31 @@ TEST(util_path_join, empty_filename_dir_alternate_slash_windows) TEST(util_path_escape, no_escape_chars) { string str = path_escape("/tmp/foo/bar"); - EXPECT_EQ("/tmp/foo/bar", str); + EXPECT_EQ(str, "/tmp/foo/bar"); } TEST(util_path_escape, simple) { string str = path_escape("/tmp/foo bar"); - EXPECT_EQ("/tmp/foo\\ bar", str); + EXPECT_EQ(str, "/tmp/foo\\ bar"); } TEST(util_path_escape, simple_end) { string str = path_escape("/tmp/foo/bar "); - EXPECT_EQ("/tmp/foo/bar\\ ", str); + EXPECT_EQ(str, "/tmp/foo/bar\\ "); } TEST(util_path_escape, multiple) { string str = path_escape("/tmp/foo bar"); - EXPECT_EQ("/tmp/foo\\ \\ bar", str); + EXPECT_EQ(str, "/tmp/foo\\ \\ bar"); } TEST(util_path_escape, simple_multiple_end) { string str = path_escape("/tmp/foo/bar "); - EXPECT_EQ("/tmp/foo/bar\\ \\ ", str); + EXPECT_EQ(str, "/tmp/foo/bar\\ \\ "); } /* ******** Tests for path_is_relative() ******** */ diff --git a/intern/cycles/test/util_string_test.cpp b/intern/cycles/test/util_string_test.cpp index e502a35704b..22ec8e0ee8e 100644 --- a/intern/cycles/test/util_string_test.cpp +++ b/intern/cycles/test/util_string_test.cpp @@ -25,25 +25,25 @@ CCL_NAMESPACE_BEGIN TEST(util_string_printf, no_format) { string str = string_printf("foo bar"); - EXPECT_EQ(str, "foo bar"); + EXPECT_EQ("foo bar", str); } TEST(util_string_printf, int_number) { string str = string_printf("foo %d bar", 314); - EXPECT_EQ(str, "foo 314 bar"); + EXPECT_EQ("foo 314 bar", str); } TEST(util_string_printf, float_number_default_precision) { string str = string_printf("foo %f bar", 3.1415); - EXPECT_EQ(str, "foo 3.141500 bar"); + EXPECT_EQ("foo 3.141500 bar", str); } TEST(util_string_printf, float_number_custom_precision) { string str = string_printf("foo %.1f bar", 3.1415); - EXPECT_EQ(str, "foo 3.1 bar"); + EXPECT_EQ("foo 3.1 bar", str); } /* ******** Tests for string_printf() ******** */ @@ -78,44 +78,44 @@ TEST(util_string_split, empty) { vector<string> tokens; string_split(tokens, ""); - EXPECT_EQ(0, tokens.size()); + EXPECT_EQ(tokens.size(), 0); } TEST(util_string_split, only_spaces) { vector<string> tokens; string_split(tokens, " \t\t \t"); - EXPECT_EQ(0, tokens.size()); + EXPECT_EQ(tokens.size(), 0); } TEST(util_string_split, single) { vector<string> tokens; string_split(tokens, "foo"); - EXPECT_EQ(1, tokens.size()); - EXPECT_EQ("foo", tokens[0]); + EXPECT_EQ(tokens.size(), 1); + EXPECT_EQ(tokens[0], "foo"); } TEST(util_string_split, simple) { vector<string> tokens; string_split(tokens, "foo a bar b"); - EXPECT_EQ(4, tokens.size()); - EXPECT_EQ("foo", tokens[0]); - EXPECT_EQ("a", tokens[1]); - EXPECT_EQ("bar", tokens[2]); - EXPECT_EQ("b", tokens[3]); + EXPECT_EQ(tokens.size(), 4); + EXPECT_EQ(tokens[0], "foo"); + EXPECT_EQ(tokens[1], "a"); + EXPECT_EQ(tokens[2], "bar"); + EXPECT_EQ(tokens[3], "b"); } TEST(util_string_split, multiple_spaces) { vector<string> tokens; string_split(tokens, " \t foo \ta bar b\t "); - EXPECT_EQ(4, tokens.size()); - EXPECT_EQ("foo", tokens[0]); - EXPECT_EQ("a", tokens[1]); - EXPECT_EQ("bar", tokens[2]); - EXPECT_EQ("b", tokens[3]); + EXPECT_EQ(tokens.size(), 4); + EXPECT_EQ(tokens[0], "foo"); + EXPECT_EQ(tokens[1], "a"); + EXPECT_EQ(tokens[2], "bar"); + EXPECT_EQ(tokens[3], "b"); } /* ******** Tests for string_replace() ******** */ @@ -124,35 +124,35 @@ TEST(util_string_replace, empty_haystack_and_other) { string str = ""; string_replace(str, "x", ""); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_string_replace, empty_haystack) { string str = ""; string_replace(str, "x", "y"); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_string_replace, empty_other) { string str = "x"; string_replace(str, "x", ""); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_string_replace, long_haystack_empty_other) { string str = "a x b xxc"; string_replace(str, "x", ""); - EXPECT_EQ("a b c", str); + EXPECT_EQ(str, "a b c"); } TEST(util_string_replace, long_haystack) { string str = "a x b xxc"; string_replace(str, "x", "FOO"); - EXPECT_EQ("a FOO b FOOFOOc", str); + EXPECT_EQ(str, "a FOO b FOOFOOc"); } /* ******** Tests for string_endswith() ******** */ @@ -192,25 +192,25 @@ TEST(util_string_endswith, simple_false) TEST(util_string_strip, empty) { string str = string_strip(""); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_string_strip, only_spaces) { string str = string_strip(" "); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_string_strip, no_spaces) { string str = string_strip("foo bar"); - EXPECT_EQ("foo bar", str); + EXPECT_EQ(str, "foo bar"); } TEST(util_string_strip, with_spaces) { string str = string_strip(" foo bar "); - EXPECT_EQ("foo bar", str); + EXPECT_EQ(str, "foo bar"); } /* ******** Tests for string_remove_trademark() ******** */ @@ -218,31 +218,31 @@ TEST(util_string_strip, with_spaces) TEST(util_string_remove_trademark, empty) { string str = string_remove_trademark(""); - EXPECT_EQ("", str); + EXPECT_EQ(str, ""); } TEST(util_string_remove_trademark, no_trademark) { string str = string_remove_trademark("foo bar"); - EXPECT_EQ("foo bar", str); + EXPECT_EQ(str, "foo bar"); } TEST(util_string_remove_trademark, only_tm) { string str = string_remove_trademark("foo bar(TM) zzz"); - EXPECT_EQ("foo bar zzz", str); + EXPECT_EQ(str, "foo bar zzz"); } TEST(util_string_remove_trademark, only_r) { string str = string_remove_trademark("foo bar(R) zzz"); - EXPECT_EQ("foo bar zzz", str); + EXPECT_EQ(str, "foo bar zzz"); } TEST(util_string_remove_trademark, both) { string str = string_remove_trademark("foo bar(TM)(R) zzz"); - EXPECT_EQ("foo bar zzz", str); + EXPECT_EQ(str, "foo bar zzz"); } CCL_NAMESPACE_END diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 992200a0b09..8cee785cdf6 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1316,10 +1316,12 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type if (type == GHOST_kDrawingContextTypeOpenGL) { // During development: + // try 4.x compatibility profile // try 3.3 compatibility profile // fall back to 3.0 if needed // // Final Blender 2.8: + // try 4.x core profile // try 3.3 core profile // no fallbacks @@ -1332,24 +1334,9 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type # error // must specify either core or compat at build time #endif - GHOST_Context *context = new GHOST_ContextGLX( - m_wantStereoVisual, - m_wantNumOfAASamples, - m_window, - m_display, - m_visualInfo, - (GLXFBConfig)m_fbconfig, - profile_mask, - 3, 3, - GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), - GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); + GHOST_Context *context; - if (context->initializeDrawingContext()) - return context; - else { - delete context; - - // since that failed try 3.0 (mostly for Mesa, which doesn't implement compatibility profile) + for (int minor = 5; minor >= 0; --minor) { context = new GHOST_ContextGLX( m_wantStereoVisual, m_wantNumOfAASamples, @@ -1357,8 +1344,8 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type m_display, m_visualInfo, (GLXFBConfig)m_fbconfig, - 0, // no profile bit - 3, 0, + profile_mask, + 4, minor, GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); @@ -1367,6 +1354,41 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type else delete context; } + + context = new GHOST_ContextGLX( + m_wantStereoVisual, + m_wantNumOfAASamples, + m_window, + m_display, + m_visualInfo, + (GLXFBConfig)m_fbconfig, + profile_mask, + 3, 3, + GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), + GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); + + if (context->initializeDrawingContext()) + return context; + else + delete context; + + // since that failed try 3.0 (mostly for Mesa, which doesn't implement compatibility profile) + context = new GHOST_ContextGLX( + m_wantStereoVisual, + m_wantNumOfAASamples, + m_window, + m_display, + m_visualInfo, + (GLXFBConfig)m_fbconfig, + 0, // no profile bit + 3, 0, + GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), + GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); + + if (context->initializeDrawingContext()) + return context; + else + delete context; } return NULL; diff --git a/intern/utfconv/utfconv.h b/intern/utfconv/utfconv.h index f00f4aeef27..d05ed61c8d8 100644 --- a/intern/utfconv/utfconv.h +++ b/intern/utfconv/utfconv.h @@ -93,7 +93,7 @@ wchar_t *alloc_utf16_from_8(const char *in8, size_t add); /* Easy allocation and conversion of new utf-16 string. New string has _16 suffix. Must be deallocated with UTF16_UN_ENCODE in right order*/ #define UTF16_ENCODE(in8str) if (1) { \ - wchar_t *in8str ## _16 = alloc_utf16_from_8((char *)in8str, 0) + wchar_t *in8str ## _16 = alloc_utf16_from_8((const char *)in8str, 0) #define UTF16_UN_ENCODE(in8str) \ free(in8str ## _16); } (void)0 diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index b54cadd40bc..e9c114ba1bd 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -14,7 +14,7 @@ height="640" id="svg2" sodipodi:version="0.32" - inkscape:version="0.91 r13725" + inkscape:version="0.91 r" version="1.0" sodipodi:docname="blender_icons.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" @@ -28201,7 +28201,7 @@ xlink:href="#linearGradient37542-29" id="linearGradient17610" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(-1,0,0,1,461.01011,-167)" + gradientTransform="matrix(-1,0,0,1,865.01833,131.0342)" x1="392.0101" y1="224.99998" x2="392.0101" @@ -28263,7 +28263,7 @@ xlink:href="#linearGradient37542-29-7" id="linearGradient17610-0" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(-1,0,0,1,461.01011,-167)" + gradientTransform="translate(128.00098,130.98191)" x1="392.0101" y1="224.99998" x2="392.0101" @@ -28402,7 +28402,7 @@ x2="228.5468" y1="118.91647" x1="228.5468" - gradientTransform="matrix(1.180548,0,0,0.90042534,265.27784,265.13062)" + gradientTransform="matrix(1.180548,0,0,0.90042534,265.83288,265.61628)" gradientUnits="userSpaceOnUse" id="linearGradient17838" xlink:href="#linearGradient319-36-40-2" @@ -28433,7 +28433,7 @@ x2="228.5468" y1="118.91647" x1="228.5468" - gradientTransform="matrix(1.180548,0,0,0.90042534,223.26222,270.47438)" + gradientTransform="matrix(1.180548,0,0,0.90042534,223.81726,270.99473)" gradientUnits="userSpaceOnUse" id="linearGradient17872" xlink:href="#linearGradient319-36-40-2-4" @@ -29073,7 +29073,7 @@ xlink:href="#linearGradient27854-0-6-9" id="linearGradient17162" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0,1,-1,0,782.48614,-14.46331)" + gradientTransform="matrix(0,1,-1,0,783.04118,-13.977664)" x1="388.86502" y1="244.02" x2="391.43173" @@ -29083,7 +29083,7 @@ xlink:href="#linearGradient37542-29-7-8" id="linearGradient17165" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0,1,-1,0,782.48614,-14.46331)" + gradientTransform="matrix(0,1,-1,0,783.04118,-13.977664)" x1="368.97806" y1="249.99998" x2="393.85385" @@ -29113,7 +29113,7 @@ xlink:href="#linearGradient37542-29-1" id="linearGradient17185" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0,-1,-1,0,740.48614,764.46331)" + gradientTransform="matrix(0,-1,-1,0,741.04118,764.98366)" x1="409.93588" y1="249.99998" x2="385.11514" @@ -31349,17 +31349,17 @@ objecttolerance="10000" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1.274018" - inkscape:cx="519.70993" - inkscape:cy="325.90484" + inkscape:zoom="14.413868" + inkscape:cx="480.24726" + inkscape:cy="269.95478" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" - inkscape:window-width="1920" - inkscape:window-height="1005" - inkscape:window-x="-2" - inkscape:window-y="27" - inkscape:snap-nodes="false" + inkscape:window-width="1680" + inkscape:window-height="1020" + inkscape:window-x="0" + inkscape:window-y="30" + inkscape:snap-nodes="true" inkscape:snap-bbox="true" showguides="true" inkscape:guide-bbox="true" @@ -31369,14 +31369,16 @@ inkscape:snap-intersection-grid-guide="false" inkscape:window-maximized="1" inkscape:bbox-paths="false" - inkscape:snap-global="false" + inkscape:snap-global="true" inkscape:snap-bbox-midpoints="false" - inkscape:snap-grids="true" + inkscape:snap-grids="false" inkscape:snap-to-guides="false" inkscape:snap-page="false" units="pt" inkscape:snap-center="false" - inkscape:snap-object-midpoints="true"> + inkscape:snap-object-midpoints="true" + inkscape:snap-midpoints="false" + inkscape:snap-others="false"> <inkscape:grid type="xygrid" id="grid17394" @@ -88001,37 +88003,37 @@ <g style="display:inline;enable-background:new" id="ICON_COLLAPSEMENU" - transform="translate(279.8665,506.92392)"> + transform="translate(280,508)"> <rect y="111" x="103" height="16" width="16" id="rect24489-7-4" - style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;enable-background:accumulate" /> <rect style="fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79452544;stroke-opacity:1" id="rect29842" - width="11.816368" - height="2.1883197" - x="105.18671" - y="-116.88043" + width="11.209318" + height="2.1883163" + x="105.39484" + y="-116.60292" transform="scale(1,-1)" /> <rect - style="fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79452544;stroke-opacity:1;display:inline;enable-background:new" + style="display:inline;fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79452544;stroke-opacity:1;enable-background:new" id="rect29842-4" - width="11.816368" - height="2.1883197" - x="105.31538" - y="-120.80865" + width="11.191971" + height="2.2056611" + x="105.41944" + y="-120.61786" transform="scale(1,-1)" /> <rect - style="fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79452544;stroke-opacity:1;display:inline;enable-background:new" + style="display:inline;fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79500002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;enable-background:new" id="rect29842-4-5" - width="11.816368" - height="2.1883197" - x="105.41832" - y="-124.71391" + width="11.22666" + height="2.2056642" + x="105.38363" + y="-124.60985" transform="scale(1,-1)" /> </g> <g @@ -89360,17 +89362,18 @@ y="69" /> <g id="g17605" - transform="translate(-1.5467961,-0.48613592)"> + transform="translate(-0.99177519,0.03419629)"> <path - sodipodi:nodetypes="ccccccccccc" + style="fill:url(#linearGradient17610);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 472.51758,370.53516 -1.04688,0.0312 0.0371,9.96875 1.00977,0 3.95117,-3.70704 -5.3e-4,3.72852 3.1119,0 0,-10.01758 -3.1119,0 5.3e-4,3.73242 z" + transform="translate(-404.00822,-298.0342)" + id="path11011-6" inkscape:connector-curvature="0" - d="m 72.839729,82.521675 2.731705,0 0,-10.016275 -2.731705,0 L 72.84,76.59374 68.51011,72.5 67.4632,72.53125 67.5,82.49999 68.51011,82.5 72.84,78.43749 z" - style="fill:url(#linearGradient17610);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path11011-6" /> + sodipodi:nodetypes="ccccccccccc" /> <path sodipodi:nodetypes="ccc" style="fill:none;stroke:url(#linearGradient17612);stroke-width:0.91056824px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 73.7503,81.408784 0,-7.99274 0.910568,-6.3e-5" + d="m 73.368723,81.408784 0,-7.99274 1.292145,-6.3e-5" id="path10830-6" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" @@ -89397,17 +89400,18 @@ y="69" /> <g id="g17605-3" - transform="translate(-1.5467961,-0.48613592)"> + transform="translate(-1.9392553,-0.11820549)"> <path - sodipodi:nodetypes="ccccccccccc" + style="fill:url(#linearGradient17610-0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 520.5,370.48242 -4.01758,3.80078 -6.6e-4,-3.79492 -3.04231,0 0,10.01563 3.04231,0 6.6e-4,-3.79297 4.01758,3.77148 1.01172,0 0.0371,-9.96875 z" + transform="matrix(-1,0,0,1,589.01109,-297.98191)" + id="path11011-6-2" inkscape:connector-curvature="0" - d="m 72.839729,82.521675 2.731705,0 0,-10.016275 -2.731705,0 L 72.84,76.59374 68.51011,72.5 67.4632,72.53125 67.5,82.49999 68.51011,82.5 72.84,78.43749 z" - style="fill:url(#linearGradient17610-0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path11011-6-2" /> + sodipodi:nodetypes="ccccccccccc" /> <path sodipodi:nodetypes="ccc" style="fill:none;stroke:url(#linearGradient17612-5);stroke-width:0.91056824px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" - d="m 74.660868,81.408784 0,-7.99274 -0.910568,-6.3e-5" + d="m 74.660868,81.408784 0,-7.99274 -1.220453,-6.3e-5" id="path10830-6-2" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" inkscape:export-xdpi="90" @@ -89432,16 +89436,16 @@ y="-546" transform="matrix(0,-1,-1,0,0,0)" /> <path + style="fill:url(#linearGradient17165);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 533.51953,371.46094 0,3.04042 3.79492,5.9e-4 -3.77343,4.01953 0,1.01172 9.96875,0.0352 0.0312,-1.04688 -3.80274,-4.01953 3.79688,-5.9e-4 0,-3.04042 z" id="path11011-6-2-1" - style="fill:url(#linearGradient17165);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 532.96447,373.70707 0,-2.7317 10.01627,0 0,2.7317 -4.08834,-2.7e-4 4.09374,4.32989 -0.0312,1.04691 -9.96874,-0.0368 -1e-5,-1.01011 4.06251,-4.32989 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" /> <path inkscape:connector-curvature="0" sodipodi:nodetypes="ccc" id="path11013-5-7-1" - d="m 541.73615,378.0468 -3.75,-4 -3.75,4" + d="m 542.29119,378.53246 -3.75,-4 -3.75,4" style="fill:none;stroke:url(#linearGradient17162);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> <path inkscape:connector-curvature="0" @@ -89449,8 +89453,8 @@ inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" id="path10830-6-2-8" - d="m 542.11634,371.83103 -8.26386,0 -6e-5,0.90043" - style="fill:none;stroke:url(#linearGradient17838);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new" + d="m 542.67138,372.31669 -8.26386,0 -6e-5,1.20843" + style="display:inline;fill:none;stroke:url(#linearGradient17838);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;enable-background:new" sodipodi:nodetypes="ccc" /> </g> <g @@ -89464,16 +89468,16 @@ y="-504" transform="matrix(0,1,-1,0,0,0)" /> <path + style="fill:url(#linearGradient17185);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 501.50977,371.4375 -9.96875,0.0352 0,1.01172 3.69336,3.93554 -3.71485,-0.005 0,3.13033 10.01563,0 0,-3.13033 -3.7168,0.007 3.72266,-3.9375 z" id="path11011-6-8" - style="fill:url(#linearGradient17185);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - d="m 490.96446,376.29293 0,2.7317 10.01628,0 0,-2.7317 -4.08834,2.7e-4 4.09374,-4.32989 -0.0312,-1.04691 -9.96874,0.0368 -10e-6,1.01011 4.06251,4.32989 z" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" /> <path inkscape:connector-curvature="0" sodipodi:nodetypes="cc" id="path11013-5-6" - d="m 492.23615,371.9532 7.5,0" + d="m 492.79119,372.47355 7.5,0" style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> <path inkscape:connector-curvature="0" @@ -89481,8 +89485,8 @@ inkscape:export-xdpi="90" inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png" id="path10830-6-2-8-8" - d="m 500.10071,377.17478 -8.26386,0 -6e-5,0.90043" - style="fill:none;stroke:url(#linearGradient17872);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new" + d="m 500.65575,377.29722 -8.26386,0 -6e-5,1.29834" + style="display:inline;fill:none;stroke:url(#linearGradient17872);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;enable-background:new" sodipodi:nodetypes="ccc" /> </g> <g diff --git a/release/datafiles/blender_icons16/icon16_collapsemenu.dat b/release/datafiles/blender_icons16/icon16_collapsemenu.dat Binary files differindex fd16fadcc8b..246afa11c6c 100644 --- a/release/datafiles/blender_icons16/icon16_collapsemenu.dat +++ b/release/datafiles/blender_icons16/icon16_collapsemenu.dat diff --git a/release/datafiles/blender_icons16/icon16_tria_down_bar.dat b/release/datafiles/blender_icons16/icon16_tria_down_bar.dat Binary files differindex 3b734da490a..191f2075b1a 100644 --- a/release/datafiles/blender_icons16/icon16_tria_down_bar.dat +++ b/release/datafiles/blender_icons16/icon16_tria_down_bar.dat diff --git a/release/datafiles/blender_icons16/icon16_tria_left_bar.dat b/release/datafiles/blender_icons16/icon16_tria_left_bar.dat Binary files differindex 15826007e7b..e1ea5764367 100644 --- a/release/datafiles/blender_icons16/icon16_tria_left_bar.dat +++ b/release/datafiles/blender_icons16/icon16_tria_left_bar.dat diff --git a/release/datafiles/blender_icons16/icon16_tria_right_bar.dat b/release/datafiles/blender_icons16/icon16_tria_right_bar.dat Binary files differindex 75b180afbd7..ce9c3f78ad7 100644 --- a/release/datafiles/blender_icons16/icon16_tria_right_bar.dat +++ b/release/datafiles/blender_icons16/icon16_tria_right_bar.dat diff --git a/release/datafiles/blender_icons16/icon16_tria_up_bar.dat b/release/datafiles/blender_icons16/icon16_tria_up_bar.dat Binary files differindex b0730cafdd4..e51757d2650 100644 --- a/release/datafiles/blender_icons16/icon16_tria_up_bar.dat +++ b/release/datafiles/blender_icons16/icon16_tria_up_bar.dat diff --git a/release/datafiles/blender_icons32/icon32_collapsemenu.dat b/release/datafiles/blender_icons32/icon32_collapsemenu.dat Binary files differindex d84dd843436..788b4009542 100644 --- a/release/datafiles/blender_icons32/icon32_collapsemenu.dat +++ b/release/datafiles/blender_icons32/icon32_collapsemenu.dat diff --git a/release/datafiles/blender_icons32/icon32_tria_down_bar.dat b/release/datafiles/blender_icons32/icon32_tria_down_bar.dat Binary files differindex 7a00e79b711..ef6e86ba154 100644 --- a/release/datafiles/blender_icons32/icon32_tria_down_bar.dat +++ b/release/datafiles/blender_icons32/icon32_tria_down_bar.dat diff --git a/release/datafiles/blender_icons32/icon32_tria_left_bar.dat b/release/datafiles/blender_icons32/icon32_tria_left_bar.dat Binary files differindex 591b2e2b1bd..a1d48baf971 100644 --- a/release/datafiles/blender_icons32/icon32_tria_left_bar.dat +++ b/release/datafiles/blender_icons32/icon32_tria_left_bar.dat diff --git a/release/datafiles/blender_icons32/icon32_tria_right_bar.dat b/release/datafiles/blender_icons32/icon32_tria_right_bar.dat Binary files differindex 1dae635d600..4f687537658 100644 --- a/release/datafiles/blender_icons32/icon32_tria_right_bar.dat +++ b/release/datafiles/blender_icons32/icon32_tria_right_bar.dat diff --git a/release/datafiles/blender_icons32/icon32_tria_up_bar.dat b/release/datafiles/blender_icons32/icon32_tria_up_bar.dat Binary files differindex 1c7b3072f31..e6c5d5561cd 100644 --- a/release/datafiles/blender_icons32/icon32_tria_up_bar.dat +++ b/release/datafiles/blender_icons32/icon32_tria_up_bar.dat diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject 88158191df4da2109bbfd9b0816d891bbc7fc78 +Subproject c93ed11a47b3016cf59711ec16de2e2e94c30e9 diff --git a/release/scripts/addons b/release/scripts/addons -Subproject a746a84f8aaf3a4843eb3f4ce3f5a0464872077 +Subproject 371960484a38fc64e0a2635170a41a0d8ab2f6b diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject 029103debce43110f93295d7633931ec100d301 +Subproject a8515cfdfe9a98127b592f36fcbe51b7e23b969 diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index c48f03c133d..d740137b0c3 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -103,9 +103,9 @@ def add_object_align_init(context, operator): return location * rotation -def object_data_add(context, obdata, operator=None, use_active_layer=True, name=None): +def object_data_add(context, obdata, operator=None, name=None): """ - Add an object using the view context and preference to to initialize the + Add an object using the view context and preference to initialize the location, rotation and layer. :arg context: The context to use. @@ -117,52 +117,24 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name= :arg name: Optional name :type name: string :return: the newly created object in the scene. - :rtype: :class:`bpy.types.ObjectBase` + :rtype: :class:`bpy.types.Object` """ scene = context.scene + layer = context.render_layer + scene_collection = context.scene_collection - # ugh, could be made nicer - for ob in scene.objects: - ob.select = False + bpy.ops.object.select_all(action='DESELECT') if name is None: name = "Object" if obdata is None else obdata.name obj_new = bpy.data.objects.new(name, obdata) - - base = scene.objects.link(obj_new) - base.select = True - - v3d = None - if context.space_data and context.space_data.type == 'VIEW_3D': - v3d = context.space_data - - if v3d and v3d.local_view: - base.layers_from_view(context.space_data) - - if operator is not None and any(operator.layers): - base.layers = operator.layers - else: - if use_active_layer: - if v3d and v3d.local_view: - base.layers[scene.active_layer] = True - else: - if v3d and not v3d.lock_camera_and_layers: - base.layers = [True if i == v3d.active_layer - else False for i in range(len(v3d.layers))] - else: - base.layers = [True if i == scene.active_layer - else False for i in range(len(scene.layers))] - else: - if v3d: - base.layers_from_view(context.space_data) - - if operator is not None: - operator.layers = base.layers + scene_collection.objects.link(obj_new) + obj_new.select_set(action='SELECT') obj_new.matrix_world = add_object_align_init(context, operator) - obj_act = scene.objects.active + obj_act = layer.objects.active # XXX # caused because entering edit-mode does not add a empty undo slot! @@ -174,8 +146,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name= _obdata = bpy.data.meshes.new(name) obj_act = bpy.data.objects.new(_obdata.name, _obdata) obj_act.matrix_world = obj_new.matrix_world - scene.objects.link(obj_act) - scene.objects.active = obj_act + scene_collection.objects.link(obj_act) + layer.objects.active = obj_act bpy.ops.object.mode_set(mode='EDIT') # need empty undo step bpy.ops.ed.undo_push(message="Enter Editmode") @@ -185,7 +157,7 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name= bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.mode_set(mode='OBJECT') - obj_act.select = True + obj_act.select_set(action='SELECT') scene.update() # apply location # scene.objects.active = obj_new @@ -200,16 +172,14 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name= bpy.ops.object.join() # join into the active. if obdata: bpy.data.meshes.remove(obdata) - # base is freed, set to active object - base = scene.object_bases.active bpy.ops.object.mode_set(mode='EDIT') else: - scene.objects.active = obj_new + layer.objects.active = obj_new if context.user_preferences.edit.use_enter_edit_mode: bpy.ops.object.mode_set(mode='EDIT') - return base + return obj_new class AddObjectHelper: @@ -230,12 +200,6 @@ class AddObjectHelper: name="Rotation", subtype='EULER', ) - layers = BoolVectorProperty( - name="Layers", - size=20, - subtype='LAYER', - options={'HIDDEN', 'SKIP_SAVE'}, - ) @classmethod def poll(self, context): diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py index 7694e338d68..b6b0a0c926f 100644 --- a/release/scripts/presets/keyconfig/3dsmax.py +++ b/release/scripts/presets/keyconfig/3dsmax.py @@ -330,7 +330,6 @@ kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', shift=True) kmi.properties.unselected = True kmi = km.keymap_items.new('object.hide_render_clear', 'H', 'PRESS', ctrl=True, alt=True) kmi = km.keymap_items.new('object.hide_render_set', 'H', 'PRESS', ctrl=True) -kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS') kmi = km.keymap_items.new('object.delete', 'X', 'PRESS') kmi.properties.use_global = False kmi = km.keymap_items.new('object.delete', 'X', 'PRESS', shift=True) diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index 67fd1fddcac..f542ecf810b 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -384,7 +384,6 @@ kmi = km.keymap_items.new('object.hide_view_clear', 'H', 'PRESS', shift=True, ct kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', ctrl=True) kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', alt=True) kmi.properties.unselected = True -kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS') kmi = km.keymap_items.new('object.delete', 'BACK_SPACE', 'PRESS') kmi = km.keymap_items.new('object.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True) diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index 0c77ea2ab7e..d60703236d6 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -232,7 +232,7 @@ class CLIP_OT_track_to_empty(Operator): ob = None ob = bpy.data.objects.new(name=track.name, object_data=None) - ob.select = True + ob.select_set(action='SELECT') context.scene.objects.link(ob) context.scene.objects.active = ob @@ -506,7 +506,7 @@ object's movement caused by this constraint""" # XXX, should probably use context.selected_editable_objects # since selected objects can be from a lib or in hidden layer! for ob in scene.objects: - if ob.select: + if ob.select_set(action='SELECT'): self._bake_object(scene, ob) return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/freestyle.py b/release/scripts/startup/bl_operators/freestyle.py index edda92284d2..43cd3110beb 100644 --- a/release/scripts/startup/bl_operators/freestyle.py +++ b/release/scripts/startup/bl_operators/freestyle.py @@ -62,31 +62,69 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator): m = linestyle.alpha_modifiers[self.name] else: m = linestyle.thickness_modifiers[self.name] - # Find the source object + # Find the reference object if m.type == 'DISTANCE_FROM_CAMERA': - source = scene.camera + ref = scene.camera + matrix_to_camera = ref.matrix_world.inverted() elif m.type == 'DISTANCE_FROM_OBJECT': if m.target is None: self.report({'ERROR'}, "Target object not specified") return {'CANCELLED'} - source = m.target + ref = m.target + target_location = ref.location else: self.report({'ERROR'}, "Unexpected modifier type: " + m.type) return {'CANCELLED'} - # Find selected mesh objects - selection = [ob for ob in scene.objects if ob.select and ob.type == 'MESH' and ob.name != source.name] - if selection: - # Compute the min/max distance between selected mesh objects and the source + # Find selected vertices in editmesh + ob = bpy.context.active_object + if ob.type == 'MESH' and ob.mode == 'EDIT' and ob.name != ref.name: + bpy.ops.object.mode_set(mode='OBJECT') + selected_verts = [v for v in bpy.context.active_object.data.vertices if v.select] + bpy.ops.object.mode_set(mode='EDIT') + # Compute the min/max distance from the reference to mesh vertices min_dist = sys.float_info.max max_dist = -min_dist - for ob in selection: - for vert in ob.data.vertices: - dist = (ob.matrix_world * vert.co - source.location).length + if m.type == 'DISTANCE_FROM_CAMERA': + ob_to_cam = matrix_to_camera * ob.matrix_world + for vert in selected_verts: + # dist in the camera space + dist = (ob_to_cam * vert.co).length + min_dist = min(dist, min_dist) + max_dist = max(dist, max_dist) + elif m.type == 'DISTANCE_FROM_OBJECT': + for vert in selected_verts: + # dist in the world space + dist = (ob.matrix_world * vert.co - target_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'} + # Find selected mesh objects + selection = [ob for ob in scene.objects if ob.select_get() and ob.type == 'MESH' and ob.name != source.name] + if selection: + # Compute the min/max distance from the reference to mesh vertices + min_dist = sys.float_info.max + max_dist = -min_dist + if m.type == 'DISTANCE_FROM_CAMERA': + for ob in selection: + ob_to_cam = matrix_to_camera * ob.matrix_world + for vert in ob.data.vertices: + # dist in the camera space + dist = (ob_to_cam * vert.co).length + min_dist = min(dist, min_dist) + max_dist = max(dist, max_dist) + elif m.type == 'DISTANCE_FROM_OBJECT': + for ob in selection: + for vert in ob.data.vertices: + # dist in the world space + dist = (ob.matrix_world * vert.co - target_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'} diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 6356da216b1..be680a6df0c 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -81,16 +81,18 @@ class SelectPattern(Operator): # Can be pose bones or objects for item in items: if pattern_match(item.name, self.pattern): - item.select = True # hrmf, perhaps there should be a utility function for this. if is_ebone: + item.select = True item.select_head = True item.select_tail = True if item.use_connect: item_parent = item.parent if item_parent is not None: item_parent.select_tail = True + else: + item.select_set(action='SELECT') return {'FINISHED'} @@ -136,7 +138,7 @@ class SelectCamera(Operator): bpy.ops.object.select_all(action='DESELECT') scene.objects.active = camera camera.hide = False - camera.select = True + camera.select_set(action='SELECT') return {'FINISHED'} return {'CANCELLED'} @@ -202,7 +204,7 @@ class SelectHierarchy(Operator): bpy.ops.object.select_all(action='DESELECT') for obj in select_new: - obj.select = True + obj.select_set(action='SELECT') scene.objects.active = act_new return {'FINISHED'} @@ -644,8 +646,8 @@ class MakeDupliFace(Operator): ob_new.use_dupli_faces_scale = True ob_new.dupli_faces_scale = 1.0 / SCALE_FAC - ob_inst.select = True - ob_new.select = True + ob_inst.select_set(action='SELECT') + ob_new.select_set(action='SELECT') def execute(self, context): self._main(context) @@ -664,7 +666,7 @@ class IsolateTypeRender(Operator): for obj in context.visible_objects: - if obj.select: + if obj.select_get(): obj.hide_render = False else: if obj.type == act_type: @@ -1029,8 +1031,8 @@ class LodGenerate(Operator): for level in ob.lod_levels[1:]: level.object.hide = level.object.hide_render = True - lod.select = False - ob.select = True + lod.select_set(action='DESELECT') + ob.select_set(action='SELECT') scene.objects.active = ob return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py index 750a5b0bf0f..cba49c629be 100644 --- a/release/scripts/startup/bl_operators/rigidbody.py +++ b/release/scripts/startup/bl_operators/rigidbody.py @@ -63,7 +63,7 @@ class CopyRigidbodySettings(Operator): # deselect all but mesh objects for o in context.selected_objects: if o.type != 'MESH': - o.select = False + o.select_set(action='DESELECT') elif o.rigid_body is None: # Add rigidbody to object! scene.objects.active = o @@ -125,7 +125,7 @@ class BakeToKeyframes(Operator): # filter objects selection for obj in context.selected_objects: if not obj.rigid_body or obj.rigid_body.type != 'ACTIVE': - obj.select = False + obj.select_set(action='DESELECT') objects = context.selected_objects @@ -258,7 +258,7 @@ class ConnectRigidBodies(Operator): ob.location = loc context.scene.objects.link(ob) context.scene.objects.active = ob - ob.select = True + ob.select_set(action='SELECT') bpy.ops.rigidbody.constraint_add() con_obj = context.active_object @@ -303,7 +303,7 @@ class ConnectRigidBodies(Operator): # restore selection bpy.ops.object.select_all(action='DESELECT') for obj in objects: - obj.select = True + obj.select_set(action='SELECT') scene.objects.active = obj_act return {'FINISHED'} else: diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 2389be6787d..0f26ff75715 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -29,6 +29,7 @@ if "bpy" in locals(): _modules = [ "properties_animviz", + "properties_collection", "properties_constraint", "properties_data_armature", "properties_data_bone", @@ -69,6 +70,7 @@ _modules = [ "space_graph", "space_image", "space_info", + "space_collections", "space_logic", "space_nla", "space_node", diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py new file mode 100644 index 00000000000..88d78f98ef2 --- /dev/null +++ b/release/scripts/startup/bl_ui/properties_collection.py @@ -0,0 +1,128 @@ +# ##### 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 ##### + +# <pep8 compliant> +import bpy +from bpy.types import Panel, UIList + + +class CollectionButtonsPanel: + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "collection" + + +class COLLECTION_PT_context_collection(CollectionButtonsPanel, Panel): + bl_label = "" + bl_options = {'HIDE_HEADER'} + + def draw(self, context): + layout = self.layout + space = context.space_data + + collection = context.layer_collection + name = collection.name + if name == 'Master Collection': + layout.label(text=name, icon='COLLAPSEMENU') + else: + layout.prop(collection, "name", text="", icon='COLLAPSEMENU') + + +class COLLECTION_UL_objects(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): + # assert(isinstance(item, bpy.types.Object) + ob = item + if self.layout_type in {'DEFAULT', 'COMPACT'}: + layout.label(ob.name, icon_value=icon) + + elif self.layout_type == 'GRID': + layout.alignment = 'CENTER' + layout.label("", icon_value=icon) + + +class COLLECTION_PT_objects(CollectionButtonsPanel, Panel): + bl_label = "Objects" + + def draw(self, context): + layout = self.layout + scene = context.scene + collection = context.scene_collection + + row = layout.row() + row.template_list("COLLECTION_UL_objects", "name", collection, "objects", collection.objects, "active_index", rows=2) + + col = row.column(align=True) + col.operator("collections.objects_add", icon='ZOOMIN', text="") + col.operator("collections.objects_remove", icon='ZOOMOUT', text="") + + row = layout.row(align=True) + row.operator("collections.objects_select", text="Select") + row.operator("collections.objects_deselect", text="Deselect") + + +def template_engine_settings(col, settings, name, use_icon_view=False): + icons = { + False: 'ZOOMIN', + True: 'X', + } + + use_name = "{0}_use".format(name) + use = getattr(settings, use_name) + + row = col.row() + col = row.column() + col.active = use + + if use_icon_view: + col.template_icon_view(settings, name) + else: + col.prop(settings, name) + + row.prop(settings, "{}_use".format(name), text="", icon=icons[use], emboss=False) + + +class COLLECTION_PT_clay_settings(CollectionButtonsPanel, Panel): + bl_label = "Render Settings" + COMPAT_ENGINES = {'BLENDER_CLAY'} + + @classmethod + def poll(cls, context): + scene = context.scene + return scene and (scene.render.engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + + collection = context.layer_collection + settings = collection.get_engine_settings() + + col = layout.column() + template_engine_settings(col, settings, "type") + template_engine_settings(col, settings, "matcap_icon", use_icon_view=True) + template_engine_settings(col, settings, "matcap_rotation") + template_engine_settings(col, settings, "matcap_hue") + template_engine_settings(col, settings, "matcap_saturation") + template_engine_settings(col, settings, "matcap_value") + template_engine_settings(col, settings, "ssao_factor_cavity") + template_engine_settings(col, settings, "ssao_factor_edge") + template_engine_settings(col, settings, "ssao_distance") + template_engine_settings(col, settings, "ssao_attenuation") + + +if __name__ == "__main__": # only for live edit. + bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 4d54817a21c..ec061370fe5 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -469,8 +469,86 @@ class SceneButtonsPanel: bl_context = "scene" +class SCENE_PT_game_physics(SceneButtonsPanel, Panel): + bl_label = "Physics" + COMPAT_ENGINES = {'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + scene = context.scene + return (scene.render.engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + + gs = context.scene.game_settings + + layout.prop(gs, "physics_engine", text="Engine") + if gs.physics_engine != 'NONE': + layout.prop(gs, "physics_gravity", text="Gravity") + + split = layout.split() + + col = split.column() + col.label(text="Physics Steps:") + sub = col.column(align=True) + sub.prop(gs, "physics_step_max", text="Max") + sub.prop(gs, "physics_step_sub", text="Substeps") + col.prop(gs, "fps", text="FPS") + + col = split.column() + col.label(text="Logic Steps:") + col.prop(gs, "logic_step_max", text="Max") + + col = layout.column() + col.label(text="Physics Deactivation:") + sub = col.row(align=True) + sub.prop(gs, "deactivation_linear_threshold", text="Linear Threshold") + sub.prop(gs, "deactivation_angular_threshold", text="Angular Threshold") + sub = col.row() + sub.prop(gs, "deactivation_time", text="Time") + + col = layout.column() + col.prop(gs, "use_occlusion_culling", text="Occlusion Culling") + sub = col.column() + sub.active = gs.use_occlusion_culling + sub.prop(gs, "occlusion_culling_resolution", text="Resolution") + + else: + split = layout.split() + + col = split.column() + col.label(text="Physics Steps:") + col.prop(gs, "fps", text="FPS") + + col = split.column() + col.label(text="Logic Steps:") + col.prop(gs, "logic_step_max", text="Max") + + +class SCENE_PT_game_physics_obstacles(SceneButtonsPanel, Panel): + bl_label = "Obstacle Simulation" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + scene = context.scene + return (scene.render.engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + + gs = context.scene.game_settings + + layout.prop(gs, "obstacle_simulation", text="Type") + if gs.obstacle_simulation != 'NONE': + layout.prop(gs, "level_height") + layout.prop(gs, "show_obstacle_simulation") + + class SCENE_PT_game_navmesh(SceneButtonsPanel, Panel): - bl_label = "Navigation mesh" + bl_label = "Navigation Mesh" bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_GAME'} @@ -484,7 +562,7 @@ class SCENE_PT_game_navmesh(SceneButtonsPanel, Panel): rd = context.scene.game_settings.recast_data - layout.operator("mesh.navmesh_make", text="Build navigation mesh") + layout.operator("mesh.navmesh_make", text="Build Navigation Mesh") col = layout.column() col.label(text="Rasterization:") @@ -656,83 +734,6 @@ class WORLD_PT_game_mist(WorldButtonsPanel, Panel): layout.prop(world.mist_settings, "intensity", text="Minimum Intensity") -class WORLD_PT_game_physics(WorldButtonsPanel, Panel): - bl_label = "Physics" - COMPAT_ENGINES = {'BLENDER_GAME'} - - @classmethod - def poll(cls, context): - scene = context.scene - return (scene.world and scene.render.engine in cls.COMPAT_ENGINES) - - def draw(self, context): - layout = self.layout - - gs = context.scene.game_settings - - layout.prop(gs, "physics_engine", text="Engine") - if gs.physics_engine != 'NONE': - layout.prop(gs, "physics_gravity", text="Gravity") - - split = layout.split() - - col = split.column() - col.label(text="Physics Steps:") - sub = col.column(align=True) - sub.prop(gs, "physics_step_max", text="Max") - sub.prop(gs, "physics_step_sub", text="Substeps") - col.prop(gs, "fps", text="FPS") - - col = split.column() - col.label(text="Logic Steps:") - col.prop(gs, "logic_step_max", text="Max") - - col = layout.column() - col.label(text="Physics Deactivation:") - sub = col.row(align=True) - sub.prop(gs, "deactivation_linear_threshold", text="Linear Threshold") - sub.prop(gs, "deactivation_angular_threshold", text="Angular Threshold") - sub = col.row() - sub.prop(gs, "deactivation_time", text="Time") - - col = layout.column() - col.prop(gs, "use_occlusion_culling", text="Occlusion Culling") - sub = col.column() - sub.active = gs.use_occlusion_culling - sub.prop(gs, "occlusion_culling_resolution", text="Resolution") - - else: - split = layout.split() - - col = split.column() - col.label(text="Physics Steps:") - col.prop(gs, "fps", text="FPS") - - col = split.column() - col.label(text="Logic Steps:") - col.prop(gs, "logic_step_max", text="Max") - - -class WORLD_PT_game_physics_obstacles(WorldButtonsPanel, Panel): - bl_label = "Obstacle Simulation" - COMPAT_ENGINES = {'BLENDER_GAME'} - - @classmethod - def poll(cls, context): - scene = context.scene - return (scene.world and scene.render.engine in cls.COMPAT_ENGINES) - - def draw(self, context): - layout = self.layout - - gs = context.scene.game_settings - - layout.prop(gs, "obstacle_simulation", text="Type") - if gs.obstacle_simulation != 'NONE': - layout.prop(gs, "level_height") - layout.prop(gs, "show_obstacle_simulation") - - class DataButtonsPanel: bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 850606eb80b..90d46a6ee47 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -377,7 +377,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel): sub.active = rd.use_stamp_note sub.prop(rd, "stamp_note_text", text="") if rd.use_sequencer: - layout.label("Sequencer") + layout.label("Sequencer:") layout.prop(rd, "use_stamp_strip_meta") @@ -584,5 +584,24 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel): sub.prop(rd, "bake_user_scale", text="User Scale") +class RENDER_PT_clay(RenderButtonsPanel, Panel): + bl_label = "Default Clay" + COMPAT_ENGINES = {'BLENDER_CLAY'} + + def draw(self, context): + layout = self.layout; + settings = context.scene.active_engine_settings + layout.template_icon_view(settings, "matcap_icon") + layout.prop(settings, "matcap_rotation") + layout.prop(settings, "matcap_hue") + layout.prop(settings, "matcap_saturation") + layout.prop(settings, "matcap_value") + layout.prop(settings, "ssao_factor_cavity") + layout.prop(settings, "ssao_factor_edge") + layout.prop(settings, "ssao_distance") + layout.prop(settings, "ssao_attenuation") + layout.prop(settings, "ssao_samples") + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py index 9b8bc237db9..2545eadc792 100644 --- a/release/scripts/startup/bl_ui/properties_render_layer.py +++ b/release/scripts/startup/bl_ui/properties_render_layer.py @@ -35,7 +35,7 @@ class RenderLayerButtonsPanel: class RENDERLAYER_UL_renderlayers(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): - # assert(isinstance(item, bpy.types.SceneRenderLayer) + # assert(isinstance(item, bpy.types.SceneLayer) layer = item if self.layout_type in {'DEFAULT', 'COMPACT'}: layout.prop(layer, "name", text="", icon_value=icon, emboss=False) @@ -48,7 +48,7 @@ class RENDERLAYER_UL_renderlayers(UIList): class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel): bl_label = "Layer List" bl_options = {'HIDE_HEADER'} - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'} def draw(self, context): layout = self.layout @@ -62,7 +62,7 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel): row = layout.row() col = row.column() - col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2) + col.template_list("RENDERLAYER_UL_renderlayers", "", scene, "render_layers", scene.render_layers, "active_index", rows=2) col = row.column() sub = col.column(align=True) @@ -71,103 +71,6 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel): col.prop(rd, "use_single_layer", icon_only=True) -class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel): - bl_label = "Layer" - COMPAT_ENGINES = {'BLENDER_RENDER'} - - def draw(self, context): - layout = self.layout - - scene = context.scene - rd = scene.render - rl = rd.layers.active - - split = layout.split() - - col = split.column() - col.prop(scene, "layers", text="Scene") - col.label(text="") - col.prop(rl, "light_override", text="Lights") - col.prop(rl, "material_override", text="Material") - - col = split.column() - col.prop(rl, "layers", text="Layer") - col.prop(rl, "layers_zmask", text="Mask Layer") - - layout.separator() - layout.label(text="Include:") - - split = layout.split() - - col = split.column() - col.prop(rl, "use_zmask") - row = col.row() - row.prop(rl, "invert_zmask", text="Negate") - row.active = rl.use_zmask - col.prop(rl, "use_all_z") - - col = split.column() - col.prop(rl, "use_solid") - col.prop(rl, "use_halo") - col.prop(rl, "use_ztransp") - - col = split.column() - col.prop(rl, "use_sky") - col.prop(rl, "use_edge_enhance") - col.prop(rl, "use_strand") - if bpy.app.build_options.freestyle: - row = col.row() - row.prop(rl, "use_freestyle") - row.active = rd.use_freestyle - - -class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel): - bl_label = "Passes" - bl_options = {'DEFAULT_CLOSED'} - COMPAT_ENGINES = {'BLENDER_RENDER'} - - @staticmethod - def draw_pass_type_buttons(box, rl, pass_type): - # property names - use_pass_type = "use_pass_" + pass_type - exclude_pass_type = "exclude_" + pass_type - # draw pass type buttons - row = box.row() - row.prop(rl, use_pass_type) - row.prop(rl, exclude_pass_type, text="") - - def draw(self, context): - layout = self.layout - - scene = context.scene - rd = scene.render - rl = rd.layers.active - - split = layout.split() - - col = split.column() - col.prop(rl, "use_pass_combined") - col.prop(rl, "use_pass_z") - col.prop(rl, "use_pass_vector") - col.prop(rl, "use_pass_normal") - col.prop(rl, "use_pass_uv") - col.prop(rl, "use_pass_mist") - col.prop(rl, "use_pass_object_index") - col.prop(rl, "use_pass_material_index") - col.prop(rl, "use_pass_color") - - col = split.column() - col.prop(rl, "use_pass_diffuse") - self.draw_pass_type_buttons(col, rl, "specular") - self.draw_pass_type_buttons(col, rl, "shadow") - self.draw_pass_type_buttons(col, rl, "emit") - self.draw_pass_type_buttons(col, rl, "ambient_occlusion") - self.draw_pass_type_buttons(col, rl, "environment") - self.draw_pass_type_buttons(col, rl, "indirect") - self.draw_pass_type_buttons(col, rl, "reflection") - self.draw_pass_type_buttons(col, rl, "refraction") - - class RENDERLAYER_UL_renderviews(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): # assert(isinstance(item, bpy.types.SceneRenderView) diff --git a/release/scripts/startup/bl_ui/space_collections.py b/release/scripts/startup/bl_ui/space_collections.py new file mode 100644 index 00000000000..9b612ce2ecd --- /dev/null +++ b/release/scripts/startup/bl_ui/space_collections.py @@ -0,0 +1,41 @@ +# ##### 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 ##### + +# <pep8 compliant> +import bpy +from bpy.types import Header, Menu + + +class COLLECTIONS_HT_header(Header): + bl_space_type = 'COLLECTION_MANAGER' + + def draw(self, context): + layout = self.layout + + layout.template_header() + + row = layout.row(align=True) + row.operator("collections.collection_new", text="", icon='NEW') + row.operator("collections.override_new", text="", icon='LINK_AREA') + row.operator("collections.collection_link", text="", icon='LINKED') + row.operator("collections.collection_unlink", text="", icon='UNLINKED') + row.operator("collections.delete", text="", icon='X') + + +if __name__ == "__main__": # only for live edit. + bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index 6f7c535fe21..eb3cef8012d 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -59,6 +59,14 @@ class OUTLINER_HT_header(Header): row.label(text="No Keying Set active") elif space.display_mode == 'ORPHAN_DATA': layout.operator("outliner.orphans_purge") + elif space.display_mode == 'COLLECTIONS': + row = layout.row(align=True) + + row.operator("collections.collection_new", text="", icon='NEW') + row.operator("collections.override_new", text="", icon='LINK_AREA') + row.operator("collections.collection_link", text="", icon='LINKED') + row.operator("collections.collection_unlink", text="", icon='UNLINKED') + row.operator("collections.delete", text="", icon='X') class OUTLINER_MT_editor_menus(Menu): diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index f8e4d1338f9..f605712510a 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -634,7 +634,6 @@ class VIEW3D_MT_select_object(Menu): layout.operator("object.select_all", text="Inverse").action = 'INVERT' layout.operator("object.select_random", text="Random") layout.operator("object.select_mirror", text="Mirror") - layout.operator("object.select_by_layer", text="Select All by Layer") layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...") layout.operator("object.select_camera", text="Select Camera") @@ -1311,15 +1310,6 @@ class VIEW3D_MT_object(Menu): layout.separator() - if is_local_view: - layout.operator_context = 'EXEC_REGION_WIN' - layout.operator("object.move_to_layer", text="Move out of Local View") - layout.operator_context = 'INVOKE_REGION_WIN' - else: - layout.operator("object.move_to_layer", text="Move to Layer...") - - layout.menu("VIEW3D_MT_object_showhide") - layout.operator_menu_enum("object.convert", "target") @@ -1345,9 +1335,9 @@ class VIEW3D_MT_object_clear(Menu): def draw(self, context): layout = self.layout - layout.operator("object.location_clear", text="Location") - layout.operator("object.rotation_clear", text="Rotation") - layout.operator("object.scale_clear", text="Scale") + layout.operator("object.location_clear", text="Location").clear_delta = False + layout.operator("object.rotation_clear", text="Rotation").clear_delta = False + layout.operator("object.scale_clear", text="Scale").clear_delta = False layout.operator("object.origin_clear", text="Origin") @@ -1597,17 +1587,6 @@ class VIEW3D_MT_object_quick_effects(Menu): layout.operator("object.quick_fluid") -class VIEW3D_MT_object_showhide(Menu): - bl_label = "Show/Hide" - - def draw(self, context): - layout = self.layout - - layout.operator("object.hide_view_clear", text="Show Hidden") - layout.operator("object.hide_view_set", text="Hide Selected").unselected = False - layout.operator("object.hide_view_set", text="Hide Unselected").unselected = True - - class VIEW3D_MT_make_single_user(Menu): bl_label = "Make Single User" @@ -3167,6 +3146,74 @@ class VIEW3D_PT_viewport_debug(Panel): col.row(align=True).prop(view, "debug_background", expand=True) +class VIEW3D_PT_collections_editor(Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'UI' + bl_label = "Collections" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + return context.space_data + + def draw(self, context): + layout = self.layout + layer = context.render_layer + active_collection = context.layer_collection + + col = layout.column() + box = col.box() + + index = -1 + for collection in layer.collections: + index = self._draw_layer_collection(box, index, active_collection, collection, True, True) + + row = layout.row(align=True) + row.operator("collections.collection_new", text="", icon='NEW') + row.operator("collections.override_new", text="", icon='LINK_AREA') + row.operator("collections.collection_link", text="", icon='LINKED') + row.operator("collections.collection_unlink", text="", icon='UNLINKED') + row.operator("collections.delete", text="", icon='X') + + def _draw_layer_collection(self, box, index, active_collection, collection, is_active, is_draw, depth=0): + index += 1 + nested_collections = collection.collections + + if is_draw: + row = box.row() + row.active = is_active + is_collection_selected = (collection == active_collection) + + if is_collection_selected: + sub_box = row.box() + row = sub_box.row() + + row.label(text="{0}{1}{2}".format( + " " * depth, + u'\u21b3 ' if depth else "", + collection.name)) + + row.prop(collection, "hide", text="", emboss=False) + row.prop(collection, "hide_select", text="", emboss=False) + + row.operator("collections.select", text="", icon='BLANK1' if is_collection_selected else 'HAND', emboss=False).collection_index=index + + if nested_collections: + row.prop(collection, "is_unfolded", text="", emboss=False) + else: + row.label(icon='BLANK1') + + if not collection.is_unfolded: + is_draw = False + + is_active &= not collection.hide + + for nested_collection in nested_collections: + index = self._draw_layer_collection(box, index, active_collection, nested_collection, is_active, is_draw, depth + 1) + + return index + + class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'UI' diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py index 6c77c5d6a1a..8de7a5e2903 100644 --- a/release/scripts/templates_py/batch_export.py +++ b/release/scripts/templates_py/batch_export.py @@ -18,7 +18,7 @@ bpy.ops.object.select_all(action='DESELECT') for obj in selection: - obj.select = True + obj.select_set(action='SELECT') # some exporters only use the active object scene.objects.active = obj @@ -31,7 +31,7 @@ for obj in selection: ## Can be used for multiple formats # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True) - obj.select = False + obj.select_set(action='DESELECT') print("written:", fn) @@ -39,4 +39,4 @@ for obj in selection: scene.objects.active = obj_active for obj in selection: - obj.select = True + obj.select_set(action='SELECT') diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py index c4d661b4c1f..e3b63813fc4 100644 --- a/release/scripts/templates_py/operator_modal_view3d_raycast.py +++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py @@ -67,7 +67,7 @@ def main(context, event): # now we have the object under the mouse cursor, # we could do lots of stuff but for the example just select. if best_obj is not None: - best_obj.select = True + best_obj.select_set(action='SELECT') context.scene.objects.active = best_obj diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 6f2b78e0845..47ebed8f791 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -100,6 +100,7 @@ add_subdirectory(windowmanager) add_subdirectory(blenkernel) add_subdirectory(blenlib) add_subdirectory(bmesh) +add_subdirectory(draw) add_subdirectory(render) add_subdirectory(blenfont) add_subdirectory(blentranslation) diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc index 4ecb9d944f2..282777f3af0 100644 --- a/source/blender/alembic/intern/abc_curves.cc +++ b/source/blender/alembic/intern/abc_curves.cc @@ -102,7 +102,7 @@ void AbcCurveWriter::do_write() const BPoint *point = nurbs->bp; for (int i = 0; i < totpoint; ++i, ++point) { - copy_zup_yup(temp_vert.getValue(), point->vec); + copy_yup_from_zup(temp_vert.getValue(), point->vec); verts.push_back(temp_vert); weights.push_back(point->vec[3]); widths.push_back(point->radius); @@ -118,7 +118,7 @@ void AbcCurveWriter::do_write() /* TODO(kevin): store info about handles, Alembic doesn't have this. */ for (int i = 0; i < totpoint; ++i, ++bezier) { - copy_zup_yup(temp_vert.getValue(), bezier->vec[1]); + copy_yup_from_zup(temp_vert.getValue(), bezier->vec[1]); verts.push_back(temp_vert); widths.push_back(bezier->radius); } @@ -322,7 +322,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) weight = (*weights)[idx]; } - copy_yup_zup(bp->vec, pos.getValue()); + copy_zup_from_yup(bp->vec, pos.getValue()); bp->vec[3] = weight; bp->f1 = SELECT; bp->radius = radius; @@ -389,7 +389,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float t for (int i = 0; i < totpoint; ++i, ++point, ++vertex_idx) { const Imath::V3f &pos = (*positions)[vertex_idx]; - copy_yup_zup(point->vec, pos.getValue()); + copy_zup_from_yup(point->vec, pos.getValue()); } } else if (nurbs->bezt) { @@ -397,7 +397,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float t for (int i = 0; i < totpoint; ++i, ++bezier, ++vertex_idx) { const Imath::V3f &pos = (*positions)[vertex_idx]; - copy_yup_zup(bezier->vec[1], pos.getValue()); + copy_zup_from_yup(bezier->vec[1], pos.getValue()); } } } diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index ff8b0442ab6..28d54672d20 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -123,19 +123,19 @@ static bool object_is_shape(Object *ob) } } -static bool export_object(const ExportSettings * const settings, Object *ob) +static bool export_object(const ExportSettings * const settings, const Base * const ob_base) { - if (settings->selected_only && !parent_selected(ob)) { + if (settings->selected_only && !object_selected(ob_base)) { return false; } - - if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) { + // FIXME Sybren: handle these cleanly (maybe just remove code), now using active scene layer instead. + if (settings->visible_layers_only && (ob_base->flag & BASE_VISIBLED) == 0) { return false; } - if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) { - return false; - } + // if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) { + // return false; + // } return true; } @@ -341,12 +341,10 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx) { - Base *base = static_cast<Base *>(m_scene->base.first); - - while (base) { + for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) { Object *ob = base->object; - if (export_object(&m_settings, ob)) { + if (export_object(&m_settings, base)) { switch(ob->type) { case OB_LAMP: case OB_LATTICE: @@ -356,50 +354,49 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx) break; default: - exploreTransform(eval_ctx, ob, ob->parent, NULL); + exploreTransform(eval_ctx, base, ob->parent, NULL); } } - - base = base->next; } } void AbcExporter::createTransformWritersFlat() { - Base *base = static_cast<Base *>(m_scene->base.first); - - while (base) { + for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) { Object *ob = base->object; - if (export_object(&m_settings, ob) && object_is_shape(ob)) { + if (!export_object(&m_settings, base)) { std::string name = get_id_name(ob); m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), 0, m_trans_sampling_index, m_settings); } - - base = base->next; } } -void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent) +void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent) { - createTransformWriter(ob, parent, dupliObParent); + Object *ob = ob_base->object; + + if (export_object(&m_settings, ob_base) && object_is_shape(ob)) { + createTransformWriter(ob, parent, dupliObParent); + } ListBase *lb = object_duplilist(eval_ctx, m_scene, ob); if (lb) { - DupliObject *link = static_cast<DupliObject *>(lb->first); - Object *dupli_ob = NULL; - Object *dupli_parent = NULL; - - while (link) { + Base fake_base = *ob_base; // copy flags (like selection state) from the real object. + fake_base.next = fake_base.prev = NULL; + + for (DupliObject *link = static_cast<DupliObject *>(lb->first); link; link = link->next) { + Object *dupli_ob = NULL; + Object *dupli_parent = NULL; + if (link->type == OB_DUPLIGROUP) { dupli_ob = link->ob; dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob; - exploreTransform(eval_ctx, dupli_ob, dupli_parent, ob); + fake_base.object = dupli_ob; + exploreTransform(eval_ctx, &fake_base, dupli_parent, ob); } - - link = link->next; } } @@ -410,8 +407,12 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl { const std::string name = get_object_dag_path_name(ob, dupliObParent); + /* An object should not be its own parent, or we'll get infinite loops. */ + BLI_assert(ob != parent); + BLI_assert(ob != dupliObParent); + /* check if we have already created a transform writer for this object */ - if (m_xforms.find(name) != m_xforms.end()){ + if (getXForm(name) != NULL){ std::cerr << "xform " << name << " already exists\n"; return; } @@ -426,6 +427,14 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl if (parent->parent) { createTransformWriter(parent, parent->parent, dupliObParent); } + else if (parent == dupliObParent) { + if (dupliObParent->parent == NULL) { + createTransformWriter(parent, NULL, NULL); + } + else { + createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent); + } + } else { createTransformWriter(parent, dupliObParent, dupliObParent); } @@ -445,44 +454,42 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx) { - Base *base = static_cast<Base *>(m_scene->base.first); - - while (base) { - Object *ob = base->object; - exploreObject(eval_ctx, ob, NULL); - - base = base->next; + for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) { + exploreObject(eval_ctx, base, NULL); } } -void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent) +void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent) { + Object *ob = ob_base->object; ListBase *lb = object_duplilist(eval_ctx, m_scene, ob); - createShapeWriter(ob, dupliObParent); + createShapeWriter(ob_base, dupliObParent); if (lb) { - DupliObject *dupliob = static_cast<DupliObject *>(lb->first); + Base fake_base = *ob_base; // copy flags (like selection state) from the real object. + fake_base.next = fake_base.prev = NULL; - while (dupliob) { + for (DupliObject *dupliob = static_cast<DupliObject *>(lb->first); dupliob; dupliob = dupliob->next) { if (dupliob->type == OB_DUPLIGROUP) { - exploreObject(eval_ctx, dupliob->ob, ob); + fake_base.object = dupliob->ob; + exploreObject(eval_ctx, &fake_base, ob); } - - dupliob = dupliob->next; } } free_object_duplilist(lb); } -void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent) +void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent) { + Object *ob = ob_base->object; + if (!object_is_shape(ob)) { return; } - if (!export_object(&m_settings, ob)) { + if (!export_object(&m_settings, ob_base)) { return; } diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h index b0eb8e185d6..80fee067c04 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -36,11 +36,14 @@ struct EvaluationContext; struct Main; struct Object; struct Scene; +struct SceneLayer; +struct Base; struct ExportSettings { ExportSettings(); Scene *scene; + SceneLayer *sl; // Scene layer to export; all its objects will be exported, unless selected_only=true bool selected_only; bool visible_layers_only; @@ -105,10 +108,10 @@ private: void createTransformWritersHierarchy(EvaluationContext *eval_ctx); void createTransformWritersFlat(); void createTransformWriter(Object *ob, Object *parent, Object *dupliObParent); - void exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent = NULL); - void exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent); + void exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent); + void exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent); void createShapeWriters(EvaluationContext *eval_ctx); - void createShapeWriter(Object *ob, Object *dupliObParent); + void createShapeWriter(Base *ob_base, Object *dupliObParent); AbcTransformWriter *getXForm(const std::string &name); diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc index 14bcf6731ea..e328df24e53 100644 --- a/source/blender/alembic/intern/abc_hair.cc +++ b/source/blender/alembic/intern/abc_hair.cc @@ -77,7 +77,6 @@ void AbcHairWriter::do_write() DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH); DM_ensure_tessface(dm); - DM_update_tessface_data(dm); std::vector<Imath::V3f> verts; std::vector<int32_t> hvertices; @@ -164,7 +163,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm, psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, normal, NULL, NULL, NULL, NULL); - copy_zup_yup(tmp_nor.getValue(), normal); + copy_yup_from_zup(tmp_nor.getValue(), normal); norm_values.push_back(tmp_nor); } } @@ -198,7 +197,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm, MVert *mv = mverts + vtx[o]; normal_short_to_float_v3(normal, mv->no); - copy_zup_yup(tmp_nor.getValue(), normal); + copy_yup_from_zup(tmp_nor.getValue(), normal); norm_values.push_back(tmp_nor); found = true; break; diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index bdd75f93189..8bc9c335054 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -112,7 +112,7 @@ static void get_vertices(DerivedMesh *dm, std::vector<Imath::V3f> &points) MVert *verts = dm->getVertArray(dm); for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) { - copy_zup_yup(points[i].getValue(), verts[i].co); + copy_yup_from_zup(points[i].getValue(), verts[i].co); } } @@ -182,7 +182,7 @@ static void get_vertex_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) { normal_short_to_float_v3(no, verts[i].no); - copy_zup_yup(normals[i].getValue(), no); + copy_yup_from_zup(normals[i].getValue(), no); } } @@ -211,7 +211,7 @@ static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals) for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { const int index = ml->v; - copy_zup_yup(normals[loop_index].getValue(), lnors[index]); + copy_yup_from_zup(normals[loop_index].getValue(), lnors[index]); } } } @@ -226,14 +226,14 @@ static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals) BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no); for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { - copy_zup_yup(normals[loop_index].getValue(), no); + copy_yup_from_zup(normals[loop_index].getValue(), no); } } else { /* Smooth shaded, use individual vert normals. */ for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { normal_short_to_float_v3(no, verts[ml->v].no); - copy_zup_yup(normals[loop_index].getValue(), no); + copy_yup_from_zup(normals[loop_index].getValue(), no); } } } @@ -590,7 +590,7 @@ void AbcMeshWriter::getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities); for (int i = 0; i < totverts; ++i) { - copy_zup_yup(vels[i].getValue(), mesh_vels); + copy_yup_from_zup(vels[i].getValue(), mesh_vels); mesh_vels += 3; } } @@ -726,7 +726,7 @@ static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions const Imath::V3f &ceil_pos = (*ceil_positions)[i]; interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight); - copy_yup_zup(mvert.co, tmp); + copy_zup_from_yup(mvert.co, tmp); mvert.bweight = 0; } @@ -755,7 +755,7 @@ void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArr MVert &mvert = mverts[i]; Imath::V3f pos_in = (*positions)[i]; - copy_yup_zup(mvert.co, pos_in.getValue()); + copy_zup_from_yup(mvert.co, pos_in.getValue()); mvert.bweight = 0; @@ -765,7 +765,7 @@ void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArr short no[3]; normal_float_to_short_v3(no, nor_in.getValue()); - copy_yup_zup(mvert.no, no); + copy_zup_from_yup(mvert.no, no); } } } diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc index 4f57dfdae9e..d0b9561f679 100644 --- a/source/blender/alembic/intern/abc_nurbs.cc +++ b/source/blender/alembic/intern/abc_nurbs.cc @@ -153,7 +153,7 @@ void AbcNurbsWriter::do_write() const BPoint *bp = nu->bp; for (int i = 0; i < size; ++i, ++bp) { - copy_zup_yup(positions[i].getValue(), bp->vec); + copy_yup_from_zup(positions[i].getValue(), bp->vec); weights[i] = bp->vec[3]; } @@ -281,7 +281,7 @@ void AbcNurbsReader::readObjectData(Main *bmain, float time) posw_in = (*weights)[i]; } - copy_yup_zup(bp->vec, pos_in.getValue()); + copy_zup_from_yup(bp->vec, pos_in.getValue()); bp->vec[3] = posw_in; bp->f1 = SELECT; bp->radius = 1.0f; diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index 9dfccdb8c7f..a5b8af542fc 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -97,14 +97,14 @@ Imath::Box3d AbcObjectWriter::bounds() return Imath::Box3d(); } - /* Convert Z-up to Y-up. */ + /* Convert Z-up to Y-up. This also changes which vector goes into which min/max property. */ this->m_bounds.min.x = bb->vec[0][0]; this->m_bounds.min.y = bb->vec[0][2]; - this->m_bounds.min.z = -bb->vec[0][1]; + this->m_bounds.min.z = -bb->vec[6][1]; this->m_bounds.max.x = bb->vec[6][0]; this->m_bounds.max.y = bb->vec[6][2]; - this->m_bounds.max.z = -bb->vec[6][1]; + this->m_bounds.max.z = -bb->vec[0][1]; return this->m_bounds; } diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc index f8ce72d845d..bb375eb9561 100644 --- a/source/blender/alembic/intern/abc_util.cc +++ b/source/blender/alembic/intern/abc_util.cc @@ -35,6 +35,7 @@ extern "C" { #include "DNA_object_types.h" +#include "DNA_layer_types.h" #include "BLI_math.h" } @@ -58,6 +59,16 @@ std::string get_id_name(ID *id) return name; } + +/** + * @brief get_object_dag_path_name returns the name under which the object + * will be exported in the Alembic file. It is of the form + * "[../grandparent/]parent/object" if dupli_parent is NULL, or + * "dupli_parent/[../grandparent/]parent/object" otherwise. + * @param ob + * @param dupli_parent + * @return + */ std::string get_object_dag_path_name(Object *ob, Object *dupli_parent) { std::string name = get_id_name(ob); @@ -76,31 +87,9 @@ std::string get_object_dag_path_name(Object *ob, Object *dupli_parent) return name; } -bool object_selected(Object *ob) +bool object_selected(const Base * const ob_base) { - return ob->flag & SELECT; -} - -bool parent_selected(Object *ob) -{ - if (object_selected(ob)) { - return true; - } - - bool do_export = false; - - Object *parent = ob->parent; - - while (parent != NULL) { - if (object_selected(parent)) { - do_export = true; - break; - } - - parent = parent->parent; - } - - return do_export; + return ob_base->flag & SELECT; } Imath::M44d convert_matrix(float mat[4][4]) @@ -197,7 +186,7 @@ void create_transform_matrix(float r_mat[4][4]) copy_m4_m3(transform_mat, rot_mat); /* Add translation to transformation matrix. */ - copy_yup_zup(transform_mat[3], loc); + copy_zup_from_yup(transform_mat[3], loc); /* Create scale matrix. */ scale_mat[0][0] = scale[0]; @@ -417,7 +406,7 @@ void create_transform_matrix(Object *obj, float transform_mat[4][4]) copy_m4_m3(transform_mat, rot_mat); /* Add translation to transformation matrix. */ - copy_zup_yup(transform_mat[3], loc); + copy_yup_from_zup(transform_mat[3], loc); /* Create scale matrix. */ scale_mat[0][0] = scale[0]; diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h index 60a96855d14..328f2c41a87 100644 --- a/source/blender/alembic/intern/abc_util.h +++ b/source/blender/alembic/intern/abc_util.h @@ -43,13 +43,13 @@ struct ImportSettings; struct ID; struct Object; +struct Base; std::string get_id_name(ID *id); std::string get_id_name(Object *ob); std::string get_object_dag_path_name(Object *ob, Object *dupli_parent); -bool object_selected(Object *ob); -bool parent_selected(Object *ob); +bool object_selected(const Base * const ob_base); Imath::M44d convert_matrix(float mat[4][4]); void create_transform_matrix(float r_mat[4][4]); @@ -116,14 +116,14 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe /* Copy from Y-up to Z-up. */ -ABC_INLINE void copy_yup_zup(float zup[3], const float yup[3]) +ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3]) { zup[0] = yup[0]; zup[1] = -yup[2]; zup[2] = yup[1]; } -ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3]) +ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3]) { zup[0] = yup[0]; zup[1] = -yup[2]; @@ -132,14 +132,14 @@ ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3]) /* Copy from Z-up to Y-up. */ -ABC_INLINE void copy_zup_yup(float yup[3], const float zup[3]) +ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3]) { yup[0] = zup[0]; yup[1] = zup[2]; yup[2] = -zup[1]; } -ABC_INLINE void copy_zup_yup(short yup[3], const short zup[3]) +ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3]) { yup[0] = zup[0]; yup[1] = zup[2]; diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index d8d017119b1..fcfe634924f 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -332,21 +332,37 @@ void ABC_export( BLI_strncpy(job->filename, filepath, 1024); job->settings.scene = job->scene; + + /* Sybren: for now we only export the active scene layer. + * Later in the 2.8 development process this may be replaced by using + * a specific collection for Alembic I/O, which can then be toggled + * between "real" objects and cached Alembic files. */ + job->settings.sl = CTX_data_scene_layer(C); + job->settings.frame_start = params->frame_start; job->settings.frame_end = params->frame_end; job->settings.frame_step_xform = params->frame_step_xform; job->settings.frame_step_shape = params->frame_step_shape; job->settings.shutter_open = params->shutter_open; job->settings.shutter_close = params->shutter_close; + + /* Sybren: For now this is ignored, until we can get selection + * detection working through Base pointers (instead of ob->flags). */ job->settings.selected_only = params->selected_only; + job->settings.export_face_sets = params->face_sets; job->settings.export_normals = params->normals; job->settings.export_uvs = params->uvs; job->settings.export_vcols = params->vcolors; job->settings.apply_subdiv = params->apply_subdiv; job->settings.flatten_hierarchy = params->flatten_hierarchy; + + /* Sybren: visible_layer & renderable only is ignored for now, + * to be replaced with collections later in the 2.8 dev process + * (also see note above). */ job->settings.visible_layers_only = params->visible_layers_only; job->settings.renderable_only = params->renderable_only; + job->settings.use_subdiv_schema = params->use_subdiv_schema; job->settings.export_ogawa = (params->compression_type == ABC_ARCHIVE_OGAWA); job->settings.pack_uv = params->packuv; diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 3da0434687c..1b967f889c0 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -45,6 +45,7 @@ int BLF_init(int points, int dpi); void BLF_exit(void); void BLF_default_dpi(int dpi); void BLF_default_set(int fontid); +int BLF_default(void); /* get default font ID so we can pass it to other functions */ void BLF_cache_clear(void); @@ -64,6 +65,17 @@ void BLF_aspect(int fontid, float x, float y, float z); void BLF_position(int fontid, float x, float y, float z); void BLF_size(int fontid, int size, int dpi); +/* goal: small but useful color API */ +void BLF_color4ubv(int fontid, const unsigned char rgba[4]); +void BLF_color3ubv(int fontid, const unsigned char rgb[3]); +void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha); +void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b); +void BLF_color4f(int fontid, float r, float g, float b, float a); +void BLF_color4fv(int fontid, const float rgba[4]); +void BLF_color3f(int fontid, float r, float g, float b); +void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha); +/* also available: UI_FontThemeColor(fontid, colorid) */ + /* Set a 4x4 matrix to be multiplied before draw the text. * Remember that you need call BLF_enable(BLF_MATRIX) * to enable this. @@ -125,27 +137,11 @@ void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_widt */ float BLF_fixed_width(int fontid) ATTR_WARN_UNUSED_RESULT; -/* and this two function return the width and height - * of the string, using the default font and both value - * are multiplied by the aspect of the font. - */ -void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height) ATTR_NONNULL(); -float BLF_width_default(const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BLF_height_default(const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - -/* Set rotation for default font. */ -void BLF_rotation_default(float angle); - -/* Enable/disable options to the default font. */ -void BLF_enable_default(int option); -void BLF_disable_default(int option); - /* By default, rotation and clipping are disable and * have to be enable/disable using BLF_enable/disable. */ void BLF_rotation(int fontid, float angle); void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax); -void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax); void BLF_wordwrap(int fontid, int wrap_width); #if BLF_BLUR_ENABLE diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 1ce4753cc39..ab7c831f95c 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -50,7 +50,6 @@ #include "BLI_math.h" #include "BLI_threads.h" -#include "BIF_gl.h" #include "BLF_api.h" #include "IMB_colormanagement.h" @@ -176,6 +175,12 @@ void BLF_default_set(int fontid) } } +int BLF_default(void) +{ + ASSERT_DEFAULT_SET; + return global_font_default; +} + int BLF_load(const char *name) { FontBLF *font; @@ -359,24 +364,6 @@ void BLF_disable(int fontid, int option) } } -void BLF_enable_default(int option) -{ - FontBLF *font = blf_get(global_font_default); - - if (font) { - font->flags |= option; - } -} - -void BLF_disable_default(int option) -{ - FontBLF *font = blf_get(global_font_default); - - if (font) { - font->flags &= ~option; - } -} - void BLF_aspect(int fontid, float x, float y, float z) { FontBLF *font = blf_get(fontid); @@ -466,6 +453,76 @@ void BLF_blur(int fontid, int size) } #endif +void BLF_color4ubv(int fontid, const unsigned char rgba[4]) +{ + FontBLF *font = blf_get(fontid); + + if (font) { + font->color[0] = rgba[0]; + font->color[1] = rgba[1]; + font->color[2] = rgba[2]; + font->color[3] = rgba[3]; + } +} + +void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha) +{ + FontBLF *font = blf_get(fontid); + + if (font) { + font->color[0] = rgb[0]; + font->color[1] = rgb[1]; + font->color[2] = rgb[2]; + font->color[3] = alpha; + } +} + +void BLF_color3ubv(int fontid, const unsigned char rgb[3]) +{ + BLF_color3ubv_alpha(fontid, rgb, 255); +} + +void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b) +{ + FontBLF *font = blf_get(fontid); + + if (font) { + font->color[0] = r; + font->color[1] = g; + font->color[2] = b; + font->color[3] = 255; + } +} + +void BLF_color4fv(int fontid, const float rgba[4]) +{ + FontBLF *font = blf_get(fontid); + + if (font) { + rgba_float_to_uchar(font->color, rgba); + } +} + +void BLF_color4f(int fontid, float r, float g, float b, float a) +{ + float rgba[4] = { r, g, b, a }; + BLF_color4fv(fontid, rgba); +} + +void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha) +{ + float rgba[4]; + copy_v3_v3(rgba, rgb); + rgba[3] = alpha; + BLF_color4fv(fontid, rgba); +} + +void BLF_color3f(int fontid, float r, float g, float b) +{ + float rgba[4] = { r, g, b, 1.0f }; + BLF_color4fv(fontid, rgba); +} + void BLF_draw_default(float x, float y, float z, const char *str, size_t len) { ASSERT_DEFAULT_SET; @@ -485,15 +542,6 @@ void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t l BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */ } -void BLF_rotation_default(float angle) -{ - FontBLF *font = blf_get(global_font_default); - - if (font) { - font->angle = angle; - } -} - static void blf_draw_gl__start(FontBLF *font) { /* @@ -517,10 +565,6 @@ static void blf_draw_gl__start(FontBLF *font) if (font->flags & BLF_ROTATION) /* radians -> degrees */ gpuRotateAxis(RAD2DEG(font->angle), 'Z'); - float temp_color[4]; - glGetFloatv(GL_CURRENT_COLOR, temp_color); /* TODO(merwin): new BLF_color function? */ - rgba_float_to_uchar(font->color, temp_color); - #ifndef BLF_STANDALONE VertexFormat *format = immVertexFormat(); unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); @@ -698,14 +742,6 @@ void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_widt } } -void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height) -{ - ASSERT_DEFAULT_SET; - - BLF_size(global_font_default, global_font_points, global_font_dpi); - BLF_width_and_height(global_font_default, str, len, r_width, r_height); -} - float BLF_width_ex( int fontid, const char *str, size_t len, struct ResultBLF *r_info) @@ -736,14 +772,6 @@ float BLF_fixed_width(int fontid) return 0.0f; } -float BLF_width_default(const char *str, size_t len) -{ - ASSERT_DEFAULT_SET; - - BLF_size(global_font_default, global_font_points, global_font_dpi); - return BLF_width(global_font_default, str, len); -} - float BLF_height_ex( int fontid, const char *str, size_t len, struct ResultBLF *r_info) @@ -807,15 +835,6 @@ float BLF_ascender(int fontid) return 0.0f; } -float BLF_height_default(const char *str, size_t len) -{ - ASSERT_DEFAULT_SET; - - BLF_size(global_font_default, global_font_points, global_font_dpi); - - return BLF_height(global_font_default, str, len); -} - void BLF_rotation(int fontid, float angle) { FontBLF *font = blf_get(fontid); @@ -837,18 +856,6 @@ void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax) } } -void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax) -{ - FontBLF *font = blf_get(global_font_default); - - if (font) { - font->clip_rec.xmin = xmin; - font->clip_rec.ymin = ymin; - font->clip_rec.xmax = xmax; - font->clip_rec.ymax = ymax; - } -} - void BLF_wordwrap(int fontid, int wrap_width) { FontBLF *font = blf_get(fontid); diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 71350a0f8dc..d0293eccf3a 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -933,8 +933,6 @@ void blf_font_free(FontBLF *font) static void blf_font_fill(FontBLF *font) { - unsigned int i; - font->aspect[0] = 1.0f; font->aspect[1] = 1.0f; font->aspect[2] = 1.0f; @@ -942,9 +940,15 @@ static void blf_font_fill(FontBLF *font) font->pos[1] = 0.0f; font->angle = 0.0f; - for (i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) font->m[i] = 0; + /* annoying bright color so we can see where to add BLF_color calls */ + font->color[0] = 255; + font->color[1] = 255; + font->color[2] = 0; + font->color[3] = 255; + font->clip_rec.xmin = 0.0f; font->clip_rec.xmax = 0.0f; font->clip_rec.ymin = 0.0f; diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 07db2217bac..bf45a27e51c 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -133,6 +133,12 @@ BVHTree *bvhtree_from_editmesh_edges_ex( BVHTree *bvhtree_from_mesh_edges( struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); +BVHTree *bvhtree_from_mesh_edges_ex( + struct BVHTreeFromMesh *data, + struct MVert *vert, const bool vert_allocated, + struct MEdge *edge, const int edges_num, const bool edge_allocated, + const BLI_bitmap *edges_mask, int edges_num_active, + float epsilon, int tree_type, int axis); BVHTree *bvhtree_from_mesh_faces( struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 9948f21ba90..4876461bfe0 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -79,6 +79,7 @@ DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispba */ struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm); struct DerivedMesh *CDDM_copy_from_tessface(struct DerivedMesh *dm); +struct DerivedMesh *CDDM_copy_with_tessface(struct DerivedMesh *dm); /* creates a CDDerivedMesh with the same layer stack configuration as the * given DerivedMesh and containing the requested numbers of elements. diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h new file mode 100644 index 00000000000..90904cdfddd --- /dev/null +++ b/source/blender/blenkernel/BKE_collection.h @@ -0,0 +1,91 @@ +/* + * ***** 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): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_COLLECTION_H__ +#define __BKE_COLLECTION_H__ + +/** \file blender/blenkernel/BKE_collection.h + * \ingroup bke + */ + +#include "BLI_ghash.h" +#include "BLI_iterator.h" +#include "DNA_listBase.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Iterator; +struct SceneCollection; +struct Object; +struct Base; +struct Main; +struct Scene; + +struct SceneCollection *BKE_collection_add(struct Scene *scene, struct SceneCollection *sc_parent, const char *name); +bool BKE_collection_remove(struct Scene *scene, struct SceneCollection *sc); +struct SceneCollection *BKE_collection_master(struct Scene *scene); +void BKE_collection_master_free(struct Scene *scene); +void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc, struct Object *object); +void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst); +void BKE_collection_object_remove(struct Main *bmain, struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us); +void BKE_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us); + +typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data); +typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data); + +void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data); +void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data); + +/* iterators */ +void BKE_scene_collections_Iterator_begin(struct Iterator *iter, void *data_in); +void BKE_scene_collections_Iterator_next(struct Iterator *iter); +void BKE_scene_collections_Iterator_end(struct Iterator *iter); + +void BKE_scene_objects_Iterator_begin(struct Iterator *iter, void *data_in); +void BKE_scene_objects_Iterator_next(struct Iterator *iter); +void BKE_scene_objects_Iterator_end(struct Iterator *iter); + +#define FOREACH_SCENE_COLLECTION(scene, _sc) \ + ITER_BEGIN(BKE_scene_collections_Iterator_begin, \ + BKE_scene_collections_Iterator_next, \ + BKE_scene_collections_Iterator_end, \ + scene, SceneCollection, _sc) + +#define FOREACH_SCENE_COLLECTION_END \ + ITER_END + +#define FOREACH_SCENE_OBJECT(scene, _ob) \ + ITER_BEGIN(BKE_scene_objects_Iterator_begin, \ + BKE_scene_objects_Iterator_next, \ + BKE_scene_objects_Iterator_end, \ + scene, Object, _ob) + +#define FOREACH_SCENE_OBJECT_END \ + ITER_END + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_COLLECTION_H__ */ diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 4da6a61cbfa..23f9ff28f8b 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -40,12 +40,16 @@ extern "C" { struct ARegion; struct bScreen; struct CacheFile; +struct LayerCollection; struct ListBase; struct Main; struct Object; +struct Base; struct PointerRNA; struct ReportList; struct Scene; +struct SceneCollection; +struct SceneLayer; struct ScrArea; struct SpaceLink; struct View3D; @@ -166,6 +170,7 @@ struct SpaceAction *CTX_wm_space_action(const bContext *C); struct SpaceInfo *CTX_wm_space_info(const bContext *C); struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C); struct SpaceClip *CTX_wm_space_clip(const bContext *C); +struct SpaceCollections *CTX_wm_space_collections(const bContext *C); void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm); void CTX_wm_window_set(bContext *C, struct wmWindow *win); @@ -239,6 +244,9 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas struct Main *CTX_data_main(const bContext *C); struct Scene *CTX_data_scene(const bContext *C); +struct LayerCollection *CTX_data_layer_collection(const bContext *C); +struct SceneCollection *CTX_data_scene_collection(const bContext *C); +struct SceneLayer *CTX_data_scene_layer(const bContext *C); struct ToolSettings *CTX_data_tool_settings(const bContext *C); const char *CTX_data_mode_string(const bContext *C); diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 09a069ee36f..f718e9c8555 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -33,6 +33,7 @@ * \author nzc */ +struct BaseLegacy; struct Base; struct EvaluationContext; struct Group; @@ -44,8 +45,8 @@ void BKE_group_free(struct Group *group); struct Group *BKE_group_add(struct Main *bmain, const char *name); struct Group *BKE_group_copy(struct Main *bmain, struct Group *group); void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local); -bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); -bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); +bool BKE_group_object_add(struct Group *group, struct Object *ob); +bool BKE_group_object_unlink(struct Group *group, struct Object *ob); struct Group *BKE_group_object_find(struct Group *group, struct Object *ob); bool BKE_group_object_exists(struct Group *group, struct Object *ob); bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group); diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h new file mode 100644 index 00000000000..9bee353bb3a --- /dev/null +++ b/source/blender/blenkernel/BKE_layer.h @@ -0,0 +1,221 @@ +/* + * ***** 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): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_LAYER_H__ +#define __BKE_LAYER_H__ + +/** \file blender/blenkernel/BKE_layer.h + * \ingroup bke + */ + +#include "BKE_collection.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TODO_LAYER_SYNC /* syncing of SceneCollection and LayerCollection trees*/ +#define TODO_LAYER_SYNC_FILTER /* syncing of filter_objects across all trees */ +#define TODO_LAYER_OVERRIDE /* CollectionOverride */ +#define TODO_LAYER_CONTEXT /* get/set current (context) SceneLayer */ +#define TODO_LAYER_BASE /* BaseLegacy to Base related TODO */ +#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */ +#define TODO_LAYER_DEPSGRAPH /* placeholder for real Depsgraph fix */ +#define TODO_LAYER /* generic todo */ + +struct CollectionEngineSettings; +struct LayerCollection; +struct ID; +struct ListBase; +struct Main; +struct Object; +struct Base; +struct RenderEngine; +struct Scene; +struct SceneCollection; +struct SceneLayer; + +struct SceneLayer *BKE_scene_layer_active(struct Scene *scene); +struct SceneLayer *BKE_scene_layer_add(struct Scene *scene, const char *name); + +bool BKE_scene_layer_remove(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl); + +void BKE_scene_layer_free(struct SceneLayer *sl); + +void BKE_scene_layer_engine_set(struct SceneLayer *sl, const char *engine); + +void BKE_scene_layer_selected_objects_tag(struct SceneLayer *sl, const int tag); + +struct SceneLayer *BKE_scene_layer_find_from_collection(struct Scene *scene, struct LayerCollection *lc); +struct Base *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob); +void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl); +void BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase); +void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl); + +void BKE_scene_layer_engine_settings_recalculate(struct SceneLayer *sl); +void BKE_scene_layer_engine_settings_object_recalculate(struct SceneLayer *sl, struct Object *ob); +void BKE_scene_layer_engine_settings_collection_recalculate(struct SceneLayer *sl, struct LayerCollection *lc); +void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl, const char *engine_name); + +void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc); + +struct LayerCollection *BKE_layer_collection_active(struct SceneLayer *sl); + +int BKE_layer_collection_count(struct SceneLayer *sl); + +int BKE_layer_collection_findindex(struct SceneLayer *sl, struct LayerCollection *lc); + +struct LayerCollection *BKE_collection_link(struct SceneLayer *sl, struct SceneCollection *sc); + +void BKE_collection_unlink(struct SceneLayer *sl, struct LayerCollection *lc); + +bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc); +bool BKE_scene_has_object(struct Scene *scene, struct Object *ob); + +/* syncing */ + +void BKE_layer_sync_new_scene_collection(struct Scene *scene, const struct SceneCollection *sc_parent, struct SceneCollection *sc); +void BKE_layer_sync_object_link(struct Scene *scene, struct SceneCollection *sc, struct Object *ob); +void BKE_layer_sync_object_unlink(struct Scene *scene, struct SceneCollection *sc, struct Object *ob); + +/* override */ + +void BKE_collection_override_datablock_add(struct LayerCollection *lc, const char *data_path, struct ID *id); + +/* engine settings */ +typedef void (*CollectionEngineSettingsCB)(struct RenderEngine *engine, struct CollectionEngineSettings *ces); +struct CollectionEngineSettings *BKE_layer_collection_engine_get(struct LayerCollection *lc, const char *engine_name); +void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, CollectionEngineSettingsCB func); +void BKE_layer_collection_engine_settings_callback_free(void); + +struct CollectionEngineSettings *BKE_layer_collection_engine_settings_create(const char *engine_name); +void BKE_layer_collection_engine_settings_free(struct CollectionEngineSettings *ces); + +void BKE_collection_engine_property_add_float(struct CollectionEngineSettings *ces, const char *name, float value); +void BKE_collection_engine_property_add_int(struct CollectionEngineSettings *ces, const char *name, int value); +struct CollectionEngineProperty *BKE_collection_engine_property_get(struct CollectionEngineSettings *ces, const char *name); +int BKE_collection_engine_property_value_get_int(struct CollectionEngineSettings *ces, const char *name); +float BKE_collection_engine_property_value_get_float(struct CollectionEngineSettings *ces, const char *name); +void BKE_collection_engine_property_value_set_int(struct CollectionEngineSettings *ces, const char *name, int value); +void BKE_collection_engine_property_value_set_float(struct CollectionEngineSettings *ces, const char *name, float value); +bool BKE_collection_engine_property_use_get(struct CollectionEngineSettings *ces, const char *name); +void BKE_collection_engine_property_use_set(struct CollectionEngineSettings *ces, const char *name, bool value); + +/* iterators */ + +void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in); +void BKE_selected_objects_Iterator_next(Iterator *iter); +void BKE_selected_objects_Iterator_end(Iterator *iter); + +void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in); +void BKE_visible_objects_Iterator_next(Iterator *iter); +void BKE_visible_objects_Iterator_end(Iterator *iter); + +void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in); +void BKE_visible_bases_Iterator_next(Iterator *iter); +void BKE_visible_bases_Iterator_end(Iterator *iter); + +#define FOREACH_SELECTED_OBJECT(sl, _ob) \ + ITER_BEGIN(BKE_selected_objects_Iterator_begin, \ + BKE_selected_objects_Iterator_next, \ + BKE_selected_objects_Iterator_end, \ + sl, Object, _ob) + +#define FOREACH_SELECTED_OBJECT_END \ + ITER_END + +#define FOREACH_VISIBLE_OBJECT(sl, _ob) \ + ITER_BEGIN(BKE_visible_objects_Iterator_begin, \ + BKE_visible_objects_Iterator_next, \ + BKE_visible_objects_Iterator_end, \ + sl, Object, _ob) + +#define FOREACH_VISIBLE_OBJECT_END \ + ITER_END + + +#define FOREACH_VISIBLE_BASE(sl, _object_base) \ + ITER_BEGIN(BKE_visible_bases_Iterator_begin, \ + BKE_visible_bases_Iterator_next, \ + BKE_visible_bases_Iterator_end, \ + sl, Base, _object_base) + +#define FOREACH_VISIBLE_BASE_END \ + ITER_END + + +#define FOREACH_OBJECT(sl, _ob) \ +{ \ + Base *base; \ + for (base = sl->object_bases.first; base; base = base->next) { \ + _ob = base->object; + +#define FOREACH_OBJECT_END \ + } \ +} + +#define FOREACH_OBJECT_FLAG(scene, sl, flag, _ob) \ +{ \ + IteratorBeginCb func_begin; \ + IteratorCb func_next, func_end; \ + void *data_in; \ + \ + if (flag == SELECT) { \ + func_begin = &BKE_selected_objects_Iterator_begin; \ + func_next = &BKE_selected_objects_Iterator_next; \ + func_end = &BKE_selected_objects_Iterator_end; \ + data_in = sl; \ + } \ + else { \ + func_begin = BKE_scene_objects_Iterator_begin; \ + func_next = BKE_scene_objects_Iterator_next; \ + func_end = BKE_scene_objects_Iterator_end; \ + data_in = scene; \ + } \ + ITER_BEGIN(func_begin, func_next, func_end, data_in, Object, _ob) + + +#define FOREACH_OBJECT_FLAG_END \ + ITER_END \ +} + +/* temporary hacky solution waiting for final depsgraph evaluation */ +#define DEG_OBJECT_ITER(sl_, engine_name_, ob_) \ +{ \ + /* temporary solution, waiting for depsgraph update */ \ + BKE_scene_layer_engine_settings_update(sl, engine_name_); \ + \ + /* flush all the data to objects*/ \ + Base *base_; \ + for (base_ = sl->object_bases.first; base_; base_ = base_->next) { \ + ob_ = base_->object; \ + ob_->base_flag = base_->flag; + +#define DEG_OBJECT_ITER_END \ + } \ +} + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_LAYER_H__ */ diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 2d9c35f7fd0..72ae2cf4efa 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -86,7 +86,7 @@ bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const boo bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop); bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test); void id_sort_by_name(struct ListBase *lb, struct ID *id); -void BKE_id_expand_local(struct ID *id); +void BKE_id_expand_local(struct Main *bmain, struct ID *id); void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id); bool new_id(struct ListBase *lb, struct ID *id, const char *name); @@ -105,6 +105,9 @@ void BKE_main_free(struct Main *mainvar); void BKE_main_lock(struct Main *bmain); void BKE_main_unlock(struct Main *bmain); +void BKE_main_relations_create(struct Main *bmain); +void BKE_main_relations_free(struct Main *bmain); + struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img); struct ImBuf *BKE_main_thumbnail_to_imbuf(struct Main *bmain, struct BlendThumbnail *data); void BKE_main_thumbnail_create(struct Main *bmain); diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h index a7470107c24..1258e2fa72e 100644 --- a/source/blender/blenkernel/BKE_library_query.h +++ b/source/blender/blenkernel/BKE_library_query.h @@ -36,25 +36,28 @@ struct Main; /* Tips for the callback for cases it's gonna to modify the pointer. */ enum { - IDWALK_NOP = 0, - IDWALK_NEVER_NULL = (1 << 0), - IDWALK_NEVER_SELF = (1 << 1), + IDWALK_CB_NOP = 0, + IDWALK_CB_NEVER_NULL = (1 << 0), + IDWALK_CB_NEVER_SELF = (1 << 1), /** * Indicates whether this is direct (i.e. by local data) or indirect (i.e. by linked data) usage. * \note Object proxies are half-local, half-linked... */ - IDWALK_INDIRECT_USAGE = (1 << 2), + IDWALK_CB_INDIRECT_USAGE = (1 << 2), + + /** That ID is used as mere sub-data by its owner + * (only case currently: those f***ing nodetrees in materials etc.). + * This means callback shall not *do* anything, only use this as informative data if it needs it. */ + IDWALK_CB_PRIVATE = (1 << 3), /** * Adjusts #ID.us reference-count. * \note keep in sync with 'newlibadr_us' use in readfile.c */ - IDWALK_USER = (1 << 8), - /** - * Ensure #ID.us is at least 1 on use. - */ - IDWALK_USER_ONE = (1 << 9), + IDWALK_CB_USER = (1 << 8), + /** Ensure #ID.us is at least 1 on use. */ + IDWALK_CB_USER_ONE = (1 << 9), }; enum { @@ -68,17 +71,19 @@ enum { * * \return a set of flags to control further iteration (0 to keep going). */ -typedef int (*LibraryIDLinkCallback) (void *user_data, struct ID *id_self, struct ID **id_pointer, int cd_flag); +typedef int (*LibraryIDLinkCallback) (void *user_data, struct ID *id_self, struct ID **id_pointer, int cb_flag); /* Flags for the foreach function itself. */ enum { + IDWALK_NOP = 0, IDWALK_READONLY = (1 << 0), IDWALK_RECURSE = (1 << 1), /* Also implies IDWALK_READONLY. */ }; /* Loop over all of the ID's this datablock links to. */ -void BKE_library_foreach_ID_link(struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag); -void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cd_flag); +void BKE_library_foreach_ID_link( + struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag); +void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cb_flag); int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used); diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index a4f5c425282..387045878f3 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -51,6 +51,8 @@ extern "C" { struct EvaluationContext; struct Library; struct MainLock; +struct GHash; +struct BLI_mempool; /* Blender thumbnail, as written on file (width, height, and data as char RGBA). */ /* We pack pixel data after that struct. */ @@ -59,6 +61,22 @@ typedef struct BlendThumbnail { char rect[0]; } BlendThumbnail; +/* Structs caching relations between data-blocks in a given Main. */ +typedef struct MainIDRelationsEntry { + struct MainIDRelationsEntry *next; + /* WARNING! for user_to_used, that pointer is really an ID** one, but for used_to_user, it’s only an ID* one! */ + struct ID **id_pointer; + int usage_flag; /* Using IDWALK_ enums, in BKE_library_query.h */ +} MainIDRelationsEntry; + +typedef struct MainIDRelations { + struct GHash *id_user_to_used; + struct GHash *id_used_to_user; + + /* Private... */ + struct BLI_mempool *entry_pool; +} MainIDRelations; + typedef struct Main { struct Main *next, *prev; char name[1024]; /* 1024 = FILE_MAX */ @@ -111,6 +129,11 @@ typedef struct Main { /* Evaluation context used by viewport */ struct EvaluationContext *eval_ctx; + /* Must be generated, used and freed by same code - never assume this is valid data unless you know + * when, who and how it was created. + * Used by code doing a lot of remapping etc. at once to speed things up. */ + struct MainIDRelations *relations; + struct MainLock *lock; } Main; diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 92b186d7329..7a522cba282 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -106,8 +106,8 @@ typedef enum { } ModifierTypeFlag; /* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */ -typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cd_flag); -typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cd_flag); +typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cb_flag); +typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag); typedef void (*TexWalkFunc)(void *userData, struct Object *ob, struct ModifierData *md, const char *propname); typedef enum ModifierApplyFlag { diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 546f0d97c2b..67f7fa5e029 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -687,6 +687,13 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Node Tree + */ + +void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, const int layer_index); + /* -------------------------------------------------------------------- */ /** \name Shader Nodes */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 3f1c6bae75c..4dd9e01ba32 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -35,12 +35,13 @@ extern "C" { #include "BLI_compiler_attrs.h" -struct Base; +struct BaseLegacy; struct EvaluationContext; struct Scene; struct Object; struct BoundBox; struct View3D; +struct SceneLayer; struct SoftBody; struct BulletSoftBody; struct MovieClip; @@ -89,9 +90,9 @@ struct Object *BKE_object_add_only_object( int type, const char *name) ATTR_NONNULL(1) ATTR_RETURNS_NONNULL; struct Object *BKE_object_add( - struct Main *bmain, struct Scene *scene, + struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, int type, const char *name) - ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL; + ATTR_NONNULL(1, 2, 3) ATTR_RETURNS_NONNULL; void *BKE_object_obdata_add_from_type( struct Main *bmain, int type, const char *name) @@ -136,14 +137,9 @@ void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float /* possibly belong in own moduke? */ struct BoundBox *BKE_boundbox_alloc_unit(void); void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3]); -bool BKE_boundbox_ray_hit_check( - const struct BoundBox *bb, - const float ray_start[3], const float ray_normal[3], - float *r_lambda); void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]); void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]); void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]); -void BKE_boundbox_scale(struct BoundBox *bb_dst, const struct BoundBox *bb_src, float scale); struct BoundBox *BKE_boundbox_ensure_minimum_dimensions( struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon); @@ -260,7 +256,7 @@ typedef enum eObjectSet { struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); struct LinkNode *BKE_object_groups(struct Object *ob); -void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object); +void BKE_object_groups_clear(struct Object *object); struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index b3e3968ca9b..e5967be0bc7 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -384,7 +384,7 @@ void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleDa void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params); /* Callback format for performing operations on ID-pointers for particle systems */ -typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cd_flag); +typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cb_flag); void BKE_particlesystem_id_loop(struct ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata); diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index 965a97f08ba..443c3b2b5b2 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -53,7 +53,7 @@ struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob); struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob); /* Callback format for performing operations on ID-pointers for rigidbody world. */ -typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cd_flag); +typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cb_flag); void BKE_rigidbody_world_id_loop(struct RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata); diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h index a504f1bac3d..1579a0c7bb3 100644 --- a/source/blender/blenkernel/BKE_sca.h +++ b/source/blender/blenkernel/BKE_sca.h @@ -77,9 +77,9 @@ void sca_move_controller(struct bController *cont_to_move, struct Object *ob, in void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up); /* Callback format for performing operations on ID-pointers for sensors/controllers/actuators. */ -typedef void (*SCASensorIDFunc)(struct bSensor *sensor, struct ID **idpoin, void *userdata, int cd_flag); -typedef void (*SCAControllerIDFunc)(struct bController *controller, struct ID **idpoin, void *userdata, int cd_flag); -typedef void (*SCAActuatorIDFunc)(struct bActuator *actuator, struct ID **idpoin, void *userdata, int cd_flag); +typedef void (*SCASensorIDFunc)(struct bSensor *sensor, struct ID **idpoin, void *userdata, int cb_flag); +typedef void (*SCAControllerIDFunc)(struct bController *controller, struct ID **idpoin, void *userdata, int cb_flag); +typedef void (*SCAActuatorIDFunc)(struct bActuator *actuator, struct ID **idpoin, void *userdata, int cb_flag); void BKE_sca_sensors_id_loop(struct ListBase *senslist, SCASensorIDFunc func, void *userdata); void BKE_sca_controllers_id_loop(struct ListBase *contlist, SCAControllerIDFunc func, void *userdata); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index d2152950bff..181d4b12703 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -38,14 +38,16 @@ extern "C" { #endif struct AviCodecData; -struct Base; +struct BaseLegacy; struct EvaluationContext; struct Main; struct Object; +struct Base; struct QuicktimeCodecData; struct RenderData; struct SceneRenderLayer; struct Scene; +struct SceneLayer; struct UnitSettings; struct Main; @@ -61,7 +63,7 @@ struct Main; _base; \ _base = _setlooper_base_step(&_sce_iter, _base) -struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base); +struct BaseLegacy *_setlooper_base_step(struct Scene **sce_iter, struct BaseLegacy *base); void free_avicodecdata(struct AviCodecData *acd); void free_qtcodecdata(struct QuicktimeCodecData *acd); @@ -70,13 +72,15 @@ void BKE_scene_free(struct Scene *sce); void BKE_scene_init(struct Scene *sce); struct Scene *BKE_scene_add(struct Main *bmain, const char *name); +void BKE_scene_remove_rigidbody_object(struct Scene *scene, struct Object *ob); + /* base functions */ -struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name); -struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob); -struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob); -void BKE_scene_base_unlink(struct Scene *sce, struct Base *base); +struct BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name); +struct BaseLegacy *BKE_scene_base_find(struct Scene *scene, struct Object *ob); +struct BaseLegacy *BKE_scene_base_add(struct Scene *sce, struct Object *ob); +void BKE_scene_base_unlink(struct Scene *sce, struct BaseLegacy *base); void BKE_scene_base_deselect_all(struct Scene *sce); -void BKE_scene_base_select(struct Scene *sce, struct Base *selbase); +void BKE_scene_base_select(struct Scene *sce, struct BaseLegacy *selbase); /* Scene base iteration function. * Define struct here, so no need to bother with alloc/free it. @@ -90,10 +94,14 @@ typedef struct SceneBaseIter { } SceneBaseIter; int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter, - struct Scene **scene, int val, struct Base **base, struct Object **ob); + struct Scene **scene, int val, struct BaseLegacy **base, struct Object **ob); -void BKE_scene_base_flag_to_objects(struct Scene *scene); +void BKE_scene_base_flag_to_objects(struct SceneLayer *sl); void BKE_scene_base_flag_from_objects(struct Scene *scene); +void BKE_scene_base_flag_sync_from_base(struct BaseLegacy *base); +void BKE_scene_base_flag_sync_from_object(struct BaseLegacy *base); +void BKE_scene_object_base_flag_sync_from_base(struct Base *base); +void BKE_scene_object_base_flag_sync_from_object(struct Base *base); void BKE_scene_set_background(struct Main *bmain, struct Scene *sce); struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 1c5ea946f59..9a60eb29957 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -42,6 +42,7 @@ struct Brush; struct ColorBand; struct EnvMap; struct FreestyleLineStyle; +struct ImagePool; struct Lamp; struct Main; struct Material; @@ -133,6 +134,12 @@ struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot); bool BKE_texture_dependsOnTime(const struct Tex *texture); bool BKE_texture_is_image_user(const struct Tex *tex); +void BKE_texture_get_value_ex( + const struct Scene *scene, struct Tex *texture, + float *tex_co, struct TexResult *texres, + struct ImagePool *pool, + bool use_color_management); + void BKE_texture_get_value( const struct Scene *scene, struct Tex *texture, float *tex_co, struct TexResult *texres, bool use_color_management); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index f3bab55b47d..6202c84f320 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -85,6 +85,7 @@ set(SRC intern/camera.c intern/cdderivedmesh.c intern/cloth.c + intern/collection.c intern/collision.c intern/colortools.c intern/constraint.c @@ -157,6 +158,7 @@ set(SRC intern/pbvh_bmesh.c intern/pointcache.c intern/property.c + intern/layer.c intern/report.c intern/rigidbody.c intern/sca.c @@ -214,6 +216,7 @@ set(SRC BKE_ccg.h BKE_cdderivedmesh.h BKE_cloth.h + BKE_collection.h BKE_collision.h BKE_colortools.h BKE_constraint.h @@ -274,6 +277,7 @@ set(SRC BKE_pbvh.h BKE_pointcache.h BKE_property.h + BKE_layer.h BKE_report.h BKE_rigidbody.h BKE_sca.h diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index e0bbe345fc4..39f1db0b886 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2216,6 +2216,12 @@ static void mesh_calc_modifiers( } } + /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them, + * as they are used by display code when available (i.e. even if autosmooth is disabled). */ + if (!do_loop_normals && CustomData_has_layer(&finaldm->loopData, CD_NORMAL)) { + CustomData_free_layers(&finaldm->loopData, CD_NORMAL, finaldm->numLoopData); + } + #ifdef WITH_GAMEENGINE /* NavMesh - this is a hack but saves having a NavMesh modifier */ if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) { @@ -2551,6 +2557,15 @@ static void editbmesh_calc_modifiers( /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */ if (!do_loop_normals) { dm_ensure_display_normals(*r_final); + + /* Some modifiers, like datatransfer, may generate those data, we do not want to keep them, + * as they are used by display code when available (i.e. even if autosmooth is disabled). */ + if (CustomData_has_layer(&(*r_final)->loopData, CD_NORMAL)) { + CustomData_free_layers(&(*r_final)->loopData, CD_NORMAL, (*r_final)->numLoopData); + } + if (r_cage && CustomData_has_layer(&(*r_cage)->loopData, CD_NORMAL)) { + CustomData_free_layers(&(*r_cage)->loopData, CD_NORMAL, (*r_cage)->numLoopData); + } } /* add an orco layer if needed */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 2f65e71c6d2..237e4e80172 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -283,7 +283,7 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets) /* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) { - Base *base, *baseNext; + BaseLegacy *base, *baseNext; MPathTarget *mpt; /* make sure our temp-tag isn't already in use */ @@ -321,7 +321,7 @@ static void motionpaths_calc_update_scene(Scene *scene) BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay); } else { /* otherwise we can optimize by restricting updates */ - Base *base, *last = NULL; + BaseLegacy *base, *last = NULL; /* only stuff that moves or needs display still */ DAG_scene_update_flags(G.main, scene, scene->lay, true, false); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 89e93a6384d..2565eb1900c 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1037,6 +1037,17 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float if (use_dverts) { defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone"); defnrToPCIndex = MEM_callocN(sizeof(*defnrToPCIndex) * defbase_tot, "defnrToIndex"); + /* TODO(sergey): Some considerations here: + * + * - Make it more generic function, maybe even keep together with chanhash. + * - Check whether keeping this consistent across frames gives speedup. + * - Don't use hash for small armatures. + */ + GHash *idx_hash = BLI_ghash_ptr_new("pose channel index by name"); + int pchan_index = 0; + for (pchan = armOb->pose->chanbase.first; pchan != NULL; pchan = pchan->next, ++pchan_index) { + BLI_ghash_insert(idx_hash, pchan, SET_INT_IN_POINTER(pchan_index)); + } for (i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) { defnrToPC[i] = BKE_pose_channel_find_name(armOb->pose, dg->name); /* exclude non-deforming bones */ @@ -1045,10 +1056,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float defnrToPC[i] = NULL; } else { - defnrToPCIndex[i] = BLI_findindex(&armOb->pose->chanbase, defnrToPC[i]); + defnrToPCIndex[i] = GET_INT_FROM_POINTER(BLI_ghash_lookup(idx_hash, defnrToPC[i])); } } } + BLI_ghash_free(idx_hash, NULL, NULL); } } } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index a8670395fc4..afd60102453 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -234,7 +234,7 @@ int BKE_blender_test_break(void) * \note Don't use MEM_mallocN so functions can be registered at any time. * \{ */ -struct AtExitData { +static struct AtExitData { struct AtExitData *next; void (*func)(void *user_data); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 0d509ecea06..57b707a31d3 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -239,7 +239,7 @@ void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local) if (lib_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &brush->id); - BKE_id_expand_local(&brush->id); + BKE_id_expand_local(bmain, &brush->id); /* enable fake user by default */ id_fake_user_set(&brush->id); diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 264d87b86f3..d0e0c82e3be 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -376,6 +376,45 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r } } +#define V3_MUL_ELEM(a, b) \ + (a)[0] * (b)[0], \ + (a)[1] * (b)[1], \ + (a)[2] * (b)[2] + +/* Callback to bvh tree nearest edge to ray. + * The tree must have been built using bvhtree_from_mesh_edges. + * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */ +static void mesh_edges_nearest_to_ray( + void *userdata, const float ray_co[3], const float ray_dir[3], + const float scale[3], int index, BVHTreeNearest *nearest) +{ + struct BVHTreeFromMesh *data = userdata; + const MVert *vert = data->vert; + const MEdge *e = &data->edge[index]; + + const float t0[3] = {V3_MUL_ELEM(vert[e->v1].co, scale)}; + const float t1[3] = {V3_MUL_ELEM(vert[e->v2].co, scale)}; + const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; + const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)}; + + float depth, point[3]; + const float dist_sq = dist_squared_ray_to_seg_v3(origin_sc, dir_sc, t0, t1, point, &depth); + + if (dist_sq < nearest->dist_sq) { + nearest->dist_sq = dist_sq; + nearest->index = index; + + point[0] /= scale[0]; + point[1] /= scale[1]; + point[2] /= scale[2]; + + copy_v3_v3(nearest->co, point); + sub_v3_v3v3(nearest->no, t0, t1); + } +} + +#undef V3_MUL_ELEM + /** \} */ /* @@ -393,8 +432,6 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree( BMEditMesh *em, const int verts_num, const BLI_bitmap *verts_mask, int verts_num_active) { - BVHTree *tree = NULL; - int i; BM_mesh_elem_table_ensure(em->bm, BM_VERT); if (verts_mask) { BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); @@ -403,15 +440,14 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree( verts_num_active = verts_num; } - tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis); + BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis); if (tree) { - BMIter iter; - BMVert *eve; - BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + for (int i = 0; i < verts_num; i++) { if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) { continue; } + BMVert *eve = BM_vert_at_index(em->bm, i); BLI_bvhtree_insert(tree, i, eve->co, 1); } BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active); @@ -426,28 +462,25 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree( MVert *vert, const int verts_num, const BLI_bitmap *verts_mask, int verts_num_active) { - BVHTree *tree = NULL; - int i; - if (vert) { - if (verts_mask) { - BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); - } - else { - verts_num_active = verts_num; - } + BLI_assert(vert != NULL); + if (verts_mask) { + BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); + } + else { + verts_num_active = verts_num; + } - tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis); + BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis); - if (tree) { - for (i = 0; i < verts_num; i++) { - if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) { - continue; - } - BLI_bvhtree_insert(tree, i, vert[i].co, 1); + if (tree) { + for (int i = 0; i < verts_num; i++) { + if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) { + continue; } - BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active); - BLI_bvhtree_balance(tree); + BLI_bvhtree_insert(tree, i, vert[i].co, 1); } + BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active); + BLI_bvhtree_balance(tree); } return tree; @@ -488,11 +521,9 @@ BVHTree *bvhtree_from_editmesh_verts_ex( const BLI_bitmap *verts_mask, int verts_num_active, float epsilon, int tree_type, int axis) { - int vert_num = em->bm->totvert; - BVHTree *tree = bvhtree_from_editmesh_verts_create_tree( epsilon, tree_type, axis, - em, vert_num, verts_mask, verts_num_active); + em, em->bm->totvert, verts_mask, verts_num_active); if (tree) { memset(data, 0, sizeof(*data)); @@ -505,6 +536,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex( return tree; } + BVHTree *bvhtree_from_editmesh_verts( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) @@ -515,8 +547,8 @@ BVHTree *bvhtree_from_editmesh_verts( epsilon, tree_type, axis); } - -/* Builds a bvh tree where nodes are the vertices of the given dm */ +/* Builds a bvh tree where nodes are the vertices of the given dm + * and stores the BVHTree in dm->bvhCache */ BVHTree *bvhtree_from_mesh_verts( BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis) @@ -557,7 +589,8 @@ BVHTree *bvhtree_from_mesh_verts( } /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated); + bvhtree_from_mesh_verts_setup_data( + data, tree, true, epsilon, vert, vert_allocated); return data->tree; } @@ -577,7 +610,8 @@ BVHTree *bvhtree_from_mesh_verts_ex( epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active); /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_verts_setup_data(data, tree, false, epsilon, vert, vert_allocated); + bvhtree_from_mesh_verts_setup_data( + data, tree, false, epsilon, vert, vert_allocated); return data->tree; } @@ -595,8 +629,6 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree( BMEditMesh *em, const int edges_num, const BLI_bitmap *edges_mask, int edges_num_active) { - BVHTree *tree = NULL; - int i; BM_mesh_elem_table_ensure(em->bm, BM_EDGE); if (edges_mask) { BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edges_num)); @@ -605,9 +637,10 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree( edges_num_active = edges_num; } - tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis); + BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis); if (tree) { + int i; BMIter iter; BMEdge *eed; BM_ITER_MESH_INDEX (eed, &iter, em->bm, BM_EDGES_OF_MESH, i) { @@ -627,6 +660,70 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree( return tree; } +static BVHTree *bvhtree_from_mesh_edges_create_tree( + MVert *vert, MEdge *edge, const int edge_num, + const BLI_bitmap *edges_mask, int edges_num_active, + float epsilon, int tree_type, int axis) +{ + if (edges_mask) { + BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edge_num)); + } + else { + edges_num_active = edge_num; + } + BLI_assert(vert != NULL); + BLI_assert(edge != NULL); + + /* Create a bvh-tree of the given target */ + BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis); + if (tree) { + for (int i = 0; i < edge_num; i++) { + if (edges_mask && !BLI_BITMAP_TEST_BOOL(edges_mask, i)) { + continue; + } + float co[2][3]; + copy_v3_v3(co[0], vert[edge[i].v1].co); + copy_v3_v3(co[1], vert[edge[i].v2].co); + + BLI_bvhtree_insert(tree, i, co[0], 2); + } + BLI_bvhtree_balance(tree); + } + + return tree; +} + +static void bvhtree_from_mesh_edges_setup_data( + BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon, + MVert *vert, const bool vert_allocated, MEdge *edge, const bool edge_allocated) +{ + memset(data, 0, sizeof(*data)); + data->tree = tree; + + if (data->tree) { + data->cached = is_cached; + + data->nearest_callback = mesh_edges_nearest_point; + data->raycast_callback = mesh_edges_spherecast; + data->nearest_to_ray_callback = mesh_edges_nearest_to_ray; + + data->vert = vert; + data->vert_allocated = vert_allocated; + data->edge = edge; + data->edge_allocated = edge_allocated; + + data->sphere_radius = epsilon; + } + else { + if (vert_allocated) { + MEM_freeN(vert); + } + if (edge_allocated) { + MEM_freeN(edge); + } + } +} + /* Builds a bvh tree where nodes are the edges of the given em */ BVHTree *bvhtree_from_editmesh_edges_ex( BVHTreeFromEditMesh *data, BMEditMesh *em, @@ -651,6 +748,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex( return tree; } + BVHTree *bvhtree_from_editmesh_edges( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) @@ -683,27 +781,13 @@ BVHTree *bvhtree_from_mesh_edges( BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); tree = bvhcache_find(dm->bvhCache, BVHTREE_FROM_EDGES); if (tree == NULL) { - int i; - int numEdges = dm->getNumEdges(dm); - - if (vert != NULL && edge != NULL) { - /* Create a bvh-tree of the given target */ - tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis); - if (tree != NULL) { - for (i = 0; i < numEdges; i++) { - float co[2][3]; - copy_v3_v3(co[0], vert[edge[i].v1].co); - copy_v3_v3(co[1], vert[edge[i].v2].co); - - BLI_bvhtree_insert(tree, i, co[0], 2); - } - BLI_bvhtree_balance(tree); + tree = bvhtree_from_mesh_edges_create_tree( + vert, edge, dm->getNumEdges(dm), + NULL, -1, epsilon, tree_type, axis); - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES); - } - } + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES); } BLI_rw_mutex_unlock(&cache_rwlock); } @@ -711,33 +795,34 @@ BVHTree *bvhtree_from_mesh_edges( /* printf("BVHTree is already build, using cached tree\n"); */ } - /* Setup BVHTreeFromMesh */ - memset(data, 0, sizeof(*data)); - data->tree = tree; + bvhtree_from_mesh_edges_setup_data( + data, tree, true, epsilon, vert, vert_allocated, edge, edge_allocated); - if (data->tree) { - data->cached = true; + return data->tree; +} - data->nearest_callback = mesh_edges_nearest_point; - data->raycast_callback = mesh_edges_spherecast; - data->nearest_to_ray_callback = NULL; +/** + * Builds a bvh tree where nodes are the given edges . + * \param vert/edge_allocated if true, elem freeing will be done when freeing data. + * \param edges_mask if not null, true elements give which vert to add to BVH tree. + * \param edges_num_active if >= 0, number of active edges to add to BVH tree (else will be computed from mask). + */ +BVHTree *bvhtree_from_mesh_edges_ex( + BVHTreeFromMesh *data, + MVert *vert, const bool vert_allocated, + MEdge *edge, const int edges_num, const bool edge_allocated, + const BLI_bitmap *edges_mask, int edges_num_active, + float epsilon, int tree_type, int axis) +{ + BVHTree *tree = bvhtree_from_mesh_edges_create_tree( + vert, edge, edges_num, edges_mask, edges_num_active, + epsilon, tree_type, axis); - data->vert = vert; - data->vert_allocated = vert_allocated; - data->edge = edge; - data->edge_allocated = edge_allocated; + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_edges_setup_data( + data, tree, false, epsilon, vert, vert_allocated, edge, edge_allocated); - data->sphere_radius = epsilon; - } - else { - if (vert_allocated) { - MEM_freeN(vert); - } - if (edge_allocated) { - MEM_freeN(edge); - } - } return data->tree; } diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index deeb35bd880..8630e8562b0 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -205,7 +205,7 @@ float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const f /* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file) { - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { Object *ob = base->object; ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); @@ -215,7 +215,9 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file) if (cache_file == mcmd->cache_file) { #ifdef WITH_ALEMBIC - CacheReader_free(mcmd->reader); + if (mcmd->reader != NULL) { + CacheReader_free(mcmd->reader); + } #endif mcmd->reader = NULL; mcmd->object_path[0] = '\0'; @@ -231,7 +233,9 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file) if (cache_file == data->cache_file) { #ifdef WITH_ALEMBIC - CacheReader_free(data->reader); + if (data->reader != NULL) { + CacheReader_free(data->reader); + } #endif data->reader = NULL; data->object_path[0] = '\0'; diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 9cb553aa27b..978204f1cf5 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -853,7 +853,7 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha } if (name[0] != '\0') { - Base *base = BKE_scene_base_find_by_name(scene, name); + BaseLegacy *base = BKE_scene_base_find_by_name(scene, name); if (base) { return base->object; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index f2dd2a3fcf6..483fa977aff 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2398,21 +2398,28 @@ DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps, const bo use_tessface, em->tottri, (const BMLoop *(*)[3])em->looptris); } -static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) +static DerivedMesh *cddm_copy_ex(DerivedMesh *source, + const bool need_tessface_data, + const bool faces_from_tessfaces) { + const bool copy_tessface_data = (faces_from_tessfaces || need_tessface_data); CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); DerivedMesh *dm = &cddm->dm; int numVerts = source->numVertData; int numEdges = source->numEdgeData; - int numTessFaces = source->numTessFaceData; + int numTessFaces = copy_tessface_data ? source->numTessFaceData : 0; int numLoops = source->numLoopData; int numPolys = source->numPolyData; + /* NOTE: Don't copy tessellation faces if not requested explicitly. */ + /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getTessFaceDataArray(source, CD_ORIGINDEX); source->getPolyDataArray(source, CD_ORIGINDEX); + if (copy_tessface_data) { + source->getTessFaceDataArray(source, CD_ORIGINDEX); + } /* this initializes dm, and copies all non mvert/medge/mface layers */ DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, @@ -2421,23 +2428,33 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) dm->cd_flag = source->cd_flag; dm->dirty = source->dirty; + /* Tessellation data is never copied, so tag it here. */ + dm->dirty |= DM_DIRTY_TESS_CDLAYERS; + CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges); - CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces); + if (copy_tessface_data) { + CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces); + } /* now add mvert/medge/mface layers */ cddm->mvert = source->dupVertArray(source); cddm->medge = source->dupEdgeArray(source); - cddm->mface = source->dupTessFaceArray(source); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges); - CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces); - - if (!faces_from_tessfaces) + + if (faces_from_tessfaces || copy_tessface_data) { + cddm->mface = source->dupTessFaceArray(source); + CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces); + } + + if (!faces_from_tessfaces) { DM_DupPolys(source, dm); - else + } + else { CDDM_tessfaces_to_faces(dm); + } cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); @@ -2447,12 +2464,17 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) DerivedMesh *CDDM_copy(DerivedMesh *source) { - return cddm_copy_ex(source, 0); + return cddm_copy_ex(source, false, false); } DerivedMesh *CDDM_copy_from_tessface(DerivedMesh *source) { - return cddm_copy_ex(source, 1); + return cddm_copy_ex(source, false, true); +} + +DerivedMesh *CDDM_copy_with_tessface(DerivedMesh *source) +{ + return cddm_copy_ex(source, true, false); } /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c new file mode 100644 index 00000000000..289586153ea --- /dev/null +++ b/source/blender/blenkernel/intern/collection.c @@ -0,0 +1,453 @@ +/* + * ***** 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): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/collection.c + * \ingroup bke + */ + +#include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_iterator.h" +#include "BLI_listbase.h" +#include "BLT_translation.h" +#include "BLI_string_utils.h" + +#include "BKE_collection.h" +#include "BKE_layer.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_scene.h" + +#include "DNA_ID.h" +#include "DNA_layer_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +/** + * Add a collection to a collection ListBase and syncronize all render layers + * The ListBase is NULL when the collection is to be added to the master collection + */ +SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, const char *name) +{ + SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection"); + + if (!name) { + name = DATA_("New Collection"); + } + + if (!sc_parent) { + sc_parent = sc_master; + } + + BLI_strncpy(sc->name, name, sizeof(sc->name)); + BLI_uniquename(&sc_master->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name)); + + BLI_addtail(&sc_parent->scene_collections, sc); + + BKE_layer_sync_new_scene_collection(scene, sc_parent, sc); + return sc; +} + +/** + * Free the collection items recursively + */ +static void collection_free(SceneCollection *sc) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + id_us_min(link->data); + } + BLI_freelistN(&sc->objects); + + for (LinkData *link = sc->filter_objects.first; link; link = link->next) { + id_us_min(link->data); + } + BLI_freelistN(&sc->filter_objects); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + collection_free(nsc); + } + BLI_freelistN(&sc->scene_collections); +} + +/** + * Unlink the collection recursively + * return true if unlinked + */ +static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone) +{ + for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next) + { + if (sc == sc_gone) { + BLI_remlink(&sc_parent->scene_collections, sc_gone); + return true; + } + + if (collection_remlink(sc, sc_gone)) { + return true; + } + } + return false; +} + +/** + * Recursively remove any instance of this SceneCollection + */ +static void layer_collection_remove(SceneLayer *sl, ListBase *lb, const SceneCollection *sc) +{ + LayerCollection *lc = lb->first; + while(lc) { + if (lc->scene_collection == sc) { + BKE_scene_layer_engine_settings_collection_recalculate(sl, lc); + BKE_layer_collection_free(sl, lc); + BLI_remlink(lb, lc); + + LayerCollection *lc_next = lc->next; + MEM_freeN(lc); + lc = lc_next; + + /* only the "top-level" layer collections may have the + * same SceneCollection in a sibling tree. + */ + if (lb != &sl->layer_collections) { + return; + } + } + + else { + layer_collection_remove(sl, &lc->layer_collections, sc); + lc = lc->next; + } + } +} + +/** + * Remove a collection from the scene, and syncronize all render layers + */ +bool BKE_collection_remove(Scene *scene, SceneCollection *sc) +{ + SceneCollection *sc_master = BKE_collection_master(scene); + + /* the master collection cannot be removed */ + if (sc == sc_master) { + return false; + } + + /* unlink from the respective collection tree */ + if (!collection_remlink(sc_master, sc)) { + BLI_assert(false); + } + + /* clear the collection items */ + collection_free(sc); + + /* check all layers that use this collection and clear them */ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + layer_collection_remove(sl, &sl->layer_collections, sc); + BKE_scene_layer_base_flag_recalculate(sl); + sl->active_collection = 0; + } + + MEM_freeN(sc); + return true; +} + +/** + * Returns the master collection + */ +SceneCollection *BKE_collection_master(Scene *scene) +{ + return scene->collection; +} + +/** + * Free (or release) any data used by the master collection (does not free the master collection itself). + * Used only to clear the entire scene data since it's not doing re-syncing of the LayerCollection tree + */ +void BKE_collection_master_free(Scene *scene){ + collection_free(BKE_collection_master(scene)); +} + +static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob) +{ + BLI_addtail(&sc->objects, BLI_genericNodeN(ob)); + id_us_plus((ID *)ob); + BKE_layer_sync_object_link(scene, sc, ob); +} + +/** + * Add object to collection + */ +void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob) +{ + if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) { + /* don't add the same object twice */ + return; + } + collection_object_add(scene, sc, ob); +} + +/** + * Add object to all collections that reference objects is in + * (used to copy objects) + */ +void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst) +{ + SceneCollection *sc; + FOREACH_SCENE_COLLECTION(scene, sc) + { + if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) { + collection_object_add(scene, sc, ob_dst); + } + } + FOREACH_SCENE_COLLECTION_END +} + +/** + * Remove object from collection + */ +void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc, Object *ob, const bool free_us) +{ + + LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data)); + + if (link == NULL) { + return; + } + + BLI_remlink(&sc->objects, link); + MEM_freeN(link); + + TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */ + BKE_layer_sync_object_unlink(scene, sc, ob); + + if (free_us) { + BKE_libblock_free_us(bmain, ob); + } + else { + id_us_min(&ob->id); + } +} + +/** + * Remove object from all collections of scene + */ +void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us) +{ + BKE_scene_remove_rigidbody_object(scene, ob); + + SceneCollection *sc; + FOREACH_SCENE_COLLECTION(scene, sc) + { + BKE_collection_object_remove(bmain, scene, sc, ob, free_us); + } + FOREACH_SCENE_COLLECTION_END +} + +/* ---------------------------------------------------------------------- */ +/* Iteractors */ +/* scene collection iteractor */ + +typedef struct SceneCollectionsIteratorData { + Scene *scene; + void **array; + int tot, cur; + } SceneCollectionsIteratorData; + +static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data) +{ + callback(sc, data); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + scene_collection_callback(nsc, callback, data); + } +} + +static void scene_collections_count(SceneCollection *UNUSED(sc), void *data) +{ + int *tot = data; + (*tot)++; +} + +static void scene_collections_build_array(SceneCollection *sc, void *data) +{ + SceneCollection ***array = data; + **array = sc; + (*array)++; +} + +static void scene_collections_array(Scene *scene, SceneCollection ***collections_array, int *tot) +{ + SceneCollection *sc = BKE_collection_master(scene); + SceneCollection **array; + + *collections_array = NULL; + *tot = 0; + + if (scene == NULL) + return; + + scene_collection_callback(sc, scene_collections_count, tot); + + if (*tot == 0) + return; + + *collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray"); + scene_collection_callback(sc, scene_collections_build_array, &array); +} + +/** + * Only use this in non-performance critical situations + * (it iterates over all scene collections twice) + */ +void BKE_scene_collections_Iterator_begin(Iterator *iter, void *data_in) +{ + Scene *scene = data_in; + SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __FUNCTION__); + + data->scene = scene; + iter->data = data; + + scene_collections_array(scene, (SceneCollection ***)&data->array, &data->tot); + BLI_assert(data->tot != 0); + + data->cur = 0; + iter->current = data->array[data->cur]; + iter->valid = true; +} + +void BKE_scene_collections_Iterator_next(struct Iterator *iter) +{ + SceneCollectionsIteratorData *data = iter->data; + + if (++data->cur < data->tot) { + iter->current = data->array[data->cur]; + } + else { + iter->valid = false; + } +} + +void BKE_scene_collections_Iterator_end(struct Iterator *iter) +{ + SceneCollectionsIteratorData *data = iter->data; + + if (data) { + if (data->array) { + MEM_freeN(data->array); + } + MEM_freeN(data); + } + iter->valid = false; +} + + +/* scene objects iteractor */ + +typedef struct SceneObjectsIteratorData { + GSet *visited; + LinkData *link; + Iterator scene_collection_iter; +} SceneObjectsIteratorData; + +void BKE_scene_objects_Iterator_begin(Iterator *iter, void *data_in) +{ + Scene *scene = data_in; + SceneObjectsIteratorData *data = MEM_callocN(sizeof(SceneObjectsIteratorData), __FUNCTION__); + iter->data = data; + + /* lookup list ot make sure each object is object called once */ + data->visited = BLI_gset_ptr_new(__func__); + + /* we wrap the scenecollection iterator here to go over the scene collections */ + BKE_scene_collections_Iterator_begin(&data->scene_collection_iter, scene); + + SceneCollection *sc = data->scene_collection_iter.current; + iter->current = sc->objects.first; + iter->valid = true; + + if (iter->current == NULL) { + BKE_scene_objects_Iterator_next(iter); + } +} + +/** + * Gets the first unique object in the sequence + */ +static LinkData *object_base_unique(GSet *gs, LinkData *link) +{ + if (link == NULL) { + return NULL; + } + + Object *ob = link->data; + if (!BLI_gset_haskey(gs, ob)) { + BLI_gset_add(gs, ob); + return link; + } + else { + return object_base_unique(gs, link->next); + } +} + +void BKE_scene_objects_Iterator_next(Iterator *iter) +{ + SceneObjectsIteratorData *data = iter->data; + LinkData *link = data->link ? object_base_unique(data->visited, data->link->next) : NULL; + + if (link) { + data->link = link; + iter->current = link->data; + } + else { + /* if this is the last object of this ListBase look at the next SceneCollection */ + SceneCollection *sc; + BKE_scene_collections_Iterator_next(&data->scene_collection_iter); + do { + sc = data->scene_collection_iter.current; + /* get the first unique object of this collection */ + LinkData *new_link = object_base_unique(data->visited, sc->objects.first); + if (new_link) { + data->link = new_link; + iter->current = data->link->data; + return; + } + BKE_scene_collections_Iterator_next(&data->scene_collection_iter); + } while (data->scene_collection_iter.valid); + + if (!data->scene_collection_iter.valid) { + iter->valid = false; + } + } +} + +void BKE_scene_objects_Iterator_end(Iterator *iter) +{ + SceneObjectsIteratorData *data = iter->data; + if (data) { + BKE_scene_collections_Iterator_end(&data->scene_collection_iter); + BLI_gset_free(data->visited, NULL); + MEM_freeN(data); + } +} diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index ee25be36855..b5f76240c0b 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -514,7 +514,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned // collision object will exclude self Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli) { - Base *base; + BaseLegacy *base; Object **objs; GroupObject *go; unsigned int numobj= 0, maxobj= 100; @@ -596,7 +596,7 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group) } else { Scene *sce_iter; - Base *base; + BaseLegacy *base; /* add objects in same layer in scene */ for (SETLOOPER(scene, sce_iter, base)) { diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 4c01bfd35f2..a7c53dda8c7 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -47,6 +47,7 @@ #include "BLT_translation.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_screen.h" #include "BKE_sound.h" @@ -814,6 +815,14 @@ struct SpaceClip *CTX_wm_space_clip(const bContext *C) return NULL; } +struct SpaceCollections *CTX_wm_space_collections(const bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + if (sa && sa->spacetype == SPACE_COLLECTIONS) + return sa->spacedata.first; + return NULL; +} + void CTX_wm_manager_set(bContext *C, wmWindowManager *wm) { C->wm.manager = wm; @@ -836,8 +845,9 @@ void CTX_wm_window_set(bContext *C, wmWindow *win) void CTX_wm_screen_set(bContext *C, bScreen *screen) { C->wm.screen = screen; - if (C->wm.screen) - C->data.scene = C->wm.screen->scene; + if (C->wm.screen) { + CTX_data_scene_set(C, C->wm.screen->scene); + } C->wm.area = NULL; C->wm.region = NULL; } @@ -896,6 +906,59 @@ Scene *CTX_data_scene(const bContext *C) return C->data.scene; } +SceneLayer *CTX_data_scene_layer(const bContext *C) +{ + SceneLayer *sl; + + if (ctx_data_pointer_verify(C, "render_layer", (void *)&sl)) { + return sl; + } + else { + return BKE_scene_layer_active(CTX_data_scene(C)); + } +} + +/** + * This is tricky. Sometimes the user overrides the render_layer + * but not the scene_collection. In this case what to do? + * + * If the scene_collection is linked to the SceneLayer we use it. + * Otherwise we fallback to the active one of the SceneLayer. + */ +LayerCollection *CTX_data_layer_collection(const bContext *C) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + LayerCollection *lc; + + if (ctx_data_pointer_verify(C, "layer_collection", (void *)&lc)) { + if (BKE_scene_layer_has_collection(sl, lc->scene_collection)) { + return lc; + } + } + + /* fallback */ + return BKE_layer_collection_active(sl); +} + +SceneCollection *CTX_data_scene_collection(const bContext *C) +{ + SceneCollection *sc; + if (ctx_data_pointer_verify(C, "scene_collection", (void *)&sc)) { + if (BKE_scene_layer_has_collection(CTX_data_scene_layer(C), sc)) { + return sc; + } + } + + LayerCollection *lc = CTX_data_layer_collection(C); + if (lc) { + return lc->scene_collection; + } + + /* fallback */ + Scene *scene = CTX_data_scene(C); + return BKE_collection_master(scene); +} + int CTX_data_mode_enum(const bContext *C) { Object *obedit = CTX_data_edit_object(C); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 98d37fb07bf..c9f0b8ec9ca 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2595,7 +2595,7 @@ bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, Custom if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT)) return false; -#undef TEST_RET +#undef LAYER_CMP /* if no layers are on either CustomData's, * then there was nothing to do... */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index bc9871aee54..39d06a13e6e 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -488,7 +488,7 @@ static void scene_setSubframe(Scene *scene, float subframe) static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene) { - Base *base = NULL; + BaseLegacy *base = NULL; GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; @@ -5780,7 +5780,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su * Loop through surface's target paint objects and do painting */ { - Base *base = NULL; + BaseLegacy *base = NULL; GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index fe8f5ebdca6..668d4d6c9e2 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -209,7 +209,7 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, EffectorWeights *weights, bool for_simulation) { - Base *base; + BaseLegacy *base; unsigned int layer= ob_src->lay; ListBase *effectors = NULL; diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 9b011dbb003..9c81a8b49be 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -130,18 +130,11 @@ static bool group_object_add_internal(Group *group, Object *ob) return true; } -bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base) +bool BKE_group_object_add(Group *group, Object *object) { if (group_object_add_internal(group, object)) { if ((object->flag & OB_FROMGROUP) == 0) { - - if (scene && base == NULL) - base = BKE_scene_base_find(scene, object); - object->flag |= OB_FROMGROUP; - - if (base) - base->flag |= OB_FROMGROUP; } return true; } @@ -208,18 +201,12 @@ bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group) return group_object_cyclic_check_internal(object, group); } -bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base) +bool BKE_group_object_unlink(Group *group, Object *object) { if (group_object_unlink_internal(group, object)) { /* object can be NULL */ if (object && BKE_group_object_find(NULL, object) == NULL) { - if (scene && base == NULL) - base = BKE_scene_base_find(scene, object); - object->flag &= ~OB_FROMGROUP; - - if (base) - base->flag &= ~OB_FROMGROUP; } return true; } diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index d098366aef4..69a2067f4e6 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -174,15 +174,10 @@ void BKE_lamp_make_local(Main *bmain, Lamp *la, const bool lib_local) void BKE_lamp_free(Lamp *la) { - MTex *mtex; int a; for (a = 0; a < MAX_MTEX; a++) { - mtex = la->mtex[a]; - if (mtex && mtex->tex) - id_us_min(&mtex->tex->id); - if (mtex) - MEM_freeN(mtex); + MEM_SAFE_FREE(la->mtex[a]); } BKE_animdata_free((ID *)la, false); @@ -193,6 +188,7 @@ void BKE_lamp_free(Lamp *la) if (la->nodetree) { ntreeFreeTree(la->nodetree); MEM_freeN(la->nodetree); + la->nodetree = NULL; } BKE_previewimg_free(&la->preview); diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c new file mode 100644 index 00000000000..ef4816af54d --- /dev/null +++ b/source/blender/blenkernel/intern/layer.c @@ -0,0 +1,1096 @@ +/* + * ***** 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): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/layer.c + * \ingroup bke + */ + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_string_utf8.h" +#include "BLI_string_utils.h" +#include "BLT_translation.h" + +#include "BKE_layer.h" +#include "BKE_collection.h" +#include "BKE_layer.h" +#include "BKE_main.h" +#include "BKE_node.h" + +#include "DNA_ID.h" +#include "DNA_layer_types.h" +#include "DNA_object_types.h" +#include "DNA_node_types.h" +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +/* prototype */ +struct CollectionEngineSettingsCB_Type; +static void layer_collection_free(SceneLayer *sl, LayerCollection *lc); +static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc); +static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc); +static CollectionEngineSettings *collection_engine_settings_create(struct CollectionEngineSettingsCB_Type *ces_type); +static void layer_collection_engine_settings_free(LayerCollection *lc); +static void layer_collection_create_engine_settings(LayerCollection *lc); +static void scene_layer_engine_settings_update(SceneLayer *sl, Object *ob, const char *engine_name); +static void object_bases_Iterator_next(Iterator *iter, const int flag); + +/* RenderLayer */ + +/** + * Returns the SceneLayer to be used for rendering + */ +SceneLayer *BKE_scene_layer_active(struct Scene *scene) +{ + SceneLayer *sl = BLI_findlink(&scene->render_layers, scene->active_layer); + BLI_assert(sl); + return sl; +} + +/** + * Add a new renderlayer + * by default, a renderlayer has the master collection + */ +SceneLayer *BKE_scene_layer_add(Scene *scene, const char *name) +{ + if (!name) { + name = DATA_("Render Layer"); + } + + SceneLayer *sl = MEM_callocN(sizeof(SceneLayer), "Scene Layer"); + sl->flag |= SCENE_LAYER_RENDER; + + BLI_addtail(&scene->render_layers, sl); + + /* unique name */ + BLI_strncpy_utf8(sl->name, name, sizeof(sl->name)); + BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name)); + + SceneCollection *sc = BKE_collection_master(scene); + layer_collection_add(sl, &sl->layer_collections, sc); + + return sl; +} + +bool BKE_scene_layer_remove(Main *bmain, Scene *scene, SceneLayer *sl) +{ + const int act = BLI_findindex(&scene->render_layers, sl); + + if (act == -1) { + return false; + } + else if ( (scene->render_layers.first == scene->render_layers.last) && + (scene->render_layers.first == sl)) + { + /* ensure 1 layer is kept */ + return false; + } + + BLI_remlink(&scene->render_layers, sl); + + BKE_scene_layer_free(sl); + MEM_freeN(sl); + + scene->active_layer = 0; + /* TODO WORKSPACE: set active_layer to 0 */ + + for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) { + if (sce->nodetree) { + BKE_nodetree_remove_layer_n(sce->nodetree, scene, act); + } + } + + return true; +} + +/** + * Free (or release) any data used by this SceneLayer (does not free the SceneLayer itself). + */ +void BKE_scene_layer_free(SceneLayer *sl) +{ + sl->basact = NULL; + BLI_freelistN(&sl->object_bases); + + for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) { + layer_collection_free(NULL, lc); + } + BLI_freelistN(&sl->layer_collections); +} + +/** + * Set the render engine of a renderlayer + */ +void BKE_scene_layer_engine_set(SceneLayer *sl, const char *engine) +{ + BLI_strncpy_utf8(sl->engine, engine, sizeof(sl->engine)); +} + +/** + * Tag all the selected objects of a renderlayer + */ +void BKE_scene_layer_selected_objects_tag(SceneLayer *sl, const int tag) +{ + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTED) != 0) { + base->object->flag |= tag; + } + else { + base->object->flag &= ~tag; + } + } +} + +static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc) +{ + for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) { + if (lcn == lc) { + return true; + } + if (find_scene_collection_in_scene_collections(&lcn->layer_collections, lc)) { + return true; + } + } + return false; +} + +/** + * Find the SceneLayer a LayerCollection belongs to + */ +SceneLayer *BKE_scene_layer_find_from_collection(Scene *scene, LayerCollection *lc) +{ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + if (find_scene_collection_in_scene_collections(&sl->layer_collections, lc)) { + return sl; + } + } + return NULL; +} + +/* Base */ + +Base *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob) +{ + return BLI_findptr(&sl->object_bases, ob, offsetof(Base, object)); +} + +void BKE_scene_layer_base_deselect_all(SceneLayer *sl) +{ + Base *base; + + for (base = sl->object_bases.first; base; base = base->next) { + base->flag &= ~BASE_SELECTED; + } +} + +void BKE_scene_layer_base_select(struct SceneLayer *sl, Base *selbase) +{ + sl->basact = selbase; + if ((selbase->flag & BASE_SELECTABLED) != 0) { + selbase->flag |= BASE_SELECTED; + } +} + +static void scene_layer_object_base_unref(SceneLayer* sl, Base *base) +{ + base->refcount--; + + /* It only exists in the RenderLayer */ + if (base->refcount == 0) { + if (sl->basact == base) { + sl->basact = NULL; + } + + BLI_remlink(&sl->object_bases, base); + MEM_freeN(base); + } +} + +static void layer_collection_base_flag_recalculate(LayerCollection *lc, const bool tree_is_visible, const bool tree_is_selectable) +{ + bool is_visible = tree_is_visible && ((lc->flag & COLLECTION_VISIBLE) != 0); + /* an object can only be selected if it's visible */ + bool is_selectable = tree_is_selectable && is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0); + + for (LinkData *link = lc->object_bases.first; link; link = link->next) { + Base *base = link->data; + + if (is_visible) { + base->flag |= BASE_VISIBLED; + } + else { + base->flag &= ~BASE_VISIBLED; + } + + if (is_selectable) { + base->flag |= BASE_SELECTABLED; + } + else { + base->flag &= ~BASE_SELECTABLED; + } + } + + for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) { + layer_collection_base_flag_recalculate(lcn, is_visible, is_selectable); + } +} + +/** + * Re-evaluate the ObjectBase flags for SceneLayer + */ +void BKE_scene_layer_base_flag_recalculate(SceneLayer *sl) +{ + for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) { + layer_collection_base_flag_recalculate(lc, true, true); + } + + /* if base is not selectabled, clear select */ + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTABLED) == 0) { + base->flag &= ~BASE_SELECTED; + } + } +} + +/** + * Tag Scene Layer to recalculation + * + * Temporary function, waiting for real depsgraph + */ +void BKE_scene_layer_engine_settings_recalculate(SceneLayer *sl) +{ + sl->flag |= SCENE_LAYER_ENGINE_DIRTY; + for (Base *base = sl->object_bases.first; base; base = base->next) { + base->flag |= BASE_DIRTY_ENGINE_SETTINGS; + } +} + +/** + * Tag Object in SceneLayer to recalculation + * + * Temporary function, waiting for real depsgraph + */ +void BKE_scene_layer_engine_settings_object_recalculate(SceneLayer *sl, Object *ob) +{ + Base *base = BLI_findptr(&sl->object_bases, ob, offsetof(Base, object)); + if (base) { + sl->flag |= SCENE_LAYER_ENGINE_DIRTY; + base->flag |= BASE_DIRTY_ENGINE_SETTINGS; + } +} + +/** + * Tag all Objects in LayerCollection to recalculation + * + * Temporary function, waiting for real depsgraph + */ +void BKE_scene_layer_engine_settings_collection_recalculate(SceneLayer *sl, LayerCollection *lc) +{ + sl->flag |= SCENE_LAYER_ENGINE_DIRTY; + + for (LinkData *link = lc->object_bases.first; link; link = link->next) { + Base *base = (Base *)link->data; + base->flag |= BASE_DIRTY_ENGINE_SETTINGS; + } + + for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) { + BKE_scene_layer_engine_settings_collection_recalculate(sl, lcn); + } +} + +/** + * Re-calculate the engine settings for all the objects in SceneLayer + * + * Temporary function, waiting for real depsgraph + */ +void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl, const char *engine_name) +{ + if ((sl->flag & SCENE_LAYER_ENGINE_DIRTY) == 0) { + return; + } + + /* do the complete settings update */ + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (((base->flag & BASE_DIRTY_ENGINE_SETTINGS) != 0) && \ + (base->flag & BASE_VISIBLED) != 0) + { + scene_layer_engine_settings_update(sl, base->object, engine_name); + base->flag &= ~BASE_DIRTY_ENGINE_SETTINGS; + } + } + + sl->flag &= ~SCENE_LAYER_ENGINE_DIRTY; +} + +/** + * Return the base if existent, or create it if necessary + * Always bump the refcount + */ +static Base *object_base_add(SceneLayer *sl, Object *ob) +{ + Base *base; + base = BKE_scene_layer_base_find(sl, ob); + + if (base == NULL) { + base = MEM_callocN(sizeof(Base), "Object Base"); + + /* do not bump user count, leave it for SceneCollections */ + base->object = ob; + BLI_addtail(&sl->object_bases, base); + } + base->refcount++; + return base; +} + +/* LayerCollection */ + +/** + * When freeing the entire SceneLayer at once we don't bother with unref + * otherwise SceneLayer is passed to keep the syncing of the LayerCollection tree + */ +static void layer_collection_free(SceneLayer *sl, LayerCollection *lc) +{ + if (sl) { + for (LinkData *link = lc->object_bases.first; link; link = link->next) { + scene_layer_object_base_unref(sl, link->data); + } + } + + BLI_freelistN(&lc->object_bases); + BLI_freelistN(&lc->overrides); + layer_collection_engine_settings_free(lc); + + for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { + layer_collection_free(sl, nlc); + } + + BLI_freelistN(&lc->layer_collections); +} + +/** + * Free (or release) LayerCollection from SceneLayer + * (does not free the LayerCollection itself). + */ +void BKE_layer_collection_free(SceneLayer *sl, LayerCollection *lc) +{ + layer_collection_free(sl, lc); +} + +/* LayerCollection */ + +/** + * Recursively get the collection for a given index + */ +static LayerCollection *collection_from_index(ListBase *lb, const int number, int *i) +{ + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + if (*i == number) { + return lc; + } + + (*i)++; + + LayerCollection *lc_nested = collection_from_index(&lc->layer_collections, number, i); + if (lc_nested) { + return lc_nested; + } + } + return NULL; +} + +/** + * Get the active collection + */ +LayerCollection *BKE_layer_collection_active(SceneLayer *sl) +{ + int i = 0; + return collection_from_index(&sl->layer_collections, sl->active_collection, &i); +} + +/** + * Recursively get the count of collections + */ +static int collection_count(ListBase *lb) +{ + int i = 0; + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + i += collection_count(&lc->layer_collections) + 1; + } + return i; +} + +/** + * Get the total number of collections + * (including all the nested collections) + */ +int BKE_layer_collection_count(SceneLayer *sl) +{ + return collection_count(&sl->layer_collections); +} + +/** + * Recursively get the index for a given collection + */ +static int index_from_collection(ListBase *lb, LayerCollection *lc, int *i) +{ + for (LayerCollection *lcol = lb->first; lcol; lcol = lcol->next) { + if (lcol == lc) { + return *i; + } + + (*i)++; + + int i_nested = index_from_collection(&lcol->layer_collections, lc, i); + if (i_nested != -1) { + return i_nested; + } + } + return -1; +} + +/** + * Return -1 if not found + */ +int BKE_layer_collection_findindex(SceneLayer *sl, LayerCollection *lc) +{ + int i = 0; + return index_from_collection(&sl->layer_collections, lc, &i); +} + +/** + * Link a collection to a renderlayer + * The collection needs to be created separately + */ +LayerCollection *BKE_collection_link(SceneLayer *sl, SceneCollection *sc) +{ + LayerCollection *lc = layer_collection_add(sl, &sl->layer_collections, sc); + sl->active_collection = BKE_layer_collection_findindex(sl, lc); + return lc; +} + +/** + * Unlink a collection base from a renderlayer + * The corresponding collection is not removed from the master collection + */ +void BKE_collection_unlink(SceneLayer *sl, LayerCollection *lc) +{ + BKE_layer_collection_free(sl, lc); + BKE_scene_layer_base_flag_recalculate(sl); + BKE_scene_layer_engine_settings_collection_recalculate(sl, lc); + + BLI_remlink(&sl->layer_collections, lc); + MEM_freeN(lc); + sl->active_collection = 0; +} + +static void layer_collection_object_add(SceneLayer *sl, LayerCollection *lc, Object *ob) +{ + Base *base = object_base_add(sl, ob); + + /* only add an object once - prevent SceneCollection->objects and + * SceneCollection->filter_objects to add the same object */ + + if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) { + return; + } + + BLI_addtail(&lc->object_bases, BLI_genericNodeN(base)); + + BKE_scene_layer_base_flag_recalculate(sl); + BKE_scene_layer_engine_settings_object_recalculate(sl, ob); +} + +static void layer_collection_object_remove(SceneLayer *sl, LayerCollection *lc, Object *ob) +{ + Base *base; + base = BKE_scene_layer_base_find(sl, ob); + + LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data)); + BLI_remlink(&lc->object_bases, link); + MEM_freeN(link); + + scene_layer_object_base_unref(sl, base); +} + +static void layer_collection_objects_populate(SceneLayer *sl, LayerCollection *lc, ListBase *objects) +{ + for (LinkData *link = objects->first; link; link = link->next) { + layer_collection_object_add(sl, lc, link->data); + } +} + +static void layer_collection_populate(SceneLayer *sl, LayerCollection *lc, SceneCollection *sc) +{ + layer_collection_objects_populate(sl, lc, &sc->objects); + layer_collection_objects_populate(sl, lc, &sc->filter_objects); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + layer_collection_add(sl, &lc->layer_collections, nsc); + } +} + +static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc) +{ + LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base"); + BLI_addtail(lb, lc); + + lc->scene_collection = sc; + lc->flag = COLLECTION_VISIBLE + COLLECTION_SELECTABLE + COLLECTION_FOLDED; + + layer_collection_create_engine_settings(lc); + layer_collection_populate(sl, lc, sc); + return lc; +} + + +/* ---------------------------------------------------------------------- */ + +/** + * See if render layer has the scene collection linked directly, or indirectly (nested) + */ +bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc) +{ + for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) { + if (find_layer_collection_by_scene_collection(lc, sc) != NULL) { + return true; + } + } + return false; +} + +/** + * See if the object is in any of the scene layers of the scene + */ +bool BKE_scene_has_object(Scene *scene, Object *ob) +{ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + Base *base = BKE_scene_layer_base_find(sl, ob); + if (base) { + return true; + } + } + return false; +} + + +/* ---------------------------------------------------------------------- */ +/* Syncing */ + +static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc) +{ + if (lc->scene_collection == sc) { + return lc; + } + + for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { + LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc); + if (found) { + return found; + } + } + return NULL; +} + +/** + * Add a new LayerCollection for all the SceneLayers that have sc_parent + */ +void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc_parent, SceneCollection *sc) +{ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) { + LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent); + if (lc_parent) { + layer_collection_add(sl, &lc_parent->layer_collections, sc); + } + } + } +} + +/** + * Add a corresponding ObjectBase to all the equivalent LayerCollection + */ +void BKE_layer_sync_object_link(Scene *scene, SceneCollection *sc, Object *ob) +{ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) { + LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc); + if (found) { + layer_collection_object_add(sl, found, ob); + } + } + } +} + +/** + * Remove the equivalent object base to all layers that have this collection + * also remove all reference to ob in the filter_objects + */ +void BKE_layer_sync_object_unlink(Scene *scene, SceneCollection *sc, Object *ob) +{ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) { + LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc); + if (found) { + layer_collection_object_remove(sl, found, ob); + } + } + BKE_scene_layer_base_flag_recalculate(sl); + BKE_scene_layer_engine_settings_object_recalculate(sl, ob); + } +} + +/* ---------------------------------------------------------------------- */ +/* Override */ + +/** + * Add a new datablock override + */ +void BKE_collection_override_datablock_add(LayerCollection *UNUSED(lc), const char *UNUSED(data_path), ID *UNUSED(id)) +{ + TODO_LAYER_OVERRIDE; +} + +/* ---------------------------------------------------------------------- */ +/* Engine Settings */ + +ListBase R_engines_settings_callbacks = {NULL, NULL}; + +typedef struct CollectionEngineSettingsCB_Type { + struct CollectionEngineSettingsCB_Type *next, *prev; + + char name[MAX_NAME]; /* engine name */ + + CollectionEngineSettingsCB callback; + +} CollectionEngineSettingsCB_Type; + +static void create_engine_settings_layer_collection(LayerCollection *lc, CollectionEngineSettingsCB_Type *ces_type) +{ + if (BKE_layer_collection_engine_get(lc, ces_type->name)) { + return; + } + + CollectionEngineSettings *ces = collection_engine_settings_create(ces_type); + BLI_addtail(&lc->engine_settings, ces); + + for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) { + create_engine_settings_layer_collection(lcn, ces_type); + } +} + +static void create_engines_settings_scene(Scene *scene, CollectionEngineSettingsCB_Type *ces_type) +{ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) { + create_engine_settings_layer_collection(lc, ces_type); + } + } +} + +void BKE_layer_collection_engine_settings_callback_register( + Main *bmain, const char *engine_name, CollectionEngineSettingsCB func) +{ + CollectionEngineSettingsCB_Type *ces_type; + + /* cleanup in case it existed */ + ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name)); + + if (ces_type) { + BLI_remlink(&R_engines_settings_callbacks, ces_type); + MEM_freeN(ces_type); + } + + ces_type = MEM_callocN(sizeof(CollectionEngineSettingsCB_Type), "collection_engine_type"); + BLI_strncpy_utf8(ces_type->name, engine_name, sizeof(ces_type->name)); + ces_type->callback = func; + BLI_addtail(&R_engines_settings_callbacks, ces_type); + + if (bmain) { + /* populate all of the collections of the scene with those settings */ + for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { + create_engines_settings_scene(scene, ces_type); + } + } +} + +void BKE_layer_collection_engine_settings_callback_free(void) +{ + BLI_freelistN(&R_engines_settings_callbacks); +} + +static CollectionEngineSettings *collection_engine_settings_create(CollectionEngineSettingsCB_Type *ces_type) +{ + /* create callback data */ + CollectionEngineSettings *ces = MEM_callocN(sizeof(CollectionEngineSettings), "Collection Engine Settings"); + BLI_strncpy_utf8(ces->name, ces_type->name, sizeof(ces->name)); + + /* call callback */ + ces_type->callback(NULL, ces); + + return ces; +} + +/** + * Initialize a CollectionEngineSettings + * + * Usually we would pass LayerCollection->engine_settings + * But depsgraph uses this for Object->collection_settings + */ +CollectionEngineSettings *BKE_layer_collection_engine_settings_create(const char *engine_name) +{ + CollectionEngineSettingsCB_Type *ces_type; + ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name)); + BLI_assert(ces_type); + + CollectionEngineSettings *ces = collection_engine_settings_create(ces_type); + return ces; +} + +/** + * Free the CollectionEngineSettings + */ +void BKE_layer_collection_engine_settings_free(CollectionEngineSettings *ces) +{ + BLI_freelistN(&ces->properties); +} + +static void layer_collection_engine_settings_free(LayerCollection *lc) +{ + for (CollectionEngineSettings *ces = lc->engine_settings.first; ces; ces = ces->next) { + BKE_layer_collection_engine_settings_free(ces); + } + BLI_freelistN(&lc->engine_settings); +} + +/** + * Initialize the render settings for a single LayerCollection + */ +static void layer_collection_create_engine_settings(LayerCollection *lc) +{ + CollectionEngineSettingsCB_Type *ces_type; + for (ces_type = R_engines_settings_callbacks.first; ces_type; ces_type = ces_type->next) { + create_engine_settings_layer_collection(lc, ces_type); + } +} + +/** + * Return layer collection engine settings for specified engine + */ +CollectionEngineSettings *BKE_layer_collection_engine_get(LayerCollection *lc, const char *engine_name) +{ + CollectionEngineSettings *ces; + ces = BLI_findstring(&lc->engine_settings, engine_name, offsetof(CollectionEngineSettings, name)); + return ces; +} + +/* ---------------------------------------------------------------------- */ +/* Engine Settings Properties */ + +void BKE_collection_engine_property_add_float(CollectionEngineSettings *ces, const char *name, float value) +{ + CollectionEnginePropertyFloat *prop; + prop = MEM_callocN(sizeof(CollectionEnginePropertyFloat), "collection engine settings float"); + prop->data.type = COLLECTION_PROP_TYPE_FLOAT; + BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name)); + prop->value = value; + BLI_addtail(&ces->properties, prop); +} + +void BKE_collection_engine_property_add_int(CollectionEngineSettings *ces, const char *name, int value) +{ + CollectionEnginePropertyInt *prop; + prop = MEM_callocN(sizeof(CollectionEnginePropertyInt), "collection engine settings int"); + prop->data.type = COLLECTION_PROP_TYPE_INT; + BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name)); + prop->value = value; + BLI_addtail(&ces->properties, prop); +} + +CollectionEngineProperty *BKE_collection_engine_property_get(CollectionEngineSettings *ces, const char *name) +{ + return BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name)); +} + +int BKE_collection_engine_property_value_get_int(CollectionEngineSettings *ces, const char *name) +{ + CollectionEnginePropertyInt *prop; + prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name)); + return prop->value; +} + +float BKE_collection_engine_property_value_get_float(CollectionEngineSettings *ces, const char *name) +{ + CollectionEnginePropertyFloat *prop; + prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name)); + return prop->value; +} + +void BKE_collection_engine_property_value_set_int(CollectionEngineSettings *ces, const char *name, int value) +{ + CollectionEnginePropertyInt *prop; + prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name)); + prop->value = value; + prop->data.flag |= COLLECTION_PROP_USE; +} + +void BKE_collection_engine_property_value_set_float(CollectionEngineSettings *ces, const char *name, float value) +{ + CollectionEnginePropertyFloat *prop; + prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name)); + prop->value = value; + prop->data.flag |= COLLECTION_PROP_USE; +} + +bool BKE_collection_engine_property_use_get(CollectionEngineSettings *ces, const char *name) +{ + CollectionEngineProperty *prop; + prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name)); + return ((prop->flag & COLLECTION_PROP_USE) != 0); +} + +void BKE_collection_engine_property_use_set(CollectionEngineSettings *ces, const char *name, bool value) +{ + CollectionEngineProperty *prop; + prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name)); + + if (value) { + prop->flag |= COLLECTION_PROP_USE; + } + else { + prop->flag &= ~COLLECTION_PROP_USE; + } +} + +/* Engine Settings recalculate */ + +static void collection_engine_settings_init(CollectionEngineSettings *ces, const char *engine_name) +{ + CollectionEngineSettingsCB_Type *ces_type; + ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name)); + + BLI_listbase_clear(&ces->properties); + BLI_strncpy_utf8(ces->name, ces_type->name, sizeof(ces->name)); + + /* call callback */ + ces_type->callback(NULL, ces); +} + +static void collection_engine_settings_copy(CollectionEngineSettings *ces_dst, CollectionEngineSettings *ces_src) +{ + BLI_strncpy_utf8(ces_dst->name, ces_src->name, sizeof(ces_dst->name)); + BLI_freelistN(&ces_dst->properties); + + for (CollectionEngineProperty *prop = ces_src->properties.first; prop; prop = prop->next) { + CollectionEngineProperty *prop_new = MEM_dupallocN(prop); + BLI_addtail(&ces_dst->properties, prop_new); + } +} + +/** + * Set a value from a CollectionProperty to another + */ +static void collection_engine_property_set (CollectionEngineProperty *prop_dst, CollectionEngineProperty *prop_src){ + if ((prop_src->flag & COLLECTION_PROP_USE) != 0) { + /* mark the property as used, so the engine knows if the value was ever set*/ + prop_dst->flag |= COLLECTION_PROP_USE; + switch (prop_src->type) { + case COLLECTION_PROP_TYPE_FLOAT: + ((CollectionEnginePropertyFloat *)prop_dst)->value = ((CollectionEnginePropertyFloat *)prop_src)->value; + break; + case COLLECTION_PROP_TYPE_INT: + ((CollectionEnginePropertyInt *)prop_dst)->value = ((CollectionEnginePropertyInt *)prop_src)->value; + break; + default: + BLI_assert(false); + break; + } + } +} + +static void collection_engine_settings_merge(CollectionEngineSettings *ces_dst, CollectionEngineSettings *ces_src) +{ + CollectionEngineProperty *prop_src, *prop_dst; + + prop_dst = ces_dst->properties.first; + for (prop_src = ces_src->properties.first; prop_src; prop_src = prop_src->next, prop_dst = prop_dst->next) { + collection_engine_property_set(prop_dst, prop_src); + } +} + +static void layer_collection_engine_settings_update( + LayerCollection *lc, CollectionEngineSettings *ces_parent, + Base *base, CollectionEngineSettings *ces_ob) +{ + if ((lc->flag & COLLECTION_VISIBLE) == 0) { + return; + } + + CollectionEngineSettings ces = {NULL}; + collection_engine_settings_copy(&ces, ces_parent); + + CollectionEngineSettings *ces_lc = BKE_layer_collection_engine_get(lc, ces.name); + collection_engine_settings_merge(&ces, ces_lc); + + if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data)) != NULL) { + collection_engine_settings_merge(ces_ob, &ces); + } + + /* do it recursively */ + for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) { + layer_collection_engine_settings_update(lcn, &ces, base, ces_ob); + } + + BKE_layer_collection_engine_settings_free(&ces); +} + +/** + * Update the collection settings pointer allocated in the object + * This is to be flushed from the Depsgraph + */ +static void scene_layer_engine_settings_update(SceneLayer *sl, Object *ob, const char *engine_name) +{ + Base *base = BKE_scene_layer_base_find(sl, ob); + CollectionEngineSettings ces_layer = {NULL}, *ces_ob; + + collection_engine_settings_init(&ces_layer, engine_name); + + if (ob->collection_settings) { + BKE_layer_collection_engine_settings_free(ob->collection_settings); + MEM_freeN(ob->collection_settings); + } + + CollectionEngineSettingsCB_Type *ces_type; + ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name)); + ces_ob = collection_engine_settings_create(ces_type); + + for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) { + layer_collection_engine_settings_update(lc, &ces_layer, base, ces_ob); + } + + BKE_layer_collection_engine_settings_free(&ces_layer); + ob->collection_settings = ces_ob; +} + +/* ---------------------------------------------------------------------- */ +/* Iterators */ + +static void object_bases_Iterator_begin(Iterator *iter, void *data_in, const int flag) +{ + SceneLayer *sl = data_in; + Base *base = sl->object_bases.first; + + /* when there are no objects */ + if (base == NULL) { + iter->valid = false; + return; + } + + iter->valid = true; + iter->data = base; + + if ((base->flag & flag) == 0) { + object_bases_Iterator_next(iter, flag); + } + else { + iter->current = base; + } +} + +static void object_bases_Iterator_next(Iterator *iter, const int flag) +{ + Base *base = ((Base *)iter->data)->next; + + while (base) { + if ((base->flag & flag) != 0) { + iter->current = base; + iter->data = base; + return; + } + base = base->next; + } + + iter->current = NULL; + iter->valid = false; +} + +static void objects_Iterator_begin(Iterator *iter, void *data_in, const int flag) +{ + object_bases_Iterator_begin(iter, data_in, flag); + + if (iter->valid) { + iter->current = ((Base *)iter->current)->object; + } +} + +static void objects_Iterator_next(Iterator *iter, const int flag) +{ + object_bases_Iterator_next(iter, flag); + + if (iter->valid) { + iter->current = ((Base *)iter->current)->object; + } +} + +void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in) +{ + objects_Iterator_begin(iter, data_in, BASE_SELECTED); +} + +void BKE_selected_objects_Iterator_next(Iterator *iter) +{ + objects_Iterator_next(iter, BASE_SELECTED); +} + +void BKE_selected_objects_Iterator_end(Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in) +{ + objects_Iterator_begin(iter, data_in, BASE_VISIBLED); +} + +void BKE_visible_objects_Iterator_next(Iterator *iter) +{ + objects_Iterator_next(iter, BASE_VISIBLED); +} + +void BKE_visible_objects_Iterator_end(Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in) +{ + object_bases_Iterator_begin(iter, data_in, BASE_VISIBLED); +} + +void BKE_visible_bases_Iterator_next(Iterator *iter) +{ + object_bases_Iterator_next(iter, BASE_VISIBLED); +} + +void BKE_visible_bases_Iterator_end(Iterator *UNUSED(iter)) +{ + /* do nothing */ +} diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index de35d1e0eac..2398c6724ed 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -76,6 +76,7 @@ #include "BLI_ghash.h" #include "BLI_linklist.h" #include "BLI_memarena.h" +#include "BLI_mempool.h" #include "BLI_string_utils.h" #include "BLI_threads.h" @@ -273,8 +274,12 @@ void BKE_id_clear_newpoin(ID *id) } static int id_expand_local_callback( - void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int UNUSED(cd_flag)) + void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int cb_flag) { + if (cb_flag & IDWALK_CB_PRIVATE) { + return IDWALK_RET_NOP; + } + /* Can hapen that we get unlinkable ID here, e.g. with shapekey referring to itself (through drivers)... * Just skip it, shape key can only be either indirectly linked, or fully local, period. * And let's curse one more time that stupid useless shapekey ID type! */ @@ -288,9 +293,9 @@ static int id_expand_local_callback( /** * Expand ID usages of given id as 'extern' (and no more indirect) linked data. Used by ID copy/make_local functions. */ -void BKE_id_expand_local(ID *id) +void BKE_id_expand_local(Main *bmain, ID *id) { - BKE_library_foreach_ID_link(id, id_expand_local_callback, NULL, 0); + BKE_library_foreach_ID_link(bmain, id, id_expand_local_callback, NULL, IDWALK_READONLY); } /** @@ -299,7 +304,7 @@ void BKE_id_expand_local(ID *id) void BKE_id_copy_ensure_local(Main *bmain, ID *old_id, ID *new_id) { if (ID_IS_LINKED_DATABLOCK(old_id)) { - BKE_id_expand_local(new_id); + BKE_id_expand_local(bmain, new_id); BKE_id_lib_local_paths(bmain, old_id->lib, new_id); } } @@ -326,7 +331,7 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c if (lib_local || is_local) { if (!is_lib) { id_clear_lib_data_ex(bmain, id, id_in_mainlist); - BKE_id_expand_local(id); + BKE_id_expand_local(bmain, id); } else { ID *id_new; @@ -1252,6 +1257,10 @@ void BKE_main_free(Main *mainvar) } } + if (mainvar->relations) { + BKE_main_relations_free(mainvar); + } + BLI_spin_end((SpinLock *)mainvar->lock); MEM_freeN(mainvar->lock); DEG_evaluation_context_free(mainvar->eval_ctx); @@ -1268,6 +1277,78 @@ void BKE_main_unlock(struct Main *bmain) BLI_spin_unlock((SpinLock *) bmain->lock); } + +static int main_relations_create_cb(void *user_data, ID *id_self, ID **id_pointer, int cb_flag) +{ + MainIDRelations *rel = user_data; + + if (*id_pointer) { + MainIDRelationsEntry *entry, **entry_p; + + entry = BLI_mempool_alloc(rel->entry_pool); + if (BLI_ghash_ensure_p(rel->id_user_to_used, id_self, (void ***)&entry_p)) { + entry->next = *entry_p; + } + else { + entry->next = NULL; + } + entry->id_pointer = id_pointer; + entry->usage_flag = cb_flag; + *entry_p = entry; + + entry = BLI_mempool_alloc(rel->entry_pool); + if (BLI_ghash_ensure_p(rel->id_used_to_user, *id_pointer, (void ***)&entry_p)) { + entry->next = *entry_p; + } + else { + entry->next = NULL; + } + entry->id_pointer = (ID **)id_self; + entry->usage_flag = cb_flag; + *entry_p = entry; + } + + return IDWALK_RET_NOP; +} + +/** Generate the mappings between used IDs and their users, and vice-versa. */ +void BKE_main_relations_create(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + ID *id; + int a; + + if (bmain->relations != NULL) { + BKE_main_relations_free(bmain); + } + + bmain->relations = MEM_mallocN(sizeof(*bmain->relations), __func__); + bmain->relations->id_used_to_user = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + bmain->relations->id_user_to_used = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + bmain->relations->entry_pool = BLI_mempool_create(sizeof(MainIDRelationsEntry), 128, 128, BLI_MEMPOOL_NOP); + + for (a = set_listbasepointers(bmain, lbarray); a--; ) { + for (id = lbarray[a]->first; id; id = id->next) { + BKE_library_foreach_ID_link(NULL, id, main_relations_create_cb, bmain->relations, IDWALK_READONLY); + } + } +} + +void BKE_main_relations_free(Main *bmain) +{ + if (bmain->relations) { + if (bmain->relations->id_used_to_user) { + BLI_ghash_free(bmain->relations->id_used_to_user, NULL, NULL); + } + if (bmain->relations->id_user_to_used) { + BLI_ghash_free(bmain->relations->id_user_to_used, NULL, NULL); + } + BLI_mempool_destroy(bmain->relations->entry_pool); + MEM_freeN(bmain->relations); + bmain->relations = NULL; + } +} + /** * Generates a raw .blend file thumbnail data from given image. * @@ -1623,6 +1704,53 @@ void BKE_main_id_clear_newpoins(Main *bmain) } } + +static void library_make_local_copying_check(ID *id, GSet *loop_tags, MainIDRelations *id_relations, GSet *done_ids) +{ + if (BLI_gset_haskey(done_ids, id)) { + return; /* Already checked, nothing else to do. */ + } + + MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id); + BLI_gset_insert(loop_tags, id); + for (; entry != NULL; entry = entry->next) { + ID *par_id = (ID *)entry->id_pointer; /* used_to_user stores ID pointer, not pointer to ID pointer... */ + + /* Shapekeys are considered 'private' to their owner ID here, and never tagged (since they cannot be linked), + * so we have to switch effective parent to their owner. */ + if (GS(par_id->name) == ID_KE) { + par_id = ((Key *)par_id)->from; + } + + if (par_id->lib == NULL) { + /* Local user, early out to avoid some gset querying... */ + continue; + } + if (!BLI_gset_haskey(done_ids, par_id)) { + if (BLI_gset_haskey(loop_tags, par_id)) { + /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it. + * Note that this is the situation that can lead to archipelagoes of linked data-blocks + * (since all of them have non-local users, they would all be duplicated, leading to a loop of unused + * linked data-blocks that cannot be freed since they all use each other...). */ + continue; + } + /* Else, recursively check that user ID. */ + library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids); + } + + if (par_id->tag & LIB_TAG_DOIT) { + /* This user will be fully local in future, so far so good, nothing to do here but check next user. */ + } + else { + /* This user won't be fully local in future, so current ID won't be either. And we are done checking it. */ + id->tag &= ~LIB_TAG_DOIT; + break; + } + } + BLI_gset_add(done_ids, id); + BLI_gset_remove(loop_tags, id, NULL); +} + /** Make linked datablocks local. * * \param bmain Almost certainly G.main. @@ -1633,11 +1761,10 @@ void BKE_main_id_clear_newpoins(Main *bmain) /* Note: Old (2.77) version was simply making (tagging) datablocks as local, without actually making any check whether * they were also indirectly used or not... * - * Current version uses regular id_make_local callback, which is not super-efficient since this ends up - * duplicating some IDs and then removing original ones (due to missing knowledge of which ID uses some other ID). - * - * However, we now have a first check that allows us to use 'direct localization' of a lot of IDs, so performances - * are now *reasonably* OK. + * Current version uses regular id_make_local callback, with advanced pre-processing step to detect all cases of + * IDs currently indirectly used, but which will be used by local data only once this function is finished. + * This allows to avoid any uneeded duplication of IDs, and hence all time lost afterwards to remove + * orphaned linked data-blocks... */ void BKE_library_make_local( Main *bmain, const Library *lib, GHash *old_to_new_ids, const bool untagged_only, const bool set_fake) @@ -1648,9 +1775,12 @@ void BKE_library_make_local( LinkNode *todo_ids = NULL; LinkNode *copied_ids = NULL; - LinkNode *linked_loop_candidates = NULL; MemArena *linklist_mem = BLI_memarena_new(512 * sizeof(*todo_ids), __func__); + BKE_main_relations_create(bmain); + + GSet *done_ids = BLI_gset_ptr_new(__func__); + /* Step 1: Detect datablocks to make local. */ for (a = set_listbasepointers(bmain, lbarray); a--; ) { id = lbarray[a]->first; @@ -1660,16 +1790,25 @@ void BKE_library_make_local( const bool do_skip = (id && !BKE_idcode_is_linkable(GS(id->name))); for (; id; id = id->next) { + ID *ntree = (ID *)ntreeFromID(id); + id->tag &= ~LIB_TAG_DOIT; + if (ntree != NULL) { + ntree->tag &= ~LIB_TAG_DOIT; + } if (id->lib == NULL) { id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW); } - /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so its - * possible to tag data you don't want to be made local, used for - * appending data, so any libdata already linked wont become local - * (very nasty to discover all your links are lost after appending). + /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so its possible to tag data you don't want to + * be made local, used for appending data, so any libdata already linked wont become local (very nasty + * to discover all your links are lost after appending). * Also, never ever make proxified objects local, would not make any sense. */ + /* Some more notes: + * - Shapekeys are never tagged here (since they are not linkable). + * - Nodetrees used in materials etc. have to be tagged manually, since they do not exist in Main (!). + * This is ok-ish on 'make local' side of things (since those are handled by their 'owner' IDs), + * but complicates slightly the pre-processing of relations between IDs at step 2... */ else if (!do_skip && id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) && ELEM(lib, NULL, id->lib) && !(GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) && @@ -1677,13 +1816,32 @@ void BKE_library_make_local( { BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem); id->tag |= LIB_TAG_DOIT; + + /* Tag those nasty non-ID nodetrees, but do not add them to todo list, making them local is handled + * by 'owner' ID. This is needed for library_make_local_copying_check() to work OK at step 2. */ + if (ntree != NULL) { + ntree->tag |= LIB_TAG_DOIT; + } + } + else { + /* Linked ID that we won't be making local (needed info for step 2, see below). */ + BLI_gset_add(done_ids, id); } } } /* Step 2: Check which datablocks we can directly make local (because they are only used by already, or future, - * local data), others will need to be duplicated and further processed later. */ - BKE_library_indirectly_used_data_tag_clear(bmain); + * local data), others will need to be duplicated. */ + GSet *loop_tags = BLI_gset_ptr_new(__func__); + for (LinkNode *it = todo_ids; it; it = it->next) { + library_make_local_copying_check(it->link, loop_tags, bmain->relations, done_ids); + BLI_assert(BLI_gset_size(loop_tags) == 0); + } + BLI_gset_free(loop_tags, NULL); + BLI_gset_free(done_ids, NULL); + + /* Next step will most likely add new IDs, better to get rid of this mapping now. */ + BKE_main_relations_free(bmain); /* Step 3: Make IDs local, either directly (quick and simple), or using generic process, * which involves more complex checks and might instead create a local copy of original linked ID. */ @@ -1693,10 +1851,10 @@ void BKE_library_make_local( if (id->tag & LIB_TAG_DOIT) { /* We know all users of this object are local or will be made fully local, even if currently there are - * some indirect usages. So instead of making a copy that se'll likely get rid of later, directly make + * some indirect usages. So instead of making a copy that we'll likely get rid of later, directly make * that data block local. Saves a tremendous amount of time with complex scenes... */ id_clear_lib_data_ex(bmain, id, true); - BKE_id_expand_local(id); + BKE_id_expand_local(bmain, id); id->tag &= ~LIB_TAG_DOIT; } else { @@ -1732,6 +1890,9 @@ void BKE_library_make_local( /* Step 4: We have to remap local usages of old (linked) ID to new (local) id in a separated loop, * as lbarray ordering is not enough to ensure us we did catch all dependencies * (e.g. if making local a parent object before its child...). See T48907. */ + /* TODO This is now the biggest step by far (in term of processing time). We may be able to gain here by + * using again main->relations mapping, but... this implies BKE_libblock_remap & co to be able to update + * main->relations on the fly. Have to think about it a bit more, and see whether new code is OK first, anyway. */ for (LinkNode *it = copied_ids; it; it = it->next) { id = it->link; @@ -1750,6 +1911,53 @@ void BKE_library_make_local( } } + /* Note: Keeping both version of the code (old one being safer, since it still has checks against unused IDs) + * for now, we can remove old one once it has been tested for some time in master... */ +#if 1 + /* Step 5: proxy 'remapping' hack. */ + for (LinkNode *it = copied_ids; it; it = it->next) { + /* Attempt to re-link copied proxy objects. This allows appending of an entire scene + * from another blend file into this one, even when that blend file contains proxified + * armatures that have local references. Since the proxified object needs to be linked + * (not local), this will only work when the "Localize all" checkbox is disabled. + * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */ + if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) { + Object *ob = (Object *)id; + Object *ob_new = (Object *)id->newid; + bool is_local = false, is_lib = false; + + /* Proxies only work when the proxified object is linked-in from a library. */ + if (ob->proxy->id.lib == NULL) { + printf("Warning, proxy object %s will loose its link to %s, because the " + "proxified object is local.\n", id->newid->name, ob->proxy->id.name); + continue; + } + + BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib); + + /* We can only switch the proxy'ing to a made-local proxy if it is no longer + * referred to from a library. Not checking for local use; if new local proxy + * was not used locally would be a nasty bug! */ + if (is_local || is_lib) { + printf("Warning, made-local proxy object %s will loose its link to %s, " + "because the linked-in proxy is referenced (is_local=%i, is_lib=%i).\n", + id->newid->name, ob->proxy->id.name, is_local, is_lib); + } + else { + /* we can switch the proxy'ing from the linked-in to the made-local proxy. + * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that + * was already allocated by BKE_object_make_local_ex() (which called BKE_object_copy_ex). */ + ob_new->proxy = ob->proxy; + ob_new->proxy_group = ob->proxy_group; + ob_new->proxy_from = ob->proxy_from; + ob_new->proxy->proxy_from = ob_new; + ob->proxy = ob->proxy_from = ob->proxy_group = NULL; + } + } + } +#else + LinkNode *linked_loop_candidates = NULL; + /* Step 5: remove datablocks that have been copied to be localized and are no more used in the end... * Note that we may have to loop more than once here, to tackle dependencies between linked objects... */ bool do_loop = true; @@ -1800,6 +2008,8 @@ void BKE_library_make_local( if (!is_local) { if (!is_lib) { /* Not used at all, we can free it! */ + BLI_assert(!"Unused linked data copy remaining from MakeLibLocal process, should not happen anymore"); + printf("\t%s (from %s)\n", id->name, id->lib->id.name); BKE_libblock_free(bmain, id); it->link = NULL; do_loop = true; @@ -1813,7 +2023,7 @@ void BKE_library_make_local( /* Grrrrrrr... those half-datablocks-stuff... grrrrrrrrrrr... * Here we have to also tag them as potential candidates, otherwise they would falsy report - * ID they used as 'directly used' in fourth step. */ + * ID they used as 'directly used' in sixth step. */ ID *ntree = (ID *)ntreeFromID(id); if (ntree != NULL) { ntree->tag |= LIB_TAG_DOIT; @@ -1838,6 +2048,7 @@ void BKE_library_make_local( /* Note: in theory here we are only handling datablocks forming exclusive linked dependency-cycles-based * archipelagos, so no need to check again after we have deleted one, as done in previous step. */ if (id->tag & LIB_TAG_DOIT) { + BLI_assert(!"Unused linked data copy remaining from MakeLibLocal process (archipelago case), should not happen anymore"); /* Object's deletion rely on valid ob->data, but ob->data may have already been freed here... * Setting it to NULL may not be 100% correct, but should be safe and do the work. */ if (GS(id->name) == ID_OB) { @@ -1858,6 +2069,7 @@ void BKE_library_make_local( it->link = NULL; } } +#endif BKE_main_id_clear_newpoins(bmain); BLI_memarena_free(linklist_mem); diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index bfc26fcac0f..a071b3202be 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -63,10 +63,12 @@ #include "DNA_world_types.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" #include "BLI_ghash.h" #include "BLI_linklist_stack.h" #include "BKE_animsys.h" +#include "BKE_collection.h" #include "BKE_constraint.h" #include "BKE_fcurve.h" #include "BKE_library.h" @@ -83,11 +85,12 @@ #define FOREACH_FINALIZE _finalize #define FOREACH_FINALIZE_VOID FOREACH_FINALIZE: (void)0 -#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, cb_flag) \ +#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, _cb_flag) \ + CHECK_TYPE(id_pp, ID **); \ if (!((_data)->status & IDWALK_STOP)) { \ const int _flag = (_data)->flag; \ ID *old_id = *(id_pp); \ - const int callback_return = (_data)->callback((_data)->user_data, (_data)->self_id, id_pp, cb_flag | (_data)->cd_flag); \ + const int callback_return = (_data)->callback((_data)->user_data, (_data)->self_id, id_pp, _cb_flag | (_data)->cb_flag); \ if (_flag & IDWALK_READONLY) { \ BLI_assert(*(id_pp) == old_id); \ } \ @@ -128,7 +131,7 @@ enum { typedef struct LibraryForeachIDData { ID *self_id; int flag; - int cd_flag; + int cb_flag; LibraryIDLinkCallback callback; void *user_data; int status; @@ -139,19 +142,19 @@ typedef struct LibraryForeachIDData { } LibraryForeachIDData; static void library_foreach_rigidbodyworldSceneLooper( - struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cd_flag) + struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); FOREACH_FINALIZE_VOID; } static void library_foreach_modifiersForeachIDLink( - void *user_data, Object *UNUSED(object), ID **id_pointer, int cd_flag) + void *user_data, Object *UNUSED(object), ID **id_pointer, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); FOREACH_FINALIZE_VOID; } @@ -160,44 +163,44 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID bool is_reference, void *user_data) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - const int cd_flag = is_reference ? IDWALK_USER : IDWALK_NOP; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + const int cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP; + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); FOREACH_FINALIZE_VOID; } static void library_foreach_particlesystemsObjectLooper( - ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cd_flag) + ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); FOREACH_FINALIZE_VOID; } static void library_foreach_sensorsObjectLooper( - bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cd_flag) + bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); FOREACH_FINALIZE_VOID; } static void library_foreach_controllersObjectLooper( - bController *UNUSED(controller), ID **id_pointer, void *user_data, int cd_flag) + bController *UNUSED(controller), ID **id_pointer, void *user_data, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); FOREACH_FINALIZE_VOID; } static void library_foreach_actuatorsObjectLooper( - bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cd_flag) + bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); FOREACH_FINALIZE_VOID; } @@ -206,7 +209,7 @@ static void library_foreach_nla_strip(LibraryForeachIDData *data, NlaStrip *stri { NlaStrip *substrip; - FOREACH_CALLBACK_INVOKE(data, strip->act, IDWALK_USER); + FOREACH_CALLBACK_INVOKE(data, strip->act, IDWALK_CB_USER); for (substrip = strip->strips.first; substrip; substrip = substrip->next) { library_foreach_nla_strip(data, substrip); @@ -229,14 +232,14 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData * /* only used targets */ DRIVER_TARGETS_USED_LOOPER(dvar) { - FOREACH_CALLBACK_INVOKE_ID(data, dtar->id, IDWALK_NOP); + FOREACH_CALLBACK_INVOKE_ID(data, dtar->id, IDWALK_CB_NOP); } DRIVER_TARGETS_LOOPER_END } } - FOREACH_CALLBACK_INVOKE(data, adt->action, IDWALK_USER); - FOREACH_CALLBACK_INVOKE(data, adt->tmpact, IDWALK_USER); + FOREACH_CALLBACK_INVOKE(data, adt->action, IDWALK_CB_USER); + FOREACH_CALLBACK_INVOKE(data, adt->tmpact, IDWALK_CB_USER); for (nla_track = adt->nla_tracks.first; nla_track; nla_track = nla_track->next) { for (nla_strip = nla_track->strips.first; nla_strip; nla_strip = nla_strip->next) { @@ -249,23 +252,28 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData * static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex) { - FOREACH_CALLBACK_INVOKE(data, mtex->object, IDWALK_NOP); - FOREACH_CALLBACK_INVOKE(data, mtex->tex, IDWALK_USER); + FOREACH_CALLBACK_INVOKE(data, mtex->object, IDWALK_CB_NOP); + FOREACH_CALLBACK_INVOKE(data, mtex->tex, IDWALK_CB_USER); FOREACH_FINALIZE_VOID; } static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint) { - FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_USER); - FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_USER); + FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_CB_USER); + FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_CB_USER); FOREACH_FINALIZE_VOID; } static void library_foreach_ID_as_subdata_link( - ID *id, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data) + ID **id_pp, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data) { + /* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */ + ID *id = *id_pp; + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pp, IDWALK_CB_PRIVATE); + BLI_assert(id == *id_pp); + if (flag & IDWALK_RECURSE) { /* Defer handling into main loop, recursively calling BKE_library_foreach_ID_link in IDWALK_RECURSE case is * troublesome, see T49553. */ @@ -275,8 +283,10 @@ static void library_foreach_ID_as_subdata_link( } } else { - BKE_library_foreach_ID_link(id, callback, user_data, flag); + BKE_library_foreach_ID_link(NULL, id, callback, user_data, flag); } + + FOREACH_FINALIZE_VOID; } /** @@ -284,7 +294,7 @@ static void library_foreach_ID_as_subdata_link( * * \note: May be extended to be recursive in the future. */ -void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *user_data, int flag) +void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag) { LibraryForeachIDData data; int i; @@ -312,9 +322,21 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u #define CALLBACK_INVOKE(check_id_super, cb_flag) \ FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag) - do { + for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) { data.self_id = id; - data.cd_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_INDIRECT_USAGE : 0; + data.cb_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_CB_INDIRECT_USAGE : 0; + + if (bmain != NULL && bmain->relations != NULL && (flag & IDWALK_READONLY)) { + /* Note that this is minor optimization, even in worst cases (like id being an object with lots of + * drivers and constraints and modifiers, or material etc. with huge node tree), + * but we might as well use it (Main->relations is always assumed valid, it's responsability of code + * creating it to free it, especially if/when it starts modifying Main database). */ + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id); + for (; entry != NULL; entry = entry->next) { + FOREACH_CALLBACK_INVOKE_ID_PP(&data, entry->id_pointer, entry->usage_flag); + } + continue; + } AnimData *adt = BKE_animdata_from_id(id); if (adt) { @@ -325,7 +347,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_LI: { Library *lib = (Library *) id; - CALLBACK_INVOKE(lib->parent, IDWALK_NOP); + CALLBACK_INVOKE(lib->parent, IDWALK_CB_NOP); break; } case ID_SCE: @@ -333,41 +355,41 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u Scene *scene = (Scene *) id; ToolSettings *toolsett = scene->toolsettings; SceneRenderLayer *srl; - Base *base; + BaseLegacy *legacy_base; - CALLBACK_INVOKE(scene->camera, IDWALK_NOP); - CALLBACK_INVOKE(scene->world, IDWALK_USER); - CALLBACK_INVOKE(scene->set, IDWALK_NOP); - CALLBACK_INVOKE(scene->clip, IDWALK_USER); + CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP); + CALLBACK_INVOKE(scene->world, IDWALK_CB_USER); + CALLBACK_INVOKE(scene->set, IDWALK_CB_NOP); + CALLBACK_INVOKE(scene->clip, IDWALK_CB_USER); if (scene->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link((ID *)scene->nodetree, callback, user_data, flag, &data); + library_foreach_ID_as_subdata_link((ID **)&scene->nodetree, callback, user_data, flag, &data); } /* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later, * since basact is just a pointer to one of those items. */ - CALLBACK_INVOKE(scene->obedit, IDWALK_NOP); + CALLBACK_INVOKE(scene->obedit, IDWALK_CB_NOP); for (srl = scene->r.layers.first; srl; srl = srl->next) { FreestyleModuleConfig *fmc; FreestyleLineSet *fls; if (srl->mat_override) { - CALLBACK_INVOKE(srl->mat_override, IDWALK_USER); + CALLBACK_INVOKE(srl->mat_override, IDWALK_CB_USER); } if (srl->light_override) { - CALLBACK_INVOKE(srl->light_override, IDWALK_USER); + CALLBACK_INVOKE(srl->light_override, IDWALK_CB_USER); } for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { if (fmc->script) { - CALLBACK_INVOKE(fmc->script, IDWALK_NOP); + CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP); } } for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { if (fls->group) { - CALLBACK_INVOKE(fls->group, IDWALK_USER); + CALLBACK_INVOKE(fls->group, IDWALK_CB_USER); } if (fls->linestyle) { - CALLBACK_INVOKE(fls->linestyle, IDWALK_USER); + CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER); } } } @@ -376,38 +398,59 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u Sequence *seq; SEQP_BEGIN(scene->ed, seq) { - CALLBACK_INVOKE(seq->scene, IDWALK_NOP); - CALLBACK_INVOKE(seq->scene_camera, IDWALK_NOP); - CALLBACK_INVOKE(seq->clip, IDWALK_USER); - CALLBACK_INVOKE(seq->mask, IDWALK_USER); - CALLBACK_INVOKE(seq->sound, IDWALK_USER); + CALLBACK_INVOKE(seq->scene, IDWALK_CB_NOP); + CALLBACK_INVOKE(seq->scene_camera, IDWALK_CB_NOP); + CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER); + CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER); + CALLBACK_INVOKE(seq->sound, IDWALK_CB_USER); for (SequenceModifierData *smd = seq->modifiers.first; smd; smd = smd->next) { - CALLBACK_INVOKE(smd->mask_id, IDWALK_USER); + CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER); } } SEQ_END } - CALLBACK_INVOKE(scene->gpd, IDWALK_USER); + CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER); + + for (legacy_base = scene->base.first; legacy_base; legacy_base = legacy_base->next) { + CALLBACK_INVOKE(legacy_base->object, IDWALK_CB_USER); + } + + SceneCollection *sc; + FOREACH_SCENE_COLLECTION(scene, sc) + { + for (LinkData *link = sc->objects.first; link; link = link->next) { + CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER); + } + + for (LinkData *link = sc->filter_objects.first; link; link = link->next) { + CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER); + } + } + FOREACH_SCENE_COLLECTION_END - for (base = scene->base.first; base; base = base->next) { - CALLBACK_INVOKE(base->object, IDWALK_USER); + SceneLayer *sl; + for (sl = scene->render_layers.first; sl; sl = sl->next) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + CALLBACK_INVOKE(base->object, IDWALK_NOP); + } } for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) { - CALLBACK_INVOKE(marker->camera, IDWALK_NOP); + CALLBACK_INVOKE(marker->camera, IDWALK_CB_NOP); } if (toolsett) { - CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_CB_NOP); + + CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_CB_NOP); + CALLBACK_INVOKE(toolsett->particle.object, IDWALK_CB_NOP); + CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_CB_NOP); - CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->particle.object, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_NOP); library_foreach_paint(&data, &toolsett->imapaint.paint); - CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_USER); - CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_USER); - CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_USER); + CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_CB_USER); + CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_CB_USER); + CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_CB_USER); if (toolsett->vpaint) { library_foreach_paint(&data, &toolsett->vpaint->paint); @@ -417,7 +460,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } if (toolsett->sculpt) { library_foreach_paint(&data, &toolsett->sculpt->paint); - CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_CB_NOP); } if (toolsett->uvsculpt) { library_foreach_paint(&data, &toolsett->uvsculpt->paint); @@ -428,7 +471,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u BKE_rigidbody_world_id_loop(scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, &data); } - CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_NOP); + CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_CB_NOP); break; } @@ -439,75 +482,75 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u ParticleSystem *psys; /* Object is special, proxies make things hard... */ - const int data_cd_flag = data.cd_flag; - const int proxy_cd_flag = (object->proxy || object->proxy_group) ? IDWALK_INDIRECT_USAGE : 0; + const int data_cb_flag = data.cb_flag; + const int proxy_cb_flag = (object->proxy || object->proxy_group) ? IDWALK_CB_INDIRECT_USAGE : 0; /* object data special case */ - data.cd_flag |= proxy_cd_flag; + data.cb_flag |= proxy_cb_flag; if (object->type == OB_EMPTY) { /* empty can have NULL or Image */ - CALLBACK_INVOKE_ID(object->data, IDWALK_USER); + CALLBACK_INVOKE_ID(object->data, IDWALK_CB_USER); } else { /* when set, this can't be NULL */ if (object->data) { - CALLBACK_INVOKE_ID(object->data, IDWALK_USER | IDWALK_NEVER_NULL); + CALLBACK_INVOKE_ID(object->data, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL); } } - data.cd_flag = data_cd_flag; + data.cb_flag = data_cb_flag; - CALLBACK_INVOKE(object->parent, IDWALK_NOP); - CALLBACK_INVOKE(object->track, IDWALK_NOP); + CALLBACK_INVOKE(object->parent, IDWALK_CB_NOP); + CALLBACK_INVOKE(object->track, IDWALK_CB_NOP); /* object->proxy is refcounted, but not object->proxy_group... *sigh* */ - CALLBACK_INVOKE(object->proxy, IDWALK_USER); - CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP); + CALLBACK_INVOKE(object->proxy, IDWALK_CB_USER); + CALLBACK_INVOKE(object->proxy_group, IDWALK_CB_NOP); /* Special case! * Since this field is set/owned by 'user' of this ID (and not ID itself), it is only indirect usage * if proxy object is linked... Twisted. */ if (object->proxy_from) { - data.cd_flag = ID_IS_LINKED_DATABLOCK(object->proxy_from) ? IDWALK_INDIRECT_USAGE : 0; + data.cb_flag = ID_IS_LINKED_DATABLOCK(object->proxy_from) ? IDWALK_CB_INDIRECT_USAGE : 0; } - CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP); - data.cd_flag = data_cd_flag; + CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_NOP); + data.cb_flag = data_cb_flag; - CALLBACK_INVOKE(object->poselib, IDWALK_USER); + CALLBACK_INVOKE(object->poselib, IDWALK_CB_USER); - data.cd_flag |= proxy_cd_flag; + data.cb_flag |= proxy_cb_flag; for (i = 0; i < object->totcol; i++) { - CALLBACK_INVOKE(object->mat[i], IDWALK_USER); + CALLBACK_INVOKE(object->mat[i], IDWALK_CB_USER); } - data.cd_flag = data_cd_flag; + data.cb_flag = data_cb_flag; - CALLBACK_INVOKE(object->gpd, IDWALK_USER); - CALLBACK_INVOKE(object->dup_group, IDWALK_USER); + CALLBACK_INVOKE(object->gpd, IDWALK_CB_USER); + CALLBACK_INVOKE(object->dup_group, IDWALK_CB_USER); if (object->pd) { - CALLBACK_INVOKE(object->pd->tex, IDWALK_USER); - CALLBACK_INVOKE(object->pd->f_source, IDWALK_NOP); + CALLBACK_INVOKE(object->pd->tex, IDWALK_CB_USER); + CALLBACK_INVOKE(object->pd->f_source, IDWALK_CB_NOP); } /* Note that ob->effect is deprecated, so no need to handle it here. */ if (object->pose) { bPoseChannel *pchan; - data.cd_flag |= proxy_cd_flag; + data.cb_flag |= proxy_cb_flag; for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) { - CALLBACK_INVOKE(pchan->custom, IDWALK_USER); + CALLBACK_INVOKE(pchan->custom, IDWALK_CB_USER); BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data); } - data.cd_flag = data_cd_flag; + data.cb_flag = data_cb_flag; } if (object->rigidbody_constraint) { - CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_NOP); - CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_NOP); + CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_CB_NOP); + CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_CB_NOP); } if (object->lodlevels.first) { LodLevel *level; for (level = object->lodlevels.first; level; level = level->next) { - CALLBACK_INVOKE(level->source, IDWALK_NOP); + CALLBACK_INVOKE(level->source, IDWALK_CB_NOP); } } @@ -519,10 +562,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } if (object->soft) { - CALLBACK_INVOKE(object->soft->collision_group, IDWALK_NOP); + CALLBACK_INVOKE(object->soft->collision_group, IDWALK_CB_NOP); if (object->soft->effector_weights) { - CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_NOP); + CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_CB_NOP); } } @@ -535,10 +578,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_ME: { Mesh *mesh = (Mesh *) id; - CALLBACK_INVOKE(mesh->texcomesh, IDWALK_USER); - CALLBACK_INVOKE(mesh->key, IDWALK_USER); + CALLBACK_INVOKE(mesh->texcomesh, IDWALK_CB_USER); + CALLBACK_INVOKE(mesh->key, IDWALK_CB_USER); for (i = 0; i < mesh->totcol; i++) { - CALLBACK_INVOKE(mesh->mat[i], IDWALK_USER); + CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER); } /* XXX Really not happy with this - probably texface should rather use some kind of @@ -550,7 +593,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u MTexPoly *txface = (MTexPoly *)mesh->pdata.layers[i].data; for (int j = 0; j < mesh->totpoly; j++, txface++) { - CALLBACK_INVOKE(txface->tpage, IDWALK_USER_ONE); + CALLBACK_INVOKE(txface->tpage, IDWALK_CB_USER_ONE); } } } @@ -560,7 +603,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u MTFace *tface = (MTFace *)mesh->fdata.layers[i].data; for (int j = 0; j < mesh->totface; j++, tface++) { - CALLBACK_INVOKE(tface->tpage, IDWALK_USER_ONE); + CALLBACK_INVOKE(tface->tpage, IDWALK_CB_USER_ONE); } } } @@ -571,17 +614,17 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_CU: { Curve *curve = (Curve *) id; - CALLBACK_INVOKE(curve->bevobj, IDWALK_NOP); - CALLBACK_INVOKE(curve->taperobj, IDWALK_NOP); - CALLBACK_INVOKE(curve->textoncurve, IDWALK_NOP); - CALLBACK_INVOKE(curve->key, IDWALK_USER); + CALLBACK_INVOKE(curve->bevobj, IDWALK_CB_NOP); + CALLBACK_INVOKE(curve->taperobj, IDWALK_CB_NOP); + CALLBACK_INVOKE(curve->textoncurve, IDWALK_CB_NOP); + CALLBACK_INVOKE(curve->key, IDWALK_CB_USER); for (i = 0; i < curve->totcol; i++) { - CALLBACK_INVOKE(curve->mat[i], IDWALK_USER); + CALLBACK_INVOKE(curve->mat[i], IDWALK_CB_USER); } - CALLBACK_INVOKE(curve->vfont, IDWALK_USER); - CALLBACK_INVOKE(curve->vfontb, IDWALK_USER); - CALLBACK_INVOKE(curve->vfonti, IDWALK_USER); - CALLBACK_INVOKE(curve->vfontbi, IDWALK_USER); + CALLBACK_INVOKE(curve->vfont, IDWALK_CB_USER); + CALLBACK_INVOKE(curve->vfontb, IDWALK_CB_USER); + CALLBACK_INVOKE(curve->vfonti, IDWALK_CB_USER); + CALLBACK_INVOKE(curve->vfontbi, IDWALK_CB_USER); break; } @@ -589,7 +632,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u { MetaBall *metaball = (MetaBall *) id; for (i = 0; i < metaball->totcol; i++) { - CALLBACK_INVOKE(metaball->mat[i], IDWALK_USER); + CALLBACK_INVOKE(metaball->mat[i], IDWALK_CB_USER); } break; } @@ -604,9 +647,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } if (material->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link((ID *)material->nodetree, callback, user_data, flag, &data); + library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data); } - CALLBACK_INVOKE(material->group, IDWALK_USER); + CALLBACK_INVOKE(material->group, IDWALK_CB_USER); break; } @@ -615,26 +658,26 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u Tex *texture = (Tex *) id; if (texture->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link((ID *)texture->nodetree, callback, user_data, flag, &data); + library_foreach_ID_as_subdata_link((ID **)&texture->nodetree, callback, user_data, flag, &data); } - CALLBACK_INVOKE(texture->ima, IDWALK_USER); + CALLBACK_INVOKE(texture->ima, IDWALK_CB_USER); if (texture->env) { - CALLBACK_INVOKE(texture->env->object, IDWALK_NOP); - CALLBACK_INVOKE(texture->env->ima, IDWALK_USER); + CALLBACK_INVOKE(texture->env->object, IDWALK_CB_NOP); + CALLBACK_INVOKE(texture->env->ima, IDWALK_CB_USER); } if (texture->pd) - CALLBACK_INVOKE(texture->pd->object, IDWALK_NOP); + CALLBACK_INVOKE(texture->pd->object, IDWALK_CB_NOP); if (texture->vd) - CALLBACK_INVOKE(texture->vd->object, IDWALK_NOP); + CALLBACK_INVOKE(texture->vd->object, IDWALK_CB_NOP); if (texture->ot) - CALLBACK_INVOKE(texture->ot->object, IDWALK_NOP); + CALLBACK_INVOKE(texture->ot->object, IDWALK_CB_NOP); break; } case ID_LT: { Lattice *lattice = (Lattice *) id; - CALLBACK_INVOKE(lattice->key, IDWALK_USER); + CALLBACK_INVOKE(lattice->key, IDWALK_CB_USER); break; } @@ -648,7 +691,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } if (lamp->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link((ID *)lamp->nodetree, callback, user_data, flag, &data); + library_foreach_ID_as_subdata_link((ID **)&lamp->nodetree, callback, user_data, flag, &data); } break; } @@ -656,7 +699,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_CA: { Camera *camera = (Camera *) id; - CALLBACK_INVOKE(camera->dof_ob, IDWALK_NOP); + CALLBACK_INVOKE(camera->dof_ob, IDWALK_CB_NOP); break; } @@ -667,14 +710,14 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u * (see also foreach_libblock_id_users_callback). */ Key *key = (Key *) id; - CALLBACK_INVOKE_ID(key->from, IDWALK_NOP); + CALLBACK_INVOKE_ID(key->from, IDWALK_CB_NOP); break; } case ID_SCR: { bScreen *screen = (bScreen *) id; - CALLBACK_INVOKE(screen->scene, IDWALK_USER_ONE); + CALLBACK_INVOKE(screen->scene, IDWALK_CB_USER_ONE); break; } @@ -688,7 +731,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } if (world->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link((ID *)world->nodetree, callback, user_data, flag, &data); + library_foreach_ID_as_subdata_link((ID **)&world->nodetree, callback, user_data, flag, &data); } break; } @@ -696,7 +739,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_SPK: { Speaker *speaker = (Speaker *) id; - CALLBACK_INVOKE(speaker->sound, IDWALK_USER); + CALLBACK_INVOKE(speaker->sound, IDWALK_CB_USER); break; } @@ -705,7 +748,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u Group *group = (Group *) id; GroupObject *gob; for (gob = group->gobject.first; gob; gob = gob->next) { - CALLBACK_INVOKE(gob->ob, IDWALK_USER_ONE); + CALLBACK_INVOKE(gob->ob, IDWALK_CB_USER_ONE); } break; } @@ -714,9 +757,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u { bNodeTree *ntree = (bNodeTree *) id; bNode *node; - CALLBACK_INVOKE(ntree->gpd, IDWALK_USER); + CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER); for (node = ntree->nodes.first; node; node = node->next) { - CALLBACK_INVOKE_ID(node->id, IDWALK_USER); + CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER); } break; } @@ -724,9 +767,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_BR: { Brush *brush = (Brush *) id; - CALLBACK_INVOKE(brush->toggle_brush, IDWALK_NOP); - CALLBACK_INVOKE(brush->clone.image, IDWALK_NOP); - CALLBACK_INVOKE(brush->paint_curve, IDWALK_USER); + CALLBACK_INVOKE(brush->toggle_brush, IDWALK_CB_NOP); + CALLBACK_INVOKE(brush->clone.image, IDWALK_CB_NOP); + CALLBACK_INVOKE(brush->paint_curve, IDWALK_CB_USER); library_foreach_mtex(&data, &brush->mtex); library_foreach_mtex(&data, &brush->mask_mtex); break; @@ -735,10 +778,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_PA: { ParticleSettings *psett = (ParticleSettings *) id; - CALLBACK_INVOKE(psett->dup_group, IDWALK_NOP); - CALLBACK_INVOKE(psett->dup_ob, IDWALK_NOP); - CALLBACK_INVOKE(psett->bb_ob, IDWALK_NOP); - CALLBACK_INVOKE(psett->collision_group, IDWALK_NOP); + CALLBACK_INVOKE(psett->dup_group, IDWALK_CB_NOP); + CALLBACK_INVOKE(psett->dup_ob, IDWALK_CB_NOP); + CALLBACK_INVOKE(psett->bb_ob, IDWALK_CB_NOP); + CALLBACK_INVOKE(psett->collision_group, IDWALK_CB_NOP); for (i = 0; i < MAX_MTEX; i++) { if (psett->mtex[i]) { @@ -747,16 +790,16 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } if (psett->effector_weights) { - CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_NOP); + CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_CB_NOP); } if (psett->pd) { - CALLBACK_INVOKE(psett->pd->tex, IDWALK_USER); - CALLBACK_INVOKE(psett->pd->f_source, IDWALK_NOP); + CALLBACK_INVOKE(psett->pd->tex, IDWALK_CB_USER); + CALLBACK_INVOKE(psett->pd->f_source, IDWALK_CB_NOP); } if (psett->pd2) { - CALLBACK_INVOKE(psett->pd2->tex, IDWALK_USER); - CALLBACK_INVOKE(psett->pd2->f_source, IDWALK_NOP); + CALLBACK_INVOKE(psett->pd2->tex, IDWALK_CB_USER); + CALLBACK_INVOKE(psett->pd2->f_source, IDWALK_CB_NOP); } if (psett->boids) { @@ -767,11 +810,11 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u for (rule = state->rules.first; rule; rule = rule->next) { if (rule->type == eBoidRuleType_Avoid) { BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; - CALLBACK_INVOKE(gabr->ob, IDWALK_NOP); + CALLBACK_INVOKE(gabr->ob, IDWALK_CB_NOP); } else if (rule->type == eBoidRuleType_FollowLeader) { BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; - CALLBACK_INVOKE(flbr->ob, IDWALK_NOP); + CALLBACK_INVOKE(flbr->ob, IDWALK_CB_NOP); } } } @@ -787,19 +830,19 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u MovieTrackingTrack *track; MovieTrackingPlaneTrack *plane_track; - CALLBACK_INVOKE(clip->gpd, IDWALK_USER); + CALLBACK_INVOKE(clip->gpd, IDWALK_CB_USER); for (track = tracking->tracks.first; track; track = track->next) { - CALLBACK_INVOKE(track->gpd, IDWALK_USER); + CALLBACK_INVOKE(track->gpd, IDWALK_CB_USER); } for (object = tracking->objects.first; object; object = object->next) { for (track = object->tracks.first; track; track = track->next) { - CALLBACK_INVOKE(track->gpd, IDWALK_USER); + CALLBACK_INVOKE(track->gpd, IDWALK_CB_USER); } } for (plane_track = tracking->plane_tracks.first; plane_track; plane_track = plane_track->next) { - CALLBACK_INVOKE(plane_track->image, IDWALK_USER); + CALLBACK_INVOKE(plane_track->image, IDWALK_CB_USER); } break; } @@ -814,7 +857,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u for (mask_spline = mask_layer->splines.first; mask_spline; mask_spline = mask_spline->next) { for (i = 0; i < mask_spline->tot_point; i++) { MaskSplinePoint *point = &mask_spline->points[i]; - CALLBACK_INVOKE_ID(point->parent.id, IDWALK_USER); + CALLBACK_INVOKE_ID(point->parent.id, IDWALK_CB_USER); } } } @@ -832,14 +875,14 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } if (linestyle->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link((ID *)linestyle->nodetree, callback, user_data, flag, &data); + library_foreach_ID_as_subdata_link((ID **)&linestyle->nodetree, callback, user_data, flag, &data); } for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) { if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)lsm; if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_NOP); + CALLBACK_INVOKE(p->target, IDWALK_CB_NOP); } } } @@ -847,7 +890,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)lsm; if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_NOP); + CALLBACK_INVOKE(p->target, IDWALK_CB_NOP); } } } @@ -855,7 +898,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)lsm; if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_NOP); + CALLBACK_INVOKE(p->target, IDWALK_CB_NOP); } } } @@ -866,7 +909,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u bAction *act = (bAction *) id; for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { - CALLBACK_INVOKE(marker->camera, IDWALK_NOP); + CALLBACK_INVOKE(marker->camera, IDWALK_CB_NOP); } break; } @@ -889,7 +932,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u break; } - } while ((id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL)); + } FOREACH_FINALIZE: if (data.ids_handled) { @@ -907,13 +950,13 @@ FOREACH_FINALIZE: /** * re-usable function, use when replacing ID's */ -void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cd_flag) +void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag) { - if (cd_flag & IDWALK_USER) { + if (cb_flag & IDWALK_CB_USER) { id_us_min(id_src); id_us_plus(id_dst); } - else if (cd_flag & IDWALK_USER_ONE) { + else if (cb_flag & IDWALK_CB_USER_ONE) { id_us_ensure_real(id_dst); } } @@ -943,7 +986,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id /* Could be the following, but simpler to just always say 'yes' here. */ #if 0 return ELEM(id_type_used, ID_ME, ID_CU, ID_MB, ID_LT, ID_SPK, ID_AR, ID_LA, ID_CA, /* obdata */ - ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC + ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_PA, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC /* + constraints, modifiers and game logic ID types... */); #else return true; @@ -1047,7 +1090,7 @@ static int foreach_libblock_id_users_callback(void *user_data, ID *self_id, ID * (iter->id->tag & LIB_TAG_EXTRAUSER) ? 1 : 0, (iter->id->tag & LIB_TAG_EXTRAUSER_SET) ? 1 : 0, (cb_flag & IDWALK_INDIRECT_USAGE) ? 1 : 0); #endif - if (cb_flag & IDWALK_INDIRECT_USAGE) { + if (cb_flag & IDWALK_CB_INDIRECT_USAGE) { iter->count_indirect++; } else { @@ -1078,7 +1121,7 @@ int BKE_library_ID_use_ID(ID *id_user, ID *id_used) iter.curr_id = id_user; iter.count_direct = iter.count_indirect = 0; - BKE_library_foreach_ID_link(iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_NOP); + BKE_library_foreach_ID_link(NULL, iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_READONLY); return iter.count_direct + iter.count_indirect; } @@ -1107,7 +1150,7 @@ static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked) } iter.curr_id = id_curr; BKE_library_foreach_ID_link( - id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP); + bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY); is_defined = ((check_linked ? iter.count_indirect : iter.count_direct) != 0); } @@ -1158,7 +1201,7 @@ void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, boo continue; } iter.curr_id = id_curr; - BKE_library_foreach_ID_link(id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP); + BKE_library_foreach_ID_link(bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY); is_defined = (iter.count_direct != 0 && iter.count_indirect != 0); } @@ -1235,7 +1278,8 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag) /* Unused ID (so far), no need to check it further. */ continue; } - BKE_library_foreach_ID_link(id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_NOP); + BKE_library_foreach_ID_link( + bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY); } } } @@ -1262,7 +1306,8 @@ void BKE_library_indirectly_used_data_tag_clear(Main *bmain) /* Local or non-indirectly-used ID (so far), no need to check it further. */ continue; } - BKE_library_foreach_ID_link(id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_NOP); + BKE_library_foreach_ID_link( + bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY); } } } diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index d7d566a9ec0..9946d1cc81f 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -71,6 +71,7 @@ #include "BKE_brush.h" #include "BKE_camera.h" #include "BKE_cachefile.h" +#include "BKE_collection.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_fcurve.h" @@ -158,6 +159,10 @@ enum { static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id_p, int cb_flag) { + if (cb_flag & IDWALK_CB_PRIVATE) { + return IDWALK_RET_NOP; + } + IDRemap *id_remap_data = user_data; ID *old_id = id_remap_data->old_id; ID *new_id = id_remap_data->new_id; @@ -169,14 +174,14 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id } if (*id_p && (*id_p == old_id)) { - const bool is_indirect = (cb_flag & IDWALK_INDIRECT_USAGE) != 0; + const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0; const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0; /* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct, * on the other hand since they get reset to lib data on file open/reload it is indirect too... * Edit Mode is also a 'skip direct' case. */ const bool is_obj = (GS(id->name) == ID_OB); const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id)); - const bool is_never_null = ((cb_flag & IDWALK_NEVER_NULL) && (new_id == NULL) && + const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) && (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0); const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0; @@ -185,7 +190,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id id->name, old_id->name, old_id, new_id ? new_id->name : "<NONE>", new_id, skip_indirect); #endif - if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_NEVER_NULL)) { + if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_CB_NEVER_NULL)) { id->tag |= LIB_TAG_DOIT; } @@ -203,10 +208,10 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id else { BLI_assert(0); } - if (cb_flag & IDWALK_USER) { + if (cb_flag & IDWALK_CB_USER) { id_remap_data->skipped_refcounted++; } - else if (cb_flag & IDWALK_USER_ONE) { + else if (cb_flag & IDWALK_CB_USER_ONE) { /* No need to count number of times this happens, just a flag is enough. */ id_remap_data->status |= ID_REMAP_IS_USER_ONE_SKIPPED; } @@ -216,13 +221,13 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id *id_p = new_id; DAG_id_tag_update_ex(id_remap_data->bmain, id_self, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } - if (cb_flag & IDWALK_USER) { + if (cb_flag & IDWALK_CB_USER) { id_us_min(old_id); /* We do not want to handle LIB_TAG_INDIRECT/LIB_TAG_EXTERN here. */ if (new_id) new_id->us++; } - else if (cb_flag & IDWALK_USER_ONE) { + else if (cb_flag & IDWALK_CB_USER_ONE) { id_us_ensure_real(new_id); /* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET) are assumed to be set as needed, * that extra user is processed in final handling... */ @@ -238,7 +243,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id /* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */ static void libblock_remap_data_preprocess_scene_base_unlink( - IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect) + IDRemap *r_id_remap_data, Scene *sce, BaseLegacy *base, const bool skip_indirect, const bool is_indirect) { if (skip_indirect && is_indirect) { r_id_remap_data->skipped_indirect++; @@ -254,6 +259,22 @@ static void libblock_remap_data_preprocess_scene_base_unlink( } } +/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */ +static void libblock_remap_data_preprocess_scene_object_unlink( + IDRemap *r_id_remap_data, Scene *sce, Object *ob, const bool skip_indirect, const bool is_indirect) +{ + if (skip_indirect && is_indirect) { + r_id_remap_data->skipped_indirect++; + r_id_remap_data->skipped_refcounted++; + } + else { + BKE_collections_object_remove(r_id_remap_data->bmain, sce, ob, false); + if (!is_indirect) { + r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT; + } + } +} + static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data) { switch (GS(r_id_remap_data->id->name)) { @@ -268,7 +289,16 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data) /* In case we are unlinking... */ if (!r_id_remap_data->old_id) { /* ... everything from scene. */ - Base *base, *base_next; + Object *ob_iter; + FOREACH_SCENE_OBJECT(sce, ob_iter) + { + libblock_remap_data_preprocess_scene_object_unlink( + r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect); + } + FOREACH_SCENE_OBJECT_END + + + BaseLegacy *base, *base_next; for (base = sce->base.first; base; base = base_next) { base_next = base->next; libblock_remap_data_preprocess_scene_base_unlink( @@ -278,8 +308,11 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data) else if (GS(r_id_remap_data->old_id->name) == ID_OB) { /* ... a specific object from scene. */ Object *old_ob = (Object *)r_id_remap_data->old_id; - Base *base = BKE_scene_base_find(sce, old_ob); + libblock_remap_data_preprocess_scene_object_unlink( + r_id_remap_data, sce, old_ob, skip_indirect, is_indirect); + + BaseLegacy *base = BKE_scene_base_find(sce, old_ob); if (base) { libblock_remap_data_preprocess_scene_base_unlink( r_id_remap_data, sce, base, skip_indirect, is_indirect); @@ -325,7 +358,7 @@ static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain, } if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */ for (Group *group = bmain->group.first; group; group = group->id.next) { - BKE_group_object_unlink(group, NULL, NULL, NULL); + BKE_group_object_unlink(group, NULL); } } else { @@ -338,23 +371,17 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai { /* Note that here we assume no object has no base (i.e. all objects are assumed instanced * in one scene...). */ - for (Base *base = sce->base.first; base; base = base->next) { - if (base->flag & OB_FROMGROUP) { - Object *ob = base->object; - - if (ob->flag & OB_FROMGROUP) { - Group *grp = BKE_group_object_find(NULL, ob); - - /* Unlinked group (old_id) is still in bmain... */ - if (grp && (&grp->id == old_id || grp->id.us == 0)) { - grp = BKE_group_object_find(grp, ob); - } - if (!grp) { - ob->flag &= ~OB_FROMGROUP; - } + for (BaseLegacy *base = sce->base.first; base; base = base->next) { + Object *ob = base->object; + if (ob->flag & OB_FROMGROUP) { + Group *grp = BKE_group_object_find(NULL, ob); + + /* Unlinked group (old_id) is still in bmain... */ + if (grp && (&grp->id == old_id || grp->id.us == 0)) { + grp = BKE_group_object_find(grp, ob); } - if (!(ob->flag & OB_FROMGROUP)) { - base->flag &= ~OB_FROMGROUP; + if (!grp) { + ob->flag &= ~OB_FROMGROUP; } } } @@ -434,7 +461,7 @@ ATTR_NONNULL(1) static void libblock_remap_data( #endif r_id_remap_data->id = id; libblock_remap_data_preprocess(r_id_remap_data); - BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP); + BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP); } else { i = set_listbasepointers(bmain, lb_array); @@ -456,7 +483,7 @@ ATTR_NONNULL(1) static void libblock_remap_data( r_id_remap_data->id = id_curr; libblock_remap_data_preprocess(r_id_remap_data); BKE_library_foreach_ID_link( - id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP); + NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP); } } } @@ -685,13 +712,17 @@ void BKE_libblock_relink_ex( } } -static int id_relink_to_newid_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cd_flag) +static int id_relink_to_newid_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cb_flag) { + if (cb_flag & IDWALK_CB_PRIVATE) { + return IDWALK_RET_NOP; + } + ID *id = *id_pointer; if (id) { /* See: NEW_ID macro */ if (id->newid) { - BKE_library_update_ID_link_user(id->newid, id, cd_flag); + BKE_library_update_ID_link_user(id->newid, id, cb_flag); *id_pointer = id->newid; } else if (id->tag & LIB_TAG_NEW) { @@ -711,7 +742,7 @@ void BKE_libblock_relink_to_newid(ID *id) if (ID_IS_LINKED_DATABLOCK(id)) return; - BKE_library_foreach_ID_link(id, id_relink_to_newid_looper, NULL, 0); + BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0); } void BKE_libblock_free_data(Main *UNUSED(bmain), ID *id) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 54945242fe4..435504859a4 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -111,6 +111,12 @@ void BKE_material_free(Material *ma) BKE_icon_id_delete((ID *)ma); BKE_previewimg_free(&ma->preview); + + for (MaterialEngineSettings *mes = ma->engines_settings.first; mes; mes = mes->next) { + if (mes->data) + MEM_SAFE_FREE(mes->data); + } + BLI_freelistN(&ma->engines_settings); } void BKE_material_init(Material *ma) @@ -248,6 +254,8 @@ Material *BKE_material_copy(Main *bmain, Material *ma) BLI_listbase_clear(&man->gpumaterial); + /* TODO Duplicate Engine Settings and set runtime to NULL */ + BKE_id_copy_ensure_local(bmain, &ma->id, &man->id); return man; @@ -279,6 +287,8 @@ Material *localize_material(Material *ma) man->nodetree = ntreeLocalize(ma->nodetree); BLI_listbase_clear(&man->gpumaterial); + + /* TODO Duplicate Engine Settings and set runtime to NULL */ return man; } @@ -1698,6 +1708,7 @@ void copy_matcopybuf(Material *ma) matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false); matcopybuf.preview = NULL; BLI_listbase_clear(&matcopybuf.gpumaterial); + /* TODO Duplicate Engine Settings and set runtime to NULL */ matcopied = 1; } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 97033a9555d..2632acea58b 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -316,7 +316,7 @@ bool BKE_mball_is_basis_for(Object *ob1, Object *ob2) void BKE_mball_properties_copy(Scene *scene, Object *active_object) { Scene *sce_iter = scene; - Base *base; + BaseLegacy *base; Object *ob; MetaBall *active_mball = (MetaBall *)active_object->data; int basisnr, obnr; @@ -359,27 +359,25 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object) */ Object *BKE_mball_basis_find(Scene *scene, Object *basis) { - Scene *sce_iter = scene; - Base *base; - Object *ob, *bob = basis; + Object *bob = basis; int basisnr, obnr; char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; - SceneBaseIter iter; - EvaluationContext *eval_ctx = G.main->eval_ctx; BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); - while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { - if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) { - if (ob != bob) { - BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); - - /* object ob has to be in same "group" ... it means, that it has to have same base of its name */ - if (STREQ(obname, basisname)) { - if (obnr < basisnr) { - basis = ob; - basisnr = obnr; + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + Object *ob = base->object; + if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) { + if (ob != bob) { + BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); + + /* object ob has to be in same "group" ... it means, that it has to have same base of its name */ + if (STREQ(obname, basisname)) { + if (obnr < basisnr) { + basis = ob; + basisnr = obnr; + } } } } diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 5c0b09f0ff0..144a885ffd4 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -1080,7 +1080,7 @@ static void polygonize(PROCESS *process) static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) { Scene *sce_iter = scene; - Base *base; + BaseLegacy *base; Object *bob; MetaBall *mb; const MetaElem *ml; @@ -1102,7 +1102,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen zero_size = 0; ml = NULL; - if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) { + if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) { mb = ob->data; if (mb->editelems) ml = mb->editelems->first; diff --git a/source/blender/blenkernel/intern/mesh_render.c b/source/blender/blenkernel/intern/mesh_render.c index 4118208d32f..fd0f49810fb 100644 --- a/source/blender/blenkernel/intern/mesh_render.c +++ b/source/blender/blenkernel/intern/mesh_render.c @@ -47,7 +47,7 @@ /* Mesh Interface */ #define MESH_RENDER_FUNCTION(func_name) \ - if (me->edit_btmesh) { \ + if (me->edit_btmesh && me->edit_btmesh->derivedFinal) { \ return mesh_bmesh_##func_name(me); \ } \ else { \ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 3f3b4896653..05422a01dbf 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3776,3 +3776,20 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, return true; } + +/* -------------------------------------------------------------------- */ +/* NodeTree kernel functions */ + +void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index) +{ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) { + if (node->custom1 == layer_index) { + node->custom1 = 0; + } + else if (node->custom1 > layer_index) { + node->custom1--; + } + } + } +} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 171c369b3b0..c0540192422 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -91,6 +91,7 @@ #include "BKE_icons.h" #include "BKE_key.h" #include "BKE_lamp.h" +#include "BKE_layer.h" #include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_library_query.h" @@ -153,7 +154,7 @@ void BKE_object_workob_clear(Object *workob) void BKE_object_update_base_layer(struct Scene *scene, Object *ob) { - Base *base = scene->base.first; + BaseLegacy *base = scene->base.first; while (base) { if (base->object == ob) base->lay = ob->lay; @@ -458,6 +459,11 @@ void BKE_object_free(Object *ob) } BKE_previewimg_free(&ob->preview); + + if (ob->collection_settings) { + BKE_layer_collection_engine_settings_free(ob->collection_settings); + MEM_freeN(ob->collection_settings); + } } /* actual check for internal data, not context or flags */ @@ -677,23 +683,25 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) /* general add: to scene, with layer from area and default name */ /* creates minimum required data, but without vertices etc. */ Object *BKE_object_add( - Main *bmain, Scene *scene, + Main *bmain, Scene *scene, SceneLayer *sl, int type, const char *name) { Object *ob; Base *base; + LayerCollection *lc; ob = BKE_object_add_only_object(bmain, type, name); ob->data = BKE_object_obdata_add_from_type(bmain, type, name); - ob->lay = scene->lay; - - base = BKE_scene_base_add(scene, ob); - BKE_scene_base_deselect_all(scene); - BKE_scene_base_select(scene, base); - DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + lc = BKE_layer_collection_active(sl); + BKE_collection_object_add(scene, lc->scene_collection, ob); + base = BKE_scene_layer_base_find(sl, ob); + BKE_scene_layer_base_deselect_all(sl); + BKE_scene_layer_base_select(sl, base); + + DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); return ob; } @@ -1204,7 +1212,7 @@ void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, con if (lib_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &ob->id); - BKE_id_expand_local(&ob->id); + BKE_id_expand_local(bmain, &ob->id); if (clear_proxy) { if (ob->proxy_from != NULL) { ob->proxy_from->proxy = NULL; @@ -2236,18 +2244,6 @@ void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3], } } -void BKE_boundbox_scale(struct BoundBox *bb_dst, const struct BoundBox *bb_src, float scale) -{ - float cent[3]; - BKE_boundbox_calc_center_aabb(bb_src, cent); - - for (int i = 0; i < ARRAY_SIZE(bb_dst->vec); i++) { - bb_dst->vec[i][0] = ((bb_src->vec[i][0] - cent[0]) * scale) + cent[0]; - bb_dst->vec[i][1] = ((bb_src->vec[i][1] - cent[1]) * scale) + cent[1]; - bb_dst->vec[i][2] = ((bb_src->vec[i][2] - cent[2]) * scale) + cent[2]; - } -} - /** * Returns a BBox which each dimensions are at least epsilon. * \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range. @@ -2554,11 +2550,11 @@ void BKE_scene_foreach_display_point( Scene *scene, View3D *v3d, const short flag, void (*func_cb)(const float[3], void *), void *user_data) { - Base *base; + BaseLegacy *base; Object *ob; for (base = FIRSTBASE; base; base = base->next) { - if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag & flag) == flag) { + if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag_legacy & flag) == flag) { ob = base->object; if ((ob->transflag & OB_DUPLI) == 0) { @@ -2816,45 +2812,6 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, return 1; } -/* - * Test a bounding box for ray intersection - * assumes the ray is already local to the boundbox space - */ -bool BKE_boundbox_ray_hit_check( - const struct BoundBox *bb, - const float ray_start[3], const float ray_normal[3], - float *r_lambda) -{ - const int triangle_indexes[12][3] = { - {0, 1, 2}, {0, 2, 3}, - {3, 2, 6}, {3, 6, 7}, - {1, 2, 6}, {1, 6, 5}, - {5, 6, 7}, {4, 5, 7}, - {0, 3, 7}, {0, 4, 7}, - {0, 1, 5}, {0, 4, 5}}; - - bool result = false; - int i; - - for (i = 0; i < 12 && (!result || r_lambda); i++) { - float lambda; - int v1, v2, v3; - v1 = triangle_indexes[i][0]; - v2 = triangle_indexes[i][1]; - v3 = triangle_indexes[i][2]; - if (isect_ray_tri_v3(ray_start, ray_normal, bb->vec[v1], bb->vec[v2], bb->vec[v3], &lambda, NULL) && - (!r_lambda || *r_lambda > lambda)) - { - result = true; - if (r_lambda) { - *r_lambda = lambda; - } - } - } - - return result; -} - static int pc_cmp(const void *a, const void *b) { const LinkData *ad = a, *bd = b; @@ -3402,7 +3359,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS { LinkNode *links = NULL; - Base *base; + BaseLegacy *base; /* Remove markers from all objects */ for (base = scene->base.first; base; base = base->next) { @@ -3446,7 +3403,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS /* child relationship */ if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) { - Base *local_base; + BaseLegacy *local_base; for (local_base = scene->base.first; local_base; local_base = local_base->next) { if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) { @@ -3492,18 +3449,11 @@ struct LinkNode *BKE_object_groups(Object *ob) return group_linknode; } -void BKE_object_groups_clear(Scene *scene, Base *base, Object *object) +void BKE_object_groups_clear(Object *ob) { Group *group = NULL; - - BLI_assert((base == NULL) || (base->object == object)); - - if (scene && base == NULL) { - base = BKE_scene_base_find(scene, object); - } - - while ((group = BKE_group_object_find(group, base->object))) { - BKE_group_object_unlink(group, object, scene, base); + while ((group = BKE_group_object_find(group, ob))) { + BKE_group_object_unlink(group, ob); } } diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index e3b801b3193..26af1c48afb 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -241,7 +241,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild else { unsigned int lay = ctx->scene->lay; int baseid = 0; - Base *base; + BaseLegacy *base; for (base = ctx->scene->base.first; base; base = base->next, baseid++) { Object *ob = base->object; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 1ea27558545..228ae6afaba 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -633,8 +633,9 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa data->childcachebufs.last = psys->childcachebufs.last; data->totchildcache = psys->totchildcache; - if (psmd->dm_final) - data->dm = CDDM_copy(psmd->dm_final); + if (psmd->dm_final) { + data->dm = CDDM_copy_with_tessface(psmd->dm_final); + } data->totdmvert = psmd->totdmvert; data->totdmedge = psmd->totdmedge; data->totdmface = psmd->totdmface; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index ee435051151..8531c7c9df9 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2896,7 +2896,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; ParticleEditSettings *pset = &sim->scene->toolsettings->particle; - Base *base; + BaseLegacy *base; int distr=0, alloc=0, skip=0; if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET) @@ -4328,12 +4328,12 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, { ParticleTarget *pt; - func(psys, (ID **)&psys->part, userdata, IDWALK_USER | IDWALK_NEVER_NULL); - func(psys, (ID **)&psys->target_ob, userdata, IDWALK_NOP); - func(psys, (ID **)&psys->parent, userdata, IDWALK_NOP); + func(psys, (ID **)&psys->part, userdata, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL); + func(psys, (ID **)&psys->target_ob, userdata, IDWALK_CB_NOP); + func(psys, (ID **)&psys->parent, userdata, IDWALK_CB_NOP); for (pt = psys->targets.first; pt; pt = pt->next) { - func(psys, (ID **)&pt->ob, userdata, IDWALK_NOP); + func(psys, (ID **)&pt->ob, userdata, IDWALK_CB_NOP); } /* Even though psys->part should never be NULL, this can happen as an exception during deletion. @@ -4343,7 +4343,7 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, int p; for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) { - func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_NOP); + func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_CB_NOP); } } } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 30eb8dcb287..c3f2107c5af 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3541,7 +3541,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) Main *bmain = baker->main; Scene *scene = baker->scene; Scene *sce_iter; /* SETLOOPER macro only */ - Base *base; + BaseLegacy *base; ListBase pidlist; PTCacheID *pid = &baker->pid; PointCache *cache = NULL; diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 6f86c68dc07..73fe5ae6cb8 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -974,14 +974,14 @@ void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw) void BKE_rigidbody_world_id_loop(RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata) { - func(rbw, (ID **)&rbw->group, userdata, IDWALK_NOP); - func(rbw, (ID **)&rbw->constraints, userdata, IDWALK_NOP); - func(rbw, (ID **)&rbw->effector_weights->group, userdata, IDWALK_NOP); + func(rbw, (ID **)&rbw->group, userdata, IDWALK_CB_NOP); + func(rbw, (ID **)&rbw->constraints, userdata, IDWALK_CB_NOP); + func(rbw, (ID **)&rbw->effector_weights->group, userdata, IDWALK_CB_NOP); if (rbw->objects) { int i; for (i = 0; i < rbw->numbodies; i++) { - func(rbw, (ID **)&rbw->objects[i], userdata, IDWALK_NOP); + func(rbw, (ID **)&rbw->objects[i], userdata, IDWALK_CB_NOP); } } } diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index fa221348932..7920d8b5696 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -992,19 +992,19 @@ void BKE_sca_sensors_id_loop(ListBase *senslist, SCASensorIDFunc func, void *use bSensor *sensor; for (sensor = senslist->first; sensor; sensor = sensor->next) { - func(sensor, (ID **)&sensor->ob, userdata, IDWALK_NOP); + func(sensor, (ID **)&sensor->ob, userdata, IDWALK_CB_NOP); switch (sensor->type) { case SENS_TOUCH: /* DEPRECATED */ { bTouchSensor *ts = sensor->data; - func(sensor, (ID **)&ts->ma, userdata, IDWALK_NOP); + func(sensor, (ID **)&ts->ma, userdata, IDWALK_CB_NOP); break; } case SENS_MESSAGE: { bMessageSensor *ms = sensor->data; - func(sensor, (ID **)&ms->fromObject, userdata, IDWALK_NOP); + func(sensor, (ID **)&ms->fromObject, userdata, IDWALK_CB_NOP); break; } case SENS_ALWAYS: @@ -1035,7 +1035,7 @@ void BKE_sca_controllers_id_loop(ListBase *contlist, SCAControllerIDFunc func, v case CONT_PYTHON: { bPythonCont *pc = controller->data; - func(controller, (ID **)&pc->text, userdata, IDWALK_NOP); + func(controller, (ID **)&pc->text, userdata, IDWALK_CB_NOP); break; } case CONT_LOGIC_AND: @@ -1056,89 +1056,89 @@ void BKE_sca_actuators_id_loop(ListBase *actlist, SCAActuatorIDFunc func, void * bActuator *actuator; for (actuator = actlist->first; actuator; actuator = actuator->next) { - func(actuator, (ID **)&actuator->ob, userdata, IDWALK_NOP); + func(actuator, (ID **)&actuator->ob, userdata, IDWALK_CB_NOP); switch (actuator->type) { case ACT_ADD_OBJECT: /* DEPRECATED */ { bAddObjectActuator *aoa = actuator->data; - func(actuator, (ID **)&aoa->ob, userdata, IDWALK_NOP); + func(actuator, (ID **)&aoa->ob, userdata, IDWALK_CB_NOP); break; } case ACT_ACTION: { bActionActuator *aa = actuator->data; - func(actuator, (ID **)&aa->act, userdata, IDWALK_NOP); + func(actuator, (ID **)&aa->act, userdata, IDWALK_CB_NOP); break; } case ACT_SOUND: { bSoundActuator *sa = actuator->data; - func(actuator, (ID **)&sa->sound, userdata, IDWALK_NOP); + func(actuator, (ID **)&sa->sound, userdata, IDWALK_CB_NOP); break; } case ACT_EDIT_OBJECT: { bEditObjectActuator *eoa = actuator->data; - func(actuator, (ID **)&eoa->ob, userdata, IDWALK_NOP); - func(actuator, (ID **)&eoa->me, userdata, IDWALK_NOP); + func(actuator, (ID **)&eoa->ob, userdata, IDWALK_CB_NOP); + func(actuator, (ID **)&eoa->me, userdata, IDWALK_CB_NOP); break; } case ACT_SCENE: { bSceneActuator *sa = actuator->data; - func(actuator, (ID **)&sa->scene, userdata, IDWALK_NOP); - func(actuator, (ID **)&sa->camera, userdata, IDWALK_NOP); + func(actuator, (ID **)&sa->scene, userdata, IDWALK_CB_NOP); + func(actuator, (ID **)&sa->camera, userdata, IDWALK_CB_NOP); break; } case ACT_PROPERTY: { bPropertyActuator *pa = actuator->data; - func(actuator, (ID **)&pa->ob, userdata, IDWALK_NOP); + func(actuator, (ID **)&pa->ob, userdata, IDWALK_CB_NOP); break; } case ACT_OBJECT: { bObjectActuator *oa = actuator->data; - func(actuator, (ID **)&oa->reference, userdata, IDWALK_NOP); + func(actuator, (ID **)&oa->reference, userdata, IDWALK_CB_NOP); break; } case ACT_CAMERA: { bCameraActuator *ca = actuator->data; - func(actuator, (ID **)&ca->ob, userdata, IDWALK_NOP); + func(actuator, (ID **)&ca->ob, userdata, IDWALK_CB_NOP); break; } case ACT_MESSAGE: { bMessageActuator *ma = actuator->data; - func(actuator, (ID **)&ma->toObject, userdata, IDWALK_NOP); + func(actuator, (ID **)&ma->toObject, userdata, IDWALK_CB_NOP); break; } case ACT_2DFILTER: { bTwoDFilterActuator *tdfa = actuator->data; - func(actuator, (ID **)&tdfa->text, userdata, IDWALK_NOP); + func(actuator, (ID **)&tdfa->text, userdata, IDWALK_CB_NOP); break; } case ACT_PARENT: { bParentActuator *pa = actuator->data; - func(actuator, (ID **)&pa->ob, userdata, IDWALK_NOP); + func(actuator, (ID **)&pa->ob, userdata, IDWALK_CB_NOP); break; } case ACT_ARMATURE: { bArmatureActuator *aa = actuator->data; - func(actuator, (ID **)&aa->target, userdata, IDWALK_NOP); - func(actuator, (ID **)&aa->subtarget, userdata, IDWALK_NOP); + func(actuator, (ID **)&aa->target, userdata, IDWALK_CB_NOP); + func(actuator, (ID **)&aa->subtarget, userdata, IDWALK_CB_NOP); break; } case ACT_STEERING: { bSteeringActuator *sa = actuator->data; - func(actuator, (ID **)&sa->target, userdata, IDWALK_NOP); - func(actuator, (ID **)&sa->navmesh, userdata, IDWALK_NOP); + func(actuator, (ID **)&sa->target, userdata, IDWALK_CB_NOP); + func(actuator, (ID **)&sa->navmesh, userdata, IDWALK_CB_NOP); break; } /* Note: some types seems to be non-implemented? ACT_LAMP, ACT_MATERIAL... */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index a1338b4ea10..dc81dac134b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -67,6 +67,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_cachefile.h" +#include "BKE_collection.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" #include "BKE_editmesh.h" @@ -78,6 +79,7 @@ #include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_remap.h" #include "BKE_linestyle.h" @@ -107,6 +109,7 @@ const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER"; const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME"; +const char *RE_engine_id_BLENDER_CLAY = "BLENDER_CLAY"; const char *RE_engine_id_CYCLES = "CYCLES"; void free_avicodecdata(AviCodecData *acd) @@ -154,13 +157,66 @@ static void remove_sequencer_fcurves(Scene *sce) } } +/* copy SceneCollection tree but keep pointing to the same objects */ +static void scene_collection_copy(SceneCollection *scn, SceneCollection *sc) +{ + BLI_duplicatelist(&scn->objects, &sc->objects); + for (LinkData *link = scn->objects.first; link; link = link->next) { + id_us_plus(link->data); + } + + BLI_duplicatelist(&scn->filter_objects, &sc->filter_objects); + for (LinkData *link = scn->filter_objects.first; link; link = link->next) { + id_us_plus(link->data); + } + + BLI_duplicatelist(&scn->scene_collections, &sc->scene_collections); + SceneCollection *nscn = scn->scene_collections.first; /* nested SceneCollection new */ + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + scene_collection_copy(nscn, nsc); + nscn = nscn->next; + } +} + +/* Find the equivalent SceneCollection in the new tree */ +static SceneCollection *scene_collection_from_new_tree(SceneCollection *sc_reference, SceneCollection *scn, SceneCollection *sc) +{ + if (sc == sc_reference) { + return scn; + } + + SceneCollection *nscn = scn->scene_collections.first; /* nested master collection new */ + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + + SceneCollection *found = scene_collection_from_new_tree(sc_reference, nscn, nsc); + if (found) { + return found; + } + nscn = nscn->next; + } + return NULL; +} + +/* recreate the LayerCollection tree */ +static void layer_collections_recreate(SceneLayer *sl, ListBase *lb, SceneCollection *mcn, SceneCollection *mc) +{ + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + + SceneCollection *sc = scene_collection_from_new_tree(lc->scene_collection, mcn, mc); + BLI_assert(sc); + + /* instead of syncronizing both trees we simply re-create it */ + BKE_collection_link(sl, sc); + } +} + Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) { Scene *scen; SceneRenderLayer *srl, *new_srl; FreestyleLineSet *lineset; ToolSettings *ts; - Base *base, *obase; + BaseLegacy *legacy_base, *olegacy_base; if (type == SCE_COPY_EMPTY) { ListBase rl, rv; @@ -214,14 +270,14 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) BKE_libblock_relink_ex(bmain, scen->nodetree, &sce->id, &scen->id, false); } - obase = sce->base.first; - base = scen->base.first; - while (base) { - id_us_plus(&base->object->id); - if (obase == sce->basact) scen->basact = base; + olegacy_base = sce->base.first; + legacy_base = scen->base.first; + while (legacy_base) { + id_us_plus(&legacy_base->object->id); + if (olegacy_base == sce->basact) scen->basact = legacy_base; - obase = obase->next; - base = base->next; + olegacy_base = olegacy_base->next; + legacy_base = legacy_base->next; } /* copy action and remove animation used by sequencer */ @@ -244,6 +300,36 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) } new_srl = new_srl->next; } + + /* layers and collections */ + scen->collection = MEM_dupallocN(sce->collection); + SceneCollection *mcn = BKE_collection_master(scen); + SceneCollection *mc = BKE_collection_master(sce); + + /* recursively creates a new SceneCollection tree */ + scene_collection_copy(mcn, mc); + + BLI_duplicatelist(&scen->render_layers, &sce->render_layers); + SceneLayer *new_sl = scen->render_layers.first; + for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) { + + /* we start fresh with no overrides and no visibility flags set + * instead of syncing both trees we simply unlink and relink the scene collection */ + BLI_listbase_clear(&new_sl->layer_collections); + BLI_listbase_clear(&new_sl->object_bases); + layer_collections_recreate(new_sl, &sl->layer_collections, mcn, mc); + + if (sl->basact) { + Object *active_ob = sl->basact->object; + for (Base *base = new_sl->object_bases.first; base; base = base->next) { + if (base->object == active_ob) { + new_sl->basact = base; + break; + } + } + } + new_sl = new_sl->next; + } } /* copy color management settings */ @@ -471,6 +557,23 @@ void BKE_scene_free(Scene *sce) BKE_previewimg_free(&sce->preview); curvemapping_free_data(&sce->r.mblur_shutter_curve); + + for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) { + BKE_scene_layer_free(sl); + } + BLI_freelistN(&sce->render_layers); + + /* Master Collection */ + BKE_collection_master_free(sce); + MEM_freeN(sce->collection); + sce->collection = NULL; + + /* Runtime Engine Data */ + for (RenderEngineSettings *res = sce->engines_settings.first; res; res = res->next) { + if (res->data) + MEM_freeN(res->data); + } + BLI_freelistN(&sce->engines_settings); } void BKE_scene_init(Scene *sce) @@ -820,6 +923,12 @@ void BKE_scene_init(Scene *sce) sce->toolsettings->gpencil_v2d_align = GP_PROJECT_VIEWSPACE; sce->toolsettings->gpencil_seq_align = GP_PROJECT_VIEWSPACE; sce->toolsettings->gpencil_ima_align = GP_PROJECT_VIEWSPACE; + + /* Master Collection */ + sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection"); + BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name)); + + BKE_scene_layer_add(sce, "Render Layer"); } Scene *BKE_scene_add(Main *bmain, const char *name) @@ -835,9 +944,9 @@ Scene *BKE_scene_add(Main *bmain, const char *name) return sce; } -Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) +BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) { - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { if (STREQ(base->object->id.name + 2, name)) { @@ -848,9 +957,9 @@ Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) return base; } -Base *BKE_scene_base_find(Scene *scene, Object *ob) +BaseLegacy *BKE_scene_base_find(Scene *scene, Object *ob) { - return BLI_findptr(&scene->base, ob, offsetof(Base, object)); + return BLI_findptr(&scene->base, ob, offsetof(BaseLegacy, object)); } /** @@ -861,11 +970,10 @@ Base *BKE_scene_base_find(Scene *scene, Object *ob) void BKE_scene_set_background(Main *bmain, Scene *scene) { Scene *sce; - Base *base; + BaseLegacy *base; Object *ob; Group *group; GroupObject *go; - int flag; /* check for cyclic sets, for reading old files but also for definite security (py?) */ BKE_scene_validate_setscene(bmain, scene); @@ -897,13 +1005,7 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) ob->lay = base->lay; /* group patch... */ - base->flag &= ~(OB_FROMGROUP); - flag = ob->flag & (OB_FROMGROUP); - base->flag |= flag; - - /* not too nice... for recovering objects with lost data */ - //if (ob->pose == NULL) base->flag &= ~OB_POSEMODE; - ob->flag = base->flag; + BKE_scene_base_flag_sync_from_base(base); } /* no full animation update, this to enable render code to work (render code calls own animation updates) */ } @@ -924,7 +1026,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name) /* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, - Scene **scene, int val, Base **base, Object **ob) + Scene **scene, int val, BaseLegacy **base, Object **ob) { bool run_again = true; @@ -1006,7 +1108,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, } /* handle dupli's */ if (iter->dupob) { - (*base)->flag |= OB_FROMDUPLI; + (*base)->flag_legacy |= OB_FROMDUPLI; *ob = iter->dupob->ob; iter->phase = F_DUPLI; @@ -1025,7 +1127,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, } else if (iter->phase == F_DUPLI) { iter->phase = F_SCENE; - (*base)->flag &= ~OB_FROMDUPLI; + (*base)->flag_legacy &= ~OB_FROMDUPLI; if (iter->dupli_refob) { /* Restore last object's real matrix. */ @@ -1052,7 +1154,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, Object *BKE_scene_camera_find(Scene *sc) { - Base *base; + BaseLegacy *base; for (base = sc->base.first; base; base = base->next) if (base->object->type == OB_CAMERA) @@ -1154,47 +1256,54 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame) return best_marker ? best_marker->name : NULL; } +void BKE_scene_remove_rigidbody_object(Scene *scene, Object *ob) +{ + /* remove rigid body constraint from world before removing object */ + if (ob->rigidbody_constraint) + BKE_rigidbody_remove_constraint(scene, ob); + /* remove rigid body object from world before removing object */ + if (ob->rigidbody_object) + BKE_rigidbody_remove_object(scene, ob); +} -Base *BKE_scene_base_add(Scene *sce, Object *ob) +BaseLegacy *BKE_scene_base_add(Scene *sce, Object *ob) { - Base *b = MEM_callocN(sizeof(*b), __func__); + BaseLegacy *b = MEM_callocN(sizeof(*b), __func__); BLI_addhead(&sce->base, b); b->object = ob; - b->flag = ob->flag; + b->flag_legacy = ob->flag; b->lay = ob->lay; return b; } -void BKE_scene_base_unlink(Scene *sce, Base *base) +void BKE_scene_base_unlink(Scene *sce, BaseLegacy *base) { - /* remove rigid body constraint from world before removing object */ - if (base->object->rigidbody_constraint) - BKE_rigidbody_remove_constraint(sce, base->object); - /* remove rigid body object from world before removing object */ - if (base->object->rigidbody_object) - BKE_rigidbody_remove_object(sce, base->object); - + BKE_scene_remove_rigidbody_object(sce, base->object); + BLI_remlink(&sce->base, base); if (sce->basact == base) sce->basact = NULL; } +/* deprecated, use BKE_scene_layer_base_deselect_all */ void BKE_scene_base_deselect_all(Scene *sce) { - Base *b; + BaseLegacy *b; for (b = sce->base.first; b; b = b->next) { - b->flag &= ~SELECT; - b->object->flag = b->flag; + b->flag_legacy &= ~SELECT; + int flag = b->object->flag & (OB_FROMGROUP); + b->object->flag = b->flag_legacy; + b->object->flag |= flag; } } -void BKE_scene_base_select(Scene *sce, Base *selbase) +void BKE_scene_base_select(Scene *sce, BaseLegacy *selbase) { - selbase->flag |= SELECT; - selbase->object->flag = selbase->flag; + selbase->flag_legacy |= SELECT; + selbase->object->flag = selbase->flag_legacy; sce->basact = selbase; } @@ -1492,15 +1601,7 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * for (sce = bmain->scene.first; sce; sce = sce->id.next) { if (sce->nodetree) { - bNode *node; - for (node = sce->nodetree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) { - if (node->custom1 == act) - node->custom1 = 0; - else if (node->custom1 > act) - node->custom1--; - } - } + BKE_nodetree_remove_layer_n(sce->nodetree, scene, act); } } @@ -1588,7 +1689,7 @@ float get_render_aosss_error(const RenderData *r, float error) } /* helper function for the SETLOOPER macro */ -Base *_setlooper_base_step(Scene **sce_iter, Base *base) +BaseLegacy *_setlooper_base_step(Scene **sce_iter, BaseLegacy *base) { if (base && base->next) { /* common case, step to the next */ @@ -1596,12 +1697,12 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base) } else if (base == NULL && (*sce_iter)->base.first) { /* first time looping, return the scenes first base */ - return (Base *)(*sce_iter)->base.first; + return (BaseLegacy *)(*sce_iter)->base.first; } else { /* reached the end, get the next base in the set */ while ((*sce_iter = (*sce_iter)->set)) { - base = (Base *)(*sce_iter)->base.first; + base = (BaseLegacy *)(*sce_iter)->base.first; if (base) { return base; } @@ -1646,23 +1747,55 @@ bool BKE_scene_uses_blender_game(const Scene *scene) return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME); } -void BKE_scene_base_flag_to_objects(struct Scene *scene) +void BKE_scene_base_flag_to_objects(SceneLayer *sl) { - Base *base = scene->base.first; + Base *base = sl->object_bases.first; while (base) { - base->object->flag = base->flag; + BKE_scene_object_base_flag_sync_from_base(base); base = base->next; } } -void BKE_scene_base_flag_from_objects(struct Scene *scene) +void BKE_scene_base_flag_sync_from_base(BaseLegacy *base) { - Base *base = scene->base.first; + BKE_scene_object_base_flag_sync_from_base(base); +} - while (base) { - base->flag = base->object->flag; - base = base->next; +void BKE_scene_base_flag_sync_from_object(BaseLegacy *base) +{ + BKE_scene_object_base_flag_sync_from_object(base); +} + +void BKE_scene_object_base_flag_sync_from_base(Base *base) +{ + Object *ob = base->object; + + /* keep the object only flags untouched */ + int flag = ob->flag & OB_FROMGROUP; + + ob->flag = base->flag; + ob->flag |= flag; + + if ((base->flag & BASE_SELECTED) != 0) { + ob->flag |= SELECT; + } + else { + ob->flag &= ~SELECT; + } +} + +void BKE_scene_object_base_flag_sync_from_object(Base *base) +{ + Object *ob = base->object; + base->flag = ob->flag; + + if ((ob->flag & SELECT) != 0) { + base->flag |= BASE_SELECTED; + BLI_assert((base->flag & BASE_SELECTABLED) != 0); + } + else { + base->flag &= ~BASE_SELECTED; } } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 1d2f5aee440..6a491ba5ec4 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -480,55 +480,74 @@ void BKE_sequencer_editing_free(Scene *scene) static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) { - if (ibuf->rect_float) { + if (ibuf->rect != NULL) { + IMB_colormanagement_assign_rect_colorspace(ibuf, scene->sequencer_colorspace_settings.name); + } + if (ibuf->rect_float != NULL) { IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name); } } void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make_float) { - const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + /* Early output check: if both buffers are NULL we have nothing to convert. */ + if (ibuf->rect_float == NULL && ibuf->rect == NULL) { + return; + } + /* Get common conversion settings. */ const char *to_colorspace = scene->sequencer_colorspace_settings.name; - const char *float_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); - - if (!ibuf->rect_float) { - if (ibuf->rect) { - const char *byte_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf); - if (make_float || !STREQ(to_colorspace, byte_colorspace)) { - /* If byte space is not in sequencer's working space, we deliver float color space, - * this is to to prevent data loss. - */ - - /* when converting byte buffer to float in sequencer we need to make float - * buffer be in sequencer's working space, which is currently only doable - * from linear space. - */ - - /* - * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's - */ - - IMB_float_from_rect(ibuf); - } - else { - return; - } + /* Perform actual conversion logic. */ + if (ibuf->rect_float == NULL) { + /* We are not requested to give float buffer and byte buffer is already + * in thee required colorspace. Can skip doing anything here. + */ + const char *from_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf); + if (!make_float && STREQ(from_colorspace, to_colorspace)) { + return; + } + if (false) { + /* The idea here is to provide as fast playback as possible and + * enforcing float buffer here (a) uses more cache memory (b) might + * make some other effects slower to apply. + * + * However, this might also have negative effect by adding weird + * artifacts which will then not happen in final render. + */ + IMB_colormanagement_transform_byte_threaded( + (unsigned char*)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace); } else { - return; + /* We perform conversion to a float buffer so we don't worry about + * precision loss. + */ + imb_addrectfloatImBuf(ibuf); + IMB_colormanagement_transform_from_byte_threaded( + ibuf->rect_float, (unsigned char*)ibuf->rect, + ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace); + /* We don't need byte buffer anymore. */ + imb_freerectImBuf(ibuf); } } - - if (from_colorspace && from_colorspace[0] != '\0') { - if (ibuf->rect) + else { + const char *from_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); + /* Unknown input color space, can't perform conversion. */ + if (from_colorspace == NULL || from_colorspace[0] == '\0') { + return; + } + /* We don't want both byte and float buffers around: they'll either run + * out of sync or conversion of byte buffer will loose precision in there. + */ + if (ibuf->rect != NULL) { imb_freerectImBuf(ibuf); - - if (!STREQ(float_colorspace, to_colorspace)) { - IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, true); - sequencer_imbuf_assign_spaces(scene, ibuf); } + IMB_colormanagement_transform_threaded(ibuf->rect_float, + ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, + true); } + sequencer_imbuf_assign_spaces(scene, ibuf); } void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index d0ef5cfc092..f1ce69d3945 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -698,7 +698,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix static int get_lamp(Scene *scene, float *light) { - Base *base_tmp = NULL; + BaseLegacy *base_tmp = NULL; int found_lamp = 0; // try to find a lamp, preferably local diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 660107eb2e6..e7df1d810c9 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -530,7 +530,7 @@ static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexo } } else { - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { /*Only proceed for mesh object in same layer */ if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) { ob= base->object; @@ -576,7 +576,7 @@ static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertex } } else { - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { /*Only proceed for mesh object in same layer */ if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) { ob= base->object; @@ -986,7 +986,7 @@ static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer) } } else { - for (Base *base = scene->base.first; base; base= base->next) { + for (BaseLegacy *base = scene->base.first; base; base= base->next) { if ( (base->lay & layer) && base->object->pd) { if (base->object->pd->deflect) return 1; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 22288127119..fe4bcc738c6 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -147,12 +147,12 @@ void BKE_sound_free(bSound *sound) BKE_sound_free_waveform(sound); +#endif /* WITH_AUDASPACE */ if (sound->spinlock) { BLI_spin_end(sound->spinlock); MEM_freeN(sound->spinlock); sound->spinlock = NULL; - } -#endif /* WITH_AUDASPACE */ + } } void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local) @@ -782,7 +782,7 @@ void BKE_sound_read_waveform(bSound *sound, short *stop) void BKE_sound_update_scene(Main *bmain, struct Scene *scene) { Object *ob; - Base *base; + BaseLegacy *base; NlaTrack *track; NlaStrip *strip; Speaker *speaker; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 88575c7d3be..298790a9e9b 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -1935,7 +1935,7 @@ void txt_do_undo(Text *text) int op = text->undo_buf[text->undo_pos]; int prev_flags; unsigned int linep; - unsigned int uchar; + unsigned int uni_char; unsigned int curln, selln; unsigned short curc, selc; unsigned short charp; @@ -1971,14 +1971,14 @@ void txt_do_undo(Text *text) case UNDO_BS_3: case UNDO_BS_4: charp = op - UNDO_BS_1 + 1; - uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); /* get and restore the cursors */ txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); txt_move_to(text, curln, curc, 0); txt_move_to(text, curln, curc, 1); - txt_add_char(text, uchar); + txt_add_char(text, uni_char); text->undo_pos--; break; @@ -1988,14 +1988,14 @@ void txt_do_undo(Text *text) case UNDO_DEL_3: case UNDO_DEL_4: charp = op - UNDO_DEL_1 + 1; - uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); /* get and restore the cursors */ txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); txt_move_to(text, curln, curc, 0); txt_move_to(text, curln, curc, 1); - txt_add_char(text, uchar); + txt_add_char(text, uni_char); txt_move_left(text, 0); @@ -2163,7 +2163,7 @@ void txt_do_redo(Text *text) char *buf; unsigned int linep; unsigned short charp; - unsigned int uchar; + unsigned int uni_uchar; unsigned int curln, selln; unsigned short curc, selc; @@ -2190,9 +2190,9 @@ void txt_do_redo(Text *text) txt_move_to(text, curln, curc, 1); charp = op - UNDO_INSERT_1 + 1; - uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp); + uni_uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp); - txt_add_char(text, uchar); + txt_add_char(text, uni_uchar); break; case UNDO_BS_1: diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 2d3ecad19ad..60990c03b0e 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -1485,9 +1485,11 @@ bool BKE_texture_dependsOnTime(const struct Tex *texture) /* ------------------------------------------------------------------------- */ -void BKE_texture_get_value( +void BKE_texture_get_value_ex( const Scene *scene, Tex *texture, - float *tex_co, TexResult *texres, bool use_color_management) + float *tex_co, TexResult *texres, + struct ImagePool *pool, + bool use_color_management) { int result_type; bool do_color_manage = false; @@ -1497,7 +1499,7 @@ void BKE_texture_get_value( } /* no node textures for now */ - result_type = multitex_ext_safe(texture, tex_co, texres, NULL, do_color_manage, false); + result_type = multitex_ext_safe(texture, tex_co, texres, pool, do_color_manage, false); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, since this is in the context of modifiers don't use perceptual color conversion. @@ -1510,3 +1512,10 @@ void BKE_texture_get_value( copy_v3_fl(&texres->tr, texres->tin); } } + +void BKE_texture_get_value( + const Scene *scene, Tex *texture, + float *tex_co, TexResult *texres, bool use_color_management) +{ + BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management); +} diff --git a/source/blender/blenlib/BLI_dynlib.h b/source/blender/blenlib/BLI_dynlib.h index 7d5eb888021..310db9ea051 100644 --- a/source/blender/blenlib/BLI_dynlib.h +++ b/source/blender/blenlib/BLI_dynlib.h @@ -34,7 +34,7 @@ typedef struct DynamicLibrary DynamicLibrary; -DynamicLibrary *BLI_dynlib_open(char *name); +DynamicLibrary *BLI_dynlib_open(const char *name); void *BLI_dynlib_find_symbol(DynamicLibrary *lib, const char *symname); char *BLI_dynlib_get_error_as_string(DynamicLibrary *lib); void BLI_dynlib_close(DynamicLibrary *lib); diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 7e3a009ede8..068c188e336 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -32,6 +32,7 @@ * \ingroup bli */ +#include "BLI_blenlib.h" #include "BLI_sys_types.h" /* for bool */ #include "BLI_compiler_attrs.h" diff --git a/source/blender/blenlib/BLI_iterator.h b/source/blender/blenlib/BLI_iterator.h new file mode 100644 index 00000000000..d154b81ac82 --- /dev/null +++ b/source/blender/blenlib/BLI_iterator.h @@ -0,0 +1,54 @@ +/* + * ***** 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): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_ITERATOR_H__ +#define __BLI_ITERATOR_H__ + +/** \file BLI_iterator.h + * \ingroup bli + */ + +typedef struct Iterator { + void *current; /* current pointer we iterate over */ + void *data; /* stored data required for this iterator */ + bool valid; +} Iterator; + +typedef void (*IteratorCb)(Iterator *iter); +typedef void (*IteratorBeginCb)(Iterator *iter, void *data_in); + +#define ITER_BEGIN(callback_begin, callback_next, callback_end, _data_in, _type, _data_out) \ +{ \ + IteratorCb callback_end_func = callback_end; \ + Iterator iter_macro; \ + for (callback_begin(&iter_macro, _data_in); \ + iter_macro.valid; \ + callback_next(&iter_macro)) \ + { \ + _data_out = (_type *) iter_macro.current; + +#define ITER_END \ + } \ + callback_end_func(&iter_macro); \ +} + +#endif /* __BLI_ITERATOR_H__ */ diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index e3635be671f..4a85e859c16 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -293,6 +293,10 @@ void isect_ray_aabb_v3_precalc( bool isect_ray_aabb_v3( const struct IsectRayAABB_Precalc *data, const float bb_min[3], const float bb_max[3], float *tmin); +bool isect_ray_aabb_v3_simple( + const float orig[3], const float dir[3], + const float bb_min[3], const float bb_max[3], + float *tmin, float *tmax); struct NearestRayToAABB_Precalc { float ray_origin[3]; diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h index 7929e1d6551..9d8222c575d 100644 --- a/source/blender/blenlib/BLI_sys_types.h +++ b/source/blender/blenlib/BLI_sys_types.h @@ -80,6 +80,11 @@ typedef uint64_t u_int64_t; #include <stddef.h> /* size_t define */ #include <stdbool.h> +typedef unsigned int uint; +typedef unsigned short ushort; +typedef unsigned long ulong; +typedef unsigned char uchar; + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 3277519c66e..97225170f67 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -155,6 +155,7 @@ set(SRC BLI_hash_md5.h BLI_hash_mm2a.h BLI_heap.h + BLI_iterator.h BLI_jitter.h BLI_kdopbvh.h BLI_kdtree.h diff --git a/source/blender/blenlib/PIL_time_utildefines.h b/source/blender/blenlib/PIL_time_utildefines.h index 9157e04a7bf..412cfb3a090 100644 --- a/source/blender/blenlib/PIL_time_utildefines.h +++ b/source/blender/blenlib/PIL_time_utildefines.h @@ -80,9 +80,10 @@ } \ const float _delta_##var = TIMEIT_VALUE(var); \ _sum_##var += _delta_##var; \ + _num_##var++; \ printf("time end (" #var "): %.6f" " " AT "\n", _delta_##var); \ - printf("time averaged (" #var "): %.6f" " " AT "\n", \ - (_sum_##var / ++_num_##var)); \ + printf("time averaged (" #var "): %.6f (total: %.6f, in %d runs)\n", \ + (_sum_##var / _num_##var), _sum_##var, (int)_num_##var); \ fflush(stdout); \ } (void)0 diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c index b47c2ee60a6..51b91fb360f 100644 --- a/source/blender/blenlib/intern/dynlib.c +++ b/source/blender/blenlib/intern/dynlib.c @@ -50,7 +50,7 @@ struct DynamicLibrary { #include "utf_winfunc.h" #include "utfconv.h" -DynamicLibrary *BLI_dynlib_open(char *name) +DynamicLibrary *BLI_dynlib_open(const char *name) { DynamicLibrary *lib; void *handle; @@ -106,7 +106,7 @@ void BLI_dynlib_close(DynamicLibrary *lib) #include <dlfcn.h> -DynamicLibrary *BLI_dynlib_open(char *name) +DynamicLibrary *BLI_dynlib_open(const char *name) { DynamicLibrary *lib; void *handle = dlopen(name, RTLD_LAZY); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 8f5d84dfa08..aeb6a550cd9 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2309,6 +2309,34 @@ bool isect_ray_aabb_v3( return true; } +/* + * Test a bounding box (AABB) for ray intersection + * assumes the ray is already local to the boundbox space + */ +bool isect_ray_aabb_v3_simple( + const float orig[3], const float dir[3], + const float bb_min[3], const float bb_max[3], + float *tmin, float *tmax) +{ + double t[7]; + float hit_dist[2]; + t[1] = (double)(bb_min[0] - orig[0]) / dir[0]; + t[2] = (double)(bb_max[0] - orig[0]) / dir[0]; + t[3] = (double)(bb_min[1] - orig[1]) / dir[1]; + t[4] = (double)(bb_max[1] - orig[1]) / dir[1]; + t[5] = (double)(bb_min[2] - orig[2]) / dir[2]; + t[6] = (double)(bb_max[2] - orig[2]) / dir[2]; + hit_dist[0] = (float)fmax(fmax(fmin(t[1], t[2]), fmin(t[3], t[4])), fmin(t[5], t[6])); + hit_dist[1] = (float)fmin(fmin(fmax(t[1], t[2]), fmax(t[3], t[4])), fmax(t[5], t[6])); + if ((hit_dist[1] < 0 || hit_dist[0] > hit_dist[1])) + return false; + else { + if (tmin) *tmin = hit_dist[0]; + if (tmax) *tmax = hit_dist[1]; + return true; + } +} + void dist_squared_ray_to_aabb_v3_precalc( struct NearestRayToAABB_Precalc *data, const float ray_origin[3], const float ray_direction[3]) diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 8cb9ef837b2..e40692f4a88 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -53,6 +53,7 @@ set(SRC intern/versioning_250.c intern/versioning_260.c intern/versioning_270.c + intern/versioning_280.c intern/versioning_defaults.c intern/versioning_legacy.c intern/writefile.c diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9ee109431e7..9af85cc9ee9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -72,6 +72,7 @@ #include "DNA_ipo_types.h" #include "DNA_key_types.h" #include "DNA_lattice_types.h" +#include "DNA_layer_types.h" #include "DNA_lamp_types.h" #include "DNA_linestyle_types.h" #include "DNA_meta_types.h" @@ -102,6 +103,8 @@ #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" +#include "RNA_access.h" + #include "MEM_guardedalloc.h" #include "BLI_endian_switch.h" @@ -3967,6 +3970,7 @@ static void lib_link_material(FileData *fd, Main *main) static void direct_link_material(FileData *fd, Material *ma) { int a; + MaterialEngineSettings *mes; ma->adt = newdataadr(fd, ma->adt); direct_link_animdata(fd, ma->adt); @@ -3987,6 +3991,11 @@ static void direct_link_material(FileData *fd, Material *ma) ma->preview = direct_link_preview_image(fd, ma->preview); BLI_listbase_clear(&ma->gpumaterial); + + link_list(fd, &ma->engines_settings); + for (mes = ma->engines_settings.first; mes; mes = mes->next) { + mes->data = newdataadr(fd, mes->data); + } } /* ************ READ PARTICLE SETTINGS ***************** */ @@ -4709,12 +4718,12 @@ static void direct_link_latt(FileData *fd, Lattice *lt) /* ************ READ OBJECT ***************** */ static void lib_link_modifiers__linkModifiers( - void *userData, Object *ob, ID **idpoin, int cd_flag) + void *userData, Object *ob, ID **idpoin, int cb_flag) { FileData *fd = userData; *idpoin = newlibadr(fd, ob->id.lib, *idpoin); - if (*idpoin != NULL && (cd_flag & IDWALK_USER) != 0) { + if (*idpoin != NULL && (cb_flag & IDWALK_CB_USER) != 0) { id_us_plus_no_lib(*idpoin); } } @@ -5549,6 +5558,7 @@ static void direct_link_object(FileData *fd, Object *ob) ob->bb = NULL; ob->derivedDeform = NULL; ob->derivedFinal = NULL; + ob->collection_settings = NULL; BLI_listbase_clear(&ob->gpulamp); link_list(fd, &ob->pc_ids); @@ -5630,11 +5640,29 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene) } #endif +static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + link->data = newlibadr_us(fd, lib, link->data); + BLI_assert(link->data); + } + + for (LinkData *link = sc->filter_objects.first; link; link = link->next) { + link->data = newlibadr_us(fd, lib, link->data); + BLI_assert(link->data); + } + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + lib_link_scene_collection(fd, lib, nsc); + } +} + static void lib_link_scene(FileData *fd, Main *main) { Scene *sce; - Base *base, *next; + BaseLegacy *base_legacy, *base_legacy_next; Sequence *seq; + SceneLayer *sl; SceneRenderLayer *srl; FreestyleModuleConfig *fmc; FreestyleLineSet *fls; @@ -5684,17 +5712,17 @@ static void lib_link_scene(FileData *fd, Main *main) sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object); - for (base = sce->base.first; base; base = next) { - next = base->next; + for (base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) { + base_legacy_next = base_legacy->next; - base->object = newlibadr_us(fd, sce->id.lib, base->object); + base_legacy->object = newlibadr_us(fd, sce->id.lib, base_legacy->object); - if (base->object == NULL) { + if (base_legacy->object == NULL) { blo_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB: object lost from scene: '%s'"), sce->id.name + 2); - BLI_remlink(&sce->base, base); - if (base == sce->basact) sce->basact = NULL; - MEM_freeN(base); + BLI_remlink(&sce->base, base_legacy); + if (base_legacy == sce->basact) sce->basact = NULL; + MEM_freeN(base_legacy); } } @@ -5780,6 +5808,15 @@ static void lib_link_scene(FileData *fd, Main *main) /* Motion Tracking */ sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip); + lib_link_scene_collection(fd, sce->id.lib, sce->collection); + + for (sl = sce->render_layers.first; sl; sl = sl->next) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + /* we only bump the use count for the collection objects */ + base->object = newlibadr(fd, sce->id.lib, base->object); + } + } + #ifdef USE_SETSCENE_CHECK if (sce->set != NULL) { /* link flag for scenes with set would be reset later, @@ -5883,13 +5920,54 @@ static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *vi direct_link_curvemapping(fd, view_settings->curve_mapping); } +static void direct_link_scene_collection(FileData *fd, SceneCollection *sc) +{ + link_list(fd, &sc->objects); + link_list(fd, &sc->filter_objects); + link_list(fd, &sc->scene_collections); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + direct_link_scene_collection(fd, nsc); + } +} + +static void direct_link_engine_settings(FileData *fd, ListBase *lb) +{ + link_list(fd, lb); + for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) { + link_list(fd, &ces->properties); + } +} + +static void direct_link_layer_collections(FileData *fd, ListBase *lb) +{ + link_list(fd, lb); + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + lc->scene_collection = newdataadr(fd, lc->scene_collection); + + link_list(fd, &lc->object_bases); + + for (LinkData *link = lc->object_bases.first; link; link = link->next) { + link->data = newdataadr(fd, link->data); + } + + link_list(fd, &lc->overrides); + + direct_link_engine_settings(fd, &lc->engine_settings); + + direct_link_layer_collections(fd, &lc->layer_collections); + } +} + static void direct_link_scene(FileData *fd, Scene *sce) { Editing *ed; Sequence *seq; MetaStack *ms; RigidBodyWorld *rbw; + SceneLayer *sl; SceneRenderLayer *srl; + RenderEngineSettings *res; sce->theDag = NULL; sce->depsgraph = NULL; @@ -6139,6 +6217,24 @@ static void direct_link_scene(FileData *fd, Scene *sce) sce->preview = direct_link_preview_image(fd, sce->preview); direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve); + + /* this runs before the very first doversion */ + if (sce->collection) { + sce->collection = newdataadr(fd, sce->collection); + direct_link_scene_collection(fd, sce->collection); + } + + link_list(fd, &sce->render_layers); + for (sl = sce->render_layers.first; sl; sl = sl->next) { + link_list(fd, &sl->object_bases); + sl->basact = newdataadr(fd, sl->basact); + direct_link_layer_collections(fd, &sl->layer_collections); + } + + link_list(fd, &sce->engines_settings); + for (res = sce->engines_settings.first; res; res = res->next) { + res->data = newdataadr(fd, res->data); + } } /* ************ READ WM ***************** */ @@ -6482,6 +6578,10 @@ static void lib_link_screen(FileData *fd, Main *main) slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd); } + else if (sl->spacetype == SPACE_COLLECTIONS) { + SpaceCollections *slayer = (SpaceCollections *)sl; + slayer->flag |= SC_COLLECTION_DATA_REFRESH; + } } } sc->id.tag &= ~LIB_TAG_NEED_LINK; @@ -6867,6 +6967,10 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc slogic->gpd = restore_pointer_by_name(id_map, (ID *)slogic->gpd, USER_REAL); } + else if (sl->spacetype == SPACE_COLLECTIONS) { + SpaceCollections *slayer = (SpaceCollections *)sl; + slayer->flag |= SC_COLLECTION_DATA_REFRESH; + } } } } @@ -7261,6 +7365,10 @@ static bool direct_link_screen(FileData *fd, bScreen *sc) sclip->scopes.track_preview = NULL; sclip->scopes.ok = 0; } + else if (sl->spacetype == SPACE_COLLECTIONS) { + SpaceCollections *slayer = (SpaceCollections *)sl; + slayer->flag |= SC_COLLECTION_DATA_REFRESH; + } } BLI_listbase_clear(&sa->actionzones); @@ -7457,7 +7565,7 @@ static void lib_link_group(FileData *fd, Main *main) if (add_us) { id_us_ensure_real(&group->id); } - BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */ + BKE_group_object_unlink(group, NULL); /* removes NULL entries */ } } } @@ -8389,6 +8497,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) blo_do_versions_250(fd, lib, main); blo_do_versions_260(fd, lib, main); blo_do_versions_270(fd, lib, main); + blo_do_versions_280(fd, lib, main); /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */ @@ -8400,8 +8509,8 @@ static void do_versions_after_linking(Main *main) { // printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->name : main->name, // main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile); - do_versions_after_linking_270(main); + do_versions_after_linking_280(main); } static void lib_link_all(FileData *fd, Main *main) @@ -9308,7 +9417,7 @@ static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm) } static void expand_object_expandModifiers( - void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag)) + void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cb_flag)) { struct { FileData *fd; Main *mainvar; } *data= userData; @@ -9484,9 +9593,24 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) } } +static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + expand_doit(fd, mainvar, link->data); + } + + for (LinkData *link = sc->filter_objects.first; link; link = link->next) { + expand_doit(fd, mainvar, link->data); + } + + for (SceneCollection *nsc= sc->scene_collections.first; nsc; nsc = nsc->next) { + expand_scene_collection(fd, mainvar, nsc); + } +} + static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) { - Base *base; + BaseLegacy *base; SceneRenderLayer *srl; FreestyleModuleConfig *module; FreestyleLineSet *lineset; @@ -9553,6 +9677,8 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) } expand_doit(fd, mainvar, sce->clip); + + expand_scene_collection(fd, mainvar, sce->collection); } static void expand_camera(FileData *fd, Main *mainvar, Camera *ca) @@ -9799,7 +9925,7 @@ static bool object_in_any_scene(Main *mainvar, Object *ob) static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Library *lib, const short flag) { Object *ob; - Base *base; + BaseLegacy *base; const unsigned int active_lay = (flag & FILE_ACTIVELAY) ? BKE_screen_view3d_layer_active(v3d, scene) : 0; const bool is_link = (flag & FILE_LINK) != 0; @@ -9820,7 +9946,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra } if (do_it) { - base = MEM_callocN(sizeof(Base), __func__); + base = MEM_callocN(sizeof(BaseLegacy), __func__); BLI_addtail(&scene->base, base); if (active_lay) { @@ -9835,7 +9961,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra base->object = ob; base->lay = ob->lay; - base->flag = ob->flag; + BKE_scene_base_flag_sync_from_object(base); CLAMP_MIN(ob->id.us, 0); id_us_plus_no_lib((ID *)ob); @@ -9851,7 +9977,7 @@ static void give_base_to_groups( Main *mainvar, Scene *scene, View3D *v3d, Library *UNUSED(lib), const short UNUSED(flag)) { Group *group; - Base *base; + BaseLegacy *base; Object *ob; const unsigned int active_lay = BKE_screen_view3d_layer_active(v3d, scene); @@ -9868,8 +9994,8 @@ static void give_base_to_groups( /* assign the base */ base = BKE_scene_base_add(scene, ob); - base->flag |= SELECT; - base->object->flag = base->flag; + base->flag_legacy |= SELECT; + BKE_scene_base_flag_sync_from_base(base); DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); scene->basact = base; @@ -9951,10 +10077,10 @@ static ID *link_named_part( static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const short flag) { if (scene) { - Base *base; + BaseLegacy *base; Object *ob; - base = MEM_callocN(sizeof(Base), "app_nam_part"); + base = MEM_callocN(sizeof(BaseLegacy), "app_nam_part"); BLI_addtail(&scene->base, base); ob = (Object *)id; @@ -9967,12 +10093,12 @@ static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const sho ob->mode = OB_MODE_OBJECT; base->lay = ob->lay; base->object = ob; - base->flag = ob->flag; + base->flag_legacy = ob->flag; id_us_plus_no_lib((ID *)ob); if (flag & FILE_AUTOSELECT) { - base->flag |= SELECT; - base->object->flag = base->flag; + base->flag_legacy |= SELECT; + BKE_scene_base_flag_sync_from_base(base); /* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */ } } diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index d97bef13a78..50cdeca16b5 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -34,6 +34,8 @@ #define __READFILE_H__ #include "zlib.h" +#include "DNA_sdna_types.h" +#include "DNA_space_types.h" #include "DNA_windowmanager_types.h" /* for ReportType */ struct OldNewMap; @@ -169,8 +171,10 @@ void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Mai void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main); void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *main); void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *main); +void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *main); void do_versions_after_linking_270(struct Main *main); +void do_versions_after_linking_280(struct Main *main); #endif diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 1956a17d57b..943e5479d9a 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -736,7 +736,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) if (main->versionfile < 250) { bScreen *screen; Scene *scene; - Base *base; + BaseLegacy *base; Material *ma; Camera *cam; Mesh *me; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 21880fdb2dd..5df20d443a6 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -216,6 +216,10 @@ static void anim_change_prop_name(FCurve *fcu, static void do_version_hue_sat_node(bNodeTree *ntree, bNode *node) { + if (node->storage == NULL) { + return; + } + /* Make sure new sockets are properly created. */ node_verify_socket_templates(ntree, node); /* Convert value from old storage to new sockets. */ diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c new file mode 100644 index 00000000000..432d8be0a6d --- /dev/null +++ b/source/blender/blenloader/intern/versioning_280.c @@ -0,0 +1,187 @@ +/* + * ***** 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): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/blenloader/intern/versioning_280.c + * \ingroup blenloader + */ + +/* allow readfile to use deprecated functionality */ +#define DNA_DEPRECATED_ALLOW + +#include "DNA_object_types.h" +#include "DNA_layer_types.h" +#include "DNA_material_types.h" +#include "DNA_scene_types.h" +#include "DNA_genfile.h" + +#include "BKE_collection.h" +#include "BKE_layer.h" +#include "BKE_main.h" +#include "BKE_scene.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "BLO_readfile.h" +#include "readfile.h" + +#include "MEM_guardedalloc.h" + +void do_versions_after_linking_280(Main *main) +{ + if (!MAIN_VERSION_ATLEAST(main, 280, 0)) { + for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { + /* since we don't have access to FileData we check the (always valid) first render layer instead */ + if (scene->render_layers.first == NULL) { + SceneCollection *sc_master = BKE_collection_master(scene); + BLI_strncpy(sc_master->name, "Master Collection", sizeof(sc_master->name)); + + SceneCollection *collections[20] = {NULL}; + bool is_visible[20]; + + int lay_used = 0; + for (int i = 0; i < 20; i++) { + char name[MAX_NAME]; + + BLI_snprintf(name, sizeof(collections[i]->name), "%d", i + 1); + collections[i] = BKE_collection_add(scene, sc_master, name); + + is_visible[i] = (scene->lay & (1 << i)); + } + + for (Base *base = scene->base.first; base; base = base->next) { + lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */ + + for (int i = 0; i < 20; i++) { + if ((base->lay & (1 << i)) != 0) { + BKE_collection_object_add(scene, collections[i], base->object); + } + } + } + + scene->active_layer = 0; + + if (!BKE_scene_uses_blender_game(scene)) { + for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) { + + SceneLayer *sl = BKE_scene_layer_add(scene, srl->name); + BKE_scene_layer_engine_set(sl, scene->r.engine); + + if (srl->mat_override) { + BKE_collection_override_datablock_add((LayerCollection *)sl->layer_collections.first, "material", (ID *)srl->mat_override); + } + + if (srl->light_override && BKE_scene_uses_blender_internal(scene)) { + /* not sure how we handle this, pending until we design the override system */ + TODO_LAYER_OVERRIDE; + } + + if (srl->lay != scene->lay) { + /* unlink master collection */ + BKE_collection_unlink(sl, sl->layer_collections.first); + + /* add new collection bases */ + for (int i = 0; i < 20; i++) { + if ((srl->lay & (1 << i)) != 0) { + BKE_collection_link(sl, collections[i]); + } + } + } + + /* for convenience set the same active object in all the layers */ + if (scene->basact) { + sl->basact = BKE_scene_layer_base_find(sl, scene->basact->object); + } + + /* TODO: passes, samples, mask_layesr, exclude, ... */ + } + + if (BLI_findlink(&scene->render_layers, scene->r.actlay)) { + scene->active_layer = scene->r.actlay; + } + } + + SceneLayer *sl = BKE_scene_layer_add(scene, "Render Layer"); + + /* In this particular case we can safely assume the data struct */ + LayerCollection *lc = ((LayerCollection *)sl->layer_collections.first)->layer_collections.first; + for (int i = 0; i < 20; i++) { + if (!is_visible[i]) { + lc->flag &= ~COLLECTION_VISIBLE; + } + lc = lc->next; + } + + /* but we still need to make the flags synced */ + BKE_scene_layer_base_flag_recalculate(sl); + + /* convert active base */ + if (scene->basact) { + sl->basact = BKE_scene_layer_base_find(sl, scene->basact->object); + } + + /* convert selected bases */ + for (Base *base = scene->base.first; base; base = base->next) { + Base *ob_base = BKE_scene_layer_base_find(sl, base->object); + if ((base->flag & SELECT) != 0) { + if ((ob_base->flag & BASE_SELECTABLED) != 0) { + ob_base->flag |= BASE_SELECTED; + } + } + else { + ob_base->flag &= ~BASE_SELECTED; + } + } + + /* TODO: copy scene render data to layer */ + + /* Cleanup */ + for (int i = 0; i < 20; i++) { + if ((lay_used & (1 << i)) == 0) { + BKE_collection_remove(scene, collections[i]); + } + } + + /* remove bases once and for all */ + for (Base *base = scene->base.first; base; base = base->next) { + id_us_min(&base->object->id); + } + BLI_freelistN(&scene->base); + scene->basact = NULL; + } + } + } +} + +void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) +{ + if (!MAIN_VERSION_ATLEAST(main, 280, 0)) { + if (!DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "render_layers")) { + for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { + /* Master Collection */ + scene->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection"); + BLI_strncpy(scene->collection->name, "Master Collection", sizeof(scene->collection->name)); + } + } + } +} diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 5011f9836b7..16d73557bb0 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -120,6 +120,7 @@ #include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_lamp_types.h" +#include "DNA_layer_types.h" #include "DNA_linestyle_types.h" #include "DNA_meta_types.h" #include "DNA_mesh_types.h" @@ -799,22 +800,18 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) static void write_actions(WriteData *wd, ListBase *idbase) { - bAction *act; - bActionGroup *grp; - TimeMarker *marker; - - for (act = idbase->first; act; act = act->id.next) { + for (bAction *act = idbase->first; act; act = act->id.next) { if (act->id.us > 0 || wd->current) { writestruct(wd, ID_AC, bAction, 1, act); write_iddata(wd, &act->id); write_fcurves(wd, &act->curves); - for (grp = act->groups.first; grp; grp = grp->next) { + for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) { writestruct(wd, DATA, bActionGroup, 1, grp); } - for (marker = act->markers.first; marker; marker = marker->next) { + for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { writestruct(wd, DATA, TimeMarker, 1, marker); } } @@ -1280,13 +1277,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches) } static void write_particlesettings(WriteData *wd, ListBase *idbase) { - ParticleSettings *part; - ParticleDupliWeight *dw; - GroupObject *go; - int a; - - part = idbase->first; - while (part) { + for (ParticleSettings *part = idbase->first; part; part = part->id.next) { if (part->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_PA, ParticleSettings, 1, part); @@ -1306,24 +1297,23 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) write_curvemapping(wd, part->roughcurve); } - dw = part->dupliweights.first; - for (; dw; dw = dw->next) { + for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) { /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ if (dw->ob != NULL) { dw->index = 0; if (part->dup_group) { /* can be NULL if lining fails or set to None */ - for (go = part->dup_group->gobject.first; go && go->ob != dw->ob; go = go->next, dw->index++); + for (GroupObject *go = part->dup_group->gobject.first; + go && go->ob != dw->ob; + go = go->next, dw->index++); } } writestruct(wd, DATA, ParticleDupliWeight, 1, dw); } if (part->boids && part->phystype == PART_PHYS_BOIDS) { - BoidState *state = part->boids->states.first; - writestruct(wd, DATA, BoidSettings, 1, part->boids); - for (; state; state = state->next) { + for (BoidState *state = part->boids->states.first; state; state = state->next) { write_boid_state(wd, state); } } @@ -1331,13 +1321,12 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid); } - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (part->mtex[a]) { writestruct(wd, DATA, MTex, 1, part->mtex[a]); } } } - part = part->id.next; } } static void write_particlesystems(WriteData *wd, ListBase *particles) @@ -1834,10 +1823,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) static void write_objects(WriteData *wd, ListBase *idbase) { - Object *ob; - - ob = idbase->first; - while (ob) { + for (Object *ob = idbase->first; ob; ob = ob->id.next) { if (ob->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_OB, Object, 1, ob); @@ -1893,11 +1879,9 @@ static void write_objects(WriteData *wd, ListBase *idbase) writelist(wd, DATA, LinkData, &ob->pc_ids); writelist(wd, DATA, LodLevel, &ob->lodlevels); - } - write_previews(wd, ob->preview); - - ob = ob->id.next; + write_previews(wd, ob->preview); + } } mywrite_flush(wd); @@ -1906,26 +1890,19 @@ static void write_objects(WriteData *wd, ListBase *idbase) static void write_vfonts(WriteData *wd, ListBase *idbase) { - VFont *vf; - PackedFile *pf; - - vf = idbase->first; - while (vf) { + for (VFont *vf = idbase->first; vf; vf = vf->id.next) { if (vf->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_VF, VFont, 1, vf); write_iddata(wd, &vf->id); /* direct data */ - if (vf->packedfile) { - pf = vf->packedfile; + PackedFile *pf = vf->packedfile; writestruct(wd, DATA, PackedFile, 1, pf); writedata(wd, DATA, pf->size, pf->data); } } - - vf = vf->id.next; } mywrite_flush(wd); @@ -1934,11 +1911,7 @@ static void write_vfonts(WriteData *wd, ListBase *idbase) static void write_keys(WriteData *wd, ListBase *idbase) { - Key *key; - KeyBlock *kb; - - key = idbase->first; - while (key) { + for (Key *key = idbase->first; key; key = key->id.next) { if (key->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_KE, Key, 1, key); @@ -1949,17 +1922,13 @@ static void write_keys(WriteData *wd, ListBase *idbase) } /* direct data */ - kb = key->block.first; - while (kb) { + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { writestruct(wd, DATA, KeyBlock, 1, kb); if (kb->data) { writedata(wd, DATA, kb->totelem * key->elemsize, kb->data); } - kb = kb->next; } } - - key = key->id.next; } mywrite_flush(wd); @@ -1967,10 +1936,7 @@ static void write_keys(WriteData *wd, ListBase *idbase) static void write_cameras(WriteData *wd, ListBase *idbase) { - Camera *cam; - - cam = idbase->first; - while (cam) { + for (Camera *cam = idbase->first; cam; cam = cam->id.next) { if (cam->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_CA, Camera, 1, cam); @@ -1980,18 +1946,12 @@ static void write_cameras(WriteData *wd, ListBase *idbase) write_animdata(wd, cam->adt); } } - - cam = cam->id.next; } } static void write_mballs(WriteData *wd, ListBase *idbase) { - MetaBall *mb; - MetaElem *ml; - - mb = idbase->first; - while (mb) { + for (MetaBall *mb = idbase->first; mb; mb = mb->id.next) { if (mb->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_MB, MetaBall, 1, mb); @@ -2003,23 +1963,16 @@ static void write_mballs(WriteData *wd, ListBase *idbase) write_animdata(wd, mb->adt); } - ml = mb->elems.first; - while (ml) { + for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) { writestruct(wd, DATA, MetaElem, 1, ml); - ml = ml->next; } } - mb = mb->id.next; } } static void write_curves(WriteData *wd, ListBase *idbase) { - Curve *cu; - Nurb *nu; - - cu = idbase->first; - while (cu) { + for (Curve *cu = idbase->first; cu; cu = cu->id.next) { if (cu->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_CU, Curve, 1, cu); @@ -2038,13 +1991,10 @@ static void write_curves(WriteData *wd, ListBase *idbase) } else { /* is also the order of reading */ - nu = cu->nurb.first; - while (nu) { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { writestruct(wd, DATA, Nurb, 1, nu); - nu = nu->next; } - nu = cu->nurb.first; - while (nu) { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt); } @@ -2057,11 +2007,9 @@ static void write_curves(WriteData *wd, ListBase *idbase) writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv); } } - nu = nu->next; } } } - cu = cu->id.next; } mywrite_flush(wd); @@ -2183,15 +2131,13 @@ static void write_customdata( static void write_meshes(WriteData *wd, ListBase *idbase) { - Mesh *mesh; - bool save_for_old_blender = false; - #ifdef USE_BMESH_SAVE_AS_COMPAT - save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */ + const bool save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */ +#else + const bool save_for_old_blender = false; #endif - mesh = idbase->first; - while (mesh) { + for (Mesh *mesh = idbase->first; mesh; mesh = mesh->id.next) { CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE]; CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE]; CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE]; @@ -2336,8 +2282,6 @@ static void write_meshes(WriteData *wd, ListBase *idbase) if (players && players != players_buff) { MEM_freeN(players); } - - mesh = mesh->id.next; } mywrite_flush(wd); @@ -2345,10 +2289,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase) static void write_lattices(WriteData *wd, ListBase *idbase) { - Lattice *lt; - - lt = idbase->first; - while (lt) { + for (Lattice *lt = idbase->first; lt; lt = lt->id.next) { if (lt->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_LT, Lattice, 1, lt); @@ -2363,9 +2304,7 @@ static void write_lattices(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def); write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert); - } - lt = lt->id.next; } mywrite_flush(wd); @@ -2373,14 +2312,10 @@ static void write_lattices(WriteData *wd, ListBase *idbase) static void write_images(WriteData *wd, ListBase *idbase) { - Image *ima; - PackedFile *pf; - ImageView *iv; - ImagePackedFile *imapf; - - ima = idbase->first; - while (ima) { + for (Image *ima = idbase->first; ima; ima = ima->id.next) { if (ima->id.us > 0 || wd->current) { + ImagePackedFile *imapf; + /* Some trickery to keep forward compatibility of packed images. */ BLI_assert(ima->packedfile == NULL); if (ima->packedfiles.first != NULL) { @@ -2395,7 +2330,7 @@ static void write_images(WriteData *wd, ListBase *idbase) for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { writestruct(wd, DATA, ImagePackedFile, 1, imapf); if (imapf->packedfile) { - pf = imapf->packedfile; + PackedFile *pf = imapf->packedfile; writestruct(wd, DATA, PackedFile, 1, pf); writedata(wd, DATA, pf->size, pf->data); } @@ -2403,14 +2338,13 @@ static void write_images(WriteData *wd, ListBase *idbase) write_previews(wd, ima->preview); - for (iv = ima->views.first; iv; iv = iv->next) { + for (ImageView *iv = ima->views.first; iv; iv = iv->next) { writestruct(wd, DATA, ImageView, 1, iv); } writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format); ima->packedfile = NULL; } - ima = ima->id.next; } mywrite_flush(wd); @@ -2418,10 +2352,7 @@ static void write_images(WriteData *wd, ListBase *idbase) static void write_textures(WriteData *wd, ListBase *idbase) { - Tex *tex; - - tex = idbase->first; - while (tex) { + for (Tex *tex = idbase->first; tex; tex = tex->id.next) { if (tex->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_TE, Tex, 1, tex); @@ -2462,19 +2393,29 @@ static void write_textures(WriteData *wd, ListBase *idbase) write_previews(wd, tex->preview); } - tex = tex->id.next; } mywrite_flush(wd); } -static void write_materials(WriteData *wd, ListBase *idbase) +static void write_material_engines_settings(WriteData *wd, ListBase *lb) { - Material *ma; - int a; + for (MaterialEngineSettings *res = lb->first; res; res = res->next) { + writestruct(wd, DATA, MaterialEngineSettings, 1, res); + + if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) { + writestruct(wd, DATA, MaterialEngineSettingsClay, 1, res->data); + } + else { + /* No engine matched */ + /* error: don't know how to write this file */ + } + } +} - ma = idbase->first; - while (ma) { +static void write_materials(WriteData *wd, ListBase *idbase) +{ + for (Material *ma = idbase->first; ma; ma = ma->id.next) { if (ma->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_MA, Material, 1, ma); @@ -2484,7 +2425,7 @@ static void write_materials(WriteData *wd, ListBase *idbase) write_animdata(wd, ma->adt); } - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (ma->mtex[a]) { writestruct(wd, DATA, MTex, 1, ma->mtex[a]); } @@ -2504,18 +2445,15 @@ static void write_materials(WriteData *wd, ListBase *idbase) } write_previews(wd, ma->preview); + + write_material_engines_settings(wd, &ma->engines_settings); } - ma = ma->id.next; } } static void write_worlds(WriteData *wd, ListBase *idbase) { - World *wrld; - int a; - - wrld = idbase->first; - while (wrld) { + for (World *wrld = idbase->first; wrld; wrld = wrld->id.next) { if (wrld->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_WO, World, 1, wrld); @@ -2525,7 +2463,7 @@ static void write_worlds(WriteData *wd, ListBase *idbase) write_animdata(wd, wrld->adt); } - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (wrld->mtex[a]) { writestruct(wd, DATA, MTex, 1, wrld->mtex[a]); } @@ -2539,17 +2477,12 @@ static void write_worlds(WriteData *wd, ListBase *idbase) write_previews(wd, wrld->preview); } - wrld = wrld->id.next; } } static void write_lamps(WriteData *wd, ListBase *idbase) { - Lamp *la; - int a; - - la = idbase->first; - while (la) { + for (Lamp *la = idbase->first; la; la = la->id.next) { if (la->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_LA, Lamp, 1, la); @@ -2560,7 +2493,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase) } /* direct data */ - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (la->mtex[a]) { writestruct(wd, DATA, MTex, 1, la->mtex[a]); } @@ -2577,9 +2510,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase) } write_previews(wd, la->preview); - } - la = la->id.next; } mywrite_flush(wd); @@ -2626,24 +2557,70 @@ static void write_paint(WriteData *wd, Paint *p) } } +static void write_scene_collection(WriteData *wd, SceneCollection *sc) +{ + writestruct(wd, DATA, SceneCollection, 1, sc); + + writelist(wd, DATA, LinkData, &sc->objects); + writelist(wd, DATA, LinkData, &sc->filter_objects); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + write_scene_collection(wd, nsc); + } +} + +static void write_collection_engine_settings(WriteData *wd, ListBase *lb) +{ + for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) { + writestruct(wd, DATA, CollectionEngineSettings, 1, ces); + + for (CollectionEngineProperty *prop = ces->properties.first; prop; prop = prop->next) { + switch (prop->type) { + case COLLECTION_PROP_TYPE_FLOAT: + writestruct(wd, DATA, CollectionEnginePropertyFloat, 1, prop); + break; + case COLLECTION_PROP_TYPE_INT: + writestruct(wd, DATA, CollectionEnginePropertyInt, 1, prop); + break; + default: + ; /* error: don't know how to write this file */ + } + } + } +} + +static void write_layer_collections(WriteData *wd, ListBase *lb) +{ + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + writestruct(wd, DATA, LayerCollection, 1, lc); + + writelist(wd, DATA, LinkData, &lc->object_bases); + writelist(wd, DATA, CollectionOverride, &lc->overrides); + + write_collection_engine_settings(wd, &lc->engine_settings); + + write_layer_collections(wd, &lc->layer_collections); + } +} + +static void write_render_engines_settings(WriteData *wd, ListBase *lb) +{ + for (RenderEngineSettings *res = lb->first; res; res = res->next) { + writestruct(wd, DATA, RenderEngineSettings, 1, res); + + if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) { + writestruct(wd, DATA, RenderEngineSettingsClay, 1, res->data); + } + else { + /* No engine matched */ + /* error: don't know how to write this file */ + } + } +} + static void write_scenes(WriteData *wd, ListBase *scebase) { - Scene *sce; - Base *base; - Editing *ed; - Sequence *seq; - MetaStack *ms; - Strip *strip; - TimeMarker *marker; - TransformOrientation *ts; - SceneRenderLayer *srl; - SceneRenderView *srv; - ToolSettings *tos; - FreestyleModuleConfig *fmc; - FreestyleLineSet *fls; - - sce = scebase->first; - while (sce) { + for (Scene *sce = scebase->first; sce; sce = sce->id.next) { /* write LibData */ writestruct(wd, ID_SCE, Scene, 1, sce); write_iddata(wd, &sce->id); @@ -2654,13 +2631,11 @@ static void write_scenes(WriteData *wd, ListBase *scebase) write_keyingsets(wd, &sce->keyingsets); /* direct data */ - base = sce->base.first; - while (base) { - writestruct(wd, DATA, Base, 1, base); - base = base->next; + for (BaseLegacy *base = sce->base.first; base; base = base->next) { + writestruct(wd, DATA, BaseLegacy, 1, base); } - tos = sce->toolsettings; + ToolSettings *tos = sce->toolsettings; writestruct(wd, DATA, ToolSettings, 1, tos); if (tos->vpaint) { writestruct(wd, DATA, VPaint, 1, tos->vpaint); @@ -2699,8 +2674,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase) write_paint(wd, &tos->imapaint.paint); - ed = sce->ed; + Editing *ed = sce->ed; if (ed) { + Sequence *seq; + writestruct(wd, DATA, Editing, 1, ed); /* reset write flags too */ @@ -2747,7 +2724,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format); - strip = seq->strip; + Strip *strip = seq->strip; writestruct(wd, DATA, Strip, 1, strip); if (seq->flag & SEQ_USE_CROP && strip->crop) { writestruct(wd, DATA, StripCrop, 1, strip->crop); @@ -2779,7 +2756,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) SEQ_END /* new; meta stack too, even when its nasty restore code */ - for (ms = ed->metastack.first; ms; ms = ms->next) { + for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) { writestruct(wd, DATA, MetaStack, 1, ms); } } @@ -2805,27 +2782,27 @@ static void write_scenes(WriteData *wd, ListBase *scebase) } /* writing dynamic list of TimeMarkers to the blend file */ - for (marker = sce->markers.first; marker; marker = marker->next) { + for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) { writestruct(wd, DATA, TimeMarker, 1, marker); } /* writing dynamic list of TransformOrientations to the blend file */ - for (ts = sce->transform_spaces.first; ts; ts = ts->next) { + for (TransformOrientation *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 (SceneRenderLayer *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) { + for (FreestyleModuleConfig *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) { + for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { writestruct(wd, DATA, FreestyleLineSet, 1, fls); } } /* writing MultiView to the blend file */ - for (srv = sce->r.views.first; srv; srv = srv->next) { + for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) { writestruct(wd, DATA, SceneRenderView, 1, srv); } @@ -2845,8 +2822,16 @@ static void write_scenes(WriteData *wd, ListBase *scebase) write_previews(wd, sce->preview); write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve); + write_scene_collection(wd, sce->collection); + + for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) { + writestruct(wd, DATA, SceneLayer, 1, sl); + writelist(wd, DATA, Base, &sl->object_bases); + write_layer_collections(wd, &sl->layer_collections); + } + + write_render_engines_settings(wd, &sce->engines_settings); - sce = sce->id.next; } mywrite_flush(wd); @@ -2854,13 +2839,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) static void write_gpencils(WriteData *wd, ListBase *lb) { - bGPdata *gpd; - bGPDlayer *gpl; - bGPDframe *gpf; - bGPDstroke *gps; - bGPDpalette *palette; - - for (gpd = lb->first; gpd; gpd = gpd->id.next) { + for (bGPdata *gpd = lb->first; gpd; gpd = gpd->id.next) { if (gpd->id.us > 0 || wd->current) { /* write gpd data block to file */ writestruct(wd, ID_GD, bGPdata, 1, gpd); @@ -2872,22 +2851,21 @@ static void write_gpencils(WriteData *wd, ListBase *lb) /* write grease-pencil layers to file */ writelist(wd, DATA, bGPDlayer, &gpd->layers); - for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* write this layer's frames to file */ writelist(wd, DATA, bGPDframe, &gpl->frames); - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { /* write strokes */ writelist(wd, DATA, bGPDstroke, &gpf->strokes); - for (gps = gpf->strokes.first; gps; gps = gps->next) { + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points); } } } + /* write grease-pencil palettes */ writelist(wd, DATA, bGPDpalette, &gpd->palettes); - for (palette = gpd->palettes.first; palette; palette = palette->next) { + for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) { writelist(wd, DATA, bGPDpalettecolor, &palette->colors); } } @@ -2898,14 +2876,11 @@ static void write_gpencils(WriteData *wd, ListBase *lb) static void write_windowmanagers(WriteData *wd, ListBase *lb) { - wmWindowManager *wm; - wmWindow *win; - - for (wm = lb->first; wm; wm = wm->id.next) { + for (wmWindowManager *wm = lb->first; wm; wm = wm->id.next) { writestruct(wd, ID_WM, wmWindowManager, 1, wm); write_iddata(wd, &wm->id); - for (win = wm->windows.first; win; win = win->next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { writestruct(wd, DATA, wmWindow, 1, win); writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format); } @@ -2998,14 +2973,7 @@ static void write_soops(WriteData *wd, SpaceOops *so) static void write_screens(WriteData *wd, ListBase *scrbase) { - bScreen *sc; - ScrArea *sa; - ScrVert *sv; - ScrEdge *se; - - sc = scrbase->first; - while (sc) { - + for (bScreen *sc = scrbase->first; sc; sc = sc->id.next) { /* write LibData */ /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ writestruct(wd, ID_SCRN, bScreen, 1, sc); @@ -3014,15 +2982,15 @@ static void write_screens(WriteData *wd, ListBase *scrbase) write_previews(wd, sc->preview); /* direct data */ - for (sv = sc->vertbase.first; sv; sv = sv->next) { + for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) { writestruct(wd, DATA, ScrVert, 1, sv); } - for (se = sc->edgebase.first; se; se = se->next) { + for (ScrEdge *se = sc->edgebase.first; se; se = se->next) { writestruct(wd, DATA, ScrEdge, 1, se); } - for (sa = sc->areabase.first; sa; sa = sa->next) { + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { SpaceLink *sl; Panel *pa; uiList *ui_list; @@ -3052,8 +3020,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase) } } - sl = sa->spacedata.first; - while (sl) { + for (sl = sa->spacedata.first; sl; sl = sl->next) { for (ar = sl->regionbase.first; ar; ar = ar->next) { write_region(wd, ar, sl->spacetype); } @@ -3167,12 +3134,11 @@ static void write_screens(WriteData *wd, ListBase *scrbase) else if (sl->spacetype == SPACE_INFO) { writestruct(wd, DATA, SpaceInfo, 1, sl); } - - sl = sl->next; + else if (sl->spacetype == SPACE_COLLECTIONS) { + writestruct(wd, DATA, SpaceCollections, 1, sl); + } } } - - sc = sc->id.next; } mywrite_flush(wd); @@ -3200,11 +3166,7 @@ static void write_bone(WriteData *wd, Bone *bone) static void write_armatures(WriteData *wd, ListBase *idbase) { - bArmature *arm; - Bone *bone; - - arm = idbase->first; - while (arm) { + for (bArmature *arm = idbase->first; arm; arm = arm->id.next) { if (arm->id.us > 0 || wd->current) { writestruct(wd, ID_AR, bArmature, 1, arm); write_iddata(wd, &arm->id); @@ -3214,13 +3176,10 @@ static void write_armatures(WriteData *wd, ListBase *idbase) } /* Direct data */ - bone = arm->bonebase.first; - while (bone) { + for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) { write_bone(wd, bone); - bone = bone->next; } } - arm = arm->id.next; } mywrite_flush(wd); @@ -3228,12 +3187,8 @@ static void write_armatures(WriteData *wd, ListBase *idbase) static void write_texts(WriteData *wd, ListBase *idbase) { - Text *text; - TextLine *tmp; - - text = idbase->first; - while (text) { - if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) { + for (Text *text = idbase->first; text; text = text->id.next) { + if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) { text->flags &= ~TXT_ISEXT; } @@ -3247,21 +3202,14 @@ static void write_texts(WriteData *wd, ListBase *idbase) if (!(text->flags & TXT_ISEXT)) { /* now write the text data, in two steps for optimization in the readfunction */ - tmp = text->lines.first; - while (tmp) { + for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) { writestruct(wd, DATA, TextLine, 1, tmp); - tmp = tmp->next; } - tmp = text->lines.first; - while (tmp) { + for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) { writedata(wd, DATA, tmp->len + 1, tmp->line); - tmp = tmp->next; } } - - - text = text->id.next; } mywrite_flush(wd); @@ -3269,10 +3217,7 @@ static void write_texts(WriteData *wd, ListBase *idbase) static void write_speakers(WriteData *wd, ListBase *idbase) { - Speaker *spk; - - spk = idbase->first; - while (spk) { + for (Speaker *spk = idbase->first; spk; spk = spk->id.next) { if (spk->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_SPK, Speaker, 1, spk); @@ -3282,30 +3227,23 @@ static void write_speakers(WriteData *wd, ListBase *idbase) write_animdata(wd, spk->adt); } } - spk = spk->id.next; } } static void write_sounds(WriteData *wd, ListBase *idbase) { - bSound *sound; - - PackedFile *pf; - - sound = idbase->first; - while (sound) { + for (bSound *sound = idbase->first; sound; sound = sound->id.next) { if (sound->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_SO, bSound, 1, sound); write_iddata(wd, &sound->id); if (sound->packedfile) { - pf = sound->packedfile; + PackedFile *pf = sound->packedfile; writestruct(wd, DATA, PackedFile, 1, pf); writedata(wd, DATA, pf->size, pf->data); } } - sound = sound->id.next; } mywrite_flush(wd); @@ -3313,10 +3251,7 @@ static void write_sounds(WriteData *wd, ListBase *idbase) static void write_groups(WriteData *wd, ListBase *idbase) { - Group *group; - GroupObject *go; - - for (group = idbase->first; group; group = group->id.next) { + for (Group *group = idbase->first; group; group = group->id.next) { if (group->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_GR, Group, 1, group); @@ -3324,10 +3259,8 @@ static void write_groups(WriteData *wd, ListBase *idbase) write_previews(wd, group->preview); - go = group->gobject.first; - while (go) { + for (GroupObject *go = group->gobject.first; go; go = go->next) { writestruct(wd, DATA, GroupObject, 1, go); - go = go->next; } } } @@ -3337,9 +3270,7 @@ static void write_groups(WriteData *wd, ListBase *idbase) static void write_nodetrees(WriteData *wd, ListBase *idbase) { - bNodeTree *ntree; - - for (ntree = idbase->first; ntree; ntree = ntree->id.next) { + for (bNodeTree *ntree = idbase->first; ntree; ntree = ntree->id.next) { if (ntree->id.us > 0 || wd->current) { writestruct(wd, ID_NT, bNodeTree, 1, ntree); /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot @@ -3423,9 +3354,7 @@ static void customnodes_free_deprecated_data(Main *mainvar) static void write_brushes(WriteData *wd, ListBase *idbase) { - Brush *brush; - - for (brush = idbase->first; brush; brush = brush->id.next) { + for (Brush *brush = idbase->first; brush; brush = brush->id.next) { if (brush->id.us > 0 || wd->current) { writestruct(wd, ID_BR, Brush, 1, brush); write_iddata(wd, &brush->id); @@ -3442,9 +3371,7 @@ static void write_brushes(WriteData *wd, ListBase *idbase) static void write_palettes(WriteData *wd, ListBase *idbase) { - Palette *palette; - - for (palette = idbase->first; palette; palette = palette->id.next) { + for (Palette *palette = idbase->first; palette; palette = palette->id.next) { if (palette->id.us > 0 || wd->current) { PaletteColor *color; writestruct(wd, ID_PAL, Palette, 1, palette); @@ -3459,9 +3386,7 @@ static void write_palettes(WriteData *wd, ListBase *idbase) static void write_paintcurves(WriteData *wd, ListBase *idbase) { - PaintCurve *pc; - - for (pc = idbase->first; pc; pc = pc->id.next) { + for (PaintCurve *pc = idbase->first; pc; pc = pc->id.next) { if (pc->id.us > 0 || wd->current) { writestruct(wd, ID_PC, PaintCurve, 1, pc); write_iddata(wd, &pc->id); @@ -3511,10 +3436,7 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction static void write_movieclips(WriteData *wd, ListBase *idbase) { - MovieClip *clip; - - clip = idbase->first; - while (clip) { + for (MovieClip *clip = idbase->first; clip; clip = clip->id.next) { if (clip->id.us > 0 || wd->current) { MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object; @@ -3541,8 +3463,6 @@ static void write_movieclips(WriteData *wd, ListBase *idbase) object = object->next; } } - - clip = clip->id.next; } mywrite_flush(wd); @@ -3550,10 +3470,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase) static void write_masks(WriteData *wd, ListBase *idbase) { - Mask *mask; - - mask = idbase->first; - while (mask) { + for (Mask *mask = idbase->first; mask; mask = mask->id.next) { if (mask->id.us > 0 || wd->current) { MaskLayer *masklay; @@ -3601,8 +3518,6 @@ static void write_masks(WriteData *wd, ListBase *idbase) } } } - - mask = mask->id.next; } mywrite_flush(wd); @@ -3864,10 +3779,7 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier static void write_linestyles(WriteData *wd, ListBase *idbase) { - FreestyleLineStyle *linestyle; - int a; - - for (linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) { + for (FreestyleLineStyle *linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) { if (linestyle->id.us > 0 || wd->current) { writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle); write_iddata(wd, &linestyle->id); @@ -3880,7 +3792,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase) write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers); write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers); write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers); - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (linestyle->mtex[a]) { writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]); } @@ -3895,9 +3807,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase) static void write_cachefiles(WriteData *wd, ListBase *idbase) { - CacheFile *cache_file; - - for (cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) { + for (CacheFile *cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) { if (cache_file->id.us > 0 || wd->current) { writestruct(wd, ID_CF, CacheFile, 1, cache_file); @@ -3917,7 +3827,6 @@ static void write_libraries(WriteData *wd, Main *main) bool found_one; for (; main; main = main->next) { - a = tot = set_listbasepointers(main, lbarray); /* test: is lib being used */ @@ -3926,16 +3835,13 @@ static void write_libraries(WriteData *wd, Main *main) } else { found_one = false; - while (tot--) { + while (!found_one && tot--) { for (id = lbarray[tot]->first; id; id = id->next) { if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) { found_one = true; break; } } - if (found_one) { - break; - } } } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index bb61f66e267..59ce91a3e70 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -945,6 +945,10 @@ void BM_mesh_bm_to_me( /* propagate edited basis offsets to other shapes */ if (apply_offset) { add_v3_v3(fp, *ofs_pt++); + /* Apply back new coordinates of offsetted shapekeys into BMesh. + * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous + * call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */ + copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp); } fp += 3; diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 4f5cf83f5ca..9c26ba83b44 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -69,17 +69,21 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce, // write bone nodes bArmature * armature = (bArmature *)ob_arm->data; - ED_armature_to_edit(armature); + bool is_edited = armature->edbo != NULL; - bArmature *arm = (bArmature *)ob_arm->data; - for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) { + if (!is_edited) + ED_armature_to_edit(armature); + + for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) { // start from root bones if (!bone->parent) add_bone_node(bone, ob_arm, sce, se, child_objects); } - ED_armature_from_edit(armature); - ED_armature_edit_free(armature); + if (!is_edited) { + ED_armature_from_edit(armature); + ED_armature_edit_free(armature); + } } void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 226f319cefd..5118234a587 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -57,6 +57,7 @@ extern "C" { #include "BLI_fileops.h" #include "BKE_camera.h" +#include "BKE_collection.h" #include "BKE_main.h" #include "BKE_lamp.h" #include "BKE_library.h" @@ -264,7 +265,7 @@ void DocumentImporter::finish() for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { Object *ob = *it; - Base *base = BKE_scene_base_find(sce, ob); + BaseLegacy *base = (BaseLegacy *)BKE_scene_base_find(sce, ob); if (base) { BLI_remlink(&sce->base, base); BKE_libblock_free_us(G.main, base->object); @@ -418,7 +419,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod Object *obn = BKE_object_copy(G.main, source_ob); DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - BKE_scene_base_add(sce, obn); + BKE_collection_object_add_from(sce, source_ob, obn); if (instance_node) { anim_importer.read_node_transform(instance_node, obn); diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 76b51148509..7d9599c8554 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -66,7 +66,7 @@ EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettin bool EffectsExporter::hasEffects(Scene *sce) { - Base *base = (Base *)sce->base.first; + BaseLegacy *base = (BaseLegacy *)sce->base.first; while (base) { Object *ob = base->object; diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp index b8971fffe3e..36bc176b1a6 100644 --- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp +++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp @@ -43,8 +43,6 @@ void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const NodeInput *valueSocket = this->getInputSocket(3); NodeInput *facSocket = this->getInputSocket(4); NodeOutput *outputSocket = this->getOutputSocket(0); - bNode *editorsnode = getbNode(); - NodeHueSat *storage = (NodeHueSat *)editorsnode->storage; ConvertRGBToHSVOperation *rgbToHSV = new ConvertRGBToHSVOperation(); converter.addOperation(rgbToHSV); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 4b73dfa1ec3..0f0d16907f4 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -121,11 +121,11 @@ struct BuilderWalkUserData { static void modifier_walk(void *user_data, struct Object * /*ob*/, struct Object **obpoin, - int /*cd_flag*/) + int /*cb_flag*/) { BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; if (*obpoin) { - data->builder->build_object(data->scene, NULL, *obpoin); + data->builder->build_object(data->scene, *obpoin); } } @@ -138,7 +138,7 @@ void constraint_walk(bConstraint * /*con*/, if (*idpoin) { ID *id = *idpoin; if (GS(id->name) == ID_OB) { - data->builder->build_object(data->scene, NULL, (Object *)id); + data->builder->build_object(data->scene, (Object *)id); } } } @@ -337,9 +337,7 @@ void DepsgraphNodeBuilder::begin_build(Main *bmain) { } FOREACH_NODETREE_END } -void DepsgraphNodeBuilder::build_group(Scene *scene, - Base *base, - Group *group) +void DepsgraphNodeBuilder::build_group(Scene *scene, Group *group) { ID *group_id = &group->id; if (group_id->tag & LIB_TAG_DOIT) { @@ -348,7 +346,7 @@ void DepsgraphNodeBuilder::build_group(Scene *scene, group_id->tag |= LIB_TAG_DOIT; LINKLIST_FOREACH (GroupObject *, go, &group->gobject) { - build_object(scene, base, go->ob); + build_object(scene, go->ob); } } @@ -387,7 +385,7 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group) return subgraph_node; } -void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) +void DepsgraphNodeBuilder::build_object(Scene *scene, Object *ob) { const bool has_object = (ob->id.tag & LIB_TAG_DOIT); IDDepsNode *id_node = (has_object) @@ -397,9 +395,12 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) * Do it for both new and existing ID nodes. This is so because several * bases might be sharing same object. */ - if (base != NULL) { - id_node->layers |= base->lay; - } + + /* Blender 2.8 transition: we don't have bases and do not have + * layer masks, but still want objects to be updated + */ + id_node->layers |= ((1 << 20) - 1); + if (ob == scene->camera) { /* Camera should always be updated, it used directly by viewport. */ id_node->layers |= (unsigned int)(-1); @@ -415,7 +416,7 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) build_object_transform(scene, ob); if (ob->parent != NULL) { - build_object(scene, NULL, ob->parent); + build_object(scene, ob->parent); } if (ob->modifiers.first != NULL) { BuilderWalkUserData data; @@ -927,13 +928,13 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) */ Curve *cu = (Curve *)obdata; if (cu->bevobj != NULL) { - build_object(scene, NULL, cu->bevobj); + build_object(scene, cu->bevobj); } if (cu->taperobj != NULL) { - build_object(scene, NULL, cu->taperobj); + build_object(scene, cu->taperobj); } if (ob->type == OB_FONT && cu->textoncurve != NULL) { - build_object(scene, NULL, cu->textoncurve); + build_object(scene, cu->textoncurve); } break; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index c5035f35f6e..2f3f733b8db 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -32,7 +32,6 @@ #include "intern/depsgraph_types.h" -struct Base; struct CacheFile; struct bGPdata; struct ListBase; @@ -126,8 +125,8 @@ struct DepsgraphNodeBuilder { void build_scene(Main *bmain, Scene *scene); SubgraphDepsNode *build_subgraph(Group *group); - void build_group(Scene *scene, Base *base, Group *group); - void build_object(Scene *scene, Base *base, Object *ob); + void build_group(Scene *scene, Group *group); + void build_object(Scene *scene, Object *ob); void build_object_transform(Scene *scene, Object *ob); void build_object_constraints(Scene *scene, Object *ob); void build_pose_constraints(Object *ob, bPoseChannel *pchan); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc index 99e61692231..c7e8edb122e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc @@ -46,6 +46,7 @@ extern "C" { #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" @@ -79,24 +80,25 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene) } /* scene objects */ - LINKLIST_FOREACH (Base *, base, &scene->base) { - Object *ob = base->object; - + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) + { /* object itself */ - build_object(scene, base, ob); + build_object(scene, ob); /* object that this is a proxy for */ // XXX: the way that proxies work needs to be completely reviewed! if (ob->proxy) { ob->proxy->proxy_from = ob; - build_object(scene, base, ob->proxy); + build_object(scene, ob->proxy); } /* Object dupligroup. */ if (ob->dup_group) { - build_group(scene, base, ob->dup_group); + build_group(scene, ob->dup_group); } } + FOREACH_SCENE_OBJECT_END /* rigidbody */ if (scene->rigidbody_world) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 41d2ca0ca6d..6d4597fed9d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -129,8 +129,8 @@ static bool python_driver_depends_on_time(ChannelDriver *driver) /* Function calls are considered dependent on a time. */ return true; } - if (strstr(driver->expression, "time") != NULL) { - /* Variable `time` depends on time. */ + if (strstr(driver->expression, "frame") != NULL) { + /* Variable `frame` depends on time. */ /* TODO(sergey): This is a bit weak, but not sure about better way of * handling this. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 054e4103290..2e6fa7b5801 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -45,7 +45,7 @@ #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_operation.h" -struct Base; +struct BaseLegacy; struct bGPdata; struct CacheFile; struct ListBase; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc index 8a3476cff45..2f49d5b1645 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc @@ -46,6 +46,7 @@ extern "C" { #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" @@ -74,9 +75,9 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) } /* scene objects */ - LINKLIST_FOREACH (Base *, base, &scene->base) { - Object *ob = base->object; - + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) + { /* object itself */ build_object(bmain, scene, ob); @@ -97,6 +98,7 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) build_group(bmain, scene, ob, ob->dup_group); } } + FOREACH_SCENE_OBJECT_END /* rigidbody */ if (scene->rigidbody_world) { diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 065f65659e6..3a042535d26 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -53,6 +53,7 @@ extern "C" { #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" #include "intern/depsgraph.h" +#include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" /* Unfinished and unused, and takes quite some pre-processing time. */ @@ -362,6 +363,11 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx, return; } + DEG_DEBUG_PRINTF("%s: layers:%u, graph->layers:%u\n", + __func__, + layers, + graph->layers); + /* Set time for the current graph evaluation context. */ TimeSourceDepsNode *time_src = graph->find_time_source(); eval_ctx->ctime = time_src->cfra; diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 60449ebc600..d5b54e8a746 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -26,37 +26,53 @@ set(INC . intern - nodes - operations + engines/clay + ../blenkernel ../blenlib ../blentranslation ../imbuf + ../depsgraph ../makesdna ../makesrna - ../windowmanager - ../nodes - ../nodes/composite - ../nodes/intern + ../gpu + ../editors/include + ../editors/space_view3d ../render/extern/include ../render/intern/include - ../../../extern/clew/include + + ../../../intern/glew-mx ../../../intern/guardedalloc - ../../../intern/atomic ) set(INC_SYS - + ${GLEW_INCLUDE_PATH} ) set(SRC - DRW_defines.h + intern/draw_manager.c + intern/draw_mode_pass.c + intern/draw_cache.c + engines/clay/clay.c -) + intern/DRW_render.h + intern/draw_mode_pass.h + intern/draw_cache.h + engines/clay/clay.h -list(APPEND INC + ./DRW_engine.h ) +if(WITH_CLAY_ENGINE) + add_definitions(-DWITH_CLAY_ENGINE) endif() +data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC) +data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC) +data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC) +data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC) + +list(APPEND INC +) + blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h new file mode 100644 index 00000000000..4f86e3fcd91 --- /dev/null +++ b/source/blender/draw/DRW_engine.h @@ -0,0 +1,45 @@ +/* + * Copyright 2016, 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file DRW_engine.h + * \ingroup draw + */ + +#ifndef __DRW_ENGINE_H__ +#define __DRW_ENGINE_H__ + +//#define WITH_VIEWPORT_CACHE_TEST + +struct DRWPass; +struct Material; +struct Scene; + +void DRW_engines_init(void); +void DRW_engines_free(void); + +/* This is here because GPUViewport needs it */ +void DRW_pass_free(struct DRWPass *pass); + +/* Settings */ +void *DRW_material_settings_get(struct Material *ma, const char *engine_name); +void *DRW_render_settings_get(struct Scene *scene, const char *engine_name); + +#endif /* __DRW_ENGINE_H__ */
\ No newline at end of file diff --git a/source/blender/draw/DRW_engines.h b/source/blender/draw/DRW_engines.h deleted file mode 100644 index e69de29bb2d..00000000000 --- a/source/blender/draw/DRW_engines.h +++ /dev/null diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c new file mode 100644 index 00000000000..0572f4a0dc9 --- /dev/null +++ b/source/blender/draw/engines/clay/clay.c @@ -0,0 +1,776 @@ +/* + * Copyright 2016, 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. + * + * Contributor(s): Blender Institute + * + */ + +#include "DRW_render.h" + +#include "BKE_icons.h" +#include "BKE_main.h" + +#include "BLI_dynstr.h" +#include "BLI_rand.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "UI_resources.h" +#include "UI_interface_icons.h" + +#include "clay.h" +#ifdef WITH_CLAY_ENGINE +/* Shaders */ + +#define CLAY_ENGINE "BLENDER_CLAY" + +extern char datatoc_clay_frag_glsl[]; +extern char datatoc_clay_vert_glsl[]; +extern char datatoc_ssao_alchemy_glsl[]; +extern char datatoc_ssao_groundtruth_glsl[]; + +/* Storage */ + +/* UBOs data needs to be 16 byte aligned (size of vec4) */ +/* Reminder : float, int, bool are 4 bytes */ +typedef struct CLAY_UBO_Material { + float ssao_params_var[4]; + /* - 16 -*/ + float matcap_hsv[3]; + float matcap_id; /* even float encoding have enough precision */ + /* - 16 -*/ + float matcap_rot[2]; + float pad[2]; /* ensure 16 bytes alignement */ +} CLAY_UBO_Material; /* 48 bytes */ + +#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */ + +typedef struct CLAY_UBO_Storage { + CLAY_UBO_Material materials[MAX_CLAY_MAT]; +} CLAY_UBO_Storage; + +static struct CLAY_data { + /* Depth Pre Pass */ + struct GPUShader *depth_sh; + /* Shading Pass */ + struct GPUShader *clay_sh; + + /* Matcap textures */ + struct GPUTexture *matcap_array; + float matcap_colors[24][3]; + + /* Ssao */ + float winmat[4][4]; + float viewvecs[3][4]; + float ssao_params[4]; + struct GPUTexture *jitter_tx; + struct GPUTexture *sampling_tx; +} data = {NULL}; + +/* GPUViewport.storage + * Is freed everytime the viewport engine changes */ +typedef struct CLAY_Storage { + /* Materials Parameter UBO */ + CLAY_UBO_Storage mat_storage; + int ubo_current_id; + DRWShadingGroup *shgrps[MAX_CLAY_MAT]; +} CLAY_Storage; + +/* Just a serie of int from 0 to MAX_CLAY_MAT-1 */ +static int ubo_mat_idxs[MAX_CLAY_MAT] = {0}; + +/* keep it under MAX_STORAGE */ +typedef struct CLAY_StorageList { + struct CLAY_Storage *storage; + struct GPUUniformBuffer *mat_ubo; +} CLAY_StorageList; + +/* keep it under MAX_BUFFERS */ +typedef struct CLAY_FramebufferList{ + /* default */ + struct GPUFrameBuffer *default_fb; + /* engine specific */ + struct GPUFrameBuffer *downsample_depth; +} CLAY_FramebufferList; + +/* keep it under MAX_TEXTURES */ +typedef struct CLAY_TextureList{ + /* default */ + struct GPUTexture *color; + struct GPUTexture *depth; + /* engine specific */ + struct GPUTexture *depth_low; +} CLAY_TextureList; + +/* for clarity follow the same layout as CLAY_TextureList */ +enum { + SCENE_COLOR, + SCENE_DEPTH, + SCENE_DEPTH_LOW, +}; + +/* keep it under MAX_PASSES */ +typedef struct CLAY_PassList{ + /* default */ + struct DRWPass *non_meshes_pass; + struct DRWPass *ob_center_pass; + /* engine specific */ + struct DRWPass *depth_pass; + struct DRWPass *clay_pass; + struct DRWPass *wire_overlay_pass; + struct DRWPass *wire_outline_pass; +} CLAY_PassList; + +//#define GTAO + +/* Functions */ + +static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer) +{ + int image_size = prv->w[0] * prv->h[0]; + float *new_rect = &final_rect[image_size * 4 * layer]; + + IMB_buffer_float_from_byte(new_rect, (unsigned char *)prv->rect[0], IB_PROFILE_SRGB, IB_PROFILE_SRGB, + false, prv->w[0], prv->h[0], prv->w[0], prv->w[0]); + + /* Find overall color */ + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0]; + data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1]; + data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2]; + } + } + + data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */ + data.matcap_colors[layer][1] /= 16.0f * 2.0f; + data.matcap_colors[layer][2] /= 16.0f * 2.0f; +} + +static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr) +{ + struct GPUTexture *tex; + int w = prv[0]->w[0]; + int h = prv[0]->h[0]; + float *final_rect = MEM_callocN(sizeof(float) * 4 * w * h * nbr, "Clay Matcap array rect"); + + for (int i = 0; i < nbr; ++i) { + add_icon_to_rect(prv[i], final_rect, i); + BKE_previewimg_free(&prv[i]); + } + + tex = DRW_texture_create_2D_array(w, h, nbr, DRW_TEX_RGBA_8, DRW_TEX_FILTER, final_rect); + MEM_freeN(final_rect); + + return tex; +} + +static int matcap_to_index(int matcap) +{ + if (matcap == ICON_MATCAP_02) return 1; + else if (matcap == ICON_MATCAP_03) return 2; + else if (matcap == ICON_MATCAP_04) return 3; + else if (matcap == ICON_MATCAP_05) return 4; + else if (matcap == ICON_MATCAP_06) return 5; + else if (matcap == ICON_MATCAP_07) return 6; + else if (matcap == ICON_MATCAP_08) return 7; + else if (matcap == ICON_MATCAP_09) return 8; + else if (matcap == ICON_MATCAP_10) return 9; + else if (matcap == ICON_MATCAP_11) return 10; + else if (matcap == ICON_MATCAP_12) return 11; + else if (matcap == ICON_MATCAP_13) return 12; + else if (matcap == ICON_MATCAP_14) return 13; + else if (matcap == ICON_MATCAP_15) return 14; + else if (matcap == ICON_MATCAP_16) return 15; + else if (matcap == ICON_MATCAP_17) return 16; + else if (matcap == ICON_MATCAP_18) return 17; + else if (matcap == ICON_MATCAP_19) return 18; + else if (matcap == ICON_MATCAP_20) return 19; + else if (matcap == ICON_MATCAP_21) return 20; + else if (matcap == ICON_MATCAP_22) return 21; + else if (matcap == ICON_MATCAP_23) return 22; + else if (matcap == ICON_MATCAP_24) return 23; + return 0; +} + +static struct GPUTexture *create_spiral_sample_texture(int numsaples) +{ + struct GPUTexture *tex; + float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex"); + const float numsaples_inv = 1.0f / numsaples; + int i; + /* arbitrary number to ensure we don't get conciding samples every circle */ + const float spirals = 7.357; + + for (i = 0; i < numsaples; i++) { + float r = (i + 0.5f) * numsaples_inv; + float phi = r * spirals * (float)(2.0 * M_PI); + texels[i][0] = r * cosf(phi); + texels[i][1] = r * sinf(phi); + } + + tex = DRW_texture_create_1D(numsaples, DRW_TEX_RG_16, 0, (float *)texels); + + MEM_freeN(texels); + return tex; +} + +static struct GPUTexture *create_jitter_texture(void) +{ + float jitter[64 * 64][2]; + int i; + + /* TODO replace by something more evenly distributed like blue noise */ + for (i = 0; i < 64 * 64; i++) { +#ifdef GTAO + jitter[i][0] = BLI_frand(); + jitter[i][1] = BLI_frand(); +#else + jitter[i][0] = 2.0f * BLI_frand() - 1.0f; + jitter[i][1] = 2.0f * BLI_frand() - 1.0f; + normalize_v2(jitter[i]); +#endif + } + + return DRW_texture_create_2D(64, 64, DRW_TEX_RG_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]); +} + +static void clay_material_settings_init(MaterialEngineSettingsClay *ma) +{ + ma->matcap_icon = ICON_MATCAP_01; + ma->matcap_rot = 0.0f; + ma->matcap_hue = 0.5f; + ma->matcap_sat = 0.5f; + ma->matcap_val = 0.5f; + ma->ssao_distance = 0.2; + ma->ssao_attenuation = 1.0f; + ma->ssao_factor_cavity = 1.0f; + ma->ssao_factor_edge = 1.0f; +} + +RenderEngineSettings *CLAY_render_settings_create(void) +{ + RenderEngineSettingsClay *settings = MEM_callocN(sizeof(RenderEngineSettingsClay), "RenderEngineSettingsClay"); + + clay_material_settings_init((MaterialEngineSettingsClay *)settings); + + settings->ssao_samples = 32; + + return (RenderEngineSettings *)settings; +} + +MaterialEngineSettings *CLAY_material_settings_create(void) +{ + MaterialEngineSettingsClay *settings = MEM_callocN(sizeof(MaterialEngineSettingsClay), "MaterialEngineSettingsClay"); + + clay_material_settings_init(settings); + + return (MaterialEngineSettings *)settings; +} + +static void CLAY_engine_init(CLAY_StorageList *stl) +{ + /* Create Texture Array */ + if (!data.matcap_array) { + PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */ + + /* TODO only load used matcaps */ + prv[0] = UI_icon_to_preview(ICON_MATCAP_01); + prv[1] = UI_icon_to_preview(ICON_MATCAP_02); + prv[2] = UI_icon_to_preview(ICON_MATCAP_03); + prv[3] = UI_icon_to_preview(ICON_MATCAP_04); + prv[4] = UI_icon_to_preview(ICON_MATCAP_05); + prv[5] = UI_icon_to_preview(ICON_MATCAP_06); + prv[6] = UI_icon_to_preview(ICON_MATCAP_07); + prv[7] = UI_icon_to_preview(ICON_MATCAP_08); + prv[8] = UI_icon_to_preview(ICON_MATCAP_09); + prv[9] = UI_icon_to_preview(ICON_MATCAP_10); + prv[10] = UI_icon_to_preview(ICON_MATCAP_11); + prv[11] = UI_icon_to_preview(ICON_MATCAP_12); + prv[12] = UI_icon_to_preview(ICON_MATCAP_13); + prv[13] = UI_icon_to_preview(ICON_MATCAP_14); + prv[14] = UI_icon_to_preview(ICON_MATCAP_15); + prv[15] = UI_icon_to_preview(ICON_MATCAP_16); + prv[16] = UI_icon_to_preview(ICON_MATCAP_17); + prv[17] = UI_icon_to_preview(ICON_MATCAP_18); + prv[18] = UI_icon_to_preview(ICON_MATCAP_19); + prv[19] = UI_icon_to_preview(ICON_MATCAP_20); + prv[20] = UI_icon_to_preview(ICON_MATCAP_21); + prv[21] = UI_icon_to_preview(ICON_MATCAP_22); + prv[22] = UI_icon_to_preview(ICON_MATCAP_23); + prv[23] = UI_icon_to_preview(ICON_MATCAP_24); + + data.matcap_array = load_matcaps(prv, 24); + } + + /* AO Jitter */ + if (!data.jitter_tx) { + data.jitter_tx = create_jitter_texture(); + } + + /* AO Samples */ + /* TODO use hammersley sequence */ + if (!data.sampling_tx) { + data.sampling_tx = create_spiral_sample_texture(500); + } + + /* Depth prepass */ + if (!data.depth_sh) { + data.depth_sh = DRW_shader_create_3D_depth_only(); + } + + /* Shading pass */ + if (!data.clay_sh) { + DynStr *ds = BLI_dynstr_new(); + const char *max_mat = + "#define MAX_MATERIAL 512\n" + "#define USE_ROTATION\n" + "#define USE_AO\n" + "#define USE_HSV\n"; + char *matcap_with_ao; + + BLI_dynstr_append(ds, datatoc_clay_frag_glsl); +#ifdef GTAO + BLI_dynstr_append(ds, datatoc_ssao_groundtruth_glsl); +#else + BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl); +#endif + + matcap_with_ao = BLI_dynstr_get_cstring(ds); + + data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat); + + BLI_dynstr_free(ds); + MEM_freeN(matcap_with_ao); + } + + if (!stl->storage) { + stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage"); + } + + if (!stl->mat_ubo) { + stl->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL); + } + + if (ubo_mat_idxs[1] == 0) { + /* Just int to have pointers to them */ + for (int i = 0; i < MAX_CLAY_MAT; ++i) { + ubo_mat_idxs[i] = i; + } + } +} + +static void CLAY_ssao_setup(void) +{ + float invproj[4][4]; + float dfdyfacs[2]; + bool is_persp = DRW_viewport_is_persp_get(); + /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */ + float viewvecs[3][4] = { + {-1.0f, -1.0f, -1.0f, 1.0f}, + {1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f} + }; + int i; + float *size = DRW_viewport_size_get(); + RenderEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY); + + DRW_get_dfdy_factors(dfdyfacs); + + data.ssao_params[0] = settings->ssao_samples; + data.ssao_params[1] = size[0] / 64.0; + data.ssao_params[2] = size[1] / 64.0; + data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */ + + /* invert the view matrix */ + DRW_viewport_matrix_get(data.winmat, DRW_MAT_WIN); + invert_m4_m4(invproj, data.winmat); + + /* convert the view vectors to view space */ + for (i = 0; i < 3; i++) { + mul_m4_v4(invproj, viewvecs[i]); + /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]); + if (is_persp) + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); + viewvecs[i][3] = 1.0; + + copy_v4_v4(data.viewvecs[i], viewvecs[i]); + } + + /* we need to store the differences */ + data.viewvecs[1][0] -= data.viewvecs[0][0]; + data.viewvecs[1][1] = data.viewvecs[2][1] - data.viewvecs[0][1]; + + /* calculate a depth offset as well */ + if (!is_persp) { + float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f}; + mul_m4_v4(invproj, vec_far); + mul_v3_fl(vec_far, 1.0f / vec_far[3]); + data.viewvecs[1][2] = vec_far[2] - data.viewvecs[0][2]; + } +} + +static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, int *material_id) +{ + const int depthloc = 0, matcaploc = 1, jitterloc = 2, sampleloc = 3; + + //CLAY_UBO_Material *mat = &data.mat_storage.materials[0]; + DRWShadingGroup *grp = DRW_shgroup_create(data.clay_sh, pass); + + DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_buffer(grp, "depthtex", SCENE_DEPTH, depthloc); + DRW_shgroup_uniform_texture(grp, "matcaps", data.matcap_array, matcaploc); + DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)data.winmat); + DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)data.viewvecs, 3); + DRW_shgroup_uniform_vec4(grp, "ssao_params", data.ssao_params, 1); + DRW_shgroup_uniform_vec3(grp, "matcaps_color", (float *)data.matcap_colors, 24); + + DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1); + +#ifndef GTAO + DRW_shgroup_uniform_texture(grp, "ssao_jitter", data.jitter_tx, jitterloc); + DRW_shgroup_uniform_texture(grp, "ssao_samples", data.sampling_tx, sampleloc); +#endif + + return grp; +} + +static int search_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat, + float matcap_val, float ssao_distance, float ssao_factor_cavity, + float ssao_factor_edge, float ssao_attenuation, int matcap_icon) +{ + /* For now just use a linear search and test all parameters */ + /* TODO make a hash table */ + for (int i = 0; i < storage->ubo_current_id; ++i) + { + CLAY_UBO_Material *ubo = &storage->mat_storage.materials[i]; + + if ((ubo->matcap_rot[0] == cosf(matcap_rot * 3.14159f * 2.0f)) && + (ubo->matcap_hsv[0] == matcap_hue + 0.5f) && + (ubo->matcap_hsv[1] == matcap_sat * 2.0f) && + (ubo->matcap_hsv[2] == matcap_val * 2.0f) && + (ubo->ssao_params_var[0] == ssao_distance) && + (ubo->ssao_params_var[1] == ssao_factor_cavity) && + (ubo->ssao_params_var[2] == ssao_factor_edge) && + (ubo->ssao_params_var[3] == ssao_attenuation) && + (ubo->matcap_id == matcap_to_index(matcap_icon))) + { + return i; + } + } + + return -1; +} + +static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat, + float matcap_val, float ssao_distance, float ssao_factor_cavity, + float ssao_factor_edge, float ssao_attenuation, int matcap_icon) +{ + int id = storage->ubo_current_id; + CLAY_UBO_Material *ubo = &storage->mat_storage.materials[id]; + + ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f); + ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f); + + ubo->matcap_hsv[0] = matcap_hue + 0.5f; + ubo->matcap_hsv[1] = matcap_sat * 2.0f; + ubo->matcap_hsv[2] = matcap_val * 2.0f; + + ubo->ssao_params_var[0] = ssao_distance; + ubo->ssao_params_var[1] = ssao_factor_cavity; + ubo->ssao_params_var[2] = ssao_factor_edge; + ubo->ssao_params_var[3] = ssao_attenuation; + + ubo->matcap_id = matcap_to_index(matcap_icon); + + storage->ubo_current_id++; + + return id; +} + +static int mat_in_ubo(CLAY_Storage *storage, struct GPUUniformBuffer *ubo, DRWPass *pass, + float matcap_rot, float matcap_hue, float matcap_sat, + float matcap_val, float ssao_distance, float ssao_factor_cavity, + float ssao_factor_edge, float ssao_attenuation, int matcap_icon) +{ + int id; + + /* Search material in UBO */ + id = search_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val, + ssao_distance, ssao_factor_cavity, ssao_factor_edge, + ssao_attenuation, matcap_icon); + + /* if not found create it */ + if (id == -1) { + id = push_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val, + ssao_distance, ssao_factor_cavity, ssao_factor_edge, + ssao_attenuation, matcap_icon); + + storage->shgrps[id] = CLAY_shgroup_create(pass, &ubo_mat_idxs[id]); + + /* if it's the first shgrp, pass bind the material UBO */ + if (storage->ubo_current_id == 1) { + DRW_shgroup_uniform_block(storage->shgrps[0], "material_block", ubo, 0); + } + } + + return id; +} + +/* Safe way to get override values */ +static void override_setting(CollectionEngineSettings *ces, const char *name, void *ret) +{ + CollectionEngineProperty *cep = BKE_collection_engine_property_get(ces, name); + + if (cep == NULL) { + return; + } + + if ((cep->flag & COLLECTION_PROP_USE) == 0) { + return; + } + + if (cep->type == COLLECTION_PROP_TYPE_INT) { + CollectionEnginePropertyInt *prop = (CollectionEnginePropertyInt *)cep; + *((int *)ret) = prop->value; + } + else { + CollectionEnginePropertyFloat *prop = (CollectionEnginePropertyFloat *)cep; + *((float *)ret) = prop->value; + } +} + +static DRWShadingGroup *CLAY_object_shgrp_get(Object *ob, CLAY_StorageList *stl, DRWPass *pass) +{ + MaterialEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY); + CollectionEngineSettings *ces = ob->collection_settings; + + /* Default Settings */ + float matcap_rot = settings->matcap_rot; + float matcap_hue = settings->matcap_hue; + float matcap_sat = settings->matcap_sat; + float matcap_val = settings->matcap_val; + float ssao_distance = settings->ssao_distance; + float ssao_factor_cavity = settings->ssao_factor_cavity; + float ssao_factor_edge = settings->ssao_factor_edge; + float ssao_attenuation = settings->ssao_attenuation; + int matcap_icon = settings->matcap_icon; + + /* Override settings */ + if (ces) { + override_setting(ces, "matcap_rotation", &matcap_rot); + override_setting(ces, "matcap_hue", &matcap_hue); + override_setting(ces, "matcap_saturation", &matcap_sat); + override_setting(ces, "matcap_value", &matcap_val); + override_setting(ces, "ssao_distance", &ssao_distance); + override_setting(ces, "ssao_factor_cavity", &ssao_factor_cavity); + override_setting(ces, "ssao_factor_edge", &ssao_factor_edge); + override_setting(ces, "ssao_attenuation", &ssao_attenuation); + override_setting(ces, "matcap_icon", &matcap_icon); + }; + + + int index = mat_in_ubo(stl->storage, stl->mat_ubo, pass, + matcap_rot, matcap_hue, matcap_sat, matcap_val, + ssao_distance, ssao_factor_cavity, ssao_factor_edge, + ssao_attenuation, matcap_icon); + + return stl->storage->shgrps[index]; +} + +static void CLAY_create_cache(CLAY_PassList *passes, CLAY_StorageList *stl, const struct bContext *C) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + DRWShadingGroup *clay_shgrp; + DRWShadingGroup *depth_shgrp; + + /* Depth Pass */ + { + passes->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); + + depth_shgrp = DRW_shgroup_create(data.depth_sh, passes->depth_pass); + } + + /* Clay Pass */ + { + passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS); + stl->storage->ubo_current_id = 0; + } + + /* Object Mode */ + { + DRW_pass_setup_common(&passes->wire_overlay_pass, + &passes->wire_outline_pass, + &passes->non_meshes_pass, + &passes->ob_center_pass); + } + + /* TODO Create hash table of batch based on material id*/ + Object *ob; + DEG_OBJECT_ITER(sl, CLAY_ENGINE, ob); + { + if ((ob->base_flag & BASE_VISIBLED) == 0) { + continue; + } + + struct Batch *geom; + //bool do_outlines; + + switch (ob->type) { + case OB_MESH: + clay_shgrp = CLAY_object_shgrp_get(ob, stl, passes->clay_pass); + geom = DRW_cache_surface_get(ob); + + /* Add everything for now */ + DRW_shgroup_call_add(depth_shgrp, geom, ob->obmat); + + if (clay_shgrp) + DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat); + + //DRW_shgroup_wire_overlay(passes->wire_overlay_pass, ob); + + //do_outlines = ((ob->base_flag & BASE_SELECTED) != 0); + //DRW_shgroup_wire_outline(passes->wire_outline_pass, ob, false, false, do_outlines); + + /* When encountering a new material : + * - Create new Batch + * - Initialize Batch + * - Push it to the hash table + * - The pass takes care of inserting it + * next to the same shader calls */ + + /* Free hash table */ + break; + case OB_LAMP: + case OB_CAMERA: + case OB_EMPTY: + default: + DRW_shgroup_non_meshes(passes->non_meshes_pass, ob); + break; + } + + DRW_shgroup_object_center(passes->ob_center_pass, ob); + DRW_shgroup_relationship_lines(passes->non_meshes_pass, ob); + } + DEG_OBJECT_ITER_END + + DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage); +} + +static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context) +{ + /* This function may run for multiple viewports + * so get the current viewport buffers */ + CLAY_FramebufferList *buffers = NULL; + CLAY_TextureList *textures = NULL; + CLAY_PassList *passes = NULL; + CLAY_StorageList *storage = NULL; + + DRW_viewport_init(context, (void **)&buffers, (void **)&textures, (void **)&passes, (void **)&storage); + + CLAY_engine_init(storage); + + /* TODO : tag to refresh by the deps graph */ + /* ideally only refresh when objects are added/removed */ + /* or render properties / materials change */ +#ifdef WITH_VIEWPORT_CACHE_TEST + static bool once = false; +#endif + if (DRW_viewport_cache_is_dirty() +#ifdef WITH_VIEWPORT_CACHE_TEST + && !once +#endif + ) { +#ifdef WITH_VIEWPORT_CACHE_TEST + once = true; +#endif + CLAY_create_cache(passes, storage, context); + } + + /* Start Drawing */ + DRW_draw_background(); + + /* Pass 1 : Depth pre-pass */ + DRW_draw_pass(passes->depth_pass); + + /* Pass 2 (Optionnal) : Separated Downsampled AO */ + DRW_framebuffer_texture_detach(textures->depth); + /* TODO */ + + /* Pass 3 : Shading */ + CLAY_ssao_setup(); + DRW_draw_pass(passes->clay_pass); + + /* Pass 4 : Overlays */ + DRW_framebuffer_texture_attach(buffers->default_fb, textures->depth, 0); + //DRW_draw_pass(passes->wire_overlay_pass); + //DRW_draw_pass(passes->wire_outline_pass); + DRW_draw_pass(passes->non_meshes_pass); + DRW_draw_pass(passes->ob_center_pass); + + /* Always finish by this */ + DRW_state_reset(); +} + +static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), CollectionEngineSettings *ces) +{ + BLI_assert(ces); + BKE_collection_engine_property_add_int(ces, "matcap_icon", ICON_MATCAP_01); + BKE_collection_engine_property_add_int(ces, "type", CLAY_MATCAP_NONE); + BKE_collection_engine_property_add_float(ces, "matcap_rotation", 0.0f); + BKE_collection_engine_property_add_float(ces, "matcap_hue", 0.5f); + BKE_collection_engine_property_add_float(ces, "matcap_saturation", 0.5f); + BKE_collection_engine_property_add_float(ces, "matcap_value", 0.5f); + BKE_collection_engine_property_add_float(ces, "ssao_distance", 0.2f); + BKE_collection_engine_property_add_float(ces, "ssao_attenuation", 1.0f); + BKE_collection_engine_property_add_float(ces, "ssao_factor_cavity", 1.0f); + BKE_collection_engine_property_add_float(ces, "ssao_factor_edge", 1.0f); +} + +void clay_engine_free(void) +{ + /* data.depth_sh Is builtin so it's automaticaly freed */ + if (data.clay_sh) { + DRW_shader_free(data.clay_sh); + } + + if (data.matcap_array) { + DRW_texture_free(data.matcap_array); + } + + if (data.jitter_tx) { + DRW_texture_free(data.jitter_tx); + } + + if (data.sampling_tx) { + DRW_texture_free(data.sampling_tx); + } +} + +RenderEngineType viewport_clay_type = { + NULL, NULL, + CLAY_ENGINE, N_("Clay"), RE_INTERNAL | RE_USE_OGL_PIPELINE, + NULL, NULL, NULL, NULL, &CLAY_view_draw, NULL, &CLAY_collection_settings_create, + {NULL, NULL, NULL} +}; + + +#undef CLAY_ENGINE + +#endif diff --git a/source/blender/draw/DRW_defines.h b/source/blender/draw/engines/clay/clay.h index 212c39e203b..404924be2a1 100644 --- a/source/blender/draw/DRW_defines.h +++ b/source/blender/draw/engines/clay/clay.h @@ -19,7 +19,18 @@ * */ -#ifndef __DRW_DEFINES_H__ -#define __DRW_DEFINES_H__ +/** \file clay.h + * \ingroup DNA + */ + +#ifndef __ENGINE_CLAY_H__ +#define __ENGINE_CLAY_H__ + +extern RenderEngineType viewport_clay_type; + +struct RenderEngineSettings *CLAY_render_settings_create(void); +struct MaterialEngineSettings *CLAY_material_settings_create(void); + +void clay_engine_free(void); -#endif /* __DRW_DEFINES_H__ */ +#endif /* __ENGINE_CLAY_H__ */
\ No newline at end of file diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl new file mode 100644 index 00000000000..7a38db35bcf --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl @@ -0,0 +1,205 @@ +uniform vec2 screenres; +uniform sampler2D depthtex; +uniform mat4 WinMatrix; + +/* Matcap */ +uniform sampler2DArray matcaps; +uniform vec3 matcaps_color[24]; + +/* Screen Space Occlusion */ +/* store the view space vectors for the corners of the view frustum here. + * It helps to quickly reconstruct view space vectors by using uv coordinates, + * see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ +uniform vec4 viewvecs[3]; +uniform vec4 ssao_params; + +uniform sampler2D ssao_jitter; +uniform sampler1D ssao_samples; + +/* Material Parameters packed in an UBO */ +struct Material { + vec4 ssao_params_var; + vec4 matcap_hsv_id; + vec4 matcap_rot; /* vec4 to ensure 16 bytes alignement (don't trust compiler) */ +}; + +layout(std140) uniform material_block { + Material matcaps_param[MAX_MATERIAL]; +}; + +uniform int mat_id; + +/* Aliases */ +#define ssao_samples_num ssao_params.x +#define jitter_tilling ssao_params.yz +#define dfdy_sign ssao_params.w + +#define matcap_hsv matcaps_param[mat_id].matcap_hsv_id.xyz +#define matcap_index matcaps_param[mat_id].matcap_hsv_id.w +#define matcap_rotation matcaps_param[mat_id].matcap_rot.xy + +in vec3 normal; +out vec4 fragColor; + +/* TODO Move this to SSAO modules */ +/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer + * we change the factors from the article to fit the OpennGL model. */ +vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth) +{ + if (WinMatrix[3][3] == 0.0) { + /* Perspective */ + float d = 2.0 * depth - 1.0; + + float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]); + + return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz); + } + else { + /* Orthographic */ + vec3 offset = vec3(uvcoords, depth); + + return viewvecs[0].xyz + offset * viewvecs[1].xyz; + } +} + +/* TODO remove this when switching to geometric normals */ +vec3 calculate_view_space_normal(in vec3 viewposition) +{ + vec3 normal = cross(normalize(dFdx(viewposition)), dfdy_sign * normalize(dFdy(viewposition))); + return normalize(normal); +} + +#ifdef USE_HSV +void rgb_to_hsv(vec3 rgb, out vec3 outcol) +{ + float cmax, cmin, h, s, v, cdelta; + vec3 c; + + cmax = max(rgb[0], max(rgb[1], rgb[2])); + cmin = min(rgb[0], min(rgb[1], rgb[2])); + cdelta = cmax - cmin; + + v = cmax; + if (cmax != 0.0) + s = cdelta / cmax; + else { + s = 0.0; + h = 0.0; + } + + if (s == 0.0) { + h = 0.0; + } + else { + c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta; + + if (rgb.x == cmax) h = c[2] - c[1]; + else if (rgb.y == cmax) h = 2.0 + c[0] - c[2]; + else h = 4.0 + c[1] - c[0]; + + h /= 6.0; + + if (h < 0.0) + h += 1.0; + } + + outcol = vec3(h, s, v); +} + +void hsv_to_rgb(vec3 hsv, out vec3 outcol) +{ + float i, f, p, q, t, h, s, v; + vec3 rgb; + + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; + + if (s == 0.0) { + rgb = vec3(v, v, v); + } + else { + if (h == 1.0) + h = 0.0; + + h *= 6.0; + i = floor(h); + f = h - i; + rgb = vec3(f, f, f); + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + + if (i == 0.0) rgb = vec3(v, t, p); + else if (i == 1.0) rgb = vec3(q, v, p); + else if (i == 2.0) rgb = vec3(p, v, t); + else if (i == 3.0) rgb = vec3(p, q, v); + else if (i == 4.0) rgb = vec3(t, p, v); + else rgb = vec3(v, p, q); + } + + outcol = rgb; +} + +void hue_sat(float hue, float sat, float value, inout vec3 col) +{ + vec3 hsv; + + rgb_to_hsv(col, hsv); + + hsv.x += hue; + hsv.x -= floor(hsv.x); + hsv.y *= sat; + hsv.y = clamp(hsv.y, 0.0, 1.0); + hsv.z *= value; + hsv.z = clamp(hsv.z, 0.0, 1.0); + + hsv_to_rgb(hsv, col); +} +#endif + +#ifdef USE_AO +/* Prototype */ +void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges); +#endif + +void main() { + vec2 screenco = vec2(gl_FragCoord.xy) / screenres; + float depth = texture(depthtex, screenco).r; + + vec3 position = get_view_space_from_depth(screenco, depth); + vec3 normal = calculate_view_space_normal(position); + + /* Manual Depth test */ + /* Doing this test earlier gives problem with dfdx calculations + * TODO move this before when we have proper geometric normals */ + if (gl_FragCoord.z > depth + 1e-5) + discard; + +#ifdef USE_ROTATION + /* Rotate texture coordinates */ + vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x); + vec2 texco = abs(vec2(dot(normal.xy, matcap_rotation), dot(normal.xy, rotY)) * .49 + 0.5); +#else + vec2 texco = abs(normal.xy * .49 + 0.5); +#endif + vec3 col = texture(matcaps, vec3(texco, matcap_index)).rgb; + +#ifdef USE_AO + float cavity, edges; + ssao_factors(depth, normal, position, screenco, cavity, edges); + + col *= mix(vec3(1.0), matcaps_color[int(matcap_index)], cavity); +#endif + +#ifdef USE_HSV + hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col); +#endif + +#ifdef USE_AO + /* Apply highlights after hue shift */ + col *= edges + 1.0; +#endif + + fragColor = vec4(col, 1.0); +} diff --git a/source/blender/draw/engines/clay/shaders/clay_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_vert.glsl new file mode 100644 index 00000000000..0b598ea0291 --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_vert.glsl @@ -0,0 +1,20 @@ +uniform mat4 ModelViewProjectionMatrix; +uniform mat3 NormalMatrix; + +#if __VERSION__ == 120 +attribute vec3 pos; +attribute vec3 nor; +varying vec3 normal; +#else +in vec3 pos; +in vec3 nor; +out vec3 normal; +#endif + + +void main() +{ + normal = normalize(NormalMatrix * nor); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); +} + diff --git a/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl new file mode 100644 index 00000000000..d032fb91c01 --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl @@ -0,0 +1,73 @@ +#define ssao_distance matcaps_param[mat_id].ssao_params_var.x +#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y +#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z +#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w + +/* from The Alchemy screen-space ambient obscurance algorithm + * http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */ + +void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges) +{ + /* take the normalized ray direction here */ + vec2 rotX = texture2D(ssao_jitter, screenco.xy * jitter_tilling).rg; + vec2 rotY = vec2(-rotX.y, rotX.x); + + /* find the offset in screen space by multiplying a point + * in camera space at the depth of the point by the projection matrix. */ + vec2 offset; + float homcoord = WinMatrix[2][3] * position.z + WinMatrix[3][3]; + offset.x = WinMatrix[0][0] * ssao_distance / homcoord; + offset.y = WinMatrix[1][1] * ssao_distance / homcoord; + /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */ + offset *= 0.5; + + cavities = edges = 0.0; + int x; + int num_samples = int(ssao_samples_num); + + for (x = 0; x < num_samples; x++) { + /* TODO : optimisation replace by constant */ + vec2 dir_sample = texture1D(ssao_samples, (float(x) + 0.5) / ssao_samples_num).rg; + + /* rotate with random direction to get jittered result */ + vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY)); + + vec2 uvcoords = screenco.xy + dir_jittered * offset; + + if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0) + continue; + + float depth_new = texture2D(depthtex, uvcoords).r; + + /* Handle Background case */ + bool is_background = (depth_new == 1.0); + + /* This trick provide good edge effect even if no neighboor is found. */ + vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new); + + if (is_background) + pos_new.z -= ssao_distance; + + vec3 dir = pos_new - position; + float len = length(dir); + float f_cavities = dot(dir, normal); + float f_edge = -f_cavities; + float f_bias = 0.05 * len + 0.0001; + + float attenuation = 1.0 / (len * (1.0 + len * len * ssao_attenuation)); + + /* use minor bias here to avoid self shadowing */ + if (f_cavities > -f_bias) + cavities += f_cavities * attenuation; + + if (f_edge > f_bias) + edges += f_edge * attenuation; + } + + cavities /= ssao_samples_num; + edges /= ssao_samples_num; + + /* don't let cavity wash out the surface appearance */ + cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0); + edges = edges * ssao_factor_edge; +} diff --git a/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl new file mode 100644 index 00000000000..2f29624824e --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl @@ -0,0 +1,120 @@ +#define ssao_distance matcaps_param[mat_id].ssao_params_var.x +#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y +#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z +#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w + +/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */ + +#define COSINE_WEIGHTING + +float integrate_arc(in float h1, in float h2, in float gamma, in float n_proj_len) +{ + float a = 0.0; +#ifdef COSINE_WEIGHTING + float cos_gamma = cos(gamma); + float sin_gamma_2 = 2.0 * sin(gamma); + a += -cos(2.0 * h1 - gamma) + cos_gamma + h1 * sin_gamma_2; + a += -cos(2.0 * h2 - gamma) + cos_gamma + h2 * sin_gamma_2; + a *= 0.25; /* 1/4 */ + a *= n_proj_len; +#else + /* Uniform weighting (slide 59) */ + a += 1 - cos(h1); + a += 1 - cos(h2); +#endif + return a; +} + +float get_max_horizon(in vec2 co, in vec3 x, in vec3 omega_o, in float h) +{ + if (co.x > 1.0 || co.x < 0.0 || co.y > 1.0 || co.y < 0.0) + return h; + + float depth = texture2D(depthtex, co).r; + + /* Background case */ + if (depth == 1.0) + return h; + + vec3 s = get_view_space_from_depth(co, depth); /* s View coordinate */ + vec3 omega_s = s - x; + float len = length(omega_s); + + if (len < ssao_distance) { + omega_s /= len; + h = max(h, dot(omega_s, omega_o)); + } + return h; +} + +void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges) +{ + /* Renaming */ + vec3 omega_o = -normalize(position); /* viewvec */ + vec2 x_ = screenco; /* x^ Screen coordinate */ + vec3 x = position; /* x view space coordinate */ + +#ifdef SPATIAL_DENOISE + float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); + float noise_offset = (1.0 / 4.0) * float(int(gl_FragCoord.y - gl_FragCoord.x) & 0x3); +#else + float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); + float noise_offset = (0.5 / 16.0) + (1.0 / 16.0) * float(((int(gl_FragCoord.x - gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); +#endif + + const float phi_step = 16.0; + const float theta_step = 16.0; + const float m_pi = 3.14159265358979323846; + vec2 pixel_ratio = vec2(screenres.y / screenres.x, 1.0); + vec2 pixel_size = vec2(1.0) / screenres.xy; + float min_stride = length(pixel_size); + float homcco = WinMatrix[2][3] * position.z + WinMatrix[3][3]; + float n = max(min_stride * theta_step, ssao_distance / homcco); /* Search distance */ + + /* Integral over PI */ + float A = 0.0; + for (float i = 0.0; i < phi_step; i++) { + float phi = m_pi * ((noise_dir + i) / phi_step); + + vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */ + + /* Search maximum horizon angles Theta1 and Theta2 */ + float theta1 = -1.0, theta2 = -1.0; /* init at cos(pi) */ + for (float j = 0.0; j < theta_step; j++) { + vec2 s_ = t_phi * pixel_ratio * n * ((j + noise_offset)/ theta_step); /* s^ Screen coordinate */ + vec2 co; + + co = x_ + s_; + theta1 = get_max_horizon(co, x, omega_o, theta1); + + co = x_ - s_; + theta2 = get_max_horizon(co, x, omega_o, theta2); + } + + /* (Slide 54) */ + theta1 = -acos(theta1); + theta2 = acos(theta2); + + /* Projecting Normal to Plane P defined by t_phi and omega_o */ + vec3 h = normalize(cross(vec3(t_phi, 0.0), omega_o)); /* Normal vector to Integration plane */ + vec3 t = cross(h, omega_o); /* Normal vector to plane */ + vec3 n_proj = normal - h * dot(normal, h); + float n_proj_len = length(n_proj); + vec3 n_proj_norm = normalize(n_proj); + + /* Clamping thetas (slide 58) */ + float gamma = sign(dot(n_proj_norm, t)) * acos(dot(normal, omega_o)); /* Angle between view vec and normal */ + theta1 = gamma + max(theta1 - gamma, -m_pi * 0.5); + theta2 = gamma + min(theta2 - gamma, m_pi * 0.5); + + /* Solving inner integral */ + A += integrate_arc(theta1, theta2, gamma, n_proj_len); + } + + A /= phi_step; + + cavities = 1.0 - A; + edges = 0.0; +}
\ No newline at end of file diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h new file mode 100644 index 00000000000..78edae803b5 --- /dev/null +++ b/source/blender/draw/intern/DRW_render.h @@ -0,0 +1,221 @@ +/* + * Copyright 2016, 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file DRW_render.h + * \ingroup draw + */ + +/* This is the Render Functions used by Realtime engines to draw with OpenGL */ + +#ifndef __DRW_RENDER_H__ +#define __DRW_RENDER_H__ + +#include "BKE_context.h" +#include "BKE_layer.h" +#include "BKE_scene.h" + +#include "BLI_listbase.h" +#include "BLI_math_matrix.h" +#include "BLI_math_vector.h" +#include "BLI_string.h" + +#include "BLT_translation.h" + +#include "DNA_object_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_scene_types.h" + +#include "draw_mode_pass.h" +#include "draw_cache.h" + +#include "MEM_guardedalloc.h" + +#include "RE_engine.h" + +//#define WITH_VIEWPORT_CACHE_TEST + +struct GPUFrameBuffer; +struct GPUShader; +struct GPUTexture; +struct GPUUniformBuffer; +struct Object; +struct Batch; + +typedef struct DRWUniform DRWUniform; +typedef struct DRWInterface DRWInterface; +typedef struct DRWPass DRWPass; +typedef struct DRWShadingGroup DRWShadingGroup; + +/* Textures */ + +typedef enum { + DRW_TEX_RGBA_8, + DRW_TEX_RGBA_16, + DRW_TEX_RGBA_32, + DRW_TEX_RGB_8, + DRW_TEX_RGB_16, + DRW_TEX_RGB_32, + DRW_TEX_RG_8, + DRW_TEX_RG_16, + DRW_TEX_RG_32, + DRW_TEX_R_8, + DRW_TEX_R_16, + DRW_TEX_R_32, + DRW_TEX_DEPTH_16, + DRW_TEX_DEPTH_24, + DRW_TEX_DEPTH_32, +} DRWTextureFormat; + +typedef enum { + DRW_TEX_FILTER = (1 << 0), + DRW_TEX_WRAP = (1 << 1), + DRW_TEX_COMPARE = (1 << 2), +} DRWTextureFlag; + +struct GPUTexture *DRW_texture_create_1D( + int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels); +struct GPUTexture *DRW_texture_create_2D( + int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels); +struct GPUTexture *DRW_texture_create_2D_array( + int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels); +void DRW_texture_free(struct GPUTexture *tex); + +/* UBOs */ +struct GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data); +void DRW_uniformbuffer_update(struct GPUUniformBuffer *ubo, const void *data); +void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo); + +/* Buffers */ + +/* DRWFboTexture->format */ +#define DRW_BUF_DEPTH_16 1 +#define DRW_BUF_DEPTH_24 2 +#define DRW_BUF_R_8 3 +#define DRW_BUF_R_16 4 +#define DRW_BUF_R_32 5 +#define DRW_BUF_RG_8 6 +#define DRW_BUF_RG_16 7 +#define DRW_BUF_RG_32 8 +#define DRW_BUF_RGB_8 9 +#define DRW_BUF_RGB_16 10 +#define DRW_BUF_RGB_32 11 +#define DRW_BUF_RGBA_8 12 +#define DRW_BUF_RGBA_16 13 +#define DRW_BUF_RGBA_32 14 + +#define MAX_FBO_TEX 5 + +typedef struct DRWFboTexture { + struct GPUTexture **tex; + int format; +} DRWFboTexture; + +void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr); +void DRW_framebuffer_bind(struct GPUFrameBuffer *fb); +void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot); +void DRW_framebuffer_texture_detach(struct GPUTexture *tex); +/* Shaders */ +struct GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines); +struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines); +struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines); +struct GPUShader *DRW_shader_create_3D_depth_only(void); +void DRW_shader_free(struct GPUShader *shader); + +/* Batches */ + +typedef enum { + DRW_STATE_WRITE_DEPTH = (1 << 0), + DRW_STATE_WRITE_COLOR = (1 << 1), + DRW_STATE_DEPTH_LESS = (1 << 2), + DRW_STATE_DEPTH_EQUAL = (1 << 3), + DRW_STATE_CULL_BACK = (1 << 4), + DRW_STATE_CULL_FRONT = (1 << 5), + DRW_STATE_WIRE = (1 << 6), + DRW_STATE_WIRE_LARGE = (1 << 7), + DRW_STATE_POINT = (1 << 8), + DRW_STATE_STIPPLE_2 = (1 << 9), + DRW_STATE_STIPPLE_3 = (1 << 10), + DRW_STATE_STIPPLE_4 = (1 << 11), + DRW_STATE_BLEND = (1 << 12), +} DRWState; + +DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass); +DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, struct Batch *geom); +DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass); +DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass); + +void DRW_shgroup_free(struct DRWShadingGroup *shgroup); +void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Batch *geom, float (*obmat)[4]); +void DRW_shgroup_dynamic_call_add(DRWShadingGroup *shgroup, ...); +void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state); +void DRW_shgroup_attrib_int(DRWShadingGroup *shgroup, const char *name, int size); +void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size); + +void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex, int loc); +void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo, int loc); +void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc); +void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize); +void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); +void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); +void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); +void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); +void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize); +void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize); +void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize); +void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value); +void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value); + +/* Passes */ +DRWPass *DRW_pass_create(const char *name, DRWState state); + +/* Viewport */ +typedef enum { + DRW_MAT_PERS, + DRW_MAT_WIEW, + DRW_MAT_WIN, +} DRWViewportMatrixType; + +void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes, void **storage); +void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type); +float *DRW_viewport_size_get(void); +float *DRW_viewport_screenvecs_get(void); +float *DRW_viewport_pixelsize_get(void); +bool DRW_viewport_is_persp_get(void); +bool DRW_viewport_cache_is_dirty(void); + +/* Settings */ +#ifndef __DRW_ENGINE_H__ +void *DRW_material_settings_get(Material *ma, const char *engine_name); +void *DRW_render_settings_get(Scene *scene, const char *engine_name); +#endif /* __DRW_ENGINE_H__ */ + +/* Draw commands */ +void DRW_draw_background(void); +void DRW_centercircle(const float co[3]); +void DRW_draw_pass(DRWPass *pass); + +void DRW_state_reset(void); + +/* Other */ +void DRW_get_dfdy_factors(float dfdyfac[2]); + +#endif /* __DRW_RENDER_H__ */
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c new file mode 100644 index 00000000000..7ea6b8d0066 --- /dev/null +++ b/source/blender/draw/intern/draw_cache.c @@ -0,0 +1,556 @@ +/* + * Copyright 2016, 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_cache.c + * \ingroup draw + */ + + +#include "DNA_scene_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "BKE_mesh_render.h" + +#include "GPU_batch.h" + +#include "draw_cache.h" + +static struct DRWShapeCache{ + Batch *drw_single_vertice; + Batch *drw_fullscreen_quad; + Batch *drw_plain_axes; + Batch *drw_single_arrow; + Batch *drw_cube; + Batch *drw_circle; + Batch *drw_line; + Batch *drw_empty_sphere; + Batch *drw_empty_cone; + Batch *drw_arrows; + Batch *drw_lamp; + Batch *drw_lamp_sunrays; +} SHC = {NULL}; + +void DRW_shape_cache_free(void) +{ + if (SHC.drw_single_vertice) + Batch_discard_all(SHC.drw_single_vertice); + if (SHC.drw_fullscreen_quad) + Batch_discard_all(SHC.drw_fullscreen_quad); + if (SHC.drw_plain_axes) + Batch_discard_all(SHC.drw_plain_axes); + if (SHC.drw_single_arrow) + Batch_discard_all(SHC.drw_single_arrow); + if (SHC.drw_cube) + Batch_discard_all(SHC.drw_cube); + if (SHC.drw_circle) + Batch_discard_all(SHC.drw_circle); + if (SHC.drw_line) + Batch_discard_all(SHC.drw_line); + if (SHC.drw_empty_sphere) + Batch_discard_all(SHC.drw_empty_sphere); + if (SHC.drw_empty_cone) + Batch_discard_all(SHC.drw_empty_cone); + if (SHC.drw_arrows) + Batch_discard_all(SHC.drw_arrows); + if (SHC.drw_lamp) + Batch_discard_all(SHC.drw_lamp); + if (SHC.drw_lamp_sunrays) + Batch_discard_all(SHC.drw_lamp_sunrays); +} + +/* Quads */ +Batch *DRW_cache_fullscreen_quad_get(void) +{ + if (!SHC.drw_fullscreen_quad) { + float v1[2] = {-1.0f, -1.0f}; + float v2[2] = { 1.0f, -1.0f}; + float v3[2] = {-1.0f, 1.0f}; + float v4[2] = { 1.0f, 1.0f}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 6); + + setAttrib(vbo, pos_id, 0, v1); + setAttrib(vbo, pos_id, 1, v2); + setAttrib(vbo, pos_id, 2, v3); + + setAttrib(vbo, pos_id, 3, v2); + setAttrib(vbo, pos_id, 4, v3); + setAttrib(vbo, pos_id, 5, v4); + + SHC.drw_fullscreen_quad = Batch_create(GL_TRIANGLES, vbo, NULL); + } + return SHC.drw_fullscreen_quad; +} + +/* Common */ + +Batch *DRW_cache_cube_get(void) +{ + if (!SHC.drw_cube) { + const GLfloat verts[8][3] = { + {-1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f}, + {-1.0f, 1.0f, 1.0f}, + { 1.0f, -1.0f, -1.0f}, + { 1.0f, -1.0f, 1.0f}, + { 1.0f, 1.0f, -1.0f}, + { 1.0f, 1.0f, 1.0f} + }; + + const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 24); + + for (int i = 0; i < 24; ++i) { + setAttrib(vbo, pos_id, i, verts[indices[i]]); + } + + SHC.drw_cube = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_cube; +} + +Batch *DRW_cache_circle_get(void) +{ +#define CIRCLE_RESOL 32 + if (!SHC.drw_circle) { + float v[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2); + + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[2] = 0.0f; + setAttrib(vbo, pos_id, a * 2, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[2] = 0.0f; + setAttrib(vbo, pos_id, a * 2 + 1, v); + } + + SHC.drw_circle = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_circle; +#undef CIRCLE_RESOL +} + +Batch *DRW_cache_single_line_get(void) +{ + /* Z axis line */ + if (!SHC.drw_line) { + float v1[3] = {0.0f, 0.0f, 0.0f}; + float v2[3] = {0.0f, 0.0f, 1.0f}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 2); + + setAttrib(vbo, pos_id, 0, v1); + setAttrib(vbo, pos_id, 1, v2); + + SHC.drw_line = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_line; +} + +/* Empties */ +Batch *DRW_cache_plain_axes_get(void) +{ + if (!SHC.drw_plain_axes) { + int axis; + float v1[3] = {0.0f, 0.0f, 0.0f}; + float v2[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 6); + + for (axis = 0; axis < 3; axis++) { + v1[axis] = 1.0f; + v2[axis] = -1.0f; + + setAttrib(vbo, pos_id, axis * 2, v1); + setAttrib(vbo, pos_id, axis * 2 + 1, v2); + + /* reset v1 & v2 to zero for next axis */ + v1[axis] = v2[axis] = 0.0f; + } + + SHC.drw_plain_axes = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_plain_axes; +} + +Batch *DRW_cache_single_arrow_get(void) +{ + if (!SHC.drw_single_arrow) { + float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3], v3[3]; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + /* Square Pyramid */ + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 12); + + v2[0] = 0.035f; v2[1] = 0.035f; + v3[0] = -0.035f; v3[1] = 0.035f; + v2[2] = v3[2] = 0.75f; + + for (int sides = 0; sides < 4; sides++) { + if (sides % 2 == 1) { + v2[0] = -v2[0]; + v3[1] = -v3[1]; + } + else { + v2[1] = -v2[1]; + v3[0] = -v3[0]; + } + + setAttrib(vbo, pos_id, sides * 3 + 0, v1); + setAttrib(vbo, pos_id, sides * 3 + 1, v2); + setAttrib(vbo, pos_id, sides * 3 + 2, v3); + } + + SHC.drw_single_arrow = Batch_create(GL_TRIANGLES, vbo, NULL); + } + return SHC.drw_single_arrow; +} + +Batch *DRW_cache_empty_sphere_get(void) +{ +#define NSEGMENTS 16 + if (!SHC.drw_empty_sphere) { + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = cosf(angle); + p[i][1] = sinf(angle); + } + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3); + + for (int axis = 0; axis < 3; ++axis) { + for (int i = 0; i < NSEGMENTS; ++i) { + for (int j = 0; j < 2; ++j) { + float cv[2], v[3]; + + cv[0] = p[(i+j) % NSEGMENTS][0]; + cv[1] = p[(i+j) % NSEGMENTS][1]; + + if (axis == 0) + v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f; + else if (axis == 1) + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + else + v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1]; + + setAttrib(vbo, pos_id, i*2 + j + (NSEGMENTS * 2 * axis), v); + } + } + } + + SHC.drw_empty_sphere = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_empty_sphere; +#undef NSEGMENTS +} + +Batch *DRW_cache_empty_cone_get(void) +{ +#define NSEGMENTS 8 + if (!SHC.drw_empty_cone) { + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = cosf(angle); + p[i][1] = sinf(angle); + } + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, NSEGMENTS * 4); + + for (int i = 0; i < NSEGMENTS; ++i) { + float cv[2], v[3]; + cv[0] = p[(i) % NSEGMENTS][0]; + cv[1] = p[(i) % NSEGMENTS][1]; + + /* cone sides */ + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + setAttrib(vbo, pos_id, i*4, v); + v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f; + setAttrib(vbo, pos_id, i*4 + 1, v); + + /* end ring */ + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + setAttrib(vbo, pos_id, i*4 + 2, v); + cv[0] = p[(i+1) % NSEGMENTS][0]; + cv[1] = p[(i+1) % NSEGMENTS][1]; + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + setAttrib(vbo, pos_id, i*4 + 3, v); + } + + SHC.drw_empty_cone = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_empty_cone; +#undef NSEGMENTS +} + +Batch *DRW_cache_arrows_get(void) +{ + if (!SHC.drw_arrows) { + float v1[3] = {0.0, 0.0, 0.0}; + float v2[3] = {0.0, 0.0, 0.0}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + /* Line */ + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 6 * 3); + + for (int axis = 0; axis < 3; axis++) { + const int arrow_axis = (axis == 0) ? 1 : 0; + + v2[axis] = 1.0f; + setAttrib(vbo, pos_id, axis * 6 + 0, v1); + setAttrib(vbo, pos_id, axis * 6 + 1, v2); + + v1[axis] = 0.85f; + v1[arrow_axis] = -0.08f; + setAttrib(vbo, pos_id, axis * 6 + 2, v1); + setAttrib(vbo, pos_id, axis * 6 + 3, v2); + + v1[arrow_axis] = 0.08f; + setAttrib(vbo, pos_id, axis * 6 + 4, v1); + setAttrib(vbo, pos_id, axis * 6 + 5, v2); + + /* reset v1 & v2 to zero */ + v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f; + } + + SHC.drw_arrows = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_arrows; +} + +/* Lamps */ +Batch *DRW_cache_lamp_get(void) +{ +#define NSEGMENTS 8 + if (!SHC.drw_lamp) { + float v[2]; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, NSEGMENTS * 2); + + for (int a = 0; a < NSEGMENTS; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS)); + v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS)); + setAttrib(vbo, pos_id, a * 2, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS)); + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS)); + setAttrib(vbo, pos_id, a * 2 + 1, v); + } + + SHC.drw_lamp = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_lamp; +#undef NSEGMENTS +} + +Batch *DRW_cache_lamp_sunrays_get(void) +{ + if (!SHC.drw_lamp_sunrays) { + float v[2], v1[2], v2[2]; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 16); + + for (int a = 0; a < 8; a++) { + v[0] = sinf((2.0f * M_PI * a) / 8.0f); + v[1] = cosf((2.0f * M_PI * a) / 8.0f); + + mul_v2_v2fl(v1, v, 1.2f); + mul_v2_v2fl(v2, v, 2.5f); + + setAttrib(vbo, pos_id, a * 2, v1); + setAttrib(vbo, pos_id, a * 2 + 1, v2); + } + + SHC.drw_lamp_sunrays = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_lamp_sunrays; +} + + +/* Object Center */ +Batch *DRW_cache_single_vert_get(void) +{ + if (!SHC.drw_single_vertice) { + float v1[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 1); + + setAttrib(vbo, pos_id, 0, v1); + + SHC.drw_single_vertice = Batch_create(GL_POINTS, vbo, NULL); + } + return SHC.drw_single_vertice; +} + +/* Meshes */ +Batch *DRW_cache_wire_overlay_get(Object *ob) +{ + Batch *overlay_wire = NULL; + + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; +#if 1 /* new version not working */ + overlay_wire = BKE_mesh_batch_cache_get_overlay_edges(me); +#else + overlay_wire = BKE_mesh_batch_cache_get_all_edges(me); +#endif + return overlay_wire; +} + +Batch *DRW_cache_wire_outline_get(Object *ob) +{ + Batch *fancy_wire = NULL; + + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + fancy_wire = BKE_mesh_batch_cache_get_fancy_edges(me); + + return fancy_wire; +} + +Batch *DRW_cache_surface_get(Object *ob) +{ + Batch *surface = NULL; + + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + surface = BKE_mesh_batch_cache_get_all_triangles(me); + + return surface; +} + +#if 0 /* TODO */ +struct Batch *DRW_cache_surface_material_get(Object *ob, int nr) { + /* TODO */ + return NULL; +} +#endif
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h new file mode 100644 index 00000000000..0e467bddbfa --- /dev/null +++ b/source/blender/draw/intern/draw_cache.h @@ -0,0 +1,57 @@ +/* + * Copyright 2016, 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_cache.h + * \ingroup draw + */ + +#ifndef __DRAW_CACHE_H__ +#define __DRAW_CACHE_H__ + +struct Batch; +struct Object; + +void DRW_shape_cache_free(void); + +/* Common Shapes */ +struct Batch *DRW_cache_fullscreen_quad_get(void); +struct Batch *DRW_cache_single_vert_get(void); +struct Batch *DRW_cache_single_line_get(void); + +/* Empties */ +struct Batch *DRW_cache_plain_axes_get(void); +struct Batch *DRW_cache_single_arrow_get(void); +struct Batch *DRW_cache_cube_get(void); +struct Batch *DRW_cache_circle_get(void); +struct Batch *DRW_cache_empty_sphere_get(void); +struct Batch *DRW_cache_empty_cone_get(void); +struct Batch *DRW_cache_arrows_get(void); + +/* Lamps */ +struct Batch *DRW_cache_lamp_get(void); +struct Batch *DRW_cache_lamp_sunrays_get(void); + +/* Meshes */ +struct Batch *DRW_cache_wire_overlay_get(struct Object *ob); +struct Batch *DRW_cache_wire_outline_get(struct Object *ob); +struct Batch *DRW_cache_surface_get(struct Object *ob); + +#endif /* __DRAW_CACHE_H__ */
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c new file mode 100644 index 00000000000..970bd2f6dee --- /dev/null +++ b/source/blender/draw/intern/draw_manager.c @@ -0,0 +1,1272 @@ +/* + * Copyright 2016, 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/draw_manager.c + * \ingroup draw + */ + +#include <stdio.h> + +#include "BLI_listbase.h" +#include "BLI_rect.h" +#include "BLI_string.h" + +#include "BIF_glutil.h" + +#include "BKE_global.h" + +#include "BLT_translation.h" + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_view3d_types.h" + +#include "GPU_basic_shader.h" +#include "GPU_batch.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_framebuffer.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" +#include "GPU_shader.h" +#include "GPU_texture.h" +#include "GPU_uniformbuffer.h" +#include "GPU_viewport.h" + +#include "RE_engine.h" + +#include "UI_resources.h" + +#include "clay.h" + +#define MAX_ATTRIB_NAME 32 + +extern char datatoc_gpu_shader_2D_vert_glsl[]; +extern char datatoc_gpu_shader_3D_vert_glsl[]; +extern char datatoc_gpu_shader_basic_vert_glsl[]; + +/* Structures */ +typedef enum { + DRW_UNIFORM_BOOL, + DRW_UNIFORM_INT, + DRW_UNIFORM_FLOAT, + DRW_UNIFORM_TEXTURE, + DRW_UNIFORM_BUFFER, + DRW_UNIFORM_MAT3, + DRW_UNIFORM_MAT4, + DRW_UNIFORM_BLOCK +} DRWUniformType; + +typedef enum { + DRW_ATTRIB_INT, + DRW_ATTRIB_FLOAT, +} DRWAttribType; + +typedef struct DRWUniform { + struct DRWUniform *next, *prev; + DRWUniformType type; + int location; + int length; + int arraysize; + int bindloc; + const void *value; +} DRWUniform; + +typedef struct DRWAttrib { + struct DRWAttrib *next, *prev; + char name[MAX_ATTRIB_NAME]; + int location; + int format_id; + int size; /* number of component */ + int type; +} DRWAttrib; + +struct DRWInterface { + ListBase uniforms; /* DRWUniform */ + ListBase attribs; /* DRWAttrib */ + int attribs_count; + int attribs_stride; + int attribs_size[16]; + int attribs_loc[16]; + /* matrices locations */ + int modelview; + int projection; + int modelviewprojection; + int viewprojection; + int normal; + int eye; + /* Dynamic batch */ + GLuint instance_vbo; + int instance_count; + VertexFormat vbo_format; +}; + +struct DRWPass { + ListBase shgroups; /* DRWShadingGroup */ + DRWState state; + float state_param; /* Line / Point width */ +}; + +typedef struct DRWCall { + struct DRWCall *next, *prev; + Batch *geometry; + float (*obmat)[4]; +} DRWCall; + +typedef struct DRWDynamicCall { + struct DRWDynamicCall *next, *prev; + const void *data[]; +} DRWDynamicCall; + +struct DRWShadingGroup { + struct DRWShadingGroup *next, *prev; + + struct GPUShader *shader; /* Shader to bind */ + struct DRWInterface *interface; /* Uniforms pointers */ + ListBase calls; /* DRWCall or DRWDynamicCall depending of type*/ + int state; /* State changes for this batch only */ + int type; + + Batch *instance_geom; /* Geometry to instance */ + Batch *batch_geom; /* Result of call batching */ +}; + +/* Used by DRWShadingGroup.type */ +enum { + DRW_SHG_NORMAL, + DRW_SHG_POINT_BATCH, + DRW_SHG_LINE_BATCH, + DRW_SHG_INSTANCE, +}; + +/* Render State */ +static struct DRWGlobalState{ + GPUShader *shader; + struct GPUFrameBuffer *default_framebuffer; + FramebufferList *current_fbl; + TextureList *current_txl; + PassList *current_psl; + ListBase bound_texs; + int tex_bind_id; + float size[2]; + float screenvecs[2][3]; + float pixsize; + /* Current rendering context set by DRW_viewport_init */ + const struct bContext *context; +} DST = {NULL}; + +/* ***************************************** TEXTURES ******************************************/ +static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *data_type, int *channels) +{ + switch (format) { + case DRW_TEX_RGBA_8: *data_type = GPU_RGBA8; break; + case DRW_TEX_RGBA_16: *data_type = GPU_RGBA16F; break; + case DRW_TEX_RG_16: *data_type = GPU_RG16F; break; + case DRW_TEX_RG_32: *data_type = GPU_RG32F; break; + case DRW_TEX_R_8: *data_type = GPU_R8; break; +#if 0 + case DRW_TEX_RGBA_32: *data_type = GPU_RGBA32F; break; + case DRW_TEX_RGB_8: *data_type = GPU_RGB8; break; + case DRW_TEX_RGB_16: *data_type = GPU_RGB16F; break; + case DRW_TEX_RGB_32: *data_type = GPU_RGB32F; break; + case DRW_TEX_RG_8: *data_type = GPU_RG8; break; + case DRW_TEX_R_16: *data_type = GPU_R16F; break; + case DRW_TEX_R_32: *data_type = GPU_R32F; break; +#endif + case DRW_TEX_DEPTH_16: *data_type = GPU_DEPTH_COMPONENT16; break; + case DRW_TEX_DEPTH_24: *data_type = GPU_DEPTH_COMPONENT24; break; + case DRW_TEX_DEPTH_32: *data_type = GPU_DEPTH_COMPONENT32F; break; + default : + /* file type not supported you must uncomment it from above */ + BLI_assert(false); + break; + } + + switch (format) { + case DRW_TEX_RGBA_8: + case DRW_TEX_RGBA_16: + case DRW_TEX_RGBA_32: + *channels = 4; + break; + case DRW_TEX_RGB_8: + case DRW_TEX_RGB_16: + case DRW_TEX_RGB_32: + *channels = 3; + break; + case DRW_TEX_RG_8: + case DRW_TEX_RG_16: + case DRW_TEX_RG_32: + *channels = 2; + break; + default: + *channels = 1; + break; + } +} + +static void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags) +{ + GPU_texture_bind(tex, 0); + GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER); + GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP); + GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE); + GPU_texture_unbind(tex); +} + +GPUTexture *DRW_texture_create_1D(int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels) +{ + GPUTexture *tex; + GPUTextureFormat data_type; + int channels; + + drw_texture_get_format(format, &data_type, &channels); + tex = GPU_texture_create_1D_custom(w, channels, data_type, fpixels, NULL); + drw_texture_set_parameters(tex, flags); + + return tex; +} + +GPUTexture *DRW_texture_create_2D(int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels) +{ + GPUTexture *tex; + GPUTextureFormat data_type; + int channels; + + drw_texture_get_format(format, &data_type, &channels); + tex = GPU_texture_create_2D_custom(w, h, channels, data_type, fpixels, NULL); + drw_texture_set_parameters(tex, flags); + + return tex; +} + +/* TODO make use of format */ +GPUTexture *DRW_texture_create_2D_array(int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels) +{ + GPUTexture *tex; + + tex = GPU_texture_create_2D_array(w, h, d, fpixels, NULL); + drw_texture_set_parameters(tex, flags); + + return tex; +} + +void DRW_texture_free(GPUTexture *tex) +{ + GPU_texture_free(tex); +} + + +/* ************************************ UNIFORM BUFFER OBJECT **********************************/ + +GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data) +{ + return GPU_uniformbuffer_create(size, data, NULL); +} + +void DRW_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data) +{ + GPU_uniformbuffer_update(ubo, data); +} + +void DRW_uniformbuffer_free(GPUUniformBuffer *ubo) +{ + GPU_uniformbuffer_free(ubo); +} + +/* ****************************************** SHADERS ******************************************/ + +GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines) +{ + return GPU_shader_create(vert, frag, geom, NULL, defines, 0, 0, 0); +} + +GPUShader *DRW_shader_create_2D(const char *frag, const char *defines) +{ + return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0); +} + +GPUShader *DRW_shader_create_3D(const char *frag, const char *defines) +{ + return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0); +} + +GPUShader *DRW_shader_create_3D_depth_only(void) +{ + return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY); +} + +void DRW_shader_free(GPUShader *shader) +{ + GPU_shader_free(shader); +} + +/* ***************************************** INTERFACE ******************************************/ + +static DRWInterface *DRW_interface_create(GPUShader *shader) +{ + DRWInterface *interface = MEM_mallocN(sizeof(DRWInterface), "DRWInterface"); + + interface->modelview = GPU_shader_get_uniform(shader, "ModelViewMatrix"); + interface->projection = GPU_shader_get_uniform(shader, "ProjectionMatrix"); + interface->viewprojection = GPU_shader_get_uniform(shader, "ViewProjectionMatrix"); + interface->modelviewprojection = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix"); + interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix"); + interface->eye = GPU_shader_get_uniform(shader, "eye"); + interface->instance_count = 0; + interface->attribs_count = 0; + interface->attribs_stride = 0; + interface->instance_vbo = 0; + + memset(&interface->vbo_format, 0, sizeof(VertexFormat)); + + BLI_listbase_clear(&interface->uniforms); + BLI_listbase_clear(&interface->attribs); + + return interface; +} + +static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name, + DRWUniformType type, const void *value, int length, int arraysize, int bindloc) +{ + DRWUniform *uni = MEM_mallocN(sizeof(DRWUniform), "DRWUniform"); + + if (type == DRW_UNIFORM_BLOCK) { + uni->location = GPU_shader_get_uniform_block(shgroup->shader, name); + } + else { + uni->location = GPU_shader_get_uniform(shgroup->shader, name); + } + + uni->type = type; + uni->value = value; + uni->length = length; + uni->arraysize = arraysize; + uni->bindloc = bindloc; /* for textures */ + + if (uni->location == -1) { + if (G.debug & G_DEBUG) + fprintf(stderr, "Uniform '%s' not found!\n", name); + + MEM_freeN(uni); + return; + } + + BLI_addtail(&shgroup->interface->uniforms, uni); +} + +static void DRW_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType type, int size) +{ + DRWAttrib *attrib = MEM_mallocN(sizeof(DRWAttrib), "DRWAttrib"); + GLuint program = GPU_shader_get_program(shgroup->shader); + + attrib->location = glGetAttribLocation(program, name); + attrib->type = type; + attrib->size = size; + + if (attrib->location == -1) { + if (G.debug & G_DEBUG) + fprintf(stderr, "Attribute '%s' not found!\n", name); + + MEM_freeN(attrib); + return; + } + + BLI_assert(BLI_strnlen(name, 32) < 32); + BLI_strncpy(attrib->name, name, 32); + + shgroup->interface->attribs_count += 1; + + BLI_addtail(&shgroup->interface->attribs, attrib); +} + +void DRW_get_dfdy_factors(float dfdyfac[2]) +{ + GPU_get_dfdy_factors(dfdyfac); +} + +/* ***************************************** SHADING GROUP ******************************************/ + +DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) +{ + DRWShadingGroup *shgroup = MEM_mallocN(sizeof(DRWShadingGroup), "DRWShadingGroup"); + + shgroup->type = DRW_SHG_NORMAL; + shgroup->shader = shader; + shgroup->interface = DRW_interface_create(shader); + shgroup->state = 0; + shgroup->batch_geom = NULL; + shgroup->instance_geom = NULL; + + BLI_addtail(&pass->shgroups, shgroup); + BLI_listbase_clear(&shgroup->calls); + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, Batch *geom) +{ + DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass); + + shgroup->type = DRW_SHG_INSTANCE; + shgroup->instance_geom = geom; + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass) +{ + DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass); + + shgroup->type = DRW_SHG_POINT_BATCH; + DRW_shgroup_attrib_float(shgroup, "pos", 3); + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass) +{ + DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass); + + shgroup->type = DRW_SHG_LINE_BATCH; + DRW_shgroup_attrib_float(shgroup, "pos", 3); + + return shgroup; +} + +void DRW_shgroup_free(struct DRWShadingGroup *shgroup) +{ + BLI_freelistN(&shgroup->calls); + BLI_freelistN(&shgroup->interface->uniforms); + BLI_freelistN(&shgroup->interface->attribs); + /* TODO free instance vbo */ + MEM_freeN(shgroup->interface); + + if (shgroup->batch_geom) { + Batch_discard_all(shgroup->batch_geom); + } +} + +void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Batch *geom, float (*obmat)[4]) +{ + if (geom) { + DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall"); + + call->obmat = obmat; + call->geometry = geom; + + BLI_addtail(&shgroup->calls, call); + } +} + +void DRW_shgroup_dynamic_call_add(DRWShadingGroup *shgroup, ...) +{ + va_list params; + int i; + DRWInterface *interface = shgroup->interface; + int size = sizeof(ListBase) + sizeof(void *) * interface->attribs_count; + + DRWDynamicCall *call = MEM_callocN(size, "DRWDynamicCall"); + + va_start(params, shgroup); + for (i = 0; i < interface->attribs_count; ++i) { + call->data[i] = va_arg(params, void *); + } + va_end(params); + + interface->instance_count += 1; + + BLI_addtail(&shgroup->calls, call); +} + +/* Make sure you know what you do when using this, + * State is not revert back at the end of the shgroup */ +void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state) +{ + shgroup->state = state; +} + +void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size) +{ + DRW_interface_attrib(shgroup, name, DRW_ATTRIB_FLOAT, size); +} + +void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex, int loc) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 0, loc); +} + +void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo, int loc) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 0, loc); +} + +void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc) +{ + /* we abuse the lenght attrib to store the buffer index */ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, NULL, value, 0, loc); +} + +void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize, 0); +} + +void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 1, arraysize, 0); +} + +void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 2, arraysize, 0); +} + +void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 3, arraysize, 0); +} + +void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize, 0); +} + +void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize, 0); +} + +void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 2, arraysize, 0); +} + +void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 3, arraysize, 0); +} + +void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_MAT3, value, 9, 1, 0); +} + +void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value) +{ + DRW_interface_uniform(shgroup, name, DRW_UNIFORM_MAT4, value, 16, 1, 0); +} + +/* Creates a VBO containing OGL primitives for all DRWDynamicCall */ +static void shgroup_dynamic_batch(DRWShadingGroup *shgroup) +{ + DRWInterface *interface = shgroup->interface; + int nbr = interface->instance_count; + + GLenum type = (shgroup->type == DRW_SHG_POINT_BATCH) ? GL_POINTS : GL_LINES; + + if (nbr == 0) + return; + + /* Upload Data */ + if (interface->vbo_format.attrib_ct == 0) { + for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next) { + BLI_assert(attrib->size <= 4); /* matrices have no place here for now */ + if (attrib->type == DRW_ATTRIB_FLOAT) { + attrib->format_id = add_attrib(&interface->vbo_format, attrib->name, GL_FLOAT, attrib->size, KEEP_FLOAT); + } + else if (attrib->type == DRW_ATTRIB_INT) { + attrib->format_id = add_attrib(&interface->vbo_format, attrib->name, GL_BYTE, attrib->size, KEEP_INT); + } + else { + BLI_assert(false); + } + } + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&interface->vbo_format); + VertexBuffer_allocate_data(vbo, nbr); + + int j = 0; + for (DRWDynamicCall *call = shgroup->calls.first; call; call = call->next, j++) { + int i = 0; + for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next, i++) { + setAttrib(vbo, attrib->format_id, j, call->data[i]); + } + } + + /* TODO make the batch dynamic instead of freeing it every times */ + if (shgroup->batch_geom) + Batch_discard_all(shgroup->batch_geom); + + shgroup->batch_geom = Batch_create(type, vbo, NULL); +} + +static void shgroup_dynamic_instance(DRWShadingGroup *shgroup) +{ + int i = 0; + int offset = 0; + DRWInterface *interface = shgroup->interface; + int vert_nbr = interface->instance_count; + int buffer_size = 0; + + if (vert_nbr == 0) { + if (interface->instance_vbo) { + glDeleteBuffers(1, &interface->instance_vbo); + interface->instance_vbo = 0; + } + return; + } + + /* only once */ + if (interface->attribs_stride == 0) { + for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next, i++) { + BLI_assert(attrib->type == DRW_ATTRIB_FLOAT); /* Only float for now */ + interface->attribs_stride += attrib->size; + interface->attribs_size[i] = attrib->size; + interface->attribs_loc[i] = attrib->location; + } + } + + /* Gather Data */ + buffer_size = sizeof(float) * interface->attribs_stride * vert_nbr; + float *data = MEM_mallocN(buffer_size, "Instance VBO data"); + + for (DRWDynamicCall *call = shgroup->calls.first; call; call = call->next) { + for (int j = 0; j < interface->attribs_count; ++j) { + memcpy(data + offset, call->data[j], sizeof(float) * interface->attribs_size[j]); + offset += interface->attribs_size[j]; + } + } + + /* TODO poke mike to add this to gawain */ + if (interface->instance_vbo) { + glDeleteBuffers(1, &interface->instance_vbo); + interface->instance_vbo = 0; + } + + glGenBuffers(1, &interface->instance_vbo); + glBindBuffer(GL_ARRAY_BUFFER, interface->instance_vbo); + glBufferData(GL_ARRAY_BUFFER, buffer_size, data, GL_STATIC_DRAW); + + MEM_freeN(data); +} + +static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup) +{ +#ifdef WITH_VIEWPORT_CACHE_TEST + if (shgroup->interface->instance_vbo || shgroup->batch_geom) return; +#endif + if (shgroup->type == DRW_SHG_INSTANCE) { + shgroup_dynamic_instance(shgroup); + } + else { + shgroup_dynamic_batch(shgroup); + } +} + +/* ***************************************** PASSES ******************************************/ + +DRWPass *DRW_pass_create(const char *name, DRWState state) +{ + DRWPass *pass = MEM_callocN(sizeof(DRWPass), name); + pass->state = state; + + BLI_listbase_clear(&pass->shgroups); + + return pass; +} + +void DRW_pass_free(DRWPass *pass) +{ + for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) { + DRW_shgroup_free(shgroup); + } + BLI_freelistN(&pass->shgroups); +} + +/* ****************************************** DRAW ******************************************/ + +void DRW_draw_background(void) +{ + /* Just to make sure */ + glDepthMask(GL_TRUE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { + /* Gradient background Color */ + gpuMatrixBegin3D(); /* TODO: finish 2D API */ + + glClear(GL_DEPTH_BUFFER_BIT); + + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT); + unsigned char col_hi[3], col_lo[3]; + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + + UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo); + UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi); + + immBegin(GL_QUADS, 4); + immAttrib3ubv(color, col_lo); + immVertex2f(pos, -1.0f, -1.0f); + immVertex2f(pos, 1.0f, -1.0f); + + immAttrib3ubv(color, col_hi); + immVertex2f(pos, 1.0f, 1.0f); + immVertex2f(pos, -1.0f, 1.0f); + immEnd(); + + immUnbindProgram(); + + gpuMatrixEnd(); + } + else { + /* Solid background Color */ + UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } +} +#ifdef WITH_CLAY_ENGINE +/* Only alter the state (does not reset it like set_state() ) */ +static void shgroup_set_state(DRWShadingGroup *shgroup) +{ + if (shgroup->state) { + /* Blend */ + if (shgroup->state & DRW_STATE_BLEND) { + glEnable(GL_BLEND); + } + + /* Wire width */ + if (shgroup->state & DRW_STATE_WIRE) { + glLineWidth(1.0f); + } + else if (shgroup->state & DRW_STATE_WIRE_LARGE) { + glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); + } + + /* Line Stipple */ + if (shgroup->state & DRW_STATE_STIPPLE_2) { + setlinestyle(2); + } + else if (shgroup->state & DRW_STATE_STIPPLE_3) { + setlinestyle(3); + } + else if (shgroup->state & DRW_STATE_STIPPLE_4) { + setlinestyle(4); + } + + if (shgroup->state & DRW_STATE_POINT) { + GPU_enable_program_point_size(); + glPointSize(5.0f); + } + } +} + +typedef struct DRWBoundTexture { + struct DRWBoundTexture *next, *prev; + GPUTexture *tex; +} DRWBoundTexture; + +static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*obmat)[4]) +{ + RegionView3D *rv3d = CTX_wm_region_view3d(DST.context); + DRWInterface *interface = shgroup->interface; + + float mvp[4][4], mv[4][4], n[3][3]; + float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */ + + bool do_mvp = (interface->modelviewprojection != -1); + bool do_mv = (interface->modelview != -1); + bool do_n = (interface->normal != -1); + bool do_eye = (interface->eye != -1); + + if (do_mvp) { + mul_m4_m4m4(mvp, rv3d->persmat, obmat); + } + if (do_mv || do_n || do_eye) { + mul_m4_m4m4(mv, rv3d->viewmat, obmat); + } + if (do_n || do_eye) { + copy_m3_m4(n, mv); + invert_m3(n); + transpose_m3(n); + } + if (do_eye) { + /* Used by orthographic wires */ + float tmp[3][3]; + invert_m3_m3(tmp, n); + /* set eye vector, transformed to object coords */ + mul_m3_v3(tmp, eye); + } + + /* Should be really simple */ + /* step 1 : bind object dependent matrices */ + if (interface->modelviewprojection != -1) { + GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp); + } + if (interface->viewprojection != -1) { + GPU_shader_uniform_vector(shgroup->shader, interface->viewprojection, 16, 1, (float *)rv3d->persmat); + } + if (interface->projection != -1) { + GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)rv3d->winmat); + } + if (interface->modelview != -1) { + GPU_shader_uniform_vector(shgroup->shader, interface->modelview, 16, 1, (float *)mv); + } + if (interface->normal != -1) { + GPU_shader_uniform_vector(shgroup->shader, interface->normal, 9, 1, (float *)n); + } + if (interface->eye != -1) { + GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye); + } + + /* step 2 : bind vertex array & draw */ + Batch_set_program(geom, GPU_shader_get_program(shgroup->shader)); + if (interface->instance_vbo) { + Batch_draw_stupid_instanced(geom, interface->instance_vbo, interface->instance_count, interface->attribs_count, + interface->attribs_stride, interface->attribs_size, interface->attribs_loc); + } + else { + Batch_draw_stupid(geom); + } +} + +static void draw_shgroup(DRWShadingGroup *shgroup) +{ + BLI_assert(shgroup->shader); + BLI_assert(shgroup->interface); + + DRWInterface *interface = shgroup->interface; + + if (DST.shader != shgroup->shader) { + if (DST.shader) GPU_shader_unbind(); + GPU_shader_bind(shgroup->shader); + DST.shader = shgroup->shader; + } + + if (shgroup->type != DRW_SHG_NORMAL) { + shgroup_dynamic_batch_from_calls(shgroup); + } + + shgroup_set_state(shgroup); + + /* Binding Uniform */ + /* Don't check anything, Interface should already contain the least uniform as possible */ + for (DRWUniform *uni = interface->uniforms.first; uni; uni = uni->next) { + DRWBoundTexture *bound_tex; + + switch (uni->type) { + case DRW_UNIFORM_BOOL: + case DRW_UNIFORM_INT: + GPU_shader_uniform_vector_int(shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->value); + break; + case DRW_UNIFORM_FLOAT: + case DRW_UNIFORM_MAT3: + case DRW_UNIFORM_MAT4: + GPU_shader_uniform_vector(shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->value); + break; + case DRW_UNIFORM_TEXTURE: + GPU_texture_bind((GPUTexture *)uni->value, uni->bindloc); + + bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture"); + bound_tex->tex = (GPUTexture *)uni->value; + BLI_addtail(&DST.bound_texs, bound_tex); + + GPU_shader_uniform_texture(shgroup->shader, uni->location, (GPUTexture *)uni->value); + break; + case DRW_UNIFORM_BUFFER: + /* restore index from lenght we abused */ + GPU_texture_bind(DST.current_txl->textures[uni->length], uni->bindloc); + GPU_texture_compare_mode(DST.current_txl->textures[uni->length], false); + GPU_texture_filter_mode(DST.current_txl->textures[uni->length], false); + + bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture"); + bound_tex->tex = DST.current_txl->textures[uni->length]; + BLI_addtail(&DST.bound_texs, bound_tex); + + GPU_shader_uniform_texture(shgroup->shader, uni->location, DST.current_txl->textures[uni->length]); + break; + case DRW_UNIFORM_BLOCK: + GPU_uniformbuffer_bind((GPUUniformBuffer *)uni->value, uni->bindloc); + GPU_shader_uniform_buffer(shgroup->shader, uni->location, (GPUUniformBuffer *)uni->value); + break; + } + } + + /* Rendering Calls */ + if (shgroup->type != DRW_SHG_NORMAL) { + /* Replacing multiple calls with only one */ + float obmat[4][4]; + unit_m4(obmat); + + if (shgroup->type == DRW_SHG_INSTANCE && interface->instance_count > 0) { + draw_geometry(shgroup, shgroup->instance_geom, obmat); + } + else { + /* Some dynamic batch can have no geom (no call to aggregate) */ + if (shgroup->batch_geom) { + draw_geometry(shgroup, shgroup->batch_geom, obmat); + } + } + } + else { + for (DRWCall *call = shgroup->calls.first; call; call = call->next) { + draw_geometry(shgroup, call->geometry, call->obmat); + } + } +} + +static void set_state(short flag) +{ + /* TODO Keep track of the state and only revert what is needed */ + + /* Depth Write */ + if (flag & DRW_STATE_WRITE_DEPTH) + glDepthMask(GL_TRUE); + else + glDepthMask(GL_FALSE); + + /* Color Write */ + if (flag & DRW_STATE_WRITE_COLOR) + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + else + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + /* Backface Culling */ + if (flag & DRW_STATE_CULL_BACK || + flag & DRW_STATE_CULL_FRONT) { + + glEnable(GL_CULL_FACE); + + if (flag & DRW_STATE_CULL_BACK) + glCullFace(GL_BACK); + else if (flag & DRW_STATE_CULL_FRONT) + glCullFace(GL_FRONT); + } + else { + glDisable(GL_CULL_FACE); + } + + /* Depht Test */ + if (flag & DRW_STATE_DEPTH_LESS || + flag & DRW_STATE_DEPTH_EQUAL) { + + glEnable(GL_DEPTH_TEST); + + if (flag & DRW_STATE_DEPTH_LESS) + glDepthFunc(GL_LEQUAL); + else if (flag & DRW_STATE_DEPTH_EQUAL) + glDepthFunc(GL_EQUAL); + } + else { + glDisable(GL_DEPTH_TEST); + } + + /* Wire Width */ + if (flag & DRW_STATE_WIRE) { + glLineWidth(1.0f); + } + else if (flag & DRW_STATE_WIRE_LARGE) { + glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); + } + + /* Points Size */ + if (flag & DRW_STATE_POINT) { + GPU_enable_program_point_size(); + glPointSize(5.0f); + } + else { + GPU_disable_program_point_size(); + } + + /* Blending (all buffer) */ + if (flag & DRW_STATE_BLEND) { + glEnable(GL_BLEND); + } + else { + glDisable(GL_BLEND); + } + + /* Line Stipple */ + if (flag & DRW_STATE_STIPPLE_2) { + setlinestyle(2); + } + else if (flag & DRW_STATE_STIPPLE_3) { + setlinestyle(3); + } + else if (flag & DRW_STATE_STIPPLE_4) { + setlinestyle(4); + } + else { + setlinestyle(0); + } +} + +void DRW_draw_pass(DRWPass *pass) +{ + /* Start fresh */ + DST.shader = NULL; + DST.tex_bind_id = 0; + + set_state(pass->state); + BLI_listbase_clear(&DST.bound_texs); + + for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) { + draw_shgroup(shgroup); + } + + /* Clear Bound textures */ + for (DRWBoundTexture *bound_tex = DST.bound_texs.first; bound_tex; bound_tex = bound_tex->next) { + GPU_texture_unbind(bound_tex->tex); + } + DST.tex_bind_id = 0; + BLI_freelistN(&DST.bound_texs); + + if (DST.shader) { + GPU_shader_unbind(); + DST.shader = NULL; + } +} + +/* Reset state to not interfer with other UI drawcall */ +void DRW_state_reset(void) +{ + DRWState state = 0; + state |= DRW_STATE_WRITE_DEPTH; + state |= DRW_STATE_WRITE_COLOR; + state |= DRW_STATE_DEPTH_LESS; + set_state(state); +} +#endif +/* ****************************************** Settings ******************************************/ +void *DRW_material_settings_get(Material *ma, const char *engine_name) +{ + MaterialEngineSettings *ms = NULL; + + ms = BLI_findstring(&ma->engines_settings, engine_name, offsetof(MaterialEngineSettings, name)); + +#ifdef WITH_CLAY_ENGINE + /* If the settings does not exists yet, create it */ + if (ms == NULL) { + ms = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings"); + + BLI_strncpy(ms->name, engine_name, 32); + + /* TODO make render_settings_create a polymorphic function */ + if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) { + ms->data = CLAY_material_settings_create(); + } + else { + /* No engine matched */ + BLI_assert(false); + } + + BLI_addtail(&ma->engines_settings, ms); + } +#else + return NULL; +#endif + + return ms->data; +} + +/* If scene is NULL, use context scene */ +void *DRW_render_settings_get(Scene *scene, const char *engine_name) +{ + RenderEngineSettings *rs = NULL; + + if (scene == NULL) + scene = CTX_data_scene(DST.context); + + rs = BLI_findstring(&scene->engines_settings, engine_name, offsetof(RenderEngineSettings, name)); + +#ifdef WITH_CLAY_ENGINE + /* If the settings does not exists yet, create it */ + if (rs == NULL) { + rs = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings"); + + BLI_strncpy(rs->name, engine_name, 32); + + /* TODO make render_settings_create a polymorphic function */ + if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) { + rs->data = CLAY_render_settings_create(); + } + else { + /* No engine matched */ + BLI_assert(false); + } + + BLI_addtail(&scene->engines_settings, rs); + } +#else + return NULL; +#endif + + return rs->data; +} +/* ****************************************** Framebuffers ******************************************/ + +void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], + int texnbr) +{ + if (!*fb) { + int color_attachment = -1; + *fb = GPU_framebuffer_create(); + + for (int i = 0; i < texnbr; ++i) + { + DRWFboTexture fbotex = textures[i]; + + if (!*fbotex.tex) { + /* TODO refine to opengl formats */ + if (fbotex.format == DRW_BUF_DEPTH_16 || + fbotex.format == DRW_BUF_DEPTH_24) { + *fbotex.tex = GPU_texture_create_depth(width, height, NULL); + GPU_texture_compare_mode(*fbotex.tex, false); + GPU_texture_filter_mode(*fbotex.tex, false); + } + else { + *fbotex.tex = GPU_texture_create_2D(width, height, NULL, NULL); + ++color_attachment; + } + } + + GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment); + } + + if (!GPU_framebuffer_check_valid(*fb, NULL)) { + printf("Error invalid framebuffer\n"); + } + + GPU_framebuffer_bind(DST.default_framebuffer); + } +} + +void DRW_framebuffer_bind(struct GPUFrameBuffer *fb) +{ + GPU_framebuffer_bind(fb); +} + +void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot) +{ + GPU_framebuffer_texture_attach(fb, tex, slot); +} + +void DRW_framebuffer_texture_detach(GPUTexture *tex) +{ + GPU_framebuffer_texture_detach(tex); +} + +/* ****************************************** Viewport ******************************************/ + +float *DRW_viewport_size_get(void) +{ + return &DST.size[0]; +} + +float *DRW_viewport_screenvecs_get(void) +{ + return &DST.screenvecs[0][0]; +} + +float *DRW_viewport_pixelsize_get(void) +{ + return &DST.pixsize; +} + +void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes, void **storage) +{ + RegionView3D *rv3d = CTX_wm_region_view3d(C); + GPUViewport *viewport = rv3d->viewport; + + GPU_viewport_get_engine_data(viewport, buffers, textures, passes, storage); + + /* Refresh DST.size */ + DefaultTextureList *txl = (DefaultTextureList *)*textures; + DST.size[0] = (float)GPU_texture_width(txl->color); + DST.size[1] = (float)GPU_texture_height(txl->color); + + DefaultFramebufferList *fbl = (DefaultFramebufferList *)*buffers; + DST.default_framebuffer = fbl->default_fb; + + DST.current_txl = (TextureList *)*textures; + DST.current_fbl = (FramebufferList *)*buffers; + DST.current_psl = (PassList *)*passes; + + /* Refresh DST.screenvecs */ + copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]); + copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]); + normalize_v3(DST.screenvecs[0]); + normalize_v3(DST.screenvecs[1]); + + /* Refresh DST.pixelsize */ + DST.pixsize = rv3d->pixsize; + + /* Save context for all later needs */ + DST.context = C; +} + +void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) +{ + RegionView3D *rv3d = CTX_wm_region_view3d(DST.context); + + if (type == DRW_MAT_PERS) + copy_m4_m4(mat, rv3d->persmat); + else if (type == DRW_MAT_WIEW) + copy_m4_m4(mat, rv3d->viewmat); + else if (type == DRW_MAT_WIN) + copy_m4_m4(mat, rv3d->winmat); +} + +bool DRW_viewport_is_persp_get(void) +{ + RegionView3D *rv3d = CTX_wm_region_view3d(DST.context); + return rv3d->is_persp; +} + +bool DRW_viewport_cache_is_dirty(void) +{ + /* TODO Use a dirty flag */ + return (DST.current_psl->passes[0] == NULL); +} + +/* ****************************************** INIT ******************************************/ + +void DRW_engines_init(void) +{ +#ifdef WITH_CLAY_ENGINE + RE_engines_register(NULL, &viewport_clay_type); +#endif +} + +void DRW_engines_free(void) +{ +#ifdef WITH_CLAY_ENGINE + clay_engine_free(); + + DRW_shape_cache_free(); + + BLI_remlink(&R_engines, &viewport_clay_type); +#endif +}
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_mode_pass.c b/source/blender/draw/intern/draw_mode_pass.c new file mode 100644 index 00000000000..0298db1a5ca --- /dev/null +++ b/source/blender/draw/intern/draw_mode_pass.c @@ -0,0 +1,541 @@ +/* + * Copyright 2016, 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/draw_mode_pass.c + * \ingroup draw + */ + +#include "DNA_userdef_types.h" + +#include "GPU_shader.h" + +#include "UI_resources.h" + +#include "BKE_global.h" + +#include "draw_mode_pass.h" + +/* ************************** OBJECT MODE ******************************* */ + +/* Store list of shading group for easy access*/ + +/* Empties */ +static DRWShadingGroup *plain_axes; +static DRWShadingGroup *cube; +static DRWShadingGroup *circle; +static DRWShadingGroup *sphere; +static DRWShadingGroup *cone; +static DRWShadingGroup *single_arrow; +static DRWShadingGroup *single_arrow_line; +static DRWShadingGroup *arrows; + +/* Lamps */ +static DRWShadingGroup *lamp_center; +static DRWShadingGroup *lamp_center_group; +static DRWShadingGroup *lamp_groundpoint; +static DRWShadingGroup *lamp_groundline; +static DRWShadingGroup *lamp_circle; +static DRWShadingGroup *lamp_circle_shadow; +static DRWShadingGroup *lamp_sunrays; + +/* Helpers */ +static DRWShadingGroup *relationship_lines; + +/* Objects Centers */ +static DRWShadingGroup *center_active; +static DRWShadingGroup *center_selected; +static DRWShadingGroup *center_deselected; + +/* Colors & Constant */ +static float colorWire[4], colorWireEdit[4]; +static float colorActive[4], colorSelect[4], colorTransform[4], colorGroup[4], colorGroupActive[4]; +static float colorEmpty[4], colorLamp[4], colorCamera[4], colorSpeaker[4]; +static float lampCenterSize, lampCircleRad, lampCircleShadowRad, colorLampNoAlpha[4]; + +static DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + + return grp; +} + +static DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + DRW_shgroup_uniform_float(grp, "size", size, 1); + DRW_shgroup_state_set(grp, DRW_STATE_POINT); + + return grp; +} + +static DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + + return grp; +} + +static DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + DRW_shgroup_state_set(grp, DRW_STATE_POINT); + + return grp; +} + +static DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Batch *geom, float *size) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR +); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); + DRW_shgroup_attrib_float(grp, "world_pos", 3); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_uniform_float(grp, "size", size, 1); + DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1); + DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2); + DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3); + + return grp; +} + +static DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_attrib_float(grp, "size", 1); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + + return grp; +} + +/* This Function setup the passes needed for the mode rendering. + * The passes are populated by the rendering engine using the DRW_shgroup_* functions. */ +void DRW_pass_setup_common(DRWPass **wire_overlay, DRWPass **wire_outline, DRWPass **non_meshes, DRWPass **ob_center) +{ + UI_GetThemeColor4fv(TH_WIRE, colorWire); + UI_GetThemeColor4fv(TH_WIRE_EDIT, colorWireEdit); + UI_GetThemeColor4fv(TH_ACTIVE, colorActive); + UI_GetThemeColor4fv(TH_SELECT, colorSelect); + UI_GetThemeColor4fv(TH_TRANSFORM, colorTransform); + UI_GetThemeColor4fv(TH_GROUP_ACTIVE, colorGroupActive); + UI_GetThemeColor4fv(TH_GROUP, colorGroup); + UI_GetThemeColor4fv(TH_LAMP, colorLamp); + UI_GetThemeColor4fv(TH_LAMP, colorLampNoAlpha); + UI_GetThemeColor4fv(TH_SPEAKER, colorSpeaker); + UI_GetThemeColor4fv(TH_CAMERA, colorCamera); + UI_GetThemeColor4fv(TH_EMPTY, colorEmpty); + + colorLampNoAlpha[3] = 1.0f; + + if (wire_overlay) { + /* This pass can draw mesh edges top of Shaded Meshes without any Z fighting */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND; + *wire_overlay = DRW_pass_create("Wire Overlays Pass", state); + } + + if (wire_outline) { + /* This pass can draw mesh outlines and/or fancy wireframe */ + /* Fancy wireframes are not meant to be occluded (without Z offset) */ + /* Outlines and Fancy Wires use the same VBO */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + *wire_outline = DRW_pass_create("Wire + Outlines Pass", state); + } + + if (non_meshes) { + /* Non Meshes Pass (Camera, empties, lamps ...) */ + DRWShadingGroup *grp; + struct Batch *geom; + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + state |= DRW_STATE_WIRE; + *non_meshes = DRW_pass_create("Non Meshes Pass", state); + + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + + /* Empties */ + geom = DRW_cache_plain_axes_get(); + plain_axes = shgroup_instance(*non_meshes, geom); + + geom = DRW_cache_cube_get(); + cube = shgroup_instance(*non_meshes, geom); + + geom = DRW_cache_circle_get(); + circle = shgroup_instance(*non_meshes, geom); + + geom = DRW_cache_empty_sphere_get(); + sphere = shgroup_instance(*non_meshes, geom); + + geom = DRW_cache_empty_cone_get(); + cone = shgroup_instance(*non_meshes, geom); + + geom = DRW_cache_single_arrow_get(); + single_arrow = shgroup_instance(*non_meshes, geom); + + geom = DRW_cache_single_line_get(); + single_arrow_line = shgroup_instance(*non_meshes, geom); + + geom = DRW_cache_single_arrow_get(); + arrows = shgroup_instance(*non_meshes, geom); + + /* Lamps */ + lampCenterSize = (U.obcenter_dia + 1.5f) * U.pixelsize; + lampCircleRad = U.pixelsize * 9.0f; + lampCircleShadowRad = lampCircleRad + U.pixelsize * 3.0f; + /* TODO + * for now we create 3 times the same VBO with only lamp center coordinates + * but ideally we would only create it once */ + lamp_center = shgroup_dynpoints_uniform_color(*non_meshes, colorLampNoAlpha, &lampCenterSize); + lamp_center_group = shgroup_dynpoints_uniform_color(*non_meshes, colorGroup, &lampCenterSize); + + geom = DRW_cache_lamp_get(); + lamp_circle = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleRad); + lamp_circle_shadow = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleShadowRad); + + geom = DRW_cache_lamp_sunrays_get(); + lamp_sunrays = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleRad); + + lamp_groundline = shgroup_groundlines_uniform_color(*non_meshes, colorLamp); + lamp_groundpoint = shgroup_groundpoints_uniform_color(*non_meshes, colorLamp); + + /* Stipple Wires */ + grp = DRW_shgroup_create(sh, *non_meshes); + DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_2); + + grp = DRW_shgroup_create(sh, *non_meshes); + DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3); + + grp = DRW_shgroup_create(sh, *non_meshes); + DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_4); + + /* Relationship Lines */ + relationship_lines = shgroup_dynlines_uniform_color(*non_meshes, colorWire); + DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3); + } + + if (ob_center) { + /* Object Center pass grouped by State */ + DRWShadingGroup *grp; + static float colorDeselect[4], outlineColor[4]; + static float outlineWidth, size; + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT; + *ob_center = DRW_pass_create("Obj Center Pass", state); + + outlineWidth = 1.0f * U.pixelsize; + size = U.obcenter_dia * U.pixelsize + outlineWidth; + //UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -80, colorActive); + //UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -80, colorSelect); + UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, colorDeselect); + UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor); + + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH); + + /* Active */ + grp = DRW_shgroup_point_batch_create(sh, *ob_center); + DRW_shgroup_uniform_float(grp, "size", &size, 1); + DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1); + DRW_shgroup_uniform_vec4(grp, "color", colorActive, 1); + DRW_shgroup_uniform_vec4(grp, "outlineColor", outlineColor, 1); + center_active = grp; + + /* Select */ + grp = DRW_shgroup_point_batch_create(sh, *ob_center); + DRW_shgroup_uniform_vec4(grp, "color", colorSelect, 1); + center_selected = grp; + + /* Deselect */ + grp = DRW_shgroup_point_batch_create(sh, *ob_center); + DRW_shgroup_uniform_vec4(grp, "color", colorDeselect, 1); + center_deselected = grp; + } +} + +/* ******************************************** WIRES *********************************************** */ + +/* TODO FINISH */ +/* Get the wire color theme_id of an object based on it's state + * **color is a way to get a pointer to the static color var associated */ +static int draw_object_wire_theme(Object *ob, float **color) +{ + const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0; + /* confusing logic here, there are 2 methods of setting the color + * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id. + * + * note: no theme yet for 'colindex' */ + int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE; + + if (//(scene->obedit == NULL) && + ((G.moving & G_TRANSFORM_OBJ) != 0) && + ((ob->base_flag & BASE_SELECTED) != 0)) + { + theme_id = TH_TRANSFORM; + } + else { + /* Sets the 'theme_id' or fallback to wire */ + if ((ob->flag & OB_FROMGROUP) != 0) { + if ((ob->base_flag & BASE_SELECTED) != 0) { + /* uses darker active color for non-active + selected */ + theme_id = TH_GROUP_ACTIVE; + + // if (scene->basact != base) { + // theme_shade = -16; + // } + } + else { + theme_id = TH_GROUP; + } + } + else { + if ((ob->base_flag & BASE_SELECTED) != 0) { + theme_id = //scene->basact == base ? TH_ACTIVE : + TH_SELECT; + } + else { + if (ob->type == OB_LAMP) theme_id = TH_LAMP; + else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER; + else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA; + else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY; + /* fallback to TH_WIRE */ + } + } + } + + if (color != NULL) { + switch (theme_id) { + case TH_WIRE_EDIT: *color = colorTransform; break; + case TH_ACTIVE: *color = colorActive; break; + case TH_SELECT: *color = colorSelect; break; + case TH_GROUP: *color = colorGroup; break; + case TH_GROUP_ACTIVE: *color = colorGroupActive; break; + case TH_TRANSFORM: *color = colorTransform; break; + case OB_SPEAKER: *color = colorSpeaker; break; + case OB_CAMERA: *color = colorCamera; break; + case OB_EMPTY: *color = colorEmpty; break; + case OB_LAMP: *color = colorLamp; break; + default: *color = colorWire; break; + } + } + + return theme_id; +} + +void DRW_shgroup_wire_overlay(DRWPass *wire_overlay, Object *ob) +{ +#if 1 + struct Batch *geom = DRW_cache_wire_overlay_get(ob); + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + + DRW_shgroup_call_add(grp, geom, ob->obmat); +#else + static float col[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + struct Batch *geom = DRW_cache_wire_overlay_get(ob); + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay); + DRW_shgroup_uniform_vec4(grp, "color", col, 1); + + DRW_shgroup_call_add(grp, geom, ob->obmat); +#endif +} + +void DRW_shgroup_wire_outline(DRWPass *wire_outline, Object *ob, + const bool do_front, const bool do_back, const bool do_outline) +{ + GPUShader *sh; + struct Batch *geom = DRW_cache_wire_outline_get(ob); + + /* Get color */ + /* TODO get the right color depending on ob state (Groups, overides etc..) */ + static float frontcol[4], backcol[4], color[4]; + UI_GetThemeColor4fv(TH_ACTIVE, color); + copy_v4_v4(frontcol, color); + copy_v4_v4(backcol, color); + backcol[3] = 0.333f; + frontcol[3] = 0.667f; + +#if 1 /* New wire */ + + bool is_perps = DRW_viewport_is_persp_get(); + static bool bTrue = true; + static bool bFalse = false; + + /* Note (TODO) : this requires cache to be discarded on ortho/perp switch + * It may be preferable (or not depending on performance implication) + * to introduce a shader uniform switch */ + if (is_perps) { + sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_PERSP); + } + else { + sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_ORTHO); + } + + if (do_front || do_back) { + bool *bFront = (do_front) ? &bTrue : &bFalse; + bool *bBack = (do_back) ? &bTrue : &bFalse; + + DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline); + DRW_shgroup_state_set(grp, DRW_STATE_WIRE); + DRW_shgroup_uniform_vec4(grp, "frontColor", frontcol, 1); + DRW_shgroup_uniform_vec4(grp, "backColor", backcol, 1); + DRW_shgroup_uniform_bool(grp, "drawFront", bFront, 1); + DRW_shgroup_uniform_bool(grp, "drawBack", bBack, 1); + DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bFalse, 1); + DRW_shgroup_call_add(grp, geom, ob->obmat); + } + + if (do_outline) { + DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline); + DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE); + DRW_shgroup_uniform_vec4(grp, "silhouetteColor", color, 1); + DRW_shgroup_uniform_bool(grp, "drawFront", &bFalse, 1); + DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 1); + DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bTrue, 1); + + DRW_shgroup_call_add(grp, geom, ob->obmat); + } + +#else /* Old (flat) wire */ + + sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline); + DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE); + DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1); + + DRW_shgroup_call_add(grp, geom, ob->obmat); +#endif + +} + +/* ***************************** NON MESHES ********************** */ + +static void DRW_draw_lamp(Object *ob) +{ + Lamp *la = ob->data; + float *color; + int theme_id = draw_object_wire_theme(ob, &color); + + /* Don't draw the center if it's selected or active */ + if (theme_id == TH_GROUP) + DRW_shgroup_dynamic_call_add(lamp_center_group, ob->obmat[3]); + else if (theme_id == TH_LAMP) + DRW_shgroup_dynamic_call_add(lamp_center, ob->obmat[3]); + + /* First circle */ + DRW_shgroup_dynamic_call_add(lamp_circle, ob->obmat[3], color); + + /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */ + if (la->type != LA_HEMI) { + DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color); + } + + /* Sunrays */ + if (la->type == LA_SUN) { + DRW_shgroup_dynamic_call_add(lamp_sunrays, ob->obmat[3], color); + } + + /* Line and point going to the ground */ + DRW_shgroup_dynamic_call_add(lamp_groundline, ob->obmat[3]); + DRW_shgroup_dynamic_call_add(lamp_groundpoint, ob->obmat[3]); +} + +static void DRW_draw_empty(Object *ob) +{ + float *color; + draw_object_wire_theme(ob, &color); + + switch (ob->empty_drawtype) { + case OB_PLAINAXES: + DRW_shgroup_dynamic_call_add(plain_axes, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_SINGLE_ARROW: + DRW_shgroup_dynamic_call_add(single_arrow, color, &ob->empty_drawsize, ob->obmat); + DRW_shgroup_dynamic_call_add(single_arrow_line, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_CUBE: + DRW_shgroup_dynamic_call_add(cube, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_CIRCLE: + DRW_shgroup_dynamic_call_add(circle, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_EMPTY_SPHERE: + DRW_shgroup_dynamic_call_add(sphere, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_EMPTY_CONE: + DRW_shgroup_dynamic_call_add(cone, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_ARROWS: + DRW_shgroup_dynamic_call_add(arrows, color, &ob->empty_drawsize, ob->obmat); + /* TODO Missing axes names */ + break; + } +} + +void DRW_shgroup_non_meshes(DRWPass *UNUSED(non_meshes), Object *ob) +{ + switch (ob->type) { + case OB_LAMP: + DRW_draw_lamp(ob); + break; + case OB_CAMERA: + case OB_EMPTY: + DRW_draw_empty(ob); + default: + break; + } +} + +void DRW_shgroup_relationship_lines(DRWPass *UNUSED(non_meshes), Object *ob) +{ + if (ob->parent) { + DRW_shgroup_dynamic_call_add(relationship_lines, ob->obmat[3]); + DRW_shgroup_dynamic_call_add(relationship_lines, ob->parent->obmat[3]); + } +} + +/* ***************************** COMMON **************************** */ + +void DRW_shgroup_object_center(DRWPass *UNUSED(ob_center), Object *ob) +{ + if ((ob->base_flag & BASE_SELECTED) != 0) { + DRW_shgroup_dynamic_call_add(center_selected, ob->obmat[3]); + } + else if (0) { + DRW_shgroup_dynamic_call_add(center_deselected, ob->obmat[3]); + } +} diff --git a/source/blender/draw/intern/draw_mode_pass.h b/source/blender/draw/intern/draw_mode_pass.h new file mode 100644 index 00000000000..d11213ec8a2 --- /dev/null +++ b/source/blender/draw/intern/draw_mode_pass.h @@ -0,0 +1,45 @@ +/* + * Copyright 2016, 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_mode_pass.h + * \ingroup draw + */ + +#ifndef __DRAW_MODE_PASS_H__ +#define __DRAW_MODE_PASS_H__ + +#include "DRW_render.h" + +struct DRWPass; +struct Batch; +struct Object; + +void DRW_pass_setup_common(struct DRWPass **wire_overlay, struct DRWPass **wire_outline, struct DRWPass **non_meshes, struct DRWPass **ob_center); + +void DRW_shgroup_wire_overlay(struct DRWPass *wire_overlay, struct Object *ob); +void DRW_shgroup_wire_outline( + struct DRWPass *wire_outline, struct Object *ob, const bool do_front, const bool do_back, const bool do_outline); + +void DRW_shgroup_non_meshes(struct DRWPass *non_meshes, struct Object *ob); +void DRW_shgroup_relationship_lines(struct DRWPass *non_meshes, struct Object *ob); +void DRW_shgroup_object_center(struct DRWPass *ob_center, struct Object *ob); + +#endif /* __DRAW_MODE_PASS_H__ */
\ No newline at end of file diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 1559512d713..7e804a5bbfc 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -47,6 +47,7 @@ if(WITH_BLENDER) add_subdirectory(space_graph) add_subdirectory(space_image) add_subdirectory(space_info) + add_subdirectory(space_collections) add_subdirectory(space_logic) add_subdirectory(space_nla) add_subdirectory(space_node) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 26674278a5e..f41c4741eff 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -124,7 +124,7 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); - UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + UI_draw_roundbox_gl_mode_3fvAlpha(GL_TRIANGLE_FAN, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); } @@ -143,15 +143,14 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; - VertexFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); - + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformColor3fv(color); - + /* no rounded corner - just rectangular box */ immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc); @@ -233,8 +232,7 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; - VertexFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); @@ -442,7 +440,7 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi * - special hack: make the top a bit higher, since we are first... */ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT); - UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + UI_draw_roundbox_gl_mode_3fvAlpha(GL_TRIANGLE_FAN, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); } /* name for summary entries */ @@ -631,7 +629,7 @@ static bAnimChannelType ACF_SCENE = static int acf_object_icon(bAnimListElem *ale) { - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; /* icon depends on object-type */ @@ -666,7 +664,7 @@ static int acf_object_icon(bAnimListElem *ale) /* name for object */ static void acf_object_name(bAnimListElem *ale, char *name) { - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; /* just copy the name... */ @@ -686,7 +684,7 @@ static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN /* check if some setting exists for this channel */ static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting) { - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; switch (setting) { @@ -743,7 +741,7 @@ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin /* get pointer to the setting */ static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type) { - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; /* clear extra return data first */ @@ -831,7 +829,7 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); - UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + UI_draw_roundbox_gl_mode_3fvAlpha(GL_TRIANGLE_FAN, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); } /* name for group entries */ @@ -1087,7 +1085,7 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, floa /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); - UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f); + UI_draw_roundbox_gl_mode_3fvAlpha(GL_TRIANGLE_FAN, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f); } /* name for nla controls expander entries */ @@ -3441,7 +3439,7 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y /* draw slightly shifted up vertically to look like it has more separation from other channels, * but we then need to slightly shorten it so that it doesn't look like it overlaps */ - UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8, color); } /* name for nla action entries */ @@ -3864,8 +3862,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float /* for F-Curves, draw color-preview of curve behind checkbox */ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { FCurve *fcu = (FCurve *)ale->data; - VertexFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -3903,31 +3900,32 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float if (acf->name && !achannel_is_being_renamed(ac, acf, channel_index)) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */ - + unsigned char col[4]; + /* set text color */ /* XXX: if active, highlight differently? */ + if (selected) - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4ubv(TH_TEXT_HI, col); else - UI_ThemeColor(TH_TEXT); - + UI_GetThemeColor4ubv(TH_TEXT, col); + /* get name */ acf->name(ale, name); offset += 3; - UI_fontstyle_draw_simple(fstyle, offset, ytext, name); + UI_fontstyle_draw_simple(fstyle, offset, ytext, name, col); /* draw red underline if channel is disabled */ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) { - VertexFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* FIXME: replace hardcoded color here, and check on extents! */ immUniformColor3f(1.0f, 0.0f, 0.0f); - glLineWidth(2.0); + glLineWidth(2.0f); immBegin(GL_LINES, 2); immVertex2f(pos, (float)offset, yminc); @@ -3948,8 +3946,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float short draw_sliders = 0; float ymin_ofs = 0.0f; float color[3]; - VertexFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 117b8549712..22578b6a518 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -57,6 +57,7 @@ #include "BKE_context.h" #include "BKE_mask.h" #include "BKE_global.h" +#include "BKE_scene.h" #include "UI_view2d.h" @@ -2682,31 +2683,31 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, { bDopeSheet *ads = (bDopeSheet *)ac->data; Scene *sce = (Scene *)ads->source; - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; AnimData *adt = ob->adt; /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ - base->flag ^= SELECT; - ob->flag = base->flag; + base->flag_legacy ^= SELECT; + BKE_scene_base_flag_sync_from_base(base); if (adt) adt->flag ^= ADT_UI_SELECTED; } else { - Base *b; + BaseLegacy *b; /* deselect all */ /* TODO: should this deselect all other types of channels too? */ for (b = sce->base.first; b; b = b->next) { - b->flag &= ~SELECT; - b->object->flag = b->flag; + b->flag_legacy &= ~SELECT; + BKE_scene_base_flag_sync_from_base(b); if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); } /* select object now */ - base->flag |= SELECT; + base->flag_legacy |= SELECT; ob->flag |= SELECT; if (adt) adt->flag |= ADT_UI_SELECTED; } diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 58b9b8eba91..2b830657923 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -71,6 +71,9 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const bool time) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; + VertexFormat *format = immVertexFormat(); + unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned char col[4]; float xscale, yscale, x, y; char numstr[32] = " t"; /* t is the character to start replacing from */ int slen; @@ -96,9 +99,6 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const /* get starting coordinates for drawing */ x = cfra * xscale; y = 0.9f * U.widget_unit; - - VertexFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -107,11 +107,11 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const immRectf(pos, x, y, x + slen, y + 0.75f * U.widget_unit); immUnbindProgram(); - + /* draw current frame number - black text */ - UI_ThemeColor(TH_TEXT); - UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr); - + UI_GetThemeColor4ubv(TH_TEXT, col); + UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr, col); + /* restore view transform */ glScalef(xscale, 1.0, 1.0); } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index c12a050e9ba..7b6d30469a4 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -601,7 +601,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne } case ANIMTYPE_OBJECT: { - Base *base = (Base *)data; + BaseLegacy *base = (BaseLegacy *)data; Object *ob = base->object; ale->flag = ob->flag; @@ -1683,7 +1683,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi if (ads->filterflag & ADS_FILTER_GP_3DONLY) { Scene *scene = (Scene *)ads->source; - Base *base; + BaseLegacy *base; /* Active scene's GPencil block first - No parent item needed... */ if (scene->gpd) { @@ -1714,7 +1714,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi } /* check selection and object type filters */ - if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == scene->basact)*/) ) { + if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == scene->basact)*/) ) { /* only selected should be shown */ continue; } @@ -2223,7 +2223,7 @@ typedef struct tAnimFilterModifiersContext { /* dependency walker callback for modifier dependencies */ -static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cd_flag)) +static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cb_flag)) { tAnimFilterModifiersContext *afm = (tAnimFilterModifiersContext *)afm_ptr; ID *owner_id = &ob->id; @@ -2573,7 +2573,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b } /* get animation channels from object2 */ -static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode) +static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, BaseLegacy *base, int filter_mode) { ListBase tmp_data = {NULL, NULL}; Object *ob = base->object; @@ -2629,7 +2629,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data if (filter_mode & ANIMFILTER_LIST_CHANNELS) { /* check if filtering by selection */ // XXX: double-check on this - most of the time, a lot of tools need to filter out these channels! - if (ANIMCHANNEL_SELOK((base->flag & SELECT))) { + if (ANIMCHANNEL_SELOK((base->flag_legacy & SELECT))) { /* check if filtering by active status */ if (ANIMCHANNEL_ACTIVEOK(ob)) { ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob); @@ -2853,7 +2853,7 @@ static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *a } /* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */ -static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base, int filter_mode) +static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, BaseLegacy *base, int filter_mode) { Object *ob = base->object; @@ -2906,7 +2906,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base } /* check selection and object type filters */ - if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/)) { + if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == sce->basact)*/)) { /* only selected should be shown */ return false; } @@ -2927,28 +2927,28 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base /* Helper for animdata_filter_ds_sorted_bases() - Comparison callback for two Base pointers... */ static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr) { - const Base *b1 = *((const Base **)base1_ptr); - const Base *b2 = *((const Base **)base2_ptr); + const BaseLegacy *b1 = *((const BaseLegacy **)base1_ptr); + const BaseLegacy *b2 = *((const BaseLegacy **)base2_ptr); return strcmp(b1->object->id.name + 2, b2->object->id.name + 2); } /* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */ -static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases) +static BaseLegacy **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases) { /* Create an array with space for all the bases, but only containing the usable ones */ size_t tot_bases = BLI_listbase_count(&scene->base); size_t num_bases = 0; - Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases"); - for (Base *base = scene->base.first; base; base = base->next) { + BaseLegacy **sorted_bases = MEM_mallocN(sizeof(BaseLegacy *) * tot_bases, "Dopesheet Usable Sorted Bases"); + for (BaseLegacy *base = scene->base.first; base; base = base->next) { if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) { sorted_bases[num_bases++] = base; } } /* Sort this list of pointers (based on the names) */ - qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp); + qsort(sorted_bases, num_bases, sizeof(BaseLegacy *), ds_base_sorting_cmp); /* Return list of sorted bases */ *r_usable_bases = num_bases; @@ -3002,7 +3002,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b { /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */ // TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort... - Base **sorted_bases; + BaseLegacy **sorted_bases; size_t num_bases; sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases); @@ -3022,7 +3022,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b /* Filter and add contents of each base (i.e. object) without them sorting first * NOTE: This saves performance in cases where order doesn't matter */ - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) { /* since we're still here, this object should be usable */ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode); diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 823cde75334..ef9c2ced580 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -36,7 +36,7 @@ #include "DNA_object_types.h" #include "BLI_blenlib.h" -#include "BLI_math_base.h" +#include "BLI_math.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -380,19 +380,20 @@ static void draw_marker( /* and the marker name too, shifted slightly to the top-right */ if (marker->name[0]) { + unsigned char text_col[4]; float x, y; /* minimal y coordinate which wouldn't be occluded by scroll */ int min_y = 17.0f * UI_DPI_FAC; if (marker->flag & SELECT) { - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4ubv(TH_TEXT_HI, text_col); x = xpos + 4.0f * UI_DPI_FAC; y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC; y = max_ii(y, min_y); } else { - UI_ThemeColor(TH_TEXT); + UI_GetThemeColor4ubv(TH_TEXT, text_col); if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) { x = xpos + 8.0f * UI_DPI_FAC; y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC; @@ -406,14 +407,11 @@ static void draw_marker( #ifdef DURIAN_CAMERA_SWITCH if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) { - float col[4]; - glGetFloatv(GL_CURRENT_COLOR, col); - col[3] = 0.4; - glColor4fv(col); + text_col[3] = 100; } #endif - UI_fontstyle_draw_simple(fstyle, x, y, marker->name); + UI_fontstyle_draw_simple(fstyle, x, y, marker->name, text_col); } } @@ -1124,7 +1122,7 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool if (camera) { Scene *scene = CTX_data_scene(C); - Base *base; + BaseLegacy *base; TimeMarker *marker; int sel = 0; diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 5f675e690b9..c8d141eab07 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -52,7 +52,8 @@ #include "BKE_fcurve.h" -#include "BIF_gl.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -463,49 +464,15 @@ bool actkeyblock_is_valid(ActKeyBlock *ab, DLRBT_Tree *keys) /* *************************** Keyframe Drawing *************************** */ -/* coordinates for diamond shape */ -static const float _unit_diamond_shape[4][2] = { - {0.0f, 1.0f}, /* top vert */ - {1.0f, 0.0f}, /* mid-right */ - {0.0f, -1.0f}, /* bottom vert */ - {-1.0f, 0.0f} /* mid-left */ -}; - -/* draw a simple diamond shape with OpenGL */ -void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha) +void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha, + unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id) { - static GLuint displist1 = 0; - static GLuint displist2 = 0; - - /* initialize 2 display lists for diamond shape - one empty, one filled */ - if (displist1 == 0) { - displist1 = glGenLists(1); - glNewList(displist1, GL_COMPILE); - - glBegin(GL_LINE_LOOP); - glVertex2fv(_unit_diamond_shape[0]); - glVertex2fv(_unit_diamond_shape[1]); - glVertex2fv(_unit_diamond_shape[2]); - glVertex2fv(_unit_diamond_shape[3]); - glEnd(); - - glEndList(); - } - if (displist2 == 0) { - displist2 = glGenLists(1); - glNewList(displist2, GL_COMPILE); - - glBegin(GL_QUADS); - glVertex2fv(_unit_diamond_shape[0]); - glVertex2fv(_unit_diamond_shape[1]); - glVertex2fv(_unit_diamond_shape[2]); - glVertex2fv(_unit_diamond_shape[3]); - glEnd(); - - glEndList(); - } - - /* tweak size of keyframe shape according to type of keyframe + bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH); + bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH); + + if (!(draw_fill || draw_outline)) return; /* TODO: assert this? */ + + /* tweak size of keyframe shape according to type of keyframe * - 'proper' keyframes have key_type = 0, so get drawn at full size */ switch (key_type) { @@ -513,120 +480,93 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, break; case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */ - hsize *= 0.85f; + size *= 0.85f; break; case BEZT_KEYTYPE_MOVEHOLD: /* slightly smaller than normal keyframes (but by less than for breakdowns) */ - //hsize *= 0.72f; - hsize *= 0.95f; + //size *= 0.72f; + size *= 0.95f; break; case BEZT_KEYTYPE_EXTREME: /* slightly larger */ - hsize *= 1.2f; + size *= 1.2f; break; default: - hsize -= 0.5f * key_type; - break; + size -= 0.5f * key_type; } - - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, hsize, 1.0f); - - /* anti-aliased lines for more consistent appearance */ - glEnable(GL_LINE_SMOOTH); - + + unsigned char fill_col[4]; + unsigned char outline_col[4]; + /* draw! */ - if (ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH)) { - float inner_col[4]; - + if (draw_fill) { /* get interior colors from theme (for selected and unselected only) */ switch (key_type) { case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */ - { - if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN_SELECT, inner_col); - else UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN, inner_col); + UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col); break; - } case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */ - { - if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME_SELECT, inner_col); - else UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME, inner_col); + UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col); break; - } case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */ - { - if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_JITTER_SELECT, inner_col); - else UI_GetThemeColor4fv(TH_KEYTYPE_JITTER, inner_col); + UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col); break; - } case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */ - { /* XXX: Should these get their own theme options instead? */ - if (sel) UI_GetThemeColorShade4fv(TH_STRIP_SELECT, 35, inner_col); - else UI_GetThemeColorShade4fv(TH_STRIP, 50, inner_col); - - inner_col[3] = 1.0f; /* full opacity, to avoid problems with visual glitches */ + if (sel) UI_GetThemeColorShade3ubv(TH_STRIP_SELECT, 35, fill_col); + else UI_GetThemeColorShade3ubv(TH_STRIP, 50, fill_col); + fill_col[3] = 255; /* full opacity, to avoid problems with visual glitches */ break; - } case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */ default: - { - if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME_SELECT, inner_col); - else UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME, inner_col); - break; - } + UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col); } /* NOTE: we don't use the straight alpha from the theme, or else effects such as * graying out protected/muted channels doesn't work correctly! */ - inner_col[3] *= alpha; - glColor4fv(inner_col); - - /* draw the "filled in" interior poly now */ - glCallList(displist2); + fill_col[3] *= alpha; + + if (!draw_outline) { + /* force outline color to match */ + outline_col[0] = fill_col[0]; + outline_col[1] = fill_col[1]; + outline_col[2] = fill_col[2]; + outline_col[3] = fill_col[3]; + } } - - if (ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH)) { - float border_col[4]; - + + if (draw_outline) { /* exterior - black frame */ - if (sel) UI_GetThemeColor4fv(TH_KEYBORDER_SELECT, border_col); - else UI_GetThemeColor4fv(TH_KEYBORDER, border_col); - - border_col[3] *= alpha; - glColor4fv(border_col); - - glCallList(displist1); + UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col); + outline_col[3] *= alpha; + + if (!draw_fill) { + /* fill color needs to be (outline.rgb, 0) */ + fill_col[0] = outline_col[0]; + fill_col[1] = outline_col[1]; + fill_col[2] = outline_col[2]; + fill_col[3] = 0; + } } - - glDisable(GL_LINE_SMOOTH); - - /* restore view transform */ - glScalef(xscale / hsize, 1.0f / hsize, 1.0f); - glTranslatef(-x, -y, 0.0f); + + immAttrib1f(size_id, size); + immAttrib4ubv(color_id, fill_col); + immAttrib4ubv(outline_color_id, outline_col); + immVertex2f(pos_id, x, y); } static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked) { - ActKeyColumn *ak; - ActKeyBlock *ab; - float alpha; - float xscale; - - const float iconsize = (U.widget_unit / 4.0f) * yscale_fac; - const float mhsize = iconsize * 0.7f; + const float iconsize = U.widget_unit * 0.25f * yscale_fac; + const float mhsize = iconsize * 0.7f; glEnable(GL_BLEND); - /* get View2D scaling factor */ - UI_view2d_scale_get(v2d, &xscale, NULL); - /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */ /* TODO: allow this opacity factor to be themed? */ - alpha = (channelLocked) ? 0.25f : 1.0f; + float alpha = channelLocked ? 0.25f : 1.0f; /* draw keyblocks */ if (blocks) { @@ -644,45 +584,59 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa sel_mhcol[3] *= 0.8f; copy_v4_v4(unsel_mhcol, unsel_color); unsel_mhcol[3] *= 0.8f; - + + unsigned int pos_id = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */ - for (ab = blocks->first; ab; ab = ab->next) { + for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) { if (actkeyblock_is_valid(ab, keys)) { if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) { /* draw "moving hold" long-keyframe block - slightly smaller */ - if (ab->sel) - glColor4fv(sel_mhcol); - else - glColor4fv(unsel_mhcol); - - glRectf(ab->start, ypos - mhsize, ab->end, ypos + mhsize); + immUniformColor4fv(ab->sel ? sel_mhcol : unsel_mhcol); + immRectf(pos_id, ab->start, ypos - mhsize, ab->end, ypos + mhsize); } else { /* draw standard long-keyframe block */ - if (ab->sel) - glColor4fv(sel_color); - else - glColor4fv(unsel_color); - - glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize); + immUniformColor4fv(ab->sel ? sel_color : unsel_color); + immRectf(pos_id, ab->start, ypos - iconsize, ab->end, ypos + iconsize); } } } + immUnbindProgram(); } - /* draw keys */ if (keys) { - for (ak = keys->first; ak; ak = ak->next) { + /* count keys */ + unsigned int key_ct = 0; + for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) { /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw * - this might give some improvements, since we current have to flip between view/region matrices */ - if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0) - continue; - - /* draw using OpenGL - uglier but faster */ - /* NOTE1: a previous version of this didn't work nice for some intel cards - * NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */ - draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha); + if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) + key_ct++; + } + + if (key_ct > 0) { + /* draw keys */ + VertexFormat *format = immVertexFormat(); + unsigned int pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT); + unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(PRIM_POINTS, key_ct); + + for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) { + if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) { + draw_keyframe_shape(ak->cfra, ypos, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha, + pos_id, size_id, color_id, outline_color_id); + } + } + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); } } @@ -938,7 +892,7 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl int filter; bAnimListElem dummychan = {NULL}; - Base dummybase = {NULL}; + BaseLegacy dummybase = {NULL}; if (ob == NULL) return; diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 4571df0f077..f4922fec385 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -193,7 +193,7 @@ static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *o int ret = 0; bAnimListElem dummychan = {NULL}; - Base dummybase = {NULL}; + BaseLegacy dummybase = {NULL}; if (ob == NULL) return 0; diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index b39b4bd81ee..d75193a46ff 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -37,7 +37,7 @@ struct wmOperatorType; struct bContext; struct Scene; struct Object; -struct Base; +struct BaseLegacy; struct bAction; struct bPoseChannel; @@ -248,7 +248,7 @@ void armature_select_mirrored(struct bArmature *arm); void armature_tag_unselect(struct bArmature *arm); void *get_nearest_bone(struct bContext *C, short findunsel, int x, int y); -void *get_bone_from_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest); +void *get_bone_from_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest); int bone_looper(struct Object *ob, struct Bone *bone, void *data, int (*bone_func)(struct Object *, struct Bone *, void *)); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 1c342657eec..0dc97483dfc 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -50,6 +50,7 @@ #include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_report.h" @@ -400,7 +401,7 @@ int join_armature_exec(bContext *C, wmOperator *op) } /* Free the old object data */ - ED_base_object_free_and_unlink(bmain, scene, base); + ED_base_object_free_and_unlink(bmain, scene, base->object); } } CTX_DATA_END; @@ -579,6 +580,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); Object *oldob, *newob; Base *oldbase, *newbase; @@ -602,14 +604,18 @@ static int separate_armature_exec(bContext *C, wmOperator *op) /* TODO: use context iterators for this? */ CTX_DATA_BEGIN(C, Base *, base, visible_bases) { - if (base->object == obedit) base->flag |= SELECT; - else base->flag &= ~SELECT; + if (base->object == obedit) { + ED_object_base_select(base, BA_SELECT); + } + else { + ED_object_base_select(base, BA_DESELECT); + } } CTX_DATA_END; /* 1) store starting settings and exit editmode */ oldob = obedit; - oldbase = BASACT; + oldbase = sl->basact; oldob->mode &= ~OB_MODE_POSE; //oldbase->flag &= ~OB_POSEMODE; @@ -617,13 +623,13 @@ static int separate_armature_exec(bContext *C, wmOperator *op) ED_armature_edit_free(obedit->data); /* 2) duplicate base */ - newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */ + newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, USER_DUP_ARM); /* only duplicate linked armature */ DAG_relations_tag_update(bmain); newob = newbase->object; - newbase->flag &= ~SELECT; - - + newbase->flag &= ~BASE_SELECTED; + + /* 3) remove bones that shouldn't still be around on both armatures */ separate_armature_bones(oldob, 1); separate_armature_bones(newob, 0); diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index e9946abba0b..1f994a7f13e 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -74,7 +74,7 @@ Bone *get_indexed_bone(Object *ob, int index) /* See if there are any selected bones in this buffer */ /* only bones from base are checked on */ -void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest) +void *get_bone_from_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest) { Object *obedit = scene->obedit; // XXX get from context Bone *bone; diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index cc4c1809fbc..4d9ba351c3a 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -142,7 +142,7 @@ void BIF_makeListTemplates(const bContext *C) Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); - Base *base; + BaseLegacy *base; int index = 0; if (TEMPLATES_HASH != NULL) { @@ -970,6 +970,9 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S ToolSettings *ts = CTX_data_tool_settings(C); int point_added = 0; + /* TODO: Since the function `ED_transform_snap_object_context_create_view3d` creates a cache, + * the ideal would be to call this function only at the beginning of the snap operation, + * or at the beginning of the operator itself */ struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( CTX_data_main(C), CTX_data_scene(C), 0, CTX_wm_region(C), CTX_wm_view3d(C)); @@ -1038,6 +1041,8 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S } } + /* TODO: The ideal would be to call this function only once. + * At the end of the operator */ ED_transform_snap_object_context_destroy(snap_context); return point_added; } diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 44470c1f827..903d309cb1f 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -132,7 +132,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) /* called from editview.c, for mode-less pose selection */ /* assumes scene obact and basact is still on old situation */ -int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, +int ED_do_pose_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits, bool extend, bool deselect, bool toggle, bool do_nearest) { Object *ob = base->object; diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index e9fd5fb5a43..6b5a5d81d32 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -50,6 +50,7 @@ #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_report.h" @@ -1270,6 +1271,7 @@ static int separate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *oldob, *newob; Base *oldbase, *newbase; Curve *oldcu, *newcu; @@ -1297,7 +1299,7 @@ static int separate_exec(bContext *C, wmOperator *op) } /* 2. duplicate the object and data */ - newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */ + newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, 0); /* 0 = fully linked */ DAG_relations_tag_update(bmain); newob = newbase->object; @@ -6024,7 +6026,7 @@ int join_curve_exec(bContext *C, wmOperator *op) } } - ED_base_object_free_and_unlink(bmain, scene, base); + ED_base_object_free_and_unlink(bmain, scene, base->object); } } } diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 34e026a3ef4..4720b76342c 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -48,6 +48,8 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" + #include "curve_intern.h" #include "UI_resources.h" @@ -514,30 +516,45 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS } { + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, coord_array); - - cpack(0x0); + imm_cpack(0x0); + immBegin(GL_LINE_STRIP, stroke_len); glLineWidth(3.0f); - glDrawArrays(GL_LINE_STRIP, 0, stroke_len); - if (v3d->zbuf) + if (v3d->zbuf) { glDisable(GL_DEPTH_TEST); + } + + for (int i = 0; i < stroke_len; i++) { + immVertex3fv(pos, coord_array[i]); + } + + immEnd(); - cpack(0xffffffff); + imm_cpack(0xffffffff); + immBegin(GL_LINE_STRIP, stroke_len); glLineWidth(1.0f); - glDrawArrays(GL_LINE_STRIP, 0, stroke_len); - if (v3d->zbuf) - glEnable(GL_DEPTH_TEST); + for (int i = 0; i < stroke_len; i++) { + immVertex3fv(pos, coord_array[i]); + } + + immEnd(); - glDisableClientState(GL_VERTEX_ARRAY); + if (v3d->zbuf) { + glEnable(GL_DEPTH_TEST); + } glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); + + immUnbindProgram(); } MEM_freeN(coord_array); @@ -686,6 +703,7 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke) } else { cdd->vc.scene = CTX_data_scene(C); + cdd->vc.sl = CTX_data_scene_layer(C); cdd->vc.obedit = CTX_data_edit_object(C); } diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 57e731874b4..d86091aaa77 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -420,6 +420,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Curve *cu; Object *obedit; Base *base; @@ -429,8 +430,8 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const int a; float rot[3] = {0.f, 0.f, 0.f}; - obedit = BKE_object_add(bmain, scene, OB_FONT, NULL); - base = scene->basact; + obedit = BKE_object_add(bmain, scene, sl, OB_FONT, NULL); + base = sl->basact; /* seems to assume view align ? TODO - look into this, could be an operator option */ ED_object_base_init_transform(C, base, NULL, rot); diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index e8a812817d1..05eb51fb02f 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -1563,13 +1563,15 @@ static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar) const char *printable = IFACE_("GPencil Stroke Editing"); float printable_size[2]; - BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); + int font_id = BLF_default(); + + BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; int yco = (rect.ymax - U.widget_unit); /* text label */ - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(font_id, TH_TEXT_HI); #ifdef WITH_INTERNATIONAL BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #else diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index d0f68c4b8f3..505114869ac 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1128,7 +1128,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG Object *ob; Curve *cu; Nurb *nu = NULL; - Base *base_orig = BASACT, *base_new = NULL; + BaseLegacy *base_orig = BASACT, *base_new = NULL; float minmax_weights[2] = {1.0f, 0.0f}; /* camera framing */ @@ -1217,7 +1217,8 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG /* set the layer and select */ base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene); - base_new->flag = ob->flag = base_new->flag | SELECT; + base_new->flag_legacy |= SELECT; + BKE_scene_base_flag_sync_from_base(base_new); } /* --- */ diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 76e85f20c36..e3b6b748227 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -204,7 +204,7 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C) // XXX: this should be removed... We really shouldn't duplicate logic like this! bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d) { - Base *base = scene->basact; + BaseLegacy *base = scene->basact; bGPdata *gpd = NULL; /* We have to make sure active object is actually visible and selected, else we must use default scene gpd, * to be consistent with ED_gpencil_data_get_active's behavior. diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index db0ec6a2076..87086addf52 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -49,6 +49,7 @@ struct ColorManagedDisplaySettings; void fdrawline(float x1, float y1, float x2, float y2); /* DEPRECATED */ void fdrawbox(float x1, float y1, float x2, float y2); /* DEPRECATED */ +void fdrawbox_filled(float x1, float y1, float x2, float y2); void sdrawline(int x1, int y1, int x2, int y2); /* DEPRECATED */ void sdrawbox(int x1, int y1, int x2, int y2); /* DEPRECATED */ @@ -209,6 +210,24 @@ void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int forma float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y); /** + * immDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the + * image using textures, which can be tremendously faster on low-end + * cards, and also avoids problems with the raster position being + * clipped when offscreen. Pixel unpacking parameters and + * the glPixelZoom values are _not_ respected. + * + * \attention This routine makes many assumptions: the rect data + * is expected to be in RGBA byte or float format, and the + * modelview and projection matrices are assumed to define a + * 1-to-1 mapping to screen space. + */ +void immDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, + float xzoom, float yzoom, float color[4]); +void immDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, + float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y, + float xzoom, float yzoom, float color[4]); + +/** * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef. * only RGBA * needs glaDefine2DArea to be set. @@ -222,6 +241,11 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY, float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y); +void immDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY, + float xzoom, float yzoom, float color[4]); +void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY, + float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y, + float xzoom, float yzoom, float color[4]); /* 2D Drawing Assistance */ /** Define a 2D area (viewport, scissor, matrices) for OpenGL rendering. diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 7ad61671b1b..3bde01a1bdd 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -35,7 +35,7 @@ extern "C" { #endif struct bArmature; -struct Base; +struct BaseLegacy; struct bContext; struct Bone; struct bPoseChannel; @@ -44,6 +44,7 @@ struct ListBase; struct MeshDeformModifierData; struct DerivedMesh; struct Object; +struct Base; struct ReportList; struct Scene; struct ViewContext; @@ -130,7 +131,7 @@ void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb); void ED_armature_deselect_all(struct Object *obedit); void ED_armature_deselect_all_visible(struct Object *obedit); -int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, +int ED_do_pose_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer, short hits, bool extend, bool deselect, bool toggle, bool do_nearest); bool ED_armature_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); int join_armature_exec(struct bContext *C, struct wmOperator *op); diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index c478a8b17e5..8eef016a846 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -108,8 +108,10 @@ typedef enum eKeyframeShapeDrawOpts { KEYFRAME_SHAPE_BOTH } eKeyframeShapeDrawOpts; -/* draw simple diamond-shape keyframe (with OpenGL) */ -void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha); +/* draw simple diamond-shape keyframe */ +/* caller should set up vertex format, bind GPU_SHADER_KEYFRAME_DIAMOND, immBegin(PRIM_POINTS, n), then call this n times */ +void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha, + unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id); /* ******************************* Methods ****************************** */ diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index f7b9d6b4f9e..b4cf96f27bf 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -75,7 +75,7 @@ void ED_init_custom_node_socket_type(struct bNodeSocketType *stype); void ED_init_standard_node_socket_type(struct bNodeSocketType *stype); void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype); void ED_node_sample_set(const float col[4]); -void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border); +void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos); /* node_draw.c */ void ED_node_tree_update(const struct bContext *C); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 04ff5692717..4d79a42e64e 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -35,14 +35,16 @@ extern "C" { #endif -struct Base; +struct BaseLegacy; struct EnumPropertyItem; struct ID; struct Main; struct ModifierData; struct Object; +struct Base; struct ReportList; struct Scene; +struct SceneLayer; struct bConstraint; struct bContext; struct bPoseChannel; @@ -53,6 +55,7 @@ struct wmOperatorType; struct PointerRNA; struct PropertyRNA; struct EnumPropertyItem; +struct LayerTree; /* object_edit.c */ struct Object *ED_object_context(struct bContext *C); /* context.object */ @@ -89,7 +92,6 @@ bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct struct Object *par, int partype, const bool xmirror, const bool keep_transform, const int vert_par[3]); void ED_object_parent_clear(struct Object *ob, const int type); -struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob); void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); @@ -98,14 +100,20 @@ void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMa const bool do_connected); /* send your own notifier for select! */ -void ED_base_object_select(struct Base *base, short mode); +void ED_base_object_select(struct BaseLegacy *base, short mode); /* includes notifier */ -void ED_base_object_activate(struct bContext *C, struct Base *base); +void ED_base_object_activate(struct bContext *C, struct BaseLegacy *base); + +void ED_object_base_select(struct Base *base, short mode); +void ED_object_base_activate(struct bContext *C, struct Base *base); -void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base); +void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob); + +void ED_base_object_sync_from_base(struct BaseLegacy *base, struct Object *ob); +void ED_base_object_sync_from_object(struct BaseLegacy *base, struct Object *ob); /* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */ -struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct Base *base, int dupflag); +struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct Base *base, int dupflag); void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr); @@ -191,7 +199,7 @@ void ED_object_modifier_clear(struct Main *bmain, struct Object *ob); int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md); int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md); int ED_object_modifier_convert(struct ReportList *reports, struct Main *bmain, struct Scene *scene, - struct Object *ob, struct ModifierData *md); + struct SceneLayer *sl, struct Object *ob, struct ModifierData *md); int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct ModifierData *md, int mode); int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index f5f66a07aea..01be63919be 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -162,6 +162,7 @@ int ED_operator_image_active(struct bContext *C); int ED_operator_nla_active(struct bContext *C); int ED_operator_logic_active(struct bContext *C); int ED_operator_info_active(struct bContext *C); +int ED_operator_collections_active(struct bContext *C); int ED_operator_console_active(struct bContext *C); diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h index d268c578cf2..b754e1ba20f 100644 --- a/source/blender/editors/include/ED_space_api.h +++ b/source/blender/editors/include/ED_space_api.h @@ -58,6 +58,7 @@ void ED_spacetype_logic(void); void ED_spacetype_console(void); void ED_spacetype_userpref(void); void ED_spacetype_clip(void); +void ED_spacetype_collections(void); /* calls for instancing and freeing spacetype static data * called in WM_init_exit */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 3dc84dacbf9..f55d723968f 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -103,7 +103,7 @@ enum TfmMode { #define CTX_GPENCIL_STROKES (1 << 9) struct TransInfo; -struct Base; +struct BaseLegacy; struct Scene; struct Object; struct wmOperator; diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 7944b434057..6eaae49912c 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -65,10 +65,6 @@ struct SnapObjectParams { unsigned int use_object_edit_cage : 1; }; -enum { - SNAP_OBJECT_USE_CACHE = (1 << 0), -}; - typedef struct SnapObjectContext SnapObjectContext; SnapObjectContext *ED_transform_snap_object_context_create( struct Main *bmain, struct Scene *scene, int flag); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 79176d9e9cf..cc83b97fc00 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -37,7 +37,7 @@ struct BMEdge; struct BMFace; struct BMVert; struct BPoint; -struct Base; +struct BaseLegacy; struct BezTriple; struct BoundBox; struct EditBone; @@ -49,6 +49,7 @@ struct Nurb; struct Object; struct RegionView3D; struct Scene; +struct SceneLayer; struct ScrArea; struct View3D; struct ViewContext; @@ -70,6 +71,7 @@ enum eGPUFXFlags; /* for derivedmesh drawing callbacks, for view3d_select, .... */ typedef struct ViewContext { struct Scene *scene; + struct SceneLayer *sl; struct Object *obact; struct Object *obedit; struct ARegion *ar; @@ -187,7 +189,7 @@ void pose_foreachScreenBone( void ED_view3d_project_float_v2_m4(const struct ARegion *ar, const float co[3], float r_co[2], float mat[4][4]); void ED_view3d_project_float_v3_m4(const struct ARegion *ar, const float co[3], float r_co[3], float mat[4][4]); -eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base); +eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct BaseLegacy *base); /* *** short *** */ eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local, @@ -277,6 +279,7 @@ float ED_view3d_radius_to_dist( const float radius); void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][4]); +void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos); /* backbuffer select and draw support */ void ED_view3d_backbuf_validate(struct ViewContext *vc); @@ -352,7 +355,7 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple( int alpha_mode, int samples, bool full_samples, const char *viewname, struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); -struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); +struct BaseLegacy *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip); void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]); bool ED_view3d_quat_from_axis_view(const char view, float quat[4]); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index d48cfbee413..153c3d415e6 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -212,6 +212,9 @@ enum { UI_BUT_ALIGN_STITCH_TOP = (1 << 18), UI_BUT_ALIGN_STITCH_LEFT = (1 << 19), UI_BUT_ALIGN_ALL = (UI_BUT_ALIGN | UI_BUT_ALIGN_STITCH_TOP | UI_BUT_ALIGN_STITCH_LEFT), + + /* Another hack, in some rare cases we don't want any text margin */ + UI_BUT_TEXT_NO_MARGIN = (1 << 20), }; /* scale fixed button widths by this to account for DPI */ @@ -311,14 +314,14 @@ typedef enum { void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad, const float color[4]); void UI_draw_roundbox_corner_set(int type); int UI_draw_roundbox_corner_get(void); -void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad); +void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad, const float color[4]); void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy); void UI_draw_roundbox_gl_mode_3ubAlpha(int mode, float minx, float miny, float maxx, float maxy, float rad, unsigned char col[3], unsigned char alpha); void UI_draw_roundbox_gl_mode_3fvAlpha(int mode, float minx, float miny, float maxx, float maxy, float rad, float col[3], float alpha); void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad, float col[4]); -void UI_draw_roundbox_shade_x(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown); -void UI_draw_roundbox_shade_y(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight); -void UI_draw_text_underline(int pos_x, int pos_y, int len, int height); +void UI_draw_roundbox_shade_x(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown, const float col[4]); +void UI_draw_roundbox_shade_y(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeleft, float shaderight, const float col[4]); +void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]); void UI_draw_safe_areas( unsigned pos, float x1, float x2, float y1, float y2, @@ -1044,12 +1047,14 @@ void UI_context_active_but_prop_get_templateID( /* Styled text draw */ void UI_fontstyle_set(const struct uiFontStyle *fs); -void UI_fontstyle_draw_ex( - const struct uiFontStyle *fs, const struct rcti *rect, const char *str, - size_t len, float *r_xofs, float *r_yofs); -void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str); -void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs, const struct rcti *rect, const char *str); -void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str); +void UI_fontstyle_draw_ex(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, + const unsigned char col[4], size_t len, float *r_xofs, float *r_yofs); +void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, + const unsigned char col[4]); +void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, + const unsigned char col[4]); +void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str, + const unsigned char col[4]); void UI_fontstyle_draw_simple_backdrop( const struct uiFontStyle *fs, float x, float y, const char *str, const float col_fg[4], const float col_bg[4]); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 945ac1b6db9..f08c46af8a6 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -83,5 +83,6 @@ struct PreviewImage *UI_icon_to_preview(int icon_id); int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big); int UI_idcode_icon_get(const int idcode); +int UI_colorset_icon_get(const int set_idx); #endif /* __UI_INTERFACE_ICONS_H__ */ diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index b7a5217a862..2fc76ae9563 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -347,6 +347,10 @@ void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigne // get the color, range 0.0-1.0, complete with shading offset void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3]); void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]); +void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4]); + +// get three color values, range 0-255, complete with shading offset for the RGB components and blending +void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3]); // get four color values, scaled to 0.0-1.0 range void UI_GetThemeColor4fv(int colorid, float col[4]); @@ -376,6 +380,10 @@ void UI_GetColorPtrShade3ubv(const unsigned char cp1[3], unsigned char col[3] // get a 3 byte color, blended and shaded between two other char color pointers void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], float fac, int offset); +// sets the font color +// (for anything fancy use UI_GetThemeColor[Fancy] then BLF_color) +void UI_FontThemeColor(int fontid, int colorid); + // clear the openGL ClearColor using the input colorid void UI_ThemeClearColor(int colorid); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index f17c61b8aa1..7b17c3d6440 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -57,7 +57,9 @@ #include "GPU_draw.h" #include "GPU_basic_shader.h" +#include "GPU_batch.h" #include "GPU_immediate.h" +#include "GPU_matrix.h" #include "UI_interface.h" @@ -114,9 +116,7 @@ void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, floa mul_v2_fl(vec[a], rad); } - if (mode == GL_POLYGON) { - mode = GL_TRIANGLE_FAN; - } + BLI_assert(mode != GL_POLYGON); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformColor4fv(col); @@ -174,245 +174,272 @@ void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, floa immUnbindProgram(); } -static void round_box_shade_col(const float col1[3], float const col2[3], const float fac) +static void round_box_shade_col(unsigned attrib, const float col1[3], float const col2[3], const float fac) { - float col[3] = { + float col[4] = { fac * col1[0] + (1.0f - fac) * col2[0], fac * col1[1] + (1.0f - fac) * col2[1], - fac * col1[2] + (1.0f - fac) * col2[2] + fac * col1[2] + (1.0f - fac) * col2[2], + 1.0f }; - glColor3fv(col); + immAttrib4fv(attrib, col); } /* linear horizontal shade within button or in outline */ /* view2d scrollers use it */ void UI_draw_roundbox_shade_x( int mode, float minx, float miny, float maxx, float maxy, - float rad, float shadetop, float shadedown) + float rad, float shadetop, float shadedown, const float col[4]) { float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; const float div = maxy - miny; const float idiv = 1.0f / div; - float coltop[3], coldown[3], color[4]; + float coltop[3], coldown[3]; + int vert_count = 0; int a; - + + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned color = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + /* mult */ for (a = 0; a < 7; a++) { mul_v2_fl(vec[a], rad); } - /* get current color, needs to be outside of glBegin/End */ - glGetFloatv(GL_CURRENT_COLOR, color); + + BLI_assert(mode != GL_POLYGON); /* 'shade' defines strength of shading */ - coltop[0] = min_ff(1.0f, color[0] + shadetop); - coltop[1] = min_ff(1.0f, color[1] + shadetop); - coltop[2] = min_ff(1.0f, color[2] + shadetop); - coldown[0] = max_ff(0.0f, color[0] + shadedown); - coldown[1] = max_ff(0.0f, color[1] + shadedown); - coldown[2] = max_ff(0.0f, color[2] + shadedown); + coltop[0] = min_ff(1.0f, col[0] + shadetop); + coltop[1] = min_ff(1.0f, col[1] + shadetop); + coltop[2] = min_ff(1.0f, col[2] + shadetop); + coldown[0] = max_ff(0.0f, col[0] + shadedown); + coldown[1] = max_ff(0.0f, col[1] + shadedown); + coldown[2] = max_ff(0.0f, col[2] + shadedown); - glBegin(mode); + vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; + + immBegin(mode, vert_count); /* start with corner right-bottom */ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(maxx - rad, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, vec[a][1] * idiv); - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - round_box_shade_col(coltop, coldown, rad * idiv); - glVertex2f(maxx, miny + rad); + round_box_shade_col(color, coltop, coldown, rad * idiv); + immVertex2f(pos, maxx, miny + rad); } else { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(maxx, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, maxx, miny); } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { - round_box_shade_col(coltop, coldown, (div - rad) * idiv); - glVertex2f(maxx, maxy - rad); + round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (div - rad + vec[a][1]) * idiv); - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(maxx - rad, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, maxx - rad, maxy); } else { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(maxx, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(minx + rad, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (div - vec[a][1]) * idiv); - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - round_box_shade_col(coltop, coldown, (div - rad) * idiv); - glVertex2f(minx, maxy - rad); + round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); + immVertex2f(pos, minx, maxy - rad); } else { - round_box_shade_col(coltop, coldown, 1.0); - glVertex2f(minx, maxy); + round_box_shade_col(color, coltop, coldown, 1.0); + immVertex2f(pos, minx, maxy); } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - round_box_shade_col(coltop, coldown, rad * idiv); - glVertex2f(minx, miny + rad); + round_box_shade_col(color, coltop, coldown, rad * idiv); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 7; a++) { - round_box_shade_col(coltop, coldown, (rad - vec[a][1]) * idiv); - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(minx + rad, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, minx + rad, miny); } else { - round_box_shade_col(coltop, coldown, 0.0); - glVertex2f(minx, miny); + round_box_shade_col(color, coltop, coldown, 0.0); + immVertex2f(pos, minx, miny); } - - glEnd(); + + immEnd(); + immUnbindProgram(); } /* linear vertical shade within button or in outline */ /* view2d scrollers use it */ void UI_draw_roundbox_shade_y( int mode, float minx, float miny, float maxx, float maxy, - float rad, float shadeLeft, float shadeRight) + float rad, float shadeleft, float shaderight, const float col[4]) { float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; const float div = maxx - minx; const float idiv = 1.0f / div; - float colLeft[3], colRight[3], color[4]; + float colLeft[3], colRight[3]; + int vert_count = 0; int a; /* mult */ for (a = 0; a < 7; a++) { mul_v2_fl(vec[a], rad); } - /* get current color, needs to be outside of glBegin/End */ - glGetFloatv(GL_CURRENT_COLOR, color); + + BLI_assert(mode != GL_POLYGON); + + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned color = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); /* 'shade' defines strength of shading */ - colLeft[0] = min_ff(1.0f, color[0] + shadeLeft); - colLeft[1] = min_ff(1.0f, color[1] + shadeLeft); - colLeft[2] = min_ff(1.0f, color[2] + shadeLeft); - colRight[0] = max_ff(0.0f, color[0] + shadeRight); - colRight[1] = max_ff(0.0f, color[1] + shadeRight); - colRight[2] = max_ff(0.0f, color[2] + shadeRight); + colLeft[0] = min_ff(1.0f, col[0] + shadeleft); + colLeft[1] = min_ff(1.0f, col[1] + shadeleft); + colLeft[2] = min_ff(1.0f, col[2] + shadeleft); + colRight[0] = max_ff(0.0f, col[0] + shaderight); + colRight[1] = max_ff(0.0f, col[1] + shaderight); + colRight[2] = max_ff(0.0f, col[2] + shaderight); + + + vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; + vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; - glBegin(mode); + immBegin(mode, vert_count); /* start with corner right-bottom */ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx - rad, miny); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx - rad, miny); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, vec[a][0] * idiv); - glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]); + round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv); + immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); } - round_box_shade_col(colLeft, colRight, rad * idiv); - glVertex2f(maxx, miny + rad); + round_box_shade_col(color, colLeft, colRight, rad * idiv); + immVertex2f(pos, maxx, miny + rad); } else { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, miny); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, miny); } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, maxy - rad); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, maxy - rad); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (div - rad - vec[a][0]) * idiv); - glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]); + round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv); + immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); } - round_box_shade_col(colLeft, colRight, (div - rad) * idiv); - glVertex2f(maxx - rad, maxy); + round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); + immVertex2f(pos, maxx - rad, maxy); } else { - round_box_shade_col(colLeft, colRight, 0.0); - glVertex2f(maxx, maxy); + round_box_shade_col(color, colLeft, colRight, 0.0); + immVertex2f(pos, maxx, maxy); } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { - round_box_shade_col(colLeft, colRight, (div - rad) * idiv); - glVertex2f(minx + rad, maxy); + round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); + immVertex2f(pos, minx + rad, maxy); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (div - rad + vec[a][0]) * idiv); - glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]); + round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv); + immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); } - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, maxy - rad); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, maxy - rad); } else { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, maxy); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, maxy); } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, miny + rad); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, miny + rad); for (a = 0; a < 7; a++) { - round_box_shade_col(colLeft, colRight, (vec[a][0]) * idiv); - glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]); + round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv); + immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); } - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx + rad, miny); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx + rad, miny); } else { - round_box_shade_col(colLeft, colRight, 1.0); - glVertex2f(minx, miny); + round_box_shade_col(color, colLeft, colRight, 1.0); + immVertex2f(pos, minx, miny); } - - glEnd(); + + immEnd(); + immUnbindProgram(); } /* plain antialiased unfilled rectangle */ -void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad) +void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad, const float color[4]) { - float color[4]; - + float col[4]; + + copy_v4_v4(col, color); + if (roundboxtype & UI_RB_ALPHA) { - glGetFloatv(GL_CURRENT_COLOR, color); - color[3] = 0.5; - glColor4fv(color); - glEnable(GL_BLEND); + col[3] = 0.5; } /* set antialias line */ glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad, color); + UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad, col); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); @@ -421,13 +448,21 @@ void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, f /* (old, used in outliner) plain antialiased filled box */ void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad, const float color[4]) { - ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA, color); + ui_draw_anti_roundbox(GL_TRIANGLE_FAN, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA, color); } -void UI_draw_text_underline(int pos_x, int pos_y, int len, int height) +void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]) { int ofs_y = 4 * U.pixelsize; - glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize)); + + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color); + + immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize)); + immUnbindProgram(); } /* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */ @@ -457,7 +492,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w #endif glEnable(GL_BLEND); - glColor4f(0.0, 0.0, 0.0, 0.0); + glColor4f(0.0f, 0.0f, 0.0f, 0.0f); if (w != ibuf->x || h != ibuf->y) { float facx = (float)w / (float)ibuf->x; @@ -531,45 +566,53 @@ static void draw_scope_end(const rctf *rect, GLint *scissor) static void histogram_draw_one( float r, float g, float b, float alpha, - float x, float y, float w, float h, const float *data, int res, const bool is_line) + float x, float y, float w, float h, const float *data, int res, const bool is_line, + unsigned int pos_attrib) { + float color[4] = {r, g, b, alpha}; + + /* that can happen */ + if (res == 0) + return; + glEnable(GL_LINE_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glColor4f(r, g, b, alpha); + + immUniformColor4fv(color); if (is_line) { /* curve outline */ glLineWidth(1.5); - glBegin(GL_LINE_STRIP); + immBegin(GL_LINE_STRIP, res); for (int i = 0; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); } - glEnd(); + immEnd(); } else { /* under the curve */ - glBegin(GL_TRIANGLE_STRIP); - glVertex2f(x, y); - glVertex2f(x, y + (data[0] * h)); + immBegin(GL_TRIANGLE_STRIP, res * 2); + immVertex2f(pos_attrib, x, y); + immVertex2f(pos_attrib, x, y + (data[0] * h)); for (int i = 1; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); - glVertex2f(x2, y); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y); } - glEnd(); + immEnd(); /* curve outline */ - glColor4f(0.f, 0.f, 0.f, 0.25f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBegin(GL_LINE_STRIP); + immBegin(GL_LINE_STRIP, res); for (int i = 0; i < res; i++) { float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); + immVertex2f(pos_attrib, x2, y + (data[i] * h)); } - glEnd(); + immEnd(); } glDisable(GL_LINE_SMOOTH); @@ -582,7 +625,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) Histogram *hist = (Histogram *)but->poin; int res = hist->x_resolution; const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0; - + rctf rect = { .xmin = (float)recti->xmin + 1, .xmax = (float)recti->xmax - 1, @@ -599,7 +642,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) float color[4]; UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, histogram can draw outside of boundary */ GLint scissor[4]; @@ -609,34 +652,41 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); /* draw grid lines here */ for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) { const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES; /* so we can tell the 1.0 color point */ if (i == HISTOGRAM_TOT_GRID_LINES) { - glColor4f(1.0f, 1.0f, 1.0f, 0.5f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f); } - fdrawline(rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h); - fdrawline(rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax); + imm_draw_line(pos, rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h); + imm_draw_line(pos, rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax); } - + if (hist->mode == HISTO_MODE_LUMA) { - histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line); + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos); } else if (hist->mode == HISTO_MODE_ALPHA) { - histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line); + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos); } else { if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) - histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line); + histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos); if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G) - histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line); + histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos); if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B) - histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line); + histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos); } + + immUnbindProgram(); /* outline */ draw_scope_end(&rect, scissor); @@ -644,6 +694,25 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) #undef HISTOGRAM_TOT_GRID_LINES +static void waveform_draw_one(float *waveform, int nbr, const float col[3]) +{ + VertexFormat format = {0}; + unsigned int pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, nbr); + + fillAttrib(vbo, pos_id, waveform); + + /* TODO store the Batch inside the scope */ + Batch *batch = Batch_create(GL_POINTS, vbo, NULL); + Batch_set_builtin_program(batch, GPU_SHADER_2D_UNIFORM_COLOR); + Batch_Uniform4f(batch, "color", col[0], col[1], col[2], 1.0f); + Batch_draw(batch); + + Batch_discard_all(batch); +} + void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) { Scopes *scopes = (Scopes *)but->poin; @@ -666,7 +735,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), scopes->wavefrm_yfac = 0.98f; float w = BLI_rctf_size_x(&rect) - 7; float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac; - float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f; + float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f; float w3 = w / 3.0f; /* log scale for alpha */ @@ -687,7 +756,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), float color[4]; UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, waveform can draw outside of boundary */ glGetIntegerv(GL_VIEWPORT, scissor); @@ -696,94 +765,85 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); - /* draw grid lines here */ + /* draw scale numbers first before binding any shader */ for (int i = 0; i < 6; i++) { char str[4]; BLI_snprintf(str, sizeof(str), "%-3d", i * 20); str[3] = '\0'; - fdrawline(rect.xmin + 22, yofs + (i / 5.f) * h, rect.xmax + 1, yofs + (i / 5.f) * h); - BLF_draw_default(rect.xmin + 1, yofs - 5 + (i / 5.f) * h, 0, str, sizeof(str) - 1); - /* in the loop because blf_draw reset it */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f); + BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1); + } + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); + /* draw grid lines here */ + for (int i = 0; i < 6; i++) { + imm_draw_line(pos, rect.xmin + 22, yofs + (i * 0.2f) * h, rect.xmax + 1, yofs + (i * 0.2f) * h); } /* 3 vertical separation */ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) { for (int i = 1; i < 3; i++) { - fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax); + imm_draw_line(pos, rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax); } } /* separate min max zone on the right */ - fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax); + imm_draw_line(pos, rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax); /* 16-235-240 level in case of ITU-R BT601/709 */ - glColor4f(1.f, 0.4f, 0.f, 0.2f); + immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f); if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) { - fdrawline(rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f); - fdrawline(rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f); - fdrawline(rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f); - fdrawline(rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f); + imm_draw_line(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f); + imm_draw_line(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f); + imm_draw_line(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f); + imm_draw_line(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f); } /* 7.5 IRE black point level for NTSC */ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) - fdrawline(rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f); + imm_draw_line(pos, rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f); if (scopes->ok && scopes->waveform_1 != NULL) { - - /* LUMA (1 channel) */ + gpuMatrixBegin3D_legacy(); glBlendFunc(GL_ONE, GL_ONE); - glColor3f(alpha, alpha, alpha); glPointSize(1.0); + /* LUMA (1 channel) */ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) { + float col[3] = {alpha, alpha, alpha}; - glBlendFunc(GL_ONE, GL_ONE); - - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); - - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w, h, 0.f); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuPushMatrix(); + gpuTranslate3f(rect.xmin, yofs, 0.0f); + gpuScale3f(w, h, 0.0f); + + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col); - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); /* min max */ - glColor3f(0.5f, 0.5f, 0.5f); + immUniformColor3f(0.5f, 0.5f, 0.5f); min = yofs + scopes->minmax[0][0] * h; max = yofs + scopes->minmax[0][1] * h; CLAMP(min, rect.ymin, rect.ymax); CLAMP(max, rect.ymin, rect.ymax); - fdrawline(rect.xmax - 3, min, rect.xmax - 3, max); + imm_draw_line(pos, rect.xmax - 3, min, rect.xmax - 3, max); } /* RGB (3 channel) */ else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) { - glBlendFunc(GL_ONE, GL_ONE); - - glEnableClientState(GL_VERTEX_ARRAY); - - glPushMatrix(); - - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w, h, 0.f); + gpuPushMatrix(); + gpuTranslate3f(rect.xmin, yofs, 0.0f); + gpuScale3f(w, h, 0.0f); - glColor3fv( colors_alpha[0] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]); + waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]); + waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]); - glColor3fv( colors_alpha[1] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glColor3fv( colors_alpha[2] ); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); } /* PARADE / YCC (3 channels) */ else if (ELEM(scopes->wavefrm_mode, @@ -795,49 +855,44 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), { int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE); - glBlendFunc(GL_ONE, GL_ONE); - - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); - - glTranslatef(rect.xmin, yofs, 0.f); - glScalef(w3, h, 0.f); + gpuPushMatrix(); + gpuTranslate3f(rect.xmin, yofs, 0.0f); + gpuScale3f(w3, h, 0.0f); - glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]); - glTranslatef(1.f, 0.f, 0.f); - glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuTranslate3f(1.0f, 0.0f, 0.0f); + waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]); - glTranslatef(1.f, 0.f, 0.f); - glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]); - glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + gpuTranslate3f(1.0f, 0.0f, 0.0f); + waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]); - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); } + /* min max */ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) { for (int c = 0; c < 3; c++) { if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB)) - glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f); + immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f); else - glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f); + immUniformColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f); min = yofs + scopes->minmax[c][0] * h; max = yofs + scopes->minmax[c][1] * h; CLAMP(min, rect.ymin, rect.ymax); CLAMP(max, rect.ymin, rect.ymax); - fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max); + imm_draw_line(pos, rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max); } } + gpuMatrixEnd(); } - + + immUnbindProgram(); + /* outline */ draw_scope_end(&rect, scissor); + + glDisable(GL_BLEND); } static float polar_to_x(float center, float diam, float ampli, float angle) @@ -850,10 +905,10 @@ static float polar_to_y(float center, float diam, float ampli, float angle) return center + diam * ampli * sinf(angle); } -static void vectorscope_draw_target(float centerx, float centery, float diam, const float colf[3]) +static void vectorscope_draw_target(unsigned int pos, float centerx, float centery, float diam, const float colf[3]) { float y, u, v; - float tangle = 0.f, tampli; + float tangle = 0.0f, tampli; float dangle, dampli, dangle2, dampli2; rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v); @@ -865,41 +920,41 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co tampli = sqrtf(u * u + v * v); /* small target vary by 2.5 degree and 2.5 IRE unit */ - glColor4f(1.0f, 1.0f, 1.0, 0.12f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f); dangle = DEG2RADF(2.5f); dampli = 2.5f / 200.0f; - glBegin(GL_LINE_LOOP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); - glEnd(); + immBegin(GL_LINE_LOOP, 4); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); + immEnd(); /* big target vary by 10 degree and 20% amplitude */ - glColor4f(1.0f, 1.0f, 1.0, 0.12f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f); dangle = DEG2RADF(10.0f); dampli = 0.2f * tampli; dangle2 = DEG2RADF(5.0f); dampli2 = 0.5f * dampli; - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2)); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); - glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2)); - glEnd(); + immBegin(GL_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2)); + immEnd(); + immBegin(GL_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2)); + immEnd(); + immBegin(GL_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2)); + immEnd(); + immBegin(GL_LINE_STRIP, 3); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle)); + immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2)); + immEnd(); } void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) @@ -920,8 +975,8 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco float w = BLI_rctf_size_x(&rect); float h = BLI_rctf_size_y(&rect); - float centerx = rect.xmin + w / 2; - float centery = rect.ymin + h / 2; + float centerx = rect.xmin + w * 0.5f; + float centery = rect.ymin + h * 0.5f; float diam = (w < h) ? w : h; float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha; @@ -932,7 +987,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco float color[4]; UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); /* need scissor test, hvectorscope can draw outside of boundary */ GLint scissor[4]; @@ -942,93 +997,99 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); - glColor4f(1.f, 1.f, 1.f, 0.08f); + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); /* draw grid elements */ /* cross */ - fdrawline(centerx - (diam / 2) - 5, centery, centerx + (diam / 2) + 5, centery); - fdrawline(centerx, centery - (diam / 2) - 5, centerx, centery + (diam / 2) + 5); + imm_draw_line(pos, centerx - (diam * 0.5f) - 5, centery, centerx + (diam * 0.5f) + 5, centery); + imm_draw_line(pos, centerx, centery - (diam * 0.5f) - 5, centerx, centery + (diam * 0.5f) + 5); /* circles */ for (int j = 0; j < 5; j++) { - glBegin(GL_LINE_LOOP); const int increment = 15; + immBegin(GL_LINE_LOOP, (int)(360 / increment)); for (int i = 0; i <= 360 - increment; i += increment) { const float a = DEG2RADF((float)i); - const float r = (j + 1) / 10.0f; - glVertex2f(polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a)); + const float r = (j + 1) * 0.1f; + immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a)); } - glEnd(); + immEnd(); } /* skin tone line */ - glColor4f(1.f, 0.4f, 0.f, 0.2f); - fdrawline(polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5, skin_rad), - polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1, skin_rad)); + immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f); + imm_draw_line(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad), + polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad)); /* saturation points */ for (int i = 0; i < 6; i++) - vectorscope_draw_target(centerx, centery, diam, colors[i]); + vectorscope_draw_target(pos, centerx, centery, diam, colors[i]); if (scopes->ok && scopes->vecscope != NULL) { /* pixel point cloud */ + float col[3] = {alpha, alpha, alpha}; + glBlendFunc(GL_ONE, GL_ONE); - glColor3f(alpha, alpha, alpha); + glPointSize(1.0); - glPushMatrix(); - glEnableClientState(GL_VERTEX_ARRAY); + gpuMatrixBegin3D_legacy(); + gpuPushMatrix(); + gpuTranslate3f(centerx, centery, 0.0f); + gpuScale3f(diam, diam, 0.0f); - glTranslatef(centerx, centery, 0.f); - glScalef(diam, diam, 0.f); + waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col); - glVertexPointer(2, GL_FLOAT, 0, scopes->vecscope); - glPointSize(1.0); - glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - - glDisableClientState(GL_VERTEX_ARRAY); - glPopMatrix(); + gpuPopMatrix(); + gpuMatrixEnd(); } + immUnbindProgram(); + /* outline */ draw_scope_end(&rect, scissor); glDisable(GL_BLEND); } -static void ui_draw_colorband_handle_tri_hlight(float x1, float y1, float halfwidth, float height) +static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, float y1, float halfwidth, float height) { glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_STRIP); - glVertex2f(x1 + halfwidth, y1); - glVertex2f(x1, y1 + height); - glVertex2f(x1 - halfwidth, y1); - glEnd(); + immBegin(GL_LINE_STRIP, 3); + immVertex2f(pos, x1 + halfwidth, y1); + immVertex2f(pos, x1, y1 + height); + immVertex2f(pos, x1 - halfwidth, y1); + immEnd(); glDisable(GL_LINE_SMOOTH); } -static void ui_draw_colorband_handle_tri(float x1, float y1, float halfwidth, float height, bool fill) +static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, float halfwidth, float height, bool fill) { glEnable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH); - glBegin(fill ? GL_TRIANGLES : GL_LINE_LOOP); - glVertex2f(x1 + halfwidth, y1); - glVertex2f(x1, y1 + height); - glVertex2f(x1 - halfwidth, y1); - glEnd(); + immBegin(fill ? GL_TRIANGLES : GL_LINE_LOOP, 3); + immVertex2f(pos, x1 + halfwidth, y1); + immVertex2f(pos, x1, y1 + height); + immVertex2f(pos, x1 - halfwidth, y1); + immEnd(); glDisable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH); } -static void ui_draw_colorband_handle_box(float x1, float y1, float x2, float y2, bool fill) +static void ui_draw_colorband_handle_box(unsigned int pos, float x1, float y1, float x2, float y2, bool fill) { - glBegin(fill ? GL_QUADS : GL_LINE_LOOP); - glVertex2f(x1, y1); - glVertex2f(x1, y2); - glVertex2f(x2, y2); - glVertex2f(x2, y1); - glEnd(); + immBegin(fill ? GL_QUADS : GL_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y1); + immEnd(); } static void ui_draw_colorband_handle( - const rcti *rect, float x, + unsigned int pos, const rcti *rect, float x, const float rgb[3], struct ColorManagedDisplay *display, bool active) { @@ -1047,17 +1108,18 @@ static void ui_draw_colorband_handle( y1 = floorf(y1 + 0.5f); if (active || half_width < min_width) { - glBegin(GL_LINES); - glColor3ub(0, 0, 0); - glVertex2f(x, y1); - glVertex2f(x, y2); - glEnd(); + immUniformColor3ub(0, 0, 0); + immBegin(GL_LINES, 2); + immVertex2f(pos, x, y1); + immVertex2f(pos, x, y2); + immEnd(); + setlinestyle(active ? 2 : 1); - glBegin(GL_LINES); - glColor3ub(200, 200, 200); - glVertex2f(x, y1); - glVertex2f(x, y2); - glEnd(); + immUniformColor3ub(200, 200, 200); + immBegin(GL_LINES, 2); + immVertex2f(pos, x, y1); + immVertex2f(pos, x, y2); + immEnd(); setlinestyle(0); /* hide handles when zoomed out too far */ @@ -1069,45 +1131,46 @@ static void ui_draw_colorband_handle( /* shift handle down */ y1 -= half_width; - glColor3ub(0, 0, 0); - ui_draw_colorband_handle_box(x - half_width, y1 - 1, x + half_width, y1 + height, false); + immUniformColor3ub(0, 0, 0); + ui_draw_colorband_handle_box(pos, x - half_width, y1 - 1, x + half_width, y1 + height, false); /* draw all triangles blended */ glEnable(GL_BLEND); - ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true); + ui_draw_colorband_handle_tri(pos, x, y1 + height, half_width, half_width, true); if (active) - glColor3ub(196, 196, 196); + immUniformColor3ub(196, 196, 196); else - glColor3ub(96, 96, 96); - ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true); + immUniformColor3ub(96, 96, 96); + ui_draw_colorband_handle_tri(pos, x, y1 + height, half_width, half_width, true); if (active) - glColor3ub(255, 255, 255); + immUniformColor3ub(255, 255, 255); else - glColor3ub(128, 128, 128); - ui_draw_colorband_handle_tri_hlight(x, y1 + height - 1, (half_width - 1), (half_width - 1)); + immUniformColor3ub(128, 128, 128); + ui_draw_colorband_handle_tri_hlight(pos, x, y1 + height - 1, (half_width - 1), (half_width - 1)); - glColor3ub(0, 0, 0); - ui_draw_colorband_handle_tri_hlight(x, y1 + height, half_width, half_width); + immUniformColor3ub(0, 0, 0); + ui_draw_colorband_handle_tri_hlight(pos, x, y1 + height, half_width, half_width); glDisable(GL_BLEND); - glColor3ub(128, 128, 128); - ui_draw_colorband_handle_box(x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true); + immUniformColor3ub(128, 128, 128); + ui_draw_colorband_handle_box(pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true); if (display) { IMB_colormanagement_scene_linear_to_display_v3(colf, display); } - glColor3fv(colf); - ui_draw_colorband_handle_box(x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true); + immUniformColor3fv(colf); + ui_draw_colorband_handle_box(pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true); } void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect) { struct ColorManagedDisplay *display = NULL; + unsigned int position, color; ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin); if (coba == NULL) return; @@ -1118,20 +1181,25 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti float x1 = rect->xmin; float sizex = rect->xmax - x1; float sizey = BLI_rcti_size_y(rect); - float sizey_solid = sizey / 4; + float sizey_solid = sizey * 0.25f; float y1 = rect->ymin; - /* Drawing the checkerboard. - * This could be optimized with a single checkerboard shader, - * instead of drawing twice and using stippling the second time. */ - /* layer: background, to show tranparency */ - glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255); - glRectf(x1, y1, x1 + sizex, rect->ymax); - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX); - glRectf(x1, y1, x1 + sizex, rect->ymax); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + VertexFormat *format = immVertexFormat(); + position = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); + + /* Drawing the checkerboard. */ + immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f); + immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f); + immUniform1i("size", 8); + immRectf(position, x1, y1, x1 + sizex, rect->ymax); + immUnbindProgram(); + + /* New format */ + format = immVertexFormat(); + position = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + color = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); /* layer: color ramp */ glEnable(GL_BLEND); @@ -1144,7 +1212,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[1] = y1 + sizey_solid; v2[1] = rect->ymax; - glBegin(GL_TRIANGLE_STRIP); + immBegin(GL_TRIANGLE_STRIP, (sizex + 1) * 2); for (int a = 0; a <= sizex; a++) { float pos = ((float)a) / sizex; do_colorband(coba, pos, colf); @@ -1153,17 +1221,17 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[0] = v2[0] = x1 + a; - glColor4fv(colf); - glVertex2fv(v1); - glVertex2fv(v2); + immAttrib4fv(color, colf); + immVertex2fv(position, v1); + immVertex2fv(position, v2); } - glEnd(); + immEnd(); /* layer: color ramp without alpha for reference when manipulating ramp properties */ v1[1] = y1; v2[1] = y1 + sizey_solid; - glBegin(GL_TRIANGLE_STRIP); + immBegin(GL_TRIANGLE_STRIP, (sizex + 1) * 2); for (int a = 0; a <= sizex; a++) { float pos = ((float)a) / sizex; do_colorband(coba, pos, colf); @@ -1172,31 +1240,38 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti v1[0] = v2[0] = x1 + a; - glColor4f(colf[0], colf[1], colf[2], 1.0f); - glVertex2fv(v1); - glVertex2fv(v2); + immAttrib4f(color, colf[0], colf[1], colf[2], 1.0f); + immVertex2fv(position, v1); + immVertex2fv(position, v2); } - glEnd(); + immEnd(); + + immUnbindProgram(); glDisable(GL_BLEND); + /* New format */ + format = immVertexFormat(); + position = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* layer: box outline */ - glColor4f(0.0, 0.0, 0.0, 1.0); - fdrawbox(x1, y1, x1 + sizex, rect->ymax); - + immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f); + imm_draw_line_box(position, x1, y1, x1 + sizex, rect->ymax); + /* layer: box outline */ glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - fdrawline(x1, y1, x1 + sizex, y1); - glColor4f(1.0f, 1.0f, 1.0f, 0.25f); - fdrawline(x1, y1 - 1, x1 + sizex, y1 - 1); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f); + imm_draw_line(position, x1, y1, x1 + sizex, y1); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f); + imm_draw_line(position, x1, y1 - 1, x1 + sizex, y1 - 1); glDisable(GL_BLEND); /* layer: draw handles */ for (int a = 0; a < coba->tot; a++, cbd++) { if (a != coba->cur) { float pos = x1 + cbd->pos * (sizex - 1) + 1; - ui_draw_colorband_handle(rect, pos, &cbd->r, display, false); + ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, false); } } @@ -1204,116 +1279,103 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti if (coba->tot != 0) { cbd = &coba->data[coba->cur]; float pos = x1 + cbd->pos * (sizex - 1) + 1; - ui_draw_colorband_handle(rect, pos, &cbd->r, display, true); + ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, true); } + + immUnbindProgram(); } void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect) { - static GLuint displist = 0; + /* sphere color */ float diffuse[3] = {1.0f, 1.0f, 1.0f}; + float light[3]; float size; /* backdrop */ UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode_3ubAlpha(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255); + UI_draw_roundbox_gl_mode_3ubAlpha(GL_TRIANGLE_FAN, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255); - /* sphere color */ glCullFace(GL_BACK); glEnable(GL_CULL_FACE); /* setup lights */ - GPULightData light = {0}; - light.type = GPU_LIGHT_SUN; - copy_v3_v3(light.diffuse, diffuse); - zero_v3(light.specular); - ui_but_v3_get(but, light.direction); - - GPU_basic_shader_light_set(0, &light); - for (int a = 1; a < 8; a++) - GPU_basic_shader_light_set(a, NULL); - - /* setup shader */ - GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING); + ui_but_v3_get(but, light); + light[2] = -light[2]; /* transform to button */ - glPushMatrix(); - glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f); + gpuMatrixBegin3D_legacy(); + gpuPushMatrix(); if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect)) - size = BLI_rcti_size_x(rect) / 200.f; + size = 0.5f * BLI_rcti_size_x(rect); else - size = BLI_rcti_size_y(rect) / 200.f; - - glScalef(size, size, MIN2(size, 1.0f)); - - if (displist == 0) { - GLUquadricObj *qobj; + size = 0.5f * BLI_rcti_size_y(rect); - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - GPU_basic_shader_bind(GPU_basic_shader_bound_options()); - gluSphere(qobj, 100.0, 32, 24); - gluDeleteQuadric(qobj); - - glEndList(); - } + gpuTranslate3f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f); + gpuScale3f(size, size, size); - glCallList(displist); + Batch *sphere = Batch_get_sphere(2); + Batch_set_builtin_program(sphere, GPU_SHADER_SIMPLE_LIGHTING); + Batch_Uniform4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f); + Batch_Uniform3fv(sphere, "light", light); + Batch_draw(sphere); /* restore */ - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - GPU_default_lights(); glDisable(GL_CULL_FACE); /* AA circle */ + VertexFormat *format = immVertexFormat(); + unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ubv((unsigned char *)wcol->inner); + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - glColor3ubv((unsigned char *)wcol->inner); - glutil_draw_lined_arc(0.0f, M_PI * 2.0, 100.0f, 32); + imm_draw_lined_circle(pos, 0.0f, 0.0f, 1.0f, 32); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); /* matrix after circle */ - glPopMatrix(); + gpuPopMatrix(); + gpuMatrixEnd(); - /* We disabled all blender lights above, so restore them here. */ - GPU_default_lights(); + immUnbindProgram(); } -static void ui_draw_but_curve_grid(const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step) +static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step) { - glBegin(GL_LINES); float dx = step * zoomx; float fx = rect->xmin + zoomx * (-offsx); if (fx > rect->xmin) fx -= dx * (floorf(fx - rect->xmin)); - while (fx < rect->xmax) { - glVertex2f(fx, rect->ymin); - glVertex2f(fx, rect->ymax); - fx += dx; - } float dy = step * zoomy; float fy = rect->ymin + zoomy * (-offsy); if (fy > rect->ymin) fy -= dy * (floorf(fy - rect->ymin)); + + float line_count = floorf((rect->xmax - fx) / dx) + 1.0f + + floorf((rect->ymax - fy) / dy) + 1.0f; + + immBegin(GL_LINES, (int)line_count * 2); + while (fx < rect->xmax) { + immVertex2f(pos, fx, rect->ymin); + immVertex2f(pos, fx, rect->ymax); + fx += dx; + } while (fy < rect->ymax) { - glVertex2f(rect->xmin, fy); - glVertex2f(rect->xmax, fy); + immVertex2f(pos, rect->xmin, fy); + immVertex2f(pos, rect->xmax, fy); fy += dy; } - glEnd(); + immEnd(); } static void gl_shaded_color(unsigned char *col, int shade) { - glColor3ub(col[0] - shade > 0 ? col[0] - shade : 0, - col[1] - shade > 0 ? col[1] - shade : 0, - col[2] - shade > 0 ? col[2] - shade : 0); + immUniformColor3ub(col[0] - shade > 0 ? col[0] - shade : 0, + col[1] - shade > 0 ? col[1] - shade : 0, + col[2] - shade > 0 ? col[2] - shade : 0); } void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti *rect) @@ -1349,10 +1411,8 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&cumap->curr); float offsx = cumap->curr.xmin - (1.0f / zoomx); float offsy = cumap->curr.ymin - (1.0f / zoomy); - - glLineWidth(1.0f); - /* backdrop */ + /* Do this first to not mess imm context */ if (but->a1 == UI_GRAD_H) { /* magic trigger for curve backgrounds */ float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */ @@ -1365,96 +1425,105 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti }; ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f); + } + glLineWidth(1.0f); + + VertexFormat *format = immVertexFormat(); + unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* backdrop */ + if (but->a1 == UI_GRAD_H) { /* grid, hsv uses different grid */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(0, 0, 0, 48); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.1666666f); + immUniformColor4ub(0, 0, 0, 48); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f); glDisable(GL_BLEND); } else { if (cumap->flag & CUMA_DO_CLIP) { gl_shaded_color((unsigned char *)wcol->inner, -20); - glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); - glColor3ubv((unsigned char *)wcol->inner); - glRectf(rect->xmin + zoomx * (cumap->clipr.xmin - offsx), - rect->ymin + zoomy * (cumap->clipr.ymin - offsy), - rect->xmin + zoomx * (cumap->clipr.xmax - offsx), - rect->ymin + zoomy * (cumap->clipr.ymax - offsy)); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformColor3ubv((unsigned char *)wcol->inner); + immRectf(pos, rect->xmin + zoomx * (cumap->clipr.xmin - offsx), + rect->ymin + zoomy * (cumap->clipr.ymin - offsy), + rect->xmin + zoomx * (cumap->clipr.xmax - offsx), + rect->ymin + zoomy * (cumap->clipr.ymax - offsy)); } else { - glColor3ubv((unsigned char *)wcol->inner); - glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + immUniformColor3ubv((unsigned char *)wcol->inner); + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); } /* grid, every 0.25 step */ gl_shaded_color((unsigned char *)wcol->inner, -16); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f); /* grid, every 1.0 step */ gl_shaded_color((unsigned char *)wcol->inner, -24); - ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f); + ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f); /* axes */ gl_shaded_color((unsigned char *)wcol->inner, -50); - glBegin(GL_LINES); - glVertex2f(rect->xmin, rect->ymin + zoomy * (-offsy)); - glVertex2f(rect->xmax, rect->ymin + zoomy * (-offsy)); - glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymax); - glEnd(); + immBegin(GL_LINES, 4); + immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy)); + immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy)); + immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax); + immEnd(); } /* cfra option */ /* XXX 2.48 */ #if 0 if (cumap->flag & CUMA_DRAW_CFRA) { - glColor3ub(0x60, 0xc0, 0x40); - glBegin(GL_LINES); - glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax); - glEnd(); + immUniformColor3ub(0x60, 0xc0, 0x40); + immBegin(GL_LINES, 2); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax); + immEnd(); } #endif /* sample option */ if (cumap->flag & CUMA_DRAW_SAMPLE) { - glBegin(GL_LINES); /* will draw one of the following 3 lines */ + immBegin(GL_LINES, 2); /* will draw one of the following 3 lines */ if (but->a1 == UI_GRAD_H) { float tsample[3]; float hsv[3]; linearrgb_to_srgb_v3_v3(tsample, cumap->sample); rgb_to_hsv_v(tsample, hsv); - glColor3ub(240, 240, 240); + immUniformColor3ub(240, 240, 240); - glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax); } else if (cumap->cur == 3) { float lum = IMB_colormanagement_get_luminance(cumap->sample); - glColor3ub(240, 240, 240); + immUniformColor3ub(240, 240, 240); - glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax); } else { if (cumap->cur == 0) - glColor3ub(240, 100, 100); + immUniformColor3ub(240, 100, 100); else if (cumap->cur == 1) - glColor3ub(100, 240, 100); + immUniformColor3ub(100, 240, 100); else - glColor3ub(100, 100, 240); + immUniformColor3ub(100, 100, 240); - glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin); - glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin); + immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax); } - glEnd(); + immEnd(); } /* the curve */ - glColor3ubv((unsigned char *)wcol->item); + immUniformColor3ubv((unsigned char *)wcol->item); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - glBegin(GL_LINE_STRIP); + immBegin(GL_LINE_STRIP, (CM_TABLE+1) + 2); if (cuma->table == NULL) curvemapping_changed(cumap, false); @@ -1463,52 +1532,67 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti /* first point */ if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - glVertex2f(rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy)); + immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy)); } else { float fx = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]); float fy = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } for (int a = 0; a <= CM_TABLE; a++) { float fx = rect->xmin + zoomx * (cmp[a].x - offsx); float fy = rect->ymin + zoomy * (cmp[a].y - offsy); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } /* last point */ if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - glVertex2f(rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy)); + immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy)); } else { float fx = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]); float fy = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]); - glVertex2f(fx, fy); + immVertex2f(pos, fx, fy); } - glEnd(); + immEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); + immUnbindProgram(); /* the points, use aspect to make them visible on edges */ + format = immVertexFormat(); + pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned int col = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + cmp = cuma->curve; glPointSize(3.0f); - glBegin(GL_POINTS); + immBegin(GL_POINTS, cuma->totpoint); for (int a = 0; a < cuma->totpoint; a++) { + float color[4]; if (cmp[a].flag & CUMA_SELECT) - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4fv(TH_TEXT_HI, color); else - UI_ThemeColor(TH_TEXT); + UI_GetThemeColor4fv(TH_TEXT, color); float fx = rect->xmin + zoomx * (cmp[a].x - offsx); float fy = rect->ymin + zoomy * (cmp[a].y - offsy); - glVertex2f(fx, fy); + immAttrib4fv(col, color); + immVertex2f(pos, fx, fy); } - glEnd(); + immEnd(); + immUnbindProgram(); /* restore scissortest */ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); /* outline */ - glColor3ubv((unsigned char *)wcol->outline); - fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + format = immVertexFormat(); + pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3ubv((unsigned char *)wcol->outline); + imm_draw_line_box(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + + immUnbindProgram(); } void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) @@ -1540,7 +1624,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc if (scopes->track_disabled) { float color[4] = {0.7f, 0.3f, 0.3f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); ok = true; } @@ -1567,54 +1651,66 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc } if (!ok && scopes->track_preview) { - glPushMatrix(); + gpuMatrixBegin3D_legacy(); + gpuPushMatrix(); /* draw content of pattern area */ glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]); if (width > 0 && height > 0) { ImBuf *drawibuf = scopes->track_preview; + float img_col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + float col_sel[4], col_outline[4]; if (scopes->use_track_mask) { float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); } - glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, - drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect); + immDrawPixelsTex(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, img_col); /* draw cross for pixel position */ - glTranslatef(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.f); + gpuTranslate3f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.0f); glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect)); - GPU_basic_shader_bind_enable(GPU_SHADER_LINE); - - for (int a = 0; a < 2; a++) { - if (a == 1) { - GPU_basic_shader_bind_enable(GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(3, 0xAAAA); - UI_ThemeColor(TH_SEL_MARKER); - } - else { - UI_ThemeColor(TH_MARKER_OUTLINE); + VertexFormat *format = immVertexFormat(); + unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned int col = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + + UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel); + UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline); + + /* Do stipple cross with geometry */ + immBegin(GL_LINES, 7*2*2); + float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f}; + for (int axe = 0; axe < 2; ++axe) { + for (int i = 0; i < 7; ++i) { + float x1 = pos_sel[i] * (1 - axe); + float y1 = pos_sel[i] * axe; + float x2 = pos_sel[i+1] * (1 - axe); + float y2 = pos_sel[i+1] * axe; + + if (i % 2 == 1) + immAttrib4fv(col, col_sel); + else + immAttrib4fv(col, col_outline); + + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); } - - glBegin(GL_LINES); - glVertex2f(-10.0f, 0.0f); - glVertex2f(10.0f, 0.0f); - glVertex2f(0.0f, -10.0f); - glVertex2f(0.0f, 10.0f); - glEnd(); } + immEnd(); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + immUnbindProgram(); } - glPopMatrix(); + gpuPopMatrix(); + gpuMatrixEnd(); ok = true; } @@ -1622,7 +1718,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc if (!ok) { float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); } /* outline */ @@ -1668,26 +1764,31 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol BLI_rcti_size_x(&scissor_new), BLI_rcti_size_y(&scissor_new)); - glColor4ubv(but->col); - float x = 0.5f * (recti->xmin + recti->xmax); float y = 0.5f * (recti->ymin + recti->ymax); - + + VertexFormat *format = immVertexFormat(); + unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(but->col); + glEnable(GL_BLEND); - glBegin(GL_POLYGON); + immBegin(GL_TRIANGLE_FAN, 16); for (int a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); + immVertex2f(pos, x + size * si[a], y + size * co[a]); + immEnd(); - glColor4ub(0, 0, 0, 150); + immUniformColor4ub(0, 0, 0, 150); glLineWidth(1); glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_LOOP); + immBegin(GL_LINE_LOOP, 16); for (int a = 0; a < 16; a++) - glVertex2f(x + size * si[a], y + size * co[a]); - glEnd(); + immVertex2f(pos, x + size * si[a], y + size * co[a]); + immEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); + + immUnbindProgram(); /* restore scissortest */ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); @@ -1752,8 +1853,8 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha { float rad; - if (radius > (BLI_rctf_size_y(rct) - 10.0f) / 2.0f) - rad = (BLI_rctf_size_y(rct) - 10.0f) / 2.0f; + if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f) + rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f; else rad = radius; @@ -1775,7 +1876,7 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha for (; i--; a -= aspect) { /* alpha ranges from 2 to 20 or so */ float color[4] = {0.0f, 0.0f, 0.0f, calpha}; - UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color); calpha += dalpha; } diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 0a21c89e692..a50c0f5a4f4 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -597,7 +597,7 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int const int mval[2] = { mx - ar->winrct.xmin, my - ar->winrct.ymin}; - Base *base; + BaseLegacy *base; CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 0573e8d9c94..a9cdb34f634 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -35,6 +35,7 @@ #include "GPU_extensions.h" #include "GPU_basic_shader.h" +#include "GPU_draw.h" #include "GPU_immediate.h" #include "BLI_blenlib.h" @@ -60,7 +61,6 @@ #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "ED_datafiles.h" @@ -225,13 +225,17 @@ static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float viconutil_set_point(pts[1], cx - d2, cy - d); viconutil_set_point(pts[2], cx + d2, cy); - glColor4f(0.2f, 0.2f, 0.2f, alpha); + unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.2f, 0.2f, 0.2f, alpha); - glBegin(GL_TRIANGLES); - glVertex2iv(pts[0]); - glVertex2iv(pts[1]); - glVertex2iv(pts[2]); - glEnd(); + immBegin(PRIM_TRIANGLES, 3); + immVertex2iv(pos, pts[0]); + immVertex2iv(pos, pts[1]); + immVertex2iv(pos, pts[2]); + immEnd(); + + immUnbindProgram(); } static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, short key_type) @@ -240,7 +244,6 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, * (since we're doing this offscreen, free from any particular space_id) */ struct bThemeState theme_state; - int xco, yco; UI_Theme_Store(&theme_state); UI_SetTheme(SPACE_ACTION, RGN_TYPE_WINDOW); @@ -249,16 +252,30 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, * while the draw_keyframe_shape() function needs the midpoint for * the keyframe */ - xco = x + w / 2; - yco = y + h / 2; + int xco = x + w / 2; + int yco = y + h / 2; + + VertexFormat *format = immVertexFormat(); + unsigned int pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT); + unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(PRIM_POINTS, 1); /* draw keyframe - * - xscale: 1.0 (since there's no timeline scaling to compensate for) - * - yscale: 0.3 * h (found out experimentally... dunno why!) + * - size: 0.3 * h (found out experimentally... dunno why!) * - sel: true (so that "keyframe" state shows the iconic yellow icon) */ - draw_keyframe_shape(xco, yco, 1.0f, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha); - + draw_keyframe_shape(xco, yco, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha, + pos_id, size_id, color_id, outline_color_id); + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); + UI_Theme_Restore(&theme_state); } @@ -291,7 +308,7 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU { bTheme *btheme = UI_GetTheme(); ThemeWireColor *cs = &btheme->tarm[index]; - + /* Draw three bands of color: One per color * x-----a-----b-----c * | N | S | A | @@ -300,19 +317,24 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU const int a = x + w / 3; const int b = x + w / 3 * 2; const int c = x + w; - + + unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* XXX: Include alpha into this... */ /* normal */ - glColor3ubv((unsigned char *)cs->solid); - glRecti(x, y, a, y + h); - + immUniformColor3ubv((unsigned char *)cs->solid); + immRecti(pos, x, y, a, y + h); + /* selected */ - glColor3ubv((unsigned char *)cs->select); - glRecti(a, y, b, y + h); - + immUniformColor3ubv((unsigned char *)cs->select); + immRecti(pos, a, y, b, y + h); + /* active */ - glColor3ubv((unsigned char *)cs->active); - glRecti(b, y, c, y + h); + immUniformColor3ubv((unsigned char *)cs->active); + immRecti(pos, b, y, c, y + h); + + immUnbindProgram(); } #define DEF_VICON_COLORSET_DRAW_NTH(prefix, index) \ @@ -1034,8 +1056,8 @@ static void icon_draw_texture( unsigned texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); - if (rgb) immUniform4f("color", rgb[0], rgb[1], rgb[2], alpha); - else immUniform4f("color", alpha, alpha, alpha, alpha); + if (rgb) immUniformColor3fvAlpha(rgb, alpha); + else immUniformColor4f(alpha, alpha, alpha, alpha); immUniform1i("image", 0); @@ -1385,6 +1407,14 @@ int UI_idcode_icon_get(const int idcode) } } +/** + * \param set_idx: A value from #rna_enum_color_sets_items. + */ +int UI_colorset_icon_get(const int set_idx) +{ + return (set_idx < 1) ? ICON_NONE : VICO_COLORSET_01_VEC - 1 + set_idx; +} + static void icon_draw_at_size( float x, float y, int icon_id, float aspect, float alpha, enum eIconSizes size, const bool nocreate) diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 7262b453e02..ca2538022b0 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2078,15 +2078,7 @@ static void ui_litem_estimate_row(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); - if (item->type == ITEM_BUTTON) { - const uiBut *but = ((uiButtonItem *)item)->but; - const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0'); - - min_size_flag = min_size_flag && icon_only; - } - else { - min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); - } + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); litem->w += itemw; litem->h = MAX2(itemh, litem->h); @@ -2232,15 +2224,7 @@ static void ui_litem_estimate_column(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); - if (item->type == ITEM_BUTTON) { - const uiBut *but = ((uiButtonItem *)item)->but; - const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0'); - - min_size_flag = min_size_flag && icon_only; - } - else { - min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); - } + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); litem->w = MAX2(litem->w, itemw); litem->h += itemh; @@ -3336,6 +3320,14 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but) bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem"); bitem->item.type = ITEM_BUTTON; bitem->but = but; + + int w, h; + ui_item_size((uiItem *)bitem, &w, &h); + /* XXX uiBut hasn't scaled yet + * we can flag the button as not expandable, depending on its size */ + if (w <= 2 * UI_UNIT_X) + bitem->item.flag |= UI_ITEM_MIN; + BLI_addtail(&layout->items, bitem); if (layout->context) { diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index dd06147f226..1bdc47e5037 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -536,29 +536,29 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r rcti hrect; int pnl_icons; const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname; + unsigned char col_title[4]; /* + 0.001f to avoid flirting with float inaccuracy */ if (panel->control & UI_PNL_CLOSE) pnl_icons = (panel->labelofs + 2 * PNL_ICON + 5) / block->aspect + 0.001f; else pnl_icons = (panel->labelofs + PNL_ICON + 5) / block->aspect + 0.001f; - - /* active tab */ + /* draw text label */ - UI_ThemeColor(TH_TITLE); - + UI_GetThemeColor4ubv(TH_TITLE, col_title); + hrect = *rect; if (dir == 'h') { hrect.xmin = rect->xmin + pnl_icons; hrect.ymin += 2.0f / block->aspect; - UI_fontstyle_draw(&style->paneltitle, &hrect, activename); + UI_fontstyle_draw(&style->paneltitle, &hrect, activename, col_title); } else { /* ignore 'pnl_icons', otherwise the text gets offset horizontally * + 0.001f to avoid flirting with float inaccuracy */ hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f; - UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename); + UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename, col_title); } } @@ -569,6 +569,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con rcti headrect; rctf itemrect; int ofsx; + float color[4]; const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false; const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false; @@ -659,8 +660,8 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con if (panel->control & UI_PNL_SOLID) UI_draw_roundbox_corner_set(UI_CNR_ALL); else UI_draw_roundbox_corner_set(UI_CNR_NONE); - UI_ThemeColorShade(TH_BACK, -120); - UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8); + UI_GetThemeColorShade4fv(TH_BACK, -120, color); + UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8, color); } /* panel backdrop */ @@ -1805,7 +1806,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) /* tab titles */ /* draw white shadow to give text more depth */ - glColor3ubv(theme_col_text); + BLF_color3ubv(fontid, theme_col_text); /* main tab title */ BLF_draw(fontid, category_id_draw, category_draw_len); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 62bab15dfb3..b78fa0706c0 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -194,6 +194,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) uiWidgetColors *theme = ui_tooltip_get_theme(); rcti bbox = data->bbox; float tip_colors[UI_TIP_LC_MAX][3]; + unsigned char drawcol[4] = {0, 0, 0, 255}; /* to store color in while drawing (alpha is always 255) */ float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */ float *value_color = tip_colors[UI_TIP_LC_VALUE]; @@ -260,9 +261,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) fstyle_header.shadowalpha = 1.0f; fstyle_header.word_wrap = true; + rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_MAIN]); UI_fontstyle_set(&fstyle_header); - glColor3fv(tip_colors[UI_TIP_LC_MAIN]); - UI_fontstyle_draw(&fstyle_header, &bbox, data->header); + UI_fontstyle_draw(&fstyle_header, &bbox, data->header, drawcol); /* offset to the end of the last line */ xofs = data->line_geom[i].x_pos; @@ -270,9 +271,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) bbox.xmin += xofs; bbox.ymax -= yofs; - glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]); + rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]); fstyle_header.shadow = 0; - UI_fontstyle_draw(&fstyle_header, &bbox, data->active_info); + UI_fontstyle_draw(&fstyle_header, &bbox, data->active_info, drawcol); /* undo offset */ bbox.xmin -= xofs; @@ -280,14 +281,15 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) } else if (data->format[i].style == UI_TIP_STYLE_MONO) { uiFontStyle fstyle_mono = data->fstyle; + fstyle_mono.uifont_id = blf_mono_font; fstyle_mono.word_wrap = true; UI_fontstyle_set(&fstyle_mono); /* XXX, needed because we dont have mono in 'U.uifonts' */ BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi); - glColor3fv(tip_colors[data->format[i].color_id]); - UI_fontstyle_draw(&fstyle_mono, &bbox, data->lines[i]); + rgb_float_to_uchar(drawcol, tip_colors[data->format[i].color_id]); + UI_fontstyle_draw(&fstyle_mono, &bbox, data->lines[i], drawcol); } else { uiFontStyle fstyle_normal = data->fstyle; @@ -296,8 +298,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* draw remaining data */ UI_fontstyle_set(&fstyle_normal); - glColor3fv(tip_colors[data->format[i].color_id]); - UI_fontstyle_draw(&fstyle_normal, &bbox, data->lines[i]); + rgb_float_to_uchar(drawcol, tip_colors[data->format[i].color_id]); + UI_fontstyle_draw(&fstyle_normal, &bbox, data->lines[i], drawcol); } bbox.ymax -= data->lineh * data->line_geom[i].lines; diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index 8bba8fc5534..01bce9d7bdc 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -149,7 +149,7 @@ static uiFont *uifont_to_blfont(int id) void UI_fontstyle_draw_ex( - const uiFontStyle *fs, const rcti *rect, const char *str, + const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4], size_t len, float *r_xofs, float *r_yofs) { int xofs = 0, yofs; @@ -196,6 +196,7 @@ void UI_fontstyle_draw_ex( /* clip is very strict, so we give it some space */ BLF_clipping(fs->uifont_id, rect->xmin - 2, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4); BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f); + BLF_color4ubv(fs->uifont_id, col); BLF_draw(fs->uifont_id, str, len); @@ -205,17 +206,17 @@ void UI_fontstyle_draw_ex( *r_yofs = yofs; } -void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str) +void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4]) { float xofs, yofs; UI_fontstyle_draw_ex( - fs, rect, str, + fs, rect, str, col, BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs); } /* drawn same as above, but at 90 degree angle */ -void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str) +void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4]) { float height; int xofs, yofs; @@ -249,6 +250,7 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch BLF_enable(fs->uifont_id, BLF_ROTATION); BLF_rotation(fs->uifont_id, angle); + BLF_color4ubv(fs->uifont_id, col); if (fs->shadow) { BLF_enable(fs->uifont_id, BLF_SHADOW); @@ -275,13 +277,14 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch * * For drawing on-screen labels. */ -void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str) +void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const unsigned char col[4]) { if (fs->kerning == 1) BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); UI_fontstyle_set(fs); BLF_position(fs->uifont_id, x, y, 0.0f); + BLF_color4ubv(fs->uifont_id, col); BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); if (fs->kerning == 1) @@ -315,12 +318,11 @@ void UI_fontstyle_draw_simple_backdrop( x + width + margin, (y + decent) + height + margin, margin, col_bg); - - glColor4fv(col_fg); } BLF_position(fs->uifont_id, x, y, 0.0f); + BLF_color4fv(fs->uifont_id, col_fg); BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); if (fs->kerning == 1) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index b75ecf68136..ff4762ccc6a 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1251,6 +1251,7 @@ static void widget_draw_text_ime_underline( int ofs_x, width; int rect_x = BLI_rcti_size_x(rect); int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end; + float fcol[4]; if (drawstr[0] != 0) { if (but->pos >= but->ofs) { @@ -1263,8 +1264,8 @@ static void widget_draw_text_ime_underline( width = BLF_width(fstyle->uifont_id, drawstr + but->ofs, ime_data->composite_len + but->pos - but->ofs); - glColor4ubv((unsigned char *)wcol->text); - UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1); + rgba_uchar_to_float(fcol, wcol->text); + UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1, fcol); /* draw the thick line */ if (sel_start != -1 && sel_end != -1) { @@ -1281,7 +1282,7 @@ static void widget_draw_text_ime_underline( width = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_end + sel_start - but->ofs); - UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2); + UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2, fcol); } } } @@ -1457,8 +1458,6 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b } #endif - glColor4ubv((unsigned char *)wcol->text); - if (!use_right_only) { /* for underline drawing */ float font_xofs, font_yofs; @@ -1466,7 +1465,8 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) : (drawstr_left_len - but->ofs); if (drawlen > 0) { - UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, drawlen, &font_xofs, &font_yofs); + UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, (unsigned char *)wcol->text, + drawlen, &font_xofs, &font_yofs); if (but->menu_key != '\0') { char fixedbuf[128]; @@ -1492,6 +1492,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index); BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f); + BLF_color4ubv(fstyle->uifont_id, (unsigned char *)wcol->text); BLF_draw(fstyle->uifont_id, "_", 2); if (fstyle->kerning == 1) { @@ -1506,7 +1507,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b if (drawstr_right) { fstyle->align = UI_STYLE_TEXT_RIGHT; rect->xmax -= UI_TEXT_CLIP_MARGIN; - UI_fontstyle_draw(fstyle, rect, drawstr_right); + UI_fontstyle_draw(fstyle, rect, drawstr_right, (unsigned char *)wcol->text); } } @@ -1575,7 +1576,10 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB } } - if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) { + if (but->drawflag & UI_BUT_TEXT_NO_MARGIN) { + /* skip */ + } + else if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) { rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; } else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) { @@ -4125,8 +4129,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); } - glColor4ubv((unsigned char *)wt->wcol.text); - UI_fontstyle_draw(fstyle, rect, drawstr); + UI_fontstyle_draw(fstyle, rect, drawstr, (unsigned char *)wt->wcol.text); } /* part text right aligned */ @@ -4134,7 +4137,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic if (cpoin) { fstyle->align = UI_STYLE_TEXT_RIGHT; rect->xmax = _rect.xmax - 5; - UI_fontstyle_draw(fstyle, rect, cpoin + 1); + UI_fontstyle_draw(fstyle, rect, cpoin + 1, (unsigned char *)wt->wcol.text); *cpoin = UI_SEP_CHAR; } } @@ -4192,7 +4195,6 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int BLI_strncpy(drawstr, name, sizeof(drawstr)); UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); - glColor4ubv((unsigned char *)wt->wcol.text); - UI_fontstyle_draw(fstyle, &trect, drawstr); + UI_fontstyle_draw(fstyle, &trect, drawstr, (unsigned char *)wt->wcol.text); } } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 8b8c842b2c7..bf7fc0b8bd5 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -54,6 +54,8 @@ #include "BIF_gl.h" +#include "BLF_api.h" + #include "UI_interface.h" #include "UI_interface_icons.h" @@ -166,6 +168,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case SPACE_CLIP: ts = &btheme->tclip; break; + case SPACE_COLLECTIONS: + ts = &btheme->tcollections; + break; default: ts = &btheme->tv3d; break; @@ -1207,6 +1212,11 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff); btheme->tclip.handle_vertex_size = 5; ui_theme_space_init_handles_color(&btheme->tclip); + + /* space collection manager */ + btheme->tcollections = btheme->tv3d; + rgba_char_args_set_fl(btheme->tcollections.back, 0.42, 0.42, 0.42, 1.0); + rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255); /* selected files */ } void ui_style_init_default(void) @@ -1278,18 +1288,11 @@ void UI_ThemeColor4(int colorid) /* set the color with offset for shades */ void UI_ThemeColorShade(int colorid, int offset) { - int r, g, b; - const unsigned char *cp; - - cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); - r = offset + (int) cp[0]; - CLAMP(r, 0, 255); - g = offset + (int) cp[1]; - CLAMP(g, 0, 255); - b = offset + (int) cp[2]; - CLAMP(b, 0, 255); - glColor4ub(r, g, b, cp[3]); + unsigned char col[4]; + UI_GetThemeColorShade4ubv(colorid, offset, col); + glColor4ubv(col); } + void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) { int r, g, b, a; @@ -1394,6 +1397,12 @@ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int off glColor4ub(r, g, b, a); } +void UI_FontThemeColor(int fontid, int colorid) +{ + unsigned char color[4]; + UI_GetThemeColor4ubv(colorid, color); + BLF_color4ubv(fontid, color); +} /* get individual values, not scaled */ float UI_GetThemeValuef(int colorid) @@ -1492,6 +1501,42 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]) col[2] = b; } +void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3]) +{ + const unsigned char *cp1, *cp2; + + cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1); + cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2); + + CLAMP(fac, 0.0f, 1.0f); + col[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]); + col[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]); + col[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]); + + CLAMP(col[0], 0, 255); + CLAMP(col[1], 0, 255); + CLAMP(col[2], 0, 255); +} + +void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4]) +{ + int r, g, b; + const unsigned char *cp; + + cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + r = offset + (int) cp[0]; + CLAMP(r, 0, 255); + g = offset + (int) cp[1]; + CLAMP(g, 0, 255); + b = offset + (int) cp[2]; + CLAMP(b, 0, 255); + + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = cp[3]; +} + void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]) { int r, g, b, a; @@ -2818,6 +2863,12 @@ void init_userdef_do_versions(void) */ { for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { + btheme->tcollections = btheme->tv3d; + rgba_char_args_set_fl(btheme->tcollections.back, 0.42, 0.42, 0.42, 1.0); + rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255); /* selected files */ + } + + for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { rgba_char_args_set_fl(btheme->tui.xaxis, 1.0f, 0.27f, 0.27f, 1.0f); /* red */ rgba_char_args_set_fl(btheme->tui.yaxis, 0.27f, 1.0f, 0.27f, 1.0f); /* green */ rgba_char_args_set_fl(btheme->tui.zaxis, 0.27f, 0.27f, 1.0f, 1.0f); /* blue */ diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index a358118aed1..bcac8d0b825 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -1855,6 +1855,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v /* scale indicators */ if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) { + const int font_id = BLF_default(); View2DGrid *grid = vs->grid; float fac, dfac, fac2, val; @@ -1869,7 +1870,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v dfac = dfac * BLI_rcti_size_x(&hor); /* set starting value, and text color */ - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(font_id, TH_TEXT); val = grid->startx; /* if we're clamping to whole numbers only, make sure entries won't be repeated */ @@ -1881,7 +1882,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v } if (vs->xunits == V2D_UNIT_FRAMES) grid->powerx = 1; - + /* draw numbers in the appropriate range */ if (dfac > 0.0f) { float h = 0.1f * UI_UNIT_Y + (float)(hor.ymin); @@ -1978,7 +1979,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v dfac = dfac * BLI_rcti_size_y(&vert); /* set starting value, and text color */ - UI_ThemeColor(TH_TEXT); + const int font_id = BLF_default(); + UI_FontThemeColor(font_id, TH_TEXT); val = grid->starty; /* if vertical clamping (to whole numbers) is used (i.e. in Sequencer), apply correction */ @@ -1987,9 +1989,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v /* draw vertical steps */ if (dfac > 0.0f) { - - BLF_rotation_default(M_PI_2); - BLF_enable_default(BLF_ROTATION); + BLF_rotation(font_id, M_PI_2); + BLF_enable(font_id, BLF_ROTATION); for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) { @@ -2000,7 +2001,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v scroll_printstr(scene, (float)(vert.xmax) - 2.0f, fac, val, grid->powery, vs->yunits, 'v'); } - BLF_disable_default(BLF_ROTATION); + BLF_disable(font_id, BLF_ROTATION); } } } @@ -2514,7 +2515,8 @@ void UI_view2d_text_cache_draw(ARegion *ar) int col_pack_prev = 0; /* investigate using BLF_ascender() */ - const float default_height = g_v2d_strings ? BLF_height_default("28", 3) : 0.0f; + const int font_id = BLF_default(); + const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f; wmOrtho2_region_pixelspace(ar); @@ -2525,7 +2527,7 @@ void UI_view2d_text_cache_draw(ARegion *ar) if (yofs < 1) yofs = 1; if (col_pack_prev != v2s->col.pack) { - glColor3ubv(v2s->col.ub); + BLF_color3ubv(font_id, v2s->col.ub); col_pack_prev = v2s->col.pack; } @@ -2533,11 +2535,11 @@ void UI_view2d_text_cache_draw(ARegion *ar) BLF_draw_default((float)(v2s->mval[0] + xofs), (float)(v2s->mval[1] + yofs), 0.0, v2s->str, BLF_DRAW_STR_DUMMY_MAX); else { - BLF_clipping_default(v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4); - BLF_enable_default(BLF_CLIPPING); + BLF_enable(font_id, BLF_CLIPPING); + BLF_clipping(font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4); BLF_draw_default(v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX); - BLF_disable_default(BLF_CLIPPING); + BLF_disable(font_id, BLF_CLIPPING); } } g_v2d_strings = NULL; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index d2b2f12c1a5..fa2c1f25cfc 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -447,7 +447,8 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltax", 0); RNA_int_set(op->ptr, "deltay", -40); - if (RNA_boolean_get(op->ptr, "page")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { ARegion *ar = CTX_wm_region(C); RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymin - ar->v2d.mask.ymax); } @@ -497,7 +498,8 @@ static int view_scrollup_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltax", 0); RNA_int_set(op->ptr, "deltay", 40); - if (RNA_boolean_get(op->ptr, "page")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { ARegion *ar = CTX_wm_region(C); RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask)); } diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index bf59693b856..2250aaab310 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -57,6 +57,8 @@ #include "BIF_gl.h" #include "BIF_glutil.h" /* for paint cursor */ +#include "GPU_immediate.h" + #include "ED_screen.h" #include "ED_space_api.h" #include "ED_view3d.h" @@ -1002,12 +1004,18 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd) copy_v3_v3(v2, ray_hit_best[1]); } - UI_ThemeColor(TH_TRANSFORM); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_TRANSFORM); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(v1); - glVertex3fv(v2); - glEnd(); + + immBegin(GL_LINES, 2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immEnd(); + + immUnbindProgram(); } static void knife_init_colors(KnifeColors *colors) @@ -1038,63 +1046,66 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) glPushMatrix(); glMultMatrixf(kcd->ob->obmat); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (kcd->mode == MODE_DRAGGING) { if (kcd->is_angle_snapping) knifetool_draw_angle_snapping(kcd); - glColor3ubv(kcd->colors.line); - + immUniformColor3ubv(kcd->colors.line); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(kcd->prev.cage); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GL_LINES, 2); + immVertex3fv(pos, kcd->prev.cage); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->prev.vert) { - glColor3ubv(kcd->colors.point); + immUniformColor3ubv(kcd->colors.point); glPointSize(11); - glBegin(GL_POINTS); - glVertex3fv(kcd->prev.cage); - glEnd(); + immBegin(GL_POINTS, 1); + immVertex3fv(pos, kcd->prev.cage); + immEnd(); } if (kcd->prev.bmface) { - glColor3ubv(kcd->colors.curpoint); + immUniformColor3ubv(kcd->colors.curpoint); glPointSize(9); - glBegin(GL_POINTS); - glVertex3fv(kcd->prev.cage); - glEnd(); + immBegin(GL_POINTS, 1); + immVertex3fv(pos, kcd->prev.cage); + immEnd(); } if (kcd->curr.edge) { - glColor3ubv(kcd->colors.edge); + immUniformColor3ubv(kcd->colors.edge); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(kcd->curr.edge->v1->cageco); - glVertex3fv(kcd->curr.edge->v2->cageco); - glEnd(); + immBegin(GL_LINES, 2); + immVertex3fv(pos, kcd->curr.edge->v1->cageco); + immVertex3fv(pos, kcd->curr.edge->v2->cageco); + immEnd(); } else if (kcd->curr.vert) { - glColor3ubv(kcd->colors.point); + immUniformColor3ubv(kcd->colors.point); glPointSize(11); - glBegin(GL_POINTS); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GL_POINTS, 1); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->curr.bmface) { - glColor3ubv(kcd->colors.curpoint); + immUniformColor3ubv(kcd->colors.curpoint); glPointSize(9); - glBegin(GL_POINTS); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GL_POINTS, 1); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->totlinehit > 0) { @@ -1105,26 +1116,35 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* draw any snapped verts first */ - glColor4ubv(kcd->colors.point_a); + immUniformColor4ubv(kcd->colors.point_a); glPointSize(11); - glBegin(GL_POINTS); + + immBeginAtMost(GL_POINTS, kcd->totlinehit); + lh = kcd->linehits; for (i = 0; i < kcd->totlinehit; i++, lh++) { - if (lh->v) - glVertex3fv(lh->cagehit); + if (lh->v) { + immVertex3fv(pos, lh->cagehit); + } } - glEnd(); + + immEnd(); /* now draw the rest */ - glColor4ubv(kcd->colors.curpoint_a); + immUniformColor4ubv(kcd->colors.curpoint_a); glPointSize(7); - glBegin(GL_POINTS); + + immBeginAtMost(GL_POINTS, kcd->totlinehit); + lh = kcd->linehits; for (i = 0; i < kcd->totlinehit; i++, lh++) { - if (!lh->v) - glVertex3fv(lh->cagehit); + if (!lh->v) { + immVertex3fv(pos, lh->cagehit); + } } - glEnd(); + + immEnd(); + glDisable(GL_BLEND); } @@ -1132,43 +1152,45 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) BLI_mempool_iter iter; KnifeEdge *kfe; + immUniformColor3ubv(kcd->colors.line); glLineWidth(1.0); - glBegin(GL_LINES); + + immBeginAtMost(GL_LINES, BLI_mempool_count(kcd->kedges) * 2); BLI_mempool_iternew(kcd->kedges, &iter); for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) { if (!kfe->is_cut) continue; - glColor3ubv(kcd->colors.line); - - glVertex3fv(kfe->v1->cageco); - glVertex3fv(kfe->v2->cageco); + immVertex3fv(pos, kfe->v1->cageco); + immVertex3fv(pos, kfe->v2->cageco); } - glEnd(); + immEnd(); } if (kcd->totkvert > 0) { BLI_mempool_iter iter; KnifeVert *kfv; + immUniformColor3ubv(kcd->colors.point); glPointSize(5.0); - glBegin(GL_POINTS); + immBeginAtMost(GL_POINTS, BLI_mempool_count(kcd->kverts)); + BLI_mempool_iternew(kcd->kverts, &iter); for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) { if (!kfv->is_cut) continue; - glColor3ubv(kcd->colors.point); - - glVertex3fv(kfv->cageco); + immVertex3fv(pos, kfv->cageco); } - glEnd(); + immEnd(); } + immUnbindProgram(); + glPopMatrix(); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index f1c1e4105d0..6d8a220dd86 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -45,7 +45,8 @@ #include "BKE_DerivedMesh.h" #include "BKE_unit.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "UI_interface.h" @@ -104,27 +105,41 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) if (v3d && v3d->zbuf) glDisable(GL_DEPTH_TEST); - glPushMatrix(); - glMultMatrixf(lcd->ob->obmat); + gpuMatrixBegin3D_legacy(); + gpuMultMatrix3D(lcd->ob->obmat); + + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ub(255, 0, 255); - glColor3ub(255, 0, 255); if (lcd->totedge > 0) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, lcd->edges); - glDrawArrays(GL_LINES, 0, lcd->totedge * 2); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GL_LINES, lcd->totedge * 2); + + for (int i = 0; i < lcd->totedge; i++) { + immVertex3fv(pos, lcd->edges[i][0]); + immVertex3fv(pos, lcd->edges[i][1]); + } + + immEnd(); } if (lcd->totpoint > 0) { glPointSize(3.0f); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, lcd->points); - glDrawArrays(GL_POINTS, 0, lcd->totpoint); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GL_POINTS, lcd->totpoint); + + for (int i = 0; i < lcd->totpoint; i++) { + immVertex3fv(pos, lcd->points[i]); + } + + immEnd(); } - glPopMatrix(); + immUnbindProgram(); + + gpuMatrixEnd(); + if (v3d && v3d->zbuf) glEnable(GL_DEPTH_TEST); } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 8f004bcf72b..d76dba4088a 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -47,6 +47,7 @@ #include "BLI_rand.h" #include "BLI_sort_utils.h" +#include "BKE_layer.h" #include "BKE_material.h" #include "BKE_context.h" #include "BKE_deform.h" @@ -306,7 +307,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) ED_view3d_init_mats_rv3d(obedit, ar->regiondata); struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), CTX_data_scene(C), 0, ar, CTX_wm_view3d(C)); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -3010,7 +3011,7 @@ enum { MESH_SEPARATE_LOOSE = 2, }; -static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static Base *mesh_separate_tagged(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { Base *base_new; Object *obedit = base_old->object; @@ -3031,11 +3032,11 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE); - base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH); + base_new = ED_object_add_duplicate(bmain, scene, sl, base_old, USER_DUP_MESH); /* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */ assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */ - ED_base_object_select(base_new, BA_SELECT); + ED_object_base_select(base_new, BA_SELECT); BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "duplicate geom=%hvef dest=%p", BM_ELEM_TAG, bm_new); @@ -3057,7 +3058,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe return base_new; } -static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_selected(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { /* 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); @@ -3065,7 +3066,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM /* sel -> tag */ BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT); - return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL); + return (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL); } /* flush a hflag to from verts to edges/faces */ @@ -3164,7 +3165,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const } } -static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_material(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { BMFace *f_cmp, *f; BMIter iter; @@ -3205,7 +3206,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM } /* Move selection into a separate object */ - base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old); + base_new = mesh_separate_tagged(bmain, scene, sl, base_old, bm_old); if (base_new) { mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr); } @@ -3216,7 +3217,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM return result; } -static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_loose(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { int i; BMEdge *e; @@ -3269,7 +3270,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG); /* Move selection into a separate object */ - result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL); + result |= (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL); } return result; @@ -3279,6 +3280,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); const int type = RNA_enum_get(op->ptr, "type"); int retval = 0; @@ -3299,13 +3301,13 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) /* editmode separate */ switch (type) { case MESH_SEPARATE_SELECTED: - retval = mesh_separate_selected(bmain, scene, base, em->bm); + retval = mesh_separate_selected(bmain, scene, sl, base, em->bm); break; case MESH_SEPARATE_MATERIAL: - retval = mesh_separate_material(bmain, scene, base, em->bm); + retval = mesh_separate_material(bmain, scene, sl, base, em->bm); break; case MESH_SEPARATE_LOOSE: - retval = mesh_separate_loose(bmain, scene, base, em->bm); + retval = mesh_separate_loose(bmain, scene, sl, base, em->bm); break; default: BLI_assert(0); @@ -3340,10 +3342,10 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) switch (type) { case MESH_SEPARATE_MATERIAL: - retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old); + retval_iter = mesh_separate_material(bmain, scene, sl, base_iter, bm_old); break; case MESH_SEPARATE_LOOSE: - retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old); + retval_iter = mesh_separate_loose(bmain, scene, sl, base_iter, bm_old); break; default: BLI_assert(0); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 772bb1bd308..036d084a91c 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -551,7 +551,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - Base *base; + BaseLegacy *base; Image *ima = NULL; Mesh *me; Object *obedit; diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index b95921964eb..443f2f0baa8 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -326,7 +326,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert } static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, - Base *base, unsigned int lay) + BaseLegacy *base, unsigned int lay) { float co[3], rot[3]; BMEditMesh *em; @@ -461,14 +461,15 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, static int navmesh_create_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); LinkNode *obs = NULL; - Base *navmeshBase = NULL; + BaseLegacy *navmeshBase = NULL; CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { if (base->object->type == OB_MESH) { if (base->object->body_type == OB_BODY_TYPE_NAVMESH) { - if (!navmeshBase || base == scene->basact) { + if (!navmeshBase || base == sl->basact) { navmeshBase = base; } } diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index b26989113d4..c8b0955c70f 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -75,26 +75,213 @@ /* join selected meshes into the active mesh, context sensitive * return 0 if no join is made (error) and 1 if the join is done */ +static void join_mesh_single( + Main *bmain, Scene *scene, + Object *ob_dst, Base *base_src, float imat[4][4], + MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp, + CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata, + int totvert, int totedge, int totloop, int totpoly, + Key *key, Key *nkey, + Material **matar, int *matmap, int totcol, + int *vertofs, int *edgeofs, int *loopofs, int *polyofs) +{ + int a, b; + + Mesh *me = base_src->object->data; + MVert *mvert = *mvert_pp; + MEdge *medge = *medge_pp; + MLoop *mloop = *mloop_pp; + MPoly *mpoly = *mpoly_pp; + + if (me->totvert) { + /* merge customdata flag */ + ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag; + + /* standard data */ + CustomData_merge(&me->vdata, vdata, CD_MASK_MESH, CD_DEFAULT, totvert); + CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert); + + /* vertex groups */ + MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT); + + /* NB: vertex groups here are new version */ + if (dvert) { + for (a = 0; a < me->totvert; a++) { + for (b = 0; b < dvert[a].totweight; b++) { + /* Find the old vertex group */ + bDeformGroup *dg, *odg = BLI_findlink(&base_src->object->defbase, dvert[a].dw[b].def_nr); + int index; + if (odg) { + /* Search for a match in the new object, and set new index */ + for (dg = ob_dst->defbase.first, index = 0; dg; dg = dg->next, index++) { + if (STREQ(dg->name, odg->name)) { + dvert[a].dw[b].def_nr = index; + break; + } + } + } + } + } + } + + /* if this is the object we're merging into, no need to do anything */ + if (base_src->object != ob_dst) { + float cmat[4][4]; + + /* watch this: switch matmul order really goes wrong */ + mul_m4_m4m4(cmat, imat, base_src->object->obmat); + + /* transform vertex coordinates into new space */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) { + mul_m4_v3(cmat, mvert->co); + } + + /* for each shapekey in destination mesh: + * - if there's a matching one, copy it across (will need to transform vertices into new space...) + * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) + */ + if (key) { + /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs; + + /* check if this mesh has such a shapekey */ + KeyBlock *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) */ + float (*ocos)[3] = okb->data; + for (a = 0; a < me->totvert; a++, cos++, ocos++) { + copy_v3_v3(*cos, *ocos); + mul_m4_v3(cmat, *cos); + } + } + else { + /* copy this mesh's vertex coordinates to the destination shapekey */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { + copy_v3_v3(*cos, mvert->co); + } + } + } + } + } + else { + /* for each shapekey in destination mesh: + * - if it was an 'original', copy the appropriate data from nkey + * - otherwise, copy across plain coordinates (no need to transform coordinates) + */ + if (key) { + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs; + + /* check if this was one of the original shapekeys */ + KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; + if (okb) { + /* copy this mesh's shapekey to the destination shapekey */ + float (*ocos)[3] = okb->data; + for (a = 0; a < me->totvert; a++, cos++, ocos++) { + copy_v3_v3(*cos, *ocos); + } + } + else { + /* copy base-coordinates to the destination shapekey */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { + copy_v3_v3(*cos, mvert->co); + } + } + } + } + } + } + + if (me->totedge) { + CustomData_merge(&me->edata, edata, CD_MASK_MESH, CD_DEFAULT, totedge); + CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge); + + for (a = 0; a < me->totedge; a++, medge++) { + medge->v1 += *vertofs; + medge->v2 += *vertofs; + } + } + + if (me->totloop) { + if (base_src->object != ob_dst) { + MultiresModifierData *mmd; + + multiresModifier_prepare_join(scene, base_src->object, ob_dst); + + if ((mmd = get_multires_modifier(scene, base_src->object, true))) { + ED_object_iter_other(bmain, base_src->object, true, + ED_object_multires_update_totlevels_cb, + &mmd->totlvl); + } + } + + CustomData_merge(&me->ldata, ldata, CD_MASK_MESH, CD_DEFAULT, totloop); + CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop); + + for (a = 0; a < me->totloop; a++, mloop++) { + mloop->v += *vertofs; + mloop->e += *edgeofs; + } + } + + if (me->totpoly) { + if (matmap) { + /* make mapping for materials */ + for (a = 1; a <= base_src->object->totcol; a++) { + Material *ma = give_current_material(base_src->object, a); + + for (b = 0; b < totcol; b++) { + if (ma == matar[b]) { + matmap[a - 1] = b; + break; + } + } + } + } + + CustomData_merge(&me->pdata, pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); + CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly); + + for (a = 0; a < me->totpoly; a++, mpoly++) { + mpoly->loopstart += *loopofs; + mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0; + } + } + + /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */ + *vertofs += me->totvert; + *mvert_pp += me->totvert; + *edgeofs += me->totedge; + *medge_pp += me->totedge; + *loopofs += me->totloop; + *mloop_pp += me->totloop; + *polyofs += me->totpoly; + *mpoly_pp += me->totpoly; +} + int join_mesh_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); - Material **matar, *ma; + Base *ob_base = CTX_data_active_base(C); + Object *ob = ob_base->object; + Material **matar = NULL, *ma; Mesh *me; - MVert *mvert, *mv; + MVert *mvert = NULL; MEdge *medge = NULL; MPoly *mpoly = NULL; MLoop *mloop = NULL; Key *key, *nkey = NULL; - KeyBlock *kb, *okb, *kbn; - float imat[4][4], cmat[4][4], *fp1, *fp2; + KeyBlock *kb, *kbn; + float imat[4][4]; int a, b, totcol, totmat = 0, totedge = 0, totvert = 0; int totloop = 0, totpoly = 0, vertofs, *matmap = NULL; - int i, j, index, haskey = 0, edgeofs, loopofs, polyofs; + int i, haskey = 0, edgeofs, loopofs, polyofs; bool ok = false; bDeformGroup *dg, *odg; - MDeformVert *dvert; CustomData vdata, edata, fdata, ldata, pdata; if (scene->obedit) { @@ -154,8 +341,10 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_mesh_tessface_clear(me); /* new material indices and material array */ - matar = MEM_callocN(sizeof(void *) * totmat, "join_mesh matar"); - if (totmat) matmap = MEM_callocN(sizeof(int) * totmat, "join_mesh matmap"); + if (totmat) { + matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar"); + matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap"); + } totcol = ob->totcol; /* obact materials in new main array, is nicer start! */ @@ -214,7 +403,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) ma = give_current_material(base->object, a); for (b = 0; b < totcol; b++) { - if (ma == matar[b]) break; + if (ma == matar[b]) { + break; + } } if (b == totcol) { matar[b] = ma; @@ -223,8 +414,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) } totcol++; } - if (totcol >= MAXMAT) + if (totcol >= MAXMAT) { break; + } } } @@ -301,187 +493,41 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* inverse transform for all selected meshes in this object */ invert_m4_m4(imat, ob->obmat); - + + /* Add back active mesh first. This allows to keep things similar as they were, as much as possible (i.e. data from + * active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084. + */ + join_mesh_single( + bmain, scene, + ob, ob_base, imat, + &mvert, &medge, &mloop, &mpoly, + &vdata, &edata, &ldata, &pdata, + totvert, totedge, totloop, totpoly, + key, nkey, + matar, matmap, totcol, + &vertofs, &edgeofs, &loopofs, &polyofs); + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { + if (base->object == ob) { + continue; + } /* only join if this is a mesh */ if (base->object->type == OB_MESH) { - me = base->object->data; - - if (me->totvert) { - - /* merge customdata flag */ - ((Mesh *)ob->data)->cd_flag |= me->cd_flag; - - /* standard data */ - CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); - CustomData_copy_data_named(&me->vdata, &vdata, 0, vertofs, me->totvert); - - /* vertex groups */ - dvert = CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); - - /* NB: vertex groups here are new version */ - if (dvert) { - for (i = 0; i < me->totvert; i++) { - for (j = 0; j < dvert[i].totweight; j++) { - /* Find the old vertex group */ - odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr); - if (odg) { - /* Search for a match in the new object, and set new index */ - for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) { - if (STREQ(dg->name, odg->name)) { - dvert[i].dw[j].def_nr = index; - break; - } - } - } - } - } - } - - /* if this is the object we're merging into, no need to do anything */ - if (base->object != ob) { - /* watch this: switch matmul order really goes wrong */ - mul_m4_m4m4(cmat, imat, base->object->obmat); - - /* transform vertex coordinates into new space */ - for (a = 0, mv = mvert; a < me->totvert; a++, mv++) { - mul_m4_v3(cmat, mv->co); - } - - /* for each shapekey in destination mesh: - * - if there's a matching one, copy it across (will need to transform vertices into new space...) - * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) - */ - if (key) { - /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ - for (kb = key->block.first; kb; kb = kb->next) { - /* get pointer to where to write data for this mesh in shapekey's data array */ - fp1 = ((float *)kb->data) + (vertofs * 3); - - /* check if this mesh has such a shapekey */ - 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)); - for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { - copy_v3_v3(fp1, fp2); - mul_m4_v3(cmat, fp1); - } - } - else { - /* copy this mesh's vertex coordinates to the destination shapekey */ - mv = mvert; - for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { - copy_v3_v3(fp1, mv->co); - } - } - } - } - } - else { - /* for each shapekey in destination mesh: - * - if it was an 'original', copy the appropriate data from nkey - * - otherwise, copy across plain coordinates (no need to transform coordinates) - */ - if (key) { - for (kb = key->block.first; kb; kb = kb->next) { - /* get pointer to where to write data for this mesh in shapekey's data array */ - fp1 = ((float *)kb->data) + (vertofs * 3); - - /* check if this was one of the original shapekeys */ - okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; - if (okb) { - /* copy this mesh's shapekey to the destination shapekey */ - fp2 = ((float *)(okb->data)); - for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { - copy_v3_v3(fp1, fp2); - } - } - else { - /* copy base-coordinates to the destination shapekey */ - mv = mvert; - for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { - copy_v3_v3(fp1, mv->co); - } - } - } - } - } - - /* advance mvert pointer to end of base mesh's data */ - mvert += me->totvert; - } - - if (me->totedge) { - CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); - CustomData_copy_data_named(&me->edata, &edata, 0, edgeofs, me->totedge); - - for (a = 0; a < me->totedge; a++, medge++) { - medge->v1 += vertofs; - medge->v2 += vertofs; - } - } - - if (me->totloop) { - if (base->object != ob) { - MultiresModifierData *mmd; - - multiresModifier_prepare_join(scene, base->object, ob); + join_mesh_single( + bmain, scene, + ob, base, imat, + &mvert, &medge, &mloop, &mpoly, + &vdata, &edata, &ldata, &pdata, + totvert, totedge, totloop, totpoly, + key, nkey, + matar, matmap, totcol, + &vertofs, &edgeofs, &loopofs, &polyofs); - 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); - } - } - - CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop); - CustomData_copy_data_named(&me->ldata, &ldata, 0, loopofs, me->totloop); - - for (a = 0; a < me->totloop; a++, mloop++) { - mloop->v += vertofs; - mloop->e += edgeofs; - } - } - - if (me->totpoly) { - if (totmat) { - /* make mapping for materials */ - for (a = 1; a <= base->object->totcol; a++) { - ma = give_current_material(base->object, a); - - for (b = 0; b < totcol; b++) { - if (ma == matar[b]) { - matmap[a - 1] = b; - break; - } - } - } - } - - CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); - CustomData_copy_data_named(&me->pdata, &pdata, 0, polyofs, me->totpoly); - - for (a = 0; a < me->totpoly; a++, mpoly++) { - mpoly->loopstart += loopofs; - mpoly->mat_nr = matmap ? matmap[(int)mpoly->mat_nr] : 0; - } - - polyofs += me->totpoly; - } - - /* these are used for relinking (cannot be set earlier, - * or else reattaching goes wrong) - */ - vertofs += me->totvert; - edgeofs += me->totedge; - loopofs += me->totloop; - /* free base, now that data is merged */ - if (base->object != ob) - ED_base_object_free_and_unlink(bmain, scene, base); + if (base->object != ob) { + ED_base_object_free_and_unlink(bmain, scene, base->object); + } } } CTX_DATA_END; @@ -529,34 +575,20 @@ int join_mesh_exec(bContext *C, wmOperator *op) if (totcol) { me->mat = matar; - ob->mat = MEM_callocN(sizeof(void *) * totcol, "join obmatar"); - ob->matbits = MEM_callocN(sizeof(char) * totcol, "join obmatbits"); + ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar"); + ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits"); + MEM_freeN(matmap); } - else - MEM_freeN(matar); - + ob->totcol = me->totcol = totcol; - if (matmap) MEM_freeN(matmap); - /* other mesh users */ test_all_objects_materials(bmain, (ID *)me); /* free temp copy of destination shapekeys (if applicable) */ if (nkey) { - /* XXX 2.5 Animato */ -#if 0 - /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */ - if (nkey->ipo) { - BKE_ipo_free(nkey->ipo); - BLI_remlink(&bmain->ipo, nkey->ipo); - MEM_freeN(nkey->ipo); - } -#endif - - BKE_key_free(nkey); - BLI_remlink(&bmain->key, nkey); - MEM_freeN(nkey); + /* We can assume nobody is using that ID currently. */ + BKE_libblock_free_ex(bmain, nkey, false, false); } /* ensure newly inserted keys are time sorted */ @@ -564,7 +596,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_key_sort(key); } - DAG_relations_tag_update(bmain); // removed objects, need to rebuild dag + DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 02b2d8492b4..e7223f6f1ee 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -63,6 +63,7 @@ #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_camera.h" +#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" @@ -73,6 +74,7 @@ #include "BKE_group.h" #include "BKE_lamp.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -405,10 +407,11 @@ Object *ED_object_add_type( bContext *C, int type, const char *name, const float loc[3], const float rot[3], - bool enter_editmode, unsigned int layer) + bool enter_editmode, unsigned int UNUSED(layer)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob; /* for as long scene has editmode... */ @@ -416,13 +419,12 @@ Object *ED_object_add_type( ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */ /* deselects all, sets scene->basact */ - ob = BKE_object_add(bmain, scene, type, name); - BASACT->lay = ob->lay = layer; + ob = BKE_object_add(bmain, scene, sl, type, name); /* editor level activate, notifiers */ - ED_base_object_activate(C, BASACT); + ED_object_base_activate(C, sl->basact); /* more editor stuff */ - ED_object_base_init_transform(C, BASACT, loc, rot); + ED_object_base_init_transform(C, sl->basact, loc, rot); /* Ignore collisions by default for non-mesh objects */ if (type != OB_MESH) { @@ -830,7 +832,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv { Scene *scene = CTX_data_scene(C); - Base *base = NULL; + BaseLegacy *base = NULL; Image *ima = NULL; Object *ob = NULL; @@ -1109,21 +1111,19 @@ static void object_delete_check_glsl_update(Object *ob) /* remove base from a specific scene */ /* note: now unlinks constraints as well */ -void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base) +void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Object *ob) { - if (BKE_library_ID_is_indirectly_used(bmain, base->object) && - ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) + if (BKE_library_ID_is_indirectly_used(bmain, ob) && + ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { /* We cannot delete indirectly used object... */ printf("WARNING, undeletable object '%s', should have been catched before reaching this function!", - base->object->id.name + 2); + ob->id.name + 2); return; } - BKE_scene_base_unlink(scene, base); - object_delete_check_glsl_update(base->object); - BKE_libblock_free_us(bmain, base->object); - MEM_freeN(base); + object_delete_check_glsl_update(ob); + BKE_collections_object_remove(bmain, scene, ob, true); DAG_id_type_tag(bmain, ID_OB); } @@ -1139,56 +1139,46 @@ static int object_delete_exec(bContext *C, wmOperator *op) if (CTX_data_edit_object(C)) return OPERATOR_CANCELLED; - CTX_DATA_BEGIN (C, Base *, base, selected_bases) + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, base->object); - if (base->object->id.tag & LIB_TAG_INDIRECT) { + const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob); + if (ob->id.tag & LIB_TAG_INDIRECT) { /* Can this case ever happen? */ - BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2); + BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2); continue; } - else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) { + else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { BKE_reportf(op->reports, RPT_WARNING, "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", - base->object->id.name + 2, scene->id.name + 2); + ob->id.name + 2, scene->id.name + 2); continue; } /* remove from Grease Pencil parent */ for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) { for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpl->parent != NULL) { - Object *ob = gpl->parent; - Object *curob = base->object; - if (ob == curob) { + if (gpl->parent == ob) { gpl->parent = NULL; } } } } - /* deselect object -- it could be used in other scenes */ - base->object->flag &= ~SELECT; - /* remove from current scene only */ - ED_base_object_free_and_unlink(bmain, scene, base); + ED_base_object_free_and_unlink(bmain, scene, ob); changed = true; if (use_global) { Scene *scene_iter; - Base *base_other; - for (scene_iter = bmain->scene.first; scene_iter; scene_iter = scene_iter->id.next) { if (scene_iter != scene && !ID_IS_LINKED_DATABLOCK(scene_iter)) { - base_other = BKE_scene_base_find(scene_iter, base->object); - if (base_other) { - if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) { - BKE_reportf(op->reports, RPT_WARNING, - "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", - base->object->id.name + 2, scene_iter->id.name + 2); - break; - } - ED_base_object_free_and_unlink(bmain, scene_iter, base_other); + if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { + BKE_reportf(op->reports, RPT_WARNING, + "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", + ob->id.name + 2, scene_iter->id.name + 2); + break; } + ED_base_object_free_and_unlink(bmain, scene_iter, ob); } } } @@ -1329,6 +1319,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, const bool use_hierarchy) { Main *bmain = CTX_data_main(C); + SceneLayer *sl = CTX_data_scene_layer(C); ListBase *lb; DupliObject *dob; GHash *dupli_gh = NULL, *parent_gh = NULL; @@ -1360,12 +1351,10 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, */ if (ob->mat == NULL) ob->totcol = 0; - basen = MEM_dupallocN(base); - basen->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP); - ob->flag = basen->flag; - basen->lay = base->lay; - BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */ - basen->object = ob; + BKE_collection_object_add_from(scene, dob->ob, ob); + basen = BKE_scene_layer_base_find(sl, ob); + + BKE_scene_object_base_flag_sync_from_base(basen); /* make sure apply works */ BKE_animdata_free(&ob->id, true); @@ -1380,7 +1369,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, BLI_listbase_clear(&ob->constraints); ob->curve_cache = NULL; ob->transflag &= ~OB_DUPLI; - ob->lay = base->lay; copy_m4_m4(ob->obmat, dob->mat); BKE_object_apply_mat4(ob, ob->obmat, false, false); @@ -1589,7 +1577,7 @@ static int convert_poll(bContext *C) } /* Helper for convert_exec */ -static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object *ob) +static Base *duplibase_for_convert(Main *bmain, Scene *scene, SceneLayer *sl, Base *base, Object *ob) { Object *obn; Base *basen; @@ -1600,16 +1588,11 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object obn = BKE_object_copy(bmain, ob); DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + BKE_collection_object_add_from(scene, ob, obn); - basen = MEM_mallocN(sizeof(Base), "duplibase"); - *basen = *base; - BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */ - basen->object = obn; - basen->flag |= SELECT; - obn->flag |= SELECT; - base->flag &= ~SELECT; - ob->flag &= ~SELECT; - + basen = BKE_scene_layer_base_find(sl, obn); + ED_object_base_select(basen, BA_SELECT); + ED_object_base_select(basen, BA_DESELECT); return basen; } @@ -1617,6 +1600,7 @@ static int convert_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Base *basen = NULL, *basact = NULL; Object *ob, *ob1, *newob, *obact = CTX_data_active_object(C); DerivedMesh *dm; @@ -1631,7 +1615,7 @@ static int convert_exec(bContext *C, wmOperator *op) /* don't forget multiple users! */ { - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { ob = base->object; @@ -1678,7 +1662,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, sl, base, NULL); newob = basen->object; /* decrement original mesh's usage count */ @@ -1703,7 +1687,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, sl, base, NULL); newob = basen->object; /* decrement original mesh's usage count */ @@ -1735,7 +1719,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(bmain, scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, sl, base, NULL); newob = basen->object; /* decrement original curve's usage count */ @@ -1806,7 +1790,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (target == OB_MESH) { if (keep_original) { - basen = duplibase_for_convert(bmain, scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, sl, base, NULL); newob = basen->object; /* decrement original curve's usage count */ @@ -1841,7 +1825,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (!(baseob->flag & OB_DONE)) { baseob->flag |= OB_DONE; - basen = duplibase_for_convert(bmain, scene, base, baseob); + basen = duplibase_for_convert(bmain, scene, sl, base, baseob); newob = basen->object; mb = newob->data; @@ -1892,23 +1876,21 @@ static int convert_exec(bContext *C, wmOperator *op) if (!keep_original) { if (mballConverted) { - Base *base, *base_next; - - for (base = scene->base.first; base; base = base_next) { - base_next = base->next; - - ob = base->object; + Object *ob_mball; + FOREACH_SCENE_OBJECT(scene, ob_mball) + { if (ob->type == OB_MBALL) { if (ob->flag & OB_DONE) { Object *ob_basis = NULL; - if (BKE_mball_is_basis(ob) || - ((ob_basis = BKE_mball_basis_find(scene, ob)) && (ob_basis->flag & OB_DONE))) + if (BKE_mball_is_basis(ob_mball) || + ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE))) { - ED_base_object_free_and_unlink(bmain, scene, base); + ED_base_object_free_and_unlink(bmain, scene, ob_mball); } } } } + FOREACH_SCENE_OBJECT_END } /* delete object should renew depsgraph */ @@ -1920,12 +1902,12 @@ static int convert_exec(bContext *C, wmOperator *op) if (basact) { /* active base was changed */ - ED_base_object_activate(C, basact); - BASACT = basact; + ED_object_base_activate(C, basact); + BASACT_NEW = basact; } - else if (BASACT->object->flag & OB_DONE) { - WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT->object); - WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT->object); + else if (BASACT_NEW->object->flag & OB_DONE) { + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT_NEW->object); + WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT_NEW->object); } DAG_relations_tag_update(bmain); @@ -1967,18 +1949,17 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* used below, assumes id.new is correct */ /* leaves selection of base/object unaltered */ /* Does set ID->newid pointers. */ -static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag) +static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, int dupflag) { #define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; } #define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; } Base *basen = NULL; Material ***matarar; - Object *ob, *obn; + Object *obn; ID *id; int a, didit; - ob = base->object; if (ob->mode & OB_MODE_POSE) { ; /* nothing? */ } @@ -1986,20 +1967,18 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - basen = MEM_mallocN(sizeof(Base), "duplibase"); - *basen = *base; - BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */ - basen->object = obn; + BKE_collection_object_add_from(scene, ob, obn); + basen = BKE_scene_layer_base_find(sl, obn); /* 1) duplis should end up in same group as the original * 2) Rigid Body sim participants MUST always be part of a group... */ // XXX: is 2) really a good measure here? - if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) { + if ((ob->flag & OB_FROMGROUP) != 0 || ob->rigidbody_object || ob->rigidbody_constraint) { Group *group; for (group = bmain->group.first; group; group = group->id.next) { if (BKE_group_object_exists(group, ob)) - BKE_group_object_add(group, obn, scene, basen); + BKE_group_object_add(group, obn); } } @@ -2207,14 +2186,14 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base * note: don't call this within a loop since clear_* funcs loop over the entire database. * note: caller must do DAG_relations_tag_update(bmain); * this is not done automatic since we may duplicate many objects in a batch */ -Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag) +Base *ED_object_add_duplicate(Main *bmain, Scene *scene, SceneLayer *sl, Base *base, int dupflag) { Base *basen; Object *ob; clear_sca_new_poins(); /* BGE logic */ - basen = object_add_duplicate_internal(bmain, scene, base, dupflag); + basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag); if (basen == NULL) { return NULL; } @@ -2241,6 +2220,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); const bool linked = RNA_boolean_get(op->ptr, "linked"); int dupflag = (linked) ? 0 : U.dupflag; @@ -2248,19 +2228,19 @@ static int duplicate_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag); + Base *basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag); /* note that this is safe to do with this context iterator, * the list is made in advance */ - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); if (basen == NULL) { continue; } /* new object becomes active */ - if (BASACT == base) - ED_base_object_activate(C, basen); + if (BASACT_NEW == base) + ED_object_base_activate(C, basen); if (basen->object->data) { DAG_id_tag_update(basen->object->data, 0); @@ -2308,9 +2288,9 @@ static int add_named_exec(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); const wmEvent *event = win ? win->eventstate : NULL; Main *bmain = CTX_data_main(C); - View3D *v3d = CTX_wm_view3d(C); /* may be NULL */ Scene *scene = CTX_data_scene(C); - Base *basen, *base; + SceneLayer *sl = CTX_data_scene_layer(C); + Base *basen; Object *ob; const bool linked = RNA_boolean_get(op->ptr, "linked"); int dupflag = (linked) ? 0 : U.dupflag; @@ -2325,22 +2305,17 @@ static int add_named_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - base = MEM_callocN(sizeof(Base), "duplibase"); - base->object = ob; - base->flag = ob->flag; - /* prepare dupli */ clear_sca_new_poins(); /* BGE logic */ - basen = object_add_duplicate_internal(bmain, scene, base, dupflag); + basen = object_add_duplicate_internal(bmain, scene, sl, ob, dupflag); + BKE_scene_object_base_flag_sync_from_object(basen); if (basen == NULL) { - MEM_freeN(base); BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); return OPERATOR_CANCELLED; } - basen->lay = basen->object->lay = BKE_screen_view3d_layer_active(v3d, scene); basen->object->restrictflag &= ~OB_RESTRICT_VIEW; if (event) { @@ -2351,8 +2326,8 @@ static int add_named_exec(bContext *C, wmOperator *op) ED_view3d_cursor3d_position(C, basen->object->loc, mval); } - ED_base_object_select(basen, BA_SELECT); - ED_base_object_activate(C, basen); + ED_object_base_select(basen, BA_SELECT); + ED_object_base_activate(C, basen); copy_object_set_idnew(C); @@ -2360,8 +2335,6 @@ static int add_named_exec(bContext *C, wmOperator *op) DAG_relations_tag_update(bmain); - MEM_freeN(base); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 59d78f13ccb..2437a6bff28 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1682,14 +1682,15 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob if ((found == false) && (add)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Base *base = BASACT, *newbase = NULL; + SceneLayer *sl = CTX_data_scene_layer(C); + Base *base = BASACT_NEW, *newbase = NULL; Object *obt; /* add new target object */ - obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL); + obt = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL); /* set layers OK */ - newbase = BASACT; + newbase = BASACT_NEW; newbase->lay = base->lay; obt->lay = newbase->lay; @@ -1708,8 +1709,8 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob } /* restore, BKE_object_add sets active */ - BASACT = base; - base->flag |= SELECT; + BASACT_NEW = base; + base->flag |= BASE_SELECTED; /* make our new target the new object */ *tar_ob = obt; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index edd7b5dd1be..2a4557f3610 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -132,189 +132,6 @@ Object *ED_object_active_context(bContext *C) } -/* ********* clear/set restrict view *********/ -static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Main *bmain = CTX_data_main(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = sa->spacedata.first; - Scene *scene = CTX_data_scene(C); - Base *base; - bool changed = false; - - /* XXX need a context loop to handle such cases */ - for (base = FIRSTBASE; base; base = base->next) { - if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) { - if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) { - base->flag |= SELECT; - } - base->object->flag = base->flag; - base->object->restrictflag &= ~OB_RESTRICT_VIEW; - changed = true; - } - } - if (changed) { - DAG_id_type_tag(bmain, ID_OB); - DAG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_hide_view_clear(wmOperatorType *ot) -{ - - /* identifiers */ - ot->name = "Clear Restrict View"; - ot->description = "Reveal the object by setting the hide flag"; - ot->idname = "OBJECT_OT_hide_view_clear"; - - /* api callbacks */ - ot->exec = object_hide_view_clear_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -static int object_hide_view_set_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - bool changed = false; - const bool unselected = RNA_boolean_get(op->ptr, "unselected"); - - CTX_DATA_BEGIN(C, Base *, base, visible_bases) - { - if (!unselected) { - if (base->flag & SELECT) { - base->flag &= ~SELECT; - base->object->flag = base->flag; - base->object->restrictflag |= OB_RESTRICT_VIEW; - changed = true; - if (base == BASACT) { - ED_base_object_activate(C, NULL); - } - } - } - else { - if (!(base->flag & SELECT)) { - base->object->restrictflag |= OB_RESTRICT_VIEW; - changed = true; - if (base == BASACT) { - ED_base_object_activate(C, NULL); - } - } - } - } - CTX_DATA_END; - - if (changed) { - DAG_id_type_tag(bmain, ID_OB); - DAG_relations_tag_update(bmain); - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - - } - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_hide_view_set(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Set Restrict View"; - ot->description = "Hide the object by setting the hide flag"; - ot->idname = "OBJECT_OT_hide_view_set"; - - /* api callbacks */ - ot->exec = object_hide_view_set_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); - -} - -/* 99% same as above except no need for scene refreshing (TODO, update render preview) */ -static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op)) -{ - bool changed = false; - - /* XXX need a context loop to handle such cases */ - CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) - { - if (ob->restrictflag & OB_RESTRICT_RENDER) { - ob->restrictflag &= ~OB_RESTRICT_RENDER; - changed = true; - } - } - CTX_DATA_END; - - if (changed) - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL); - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_hide_render_clear(wmOperatorType *ot) -{ - - /* identifiers */ - ot->name = "Clear Restrict Render"; - ot->description = "Reveal the render object by setting the hide render flag"; - ot->idname = "OBJECT_OT_hide_render_clear"; - - /* api callbacks */ - ot->exec = object_hide_render_clear_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -static int object_hide_render_set_exec(bContext *C, wmOperator *op) -{ - const bool unselected = RNA_boolean_get(op->ptr, "unselected"); - - CTX_DATA_BEGIN(C, Base *, base, visible_bases) - { - if (!unselected) { - if (base->flag & SELECT) { - base->object->restrictflag |= OB_RESTRICT_RENDER; - } - } - else { - if (!(base->flag & SELECT)) { - base->object->restrictflag |= OB_RESTRICT_RENDER; - } - } - } - CTX_DATA_END; - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL); - return OPERATOR_FINISHED; -} - -void OBJECT_OT_hide_render_set(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Set Restrict Render"; - ot->description = "Hide the render object by setting the hide render flag"; - ot->idname = "OBJECT_OT_hide_render_set"; - - /* api callbacks */ - ot->exec = object_hide_render_set_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); -} - /* ******************* toggle editmode operator ***************** */ static bool mesh_needs_keyindex(const Mesh *me) @@ -465,31 +282,22 @@ void ED_object_editmode_exit(bContext *C, int flag) void ED_object_editmode_enter(bContext *C, int flag) { Scene *scene = CTX_data_scene(C); - Base *base = NULL; + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob; - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = NULL; bool ok = false; if (ID_IS_LINKED_DATABLOCK(scene)) return; - if (sa && sa->spacetype == SPACE_VIEW3D) - v3d = sa->spacedata.first; - if ((flag & EM_IGNORE_LAYER) == 0) { - base = CTX_data_active_base(C); /* active layer checked here for view3d */ + ob = CTX_data_active_object(C); /* active layer checked here for view3d */ - if (base == NULL) return; - else if (v3d && (base->lay & v3d->lay) == 0) return; - else if (!v3d && (base->lay & scene->lay) == 0) return; + if (ob == NULL) return; } else { - base = scene->basact; + ob = sl->basact->object; } - if (ELEM(NULL, base, base->object, base->object->data)) return; - - ob = base->object; + if (ELEM(NULL, ob, ob->data)) return; /* this checks actual object->data, for cases when other scenes have it in editmode context */ if (BKE_object_is_in_editmode(ob)) @@ -698,7 +506,7 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) { //XXX no longer used - to be removed - replaced by game_properties_copy_exec bProperty *prop; - Base *base; + BaseLegacy *base; int nr, tot = 0; char *str; @@ -758,7 +566,7 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob) { //XXX no longer used - to be removed - replaced by logicbricks_copy_exec - Base *base; + BaseLegacy *base; for (base = FIRSTBASE; base; base = base->next) { if (base->object != ob) { @@ -844,7 +652,7 @@ static void copy_texture_space(Object *to, Object *ob) static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) { Object *ob; - Base *base; + BaseLegacy *base; Curve *cu, *cu1; Nurb *nu; bool do_depgraph_update = false; @@ -1512,7 +1320,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d) { /* all selected objects with an image map: scale in image aspect */ - Base *base; + BaseLegacy *base; Object *ob; Material *ma; Tex *tex; diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 0fe43c44d7d..b22b034ecab 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -128,7 +128,6 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); int single_group_index = RNA_enum_get(op->ptr, "group"); Group *single_group = group_object_active_find_index(ob, single_group_index); Group *group; @@ -151,7 +150,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) continue; if (!BKE_group_object_cyclic_check(bmain, base->object, group)) { - BKE_group_object_add(group, base->object, scene, base); + BKE_group_object_add(group, base->object); updated = true; } else { @@ -200,8 +199,8 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot) static int objects_remove_active_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - Object *ob = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT_NEW; int single_group_index = RNA_enum_get(op->ptr, "group"); Group *single_group = group_object_active_find_index(ob, single_group_index); Group *group; @@ -221,7 +220,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) /* Remove groups from selected objects */ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - BKE_group_object_unlink(group, base->object, scene, base); + BKE_group_object_unlink(group, base->object); ok = 1; } CTX_DATA_END; @@ -264,11 +263,10 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot) static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - BKE_object_groups_clear(scene, base, base->object); + BKE_object_groups_clear(base->object); } CTX_DATA_END; @@ -297,7 +295,6 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); int single_group_index = RNA_enum_get(op->ptr, "group"); Group *single_group = group_object_active_find_index(ob, single_group_index); Group *group; @@ -315,7 +312,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) /* now remove all selected objects from the group */ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - BKE_group_object_unlink(group, base->object, scene, base); + BKE_group_object_unlink(group, base->object); updated = true; } CTX_DATA_END; @@ -357,7 +354,6 @@ void GROUP_OT_objects_remove(wmOperatorType *ot) static int group_create_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); Group *group = NULL; char name[MAX_ID_NAME - 2]; /* id name */ @@ -367,7 +363,7 @@ static int group_create_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - BKE_group_object_add(group, base->object, scene, base); + BKE_group_object_add(group, base->object); } CTX_DATA_END; @@ -398,7 +394,6 @@ void GROUP_OT_create(wmOperatorType *ot) static int group_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_context(C); Main *bmain = CTX_data_main(C); Group *group; @@ -407,7 +402,7 @@ static int group_add_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; group = BKE_group_add(bmain, "Group"); - BKE_group_object_add(group, ob, scene, NULL); + BKE_group_object_add(group, ob); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -432,7 +427,6 @@ void OBJECT_OT_group_add(wmOperatorType *ot) static int group_link_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_context(C); Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group")); @@ -457,7 +451,7 @@ static int group_link_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_group_object_add(group, ob, scene, NULL); + BKE_group_object_add(group, ob); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -490,14 +484,13 @@ void OBJECT_OT_group_link(wmOperatorType *ot) static int group_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_context(C); Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data; if (!ob || !group) return OPERATOR_CANCELLED; - BKE_group_object_unlink(group, ob, scene, NULL); /* base will be used if found */ + BKE_group_object_unlink(group, ob); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -560,8 +553,10 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) { - ED_base_object_select(base, BA_SELECT); + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (BKE_group_object_exists(group, base->object)) { + ED_object_base_select(base, BA_SELECT); + } } } CTX_DATA_END; diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 438c10c51fa..f41f21f5bd4 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -445,12 +445,12 @@ static int hook_op_edit_poll(bContext *C) return 0; } -static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit) +static Object *add_hook_object_new(Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit) { - Base *base, *basedit; + BaseLegacy *base, *basedit; Object *ob; - ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL); + ob = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL); basedit = BKE_scene_base_find(scene, obedit); base = scene->basact; @@ -464,7 +464,7 @@ static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit) return ob; } -static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob, int mode, ReportList *reports) +static int add_hook_object(Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit, Object *ob, int mode, ReportList *reports) { ModifierData *md = NULL; HookModifierData *hmd = NULL; @@ -482,7 +482,7 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob if (mode == OBJECT_ADDHOOK_NEWOB && !ob) { - ob = add_hook_object_new(bmain, scene, obedit); + ob = add_hook_object_new(bmain, scene, sl, obedit); /* transform cent to global coords for loc */ mul_v3_m4v3(ob->loc, obedit->obmat, cent); @@ -556,6 +556,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); Object *obsel = NULL; const bool use_bone = RNA_boolean_get(op->ptr, "use_bone"); @@ -580,7 +581,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (add_hook_object(bmain, scene, obedit, obsel, mode, op->reports)) { + if (add_hook_object(bmain, scene, sl, obedit, obsel, mode, op->reports)) { WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit); return OPERATOR_FINISHED; } @@ -611,9 +612,10 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); - if (add_hook_object(bmain, scene, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) { + if (add_hook_object(bmain, scene, sl, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) { WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 9710e4f843d..fe0ceb15d70 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -70,7 +70,6 @@ void OBJECT_OT_make_local(struct wmOperatorType *ot); void OBJECT_OT_make_single_user(struct wmOperatorType *ot); void OBJECT_OT_make_links_scene(struct wmOperatorType *ot); void OBJECT_OT_make_links_data(struct wmOperatorType *ot); -void OBJECT_OT_move_to_layer(struct wmOperatorType *ot); void OBJECT_OT_drop_named_material(struct wmOperatorType *ot); void OBJECT_OT_unlink_data(struct wmOperatorType *ot); @@ -78,10 +77,6 @@ void OBJECT_OT_unlink_data(struct wmOperatorType *ot); void OBJECT_OT_mode_set(struct wmOperatorType *ot); void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot); void OBJECT_OT_posemode_toggle(struct wmOperatorType *ot); -void OBJECT_OT_hide_view_set(struct wmOperatorType *ot); -void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot); -void OBJECT_OT_hide_render_set(struct wmOperatorType *ot); -void OBJECT_OT_hide_render_clear(struct wmOperatorType *ot); void OBJECT_OT_proxy_make(struct wmOperatorType *ot); void OBJECT_OT_shade_smooth(struct wmOperatorType *ot); void OBJECT_OT_shade_flat(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 06f495fb9f1..bca7a163e90 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -411,7 +411,7 @@ int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData * return 1; } -int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md) +int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, ModifierData *md) { Object *obn; ParticleSystem *psys; @@ -463,7 +463,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * if (totvert == 0) return 0; /* add new mesh */ - obn = BKE_object_add(bmain, scene, OB_MESH, NULL); + obn = BKE_object_add(bmain, scene, sl, OB_MESH, NULL); me = obn->data; me->totvert = totvert; @@ -1048,10 +1048,11 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); - if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md)) + if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, sl, ob, md)) return OPERATOR_CANCELLED; DAG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -1683,7 +1684,7 @@ static void skin_armature_bone_create(Object *skin_ob, } } -static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *skin_ob) +static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, SceneLayer *sl, Object *skin_ob) { BLI_bitmap *edges_visited; DerivedMesh *deform_dm; @@ -1706,7 +1707,7 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object * NULL, me->totvert); - arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE, NULL); + arm_ob = BKE_object_add(bmain, scene, sl, OB_ARMATURE, NULL); BKE_object_transform_copy(arm_ob, skin_ob); arm = arm_ob->data; arm->layer = 1; @@ -1765,6 +1766,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob = CTX_data_active_object(C), *arm_ob; Mesh *me = ob->data; ModifierData *skin_md; @@ -1776,7 +1778,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) } /* create new armature */ - arm_ob = modifier_skin_armature_create(bmain, scene, ob); + arm_ob = modifier_skin_armature_create(bmain, scene, sl, ob); /* add a modifier to connect the new armature to the mesh */ arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 7e7e1ef182c..19526db2ce8 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -67,10 +67,6 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_editmode_toggle); WM_operatortype_append(OBJECT_OT_posemode_toggle); WM_operatortype_append(OBJECT_OT_proxy_make); - WM_operatortype_append(OBJECT_OT_hide_view_clear); - WM_operatortype_append(OBJECT_OT_hide_view_set); - WM_operatortype_append(OBJECT_OT_hide_render_clear); - WM_operatortype_append(OBJECT_OT_hide_render_set); WM_operatortype_append(OBJECT_OT_shade_smooth); WM_operatortype_append(OBJECT_OT_shade_flat); WM_operatortype_append(OBJECT_OT_paths_calculate); @@ -90,13 +86,11 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_make_single_user); WM_operatortype_append(OBJECT_OT_make_links_scene); WM_operatortype_append(OBJECT_OT_make_links_data); - WM_operatortype_append(OBJECT_OT_move_to_layer); WM_operatortype_append(OBJECT_OT_select_random); WM_operatortype_append(OBJECT_OT_select_all); WM_operatortype_append(OBJECT_OT_select_same_group); WM_operatortype_append(OBJECT_OT_select_by_type); - WM_operatortype_append(OBJECT_OT_select_by_layer); WM_operatortype_append(OBJECT_OT_select_linked); WM_operatortype_append(OBJECT_OT_select_grouped); WM_operatortype_append(OBJECT_OT_select_mirror); @@ -382,25 +376,6 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); - RNA_boolean_set(kmi->ptr, "unselected", false); - - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "unselected", true); - - /* same as above but for rendering */ - WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_clear", HKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); - WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_CTRL, 0); - - /* conflicts, removing */ -#if 0 - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0) - RNA_boolean_set(kmi->ptr, "unselected", true); -#endif - - WM_keymap_add_item(keymap, "OBJECT_OT_move_to_layer", MKEY, KM_PRESS, 0, 0); - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "use_global", false); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index d30022c01f8..c79c702837a 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -63,6 +63,7 @@ #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_camera.h" +#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_constraint.h" #include "BKE_curve.h" @@ -74,6 +75,7 @@ #include "BKE_fcurve.h" #include "BKE_lamp.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -331,6 +333,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op) Object *ob, *gob = ED_object_active_context(C); GroupObject *go; Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); if (gob->dup_group != NULL) { go = BLI_findlink(&gob->dup_group->gobject, RNA_enum_get(op->ptr, "object")); @@ -343,13 +346,13 @@ static int make_proxy_exec(bContext *C, wmOperator *op) if (ob) { Object *newob; - Base *newbase, *oldbase = BASACT; + BaseLegacy *newbase, *oldbase = BASACT; char name[MAX_ID_NAME + 4]; BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2); /* Add new object for the proxy */ - newob = BKE_object_add(bmain, scene, OB_EMPTY, name); + newob = BKE_object_add(bmain, scene, sl, OB_EMPTY, name); /* set layers OK */ newbase = BASACT; /* BKE_object_add sets active... */ @@ -1305,119 +1308,6 @@ void OBJECT_OT_track_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", ""); } -/************************** Move to Layer Operator *****************************/ - -static unsigned int move_to_layer_init(bContext *C, wmOperator *op) -{ - int values[20], a; - unsigned int lay = 0; - - if (!RNA_struct_property_is_set(op->ptr, "layers")) { - /* note: layers are set in bases, library objects work for this */ - CTX_DATA_BEGIN (C, Base *, base, selected_bases) - { - lay |= base->lay; - } - CTX_DATA_END; - - for (a = 0; a < 20; a++) - values[a] = (lay & (1 << a)) != 0; - - RNA_boolean_set_array(op->ptr, "layers", values); - } - else { - RNA_boolean_get_array(op->ptr, "layers", values); - - for (a = 0; a < 20; a++) - if (values[a]) - lay |= (1 << a); - } - - return lay; -} - -static int move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - View3D *v3d = CTX_wm_view3d(C); - if (v3d && v3d->localvd) { - return WM_operator_confirm_message(C, op, "Move out of Local View"); - } - else { - move_to_layer_init(C, op); - return WM_operator_props_popup(C, op, event); - } -} - -static int move_to_layer_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - unsigned int lay, local; - /* bool is_lamp = false; */ /* UNUSED */ - - lay = move_to_layer_init(C, op); - lay &= 0xFFFFFF; - - if (lay == 0) return OPERATOR_CANCELLED; - - if (v3d && v3d->localvd) { - /* now we can move out of localview. */ - /* note: layers are set in bases, library objects work for this */ - CTX_DATA_BEGIN (C, Base *, base, selected_bases) - { - lay = base->lay & ~v3d->lay; - base->lay = lay; - base->object->lay = lay; - base->object->flag &= ~SELECT; - base->flag &= ~SELECT; - /* if (base->object->type == OB_LAMP) is_lamp = true; */ - } - CTX_DATA_END; - } - else { - /* normal non localview operation */ - /* note: layers are set in bases, library objects work for this */ - CTX_DATA_BEGIN (C, Base *, base, selected_bases) - { - /* upper byte is used for local view */ - local = base->lay & 0xFF000000; - base->lay = lay + local; - base->object->lay = base->lay; - /* if (base->object->type == OB_LAMP) is_lamp = true; */ - } - CTX_DATA_END; - } - - /* warning, active object may be hidden now */ - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); - WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - - DAG_relations_tag_update(bmain); - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_move_to_layer(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Move to Layer"; - ot->description = "Move the object to different layers"; - ot->idname = "OBJECT_OT_move_to_layer"; - - /* api callbacks */ - ot->invoke = move_to_layer_invoke; - ot->exec = move_to_layer_exec; - ot->poll = ED_operator_objectmode; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", ""); -} - /************************** Link to Scene Operator *****************************/ #if 0 @@ -1440,20 +1330,6 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr)) } #endif -Base *ED_object_scene_link(Scene *scene, Object *ob) -{ - Base *base; - - if (BKE_scene_base_find(scene, ob)) { - return NULL; - } - - base = BKE_scene_base_add(scene, ob); - id_us_plus(&ob->id); - - return base; -} - static int make_links_scene_exec(bContext *C, wmOperator *op) { Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene")); @@ -1473,9 +1349,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + SceneCollection *sc_to = BKE_collection_master(scene_to); CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - ED_object_scene_link(scene_to, base->object); + BKE_collection_object_add(scene_to, sc_to, base->object); } CTX_DATA_END; @@ -1531,7 +1408,6 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst static int make_links_data_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); const int type = RNA_enum_get(op->ptr, "type"); Object *ob_src; ID *obdata_id; @@ -1594,12 +1470,12 @@ static int make_links_data_exec(bContext *C, wmOperator *op) LinkNode *group_node; /* first clear groups */ - BKE_object_groups_clear(scene, base_dst, ob_dst); + BKE_object_groups_clear(ob_dst); /* now add in the groups from the link nodes */ for (group_node = ob_groups; group_node; group_node = group_node->next) { if (ob_dst->dup_group != group_node->link) { - BKE_group_object_add(group_node->link, ob_dst, scene, base_dst); + BKE_group_object_add(group_node->link, ob_dst); } else { is_cycle = true; @@ -1732,48 +1608,82 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot) /**************************** Make Single User ********************************/ +static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups) +{ + if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) { + /* base gets copy of object */ + Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); + + if (copy_groups) { + if (ob->flag & OB_FROMGROUP) { + obn->flag |= OB_FROMGROUP; + } + } + else { + /* copy already clears */ + } + /* remap gpencil parenting */ + + if (scene->gpd) { + bGPdata *gpd = scene->gpd; + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->parent == ob) { + gpl->parent = obn; + } + } + } + + id_us_min(&ob->id); + return obn; + } + return NULL; +} + +static void libblock_relink_scene_collection(SceneCollection *sc) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + BKE_libblock_relink_to_newid(link->data); + } + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + libblock_relink_scene_collection(nsc); + } +} + +static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + Object *ob = link->data; + /* an object may be in more than one collection */ + if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) { + link->data = single_object_users_object(bmain, scene, link->data, copy_groups); + } + } + + /* we reset filter objects because they should be regenerated after this */ + BLI_freelistN(&sc->filter_objects); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups); + } +} + /* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups) { - Base *base; - Object *ob, *obn; Group *group, *groupn; GroupObject *go; clear_sca_new_poins(); /* BGE logic */ - /* duplicate (must set newid) */ - for (base = FIRSTBASE; base; base = base->next) { - ob = base->object; - - if ((base->flag & flag) == flag) { - if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) { - /* base gets copy of object */ - base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); - - if (copy_groups) { - if (ob->flag & OB_FROMGROUP) { - obn->flag |= OB_FROMGROUP; - } - } - else { - /* copy already clears */ - } - /* remap gpencil parenting */ - - if (scene->gpd) { - bGPdata *gpd = scene->gpd; - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->parent == ob) { - gpl->parent = obn; - } - } - } - - base->flag = obn->flag; + /* duplicate all the objects of the scene */ + SceneCollection *msc = BKE_collection_master(scene); + single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups); - id_us_min(&ob->id); - } + /* loop over SceneLayers and assign the pointers accordingly */ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + ID_NEW_REMAP(base->object); } } @@ -1806,27 +1716,29 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in if (v3d) ID_NEW_REMAP(v3d->camera); /* object and group pointers */ - for (base = FIRSTBASE; base; base = base->next) { - BKE_libblock_relink_to_newid(&base->object->id); - } + libblock_relink_scene_collection(msc); set_sca_new_poins(); + + /* TODO redo filter */ + TODO_LAYER_SYNC_FILTER } /* not an especially efficient function, only added so the single user * button can be functional.*/ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob) { - Base *base; - const bool copy_groups = false; - - for (base = FIRSTBASE; base; base = base->next) { - if (base->object == ob) base->flag |= OB_DONE; - else base->flag &= ~OB_DONE; + Object *ob_iter; + FOREACH_SCENE_OBJECT(scene, ob_iter) + { + ob_iter->flag &= ~OB_DONE; } + FOREACH_SCENE_OBJECT_END - single_object_users(bmain, scene, NULL, OB_DONE, copy_groups); + /* tag only the one object */ + ob->flag |= OB_DONE; + single_object_users(bmain, scene, NULL, OB_DONE, false); BKE_main_id_clear_newpoins(bmain); } @@ -1857,15 +1769,17 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) Lamp *la; Curve *cu; /* Camera *cam; */ - Base *base; + BaseLegacy *base; Mesh *me; Lattice *lat; ID *id; int a; + TODO_LAYER; /* need to use scene->collection base instead of scene->bases */ + for (base = FIRSTBASE; base; base = base->next) { ob = base->object; - if (!ID_IS_LINKED_DATABLOCK(ob) && (base->flag & flag) == flag) { + if (!ID_IS_LINKED_DATABLOCK(ob) && (base->flag_legacy & flag) == flag) { id = ob->data; if (id && id->us > 1 && !ID_IS_LINKED_DATABLOCK(id)) { @@ -1939,31 +1853,27 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) } } -static void single_object_action_users(Scene *scene, const int flag) +static void single_object_action_users(Scene *scene, SceneLayer *sl, const int flag) { Object *ob; - Base *base; - for (base = FIRSTBASE; base; base = base->next) { - ob = base->object; - if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) { + FOREACH_OBJECT_FLAG(scene, sl, flag, ob) + if (!ID_IS_LINKED_DATABLOCK(ob)) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); BKE_animdata_copy_id_action(&ob->id, false); } - } + FOREACH_OBJECT_FLAG_END } -static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bool do_textures) +static void single_mat_users(Main *bmain, Scene *scene, SceneLayer *sl, const int flag, const bool do_textures) { - Object *ob; - Base *base; Material *ma, *man; Tex *tex; int a, b; - for (base = FIRSTBASE; base; base = base->next) { - ob = base->object; - if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) { + Object *ob; + FOREACH_OBJECT_FLAG(scene, sl, flag, ob) + if (!ID_IS_LINKED_DATABLOCK(ob)) { for (a = 1; a <= ob->totcol; a++) { ma = give_current_material(ob, a); if (ma) { @@ -1992,7 +1902,7 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo } } } - } + FOREACH_OBJECT_FLAG_END } static void do_single_tex_user(Main *bmain, Tex **from) @@ -2096,7 +2006,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo if (full) { single_obdata_users(bmain, scene, 0); - single_object_action_users(scene, 0); + single_object_action_users(scene, NULL, 0); single_mat_users_expand(bmain); single_tex_users_expand(bmain); } @@ -2133,7 +2043,7 @@ enum { }; static int tag_localizable_looper( - void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cd_flag)) + void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cb_flag)) { if (*id_pointer) { (*id_pointer)->tag &= ~LIB_TAG_DOIT; @@ -2170,12 +2080,12 @@ static void tag_localizable_objects(bContext *C, const int mode) */ for (Object *object = bmain->object.first; object; object = object->id.next) { if ((object->id.tag & LIB_TAG_DOIT) == 0) { - BKE_library_foreach_ID_link(&object->id, tag_localizable_looper, NULL, IDWALK_READONLY); + BKE_library_foreach_ID_link(NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY); } if (object->data) { ID *data_id = (ID *) object->data; if ((data_id->tag & LIB_TAG_DOIT) == 0) { - BKE_library_foreach_ID_link(data_id, tag_localizable_looper, NULL, IDWALK_READONLY); + BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY); } } } @@ -2194,13 +2104,13 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene) for (ob = bmain->object.first; ob; ob = ob->id.next) { if (ID_IS_LINKED_DATABLOCK(ob) && (ob->id.us == 0)) { - Base *base; + BaseLegacy *base; id_us_plus(&ob->id); base = BKE_scene_base_add(scene, ob); - base->flag |= SELECT; - base->object->flag = base->flag; + base->flag_legacy |= SELECT; + BKE_scene_base_flag_sync_from_base(base); DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); changed = true; @@ -2366,13 +2276,20 @@ static int make_single_user_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */ const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0; const bool copy_groups = false; bool update_deps = false; if (RNA_boolean_get(op->ptr, "object")) { - single_object_users(bmain, scene, v3d, flag, copy_groups); + if (flag == SELECT) { + BKE_scene_layer_selected_objects_tag(sl, OB_DONE); + single_object_users(bmain, scene, v3d, OB_DONE, copy_groups); + } + else { + single_object_users(bmain, scene, v3d, 0, copy_groups); + } /* needed since object relationships may have changed */ update_deps = true; @@ -2383,7 +2300,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) } if (RNA_boolean_get(op->ptr, "material")) { - single_mat_users(bmain, scene, flag, RNA_boolean_get(op->ptr, "texture")); + single_mat_users(bmain, scene, sl, flag, RNA_boolean_get(op->ptr, "texture")); } #if 0 /* can't do this separate from materials */ @@ -2391,7 +2308,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) single_mat_users(scene, flag, true); #endif if (RNA_boolean_get(op->ptr, "animation")) { - single_object_action_users(scene, flag); + single_object_action_users(scene, sl, flag); } BKE_main_id_clear_newpoins(bmain); @@ -2438,7 +2355,7 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - Base *base = ED_view3d_give_base_under_cursor(C, event->mval); + BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval); Material *ma; char name[MAX_ID_NAME - 2]; diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index b5131df3eaa..37232456f48 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -52,6 +52,7 @@ #include "BKE_context.h" #include "BKE_group.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_particle.h" @@ -86,22 +87,22 @@ /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or * or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */ -void ED_base_object_select(Base *base, short mode) +void ED_base_object_select(BaseLegacy *base, short mode) { if (base) { if (mode == BA_SELECT) { if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) - base->flag |= SELECT; + base->flag_legacy |= SELECT; } else if (mode == BA_DESELECT) { - base->flag &= ~SELECT; + base->flag_legacy &= ~SELECT; } - base->object->flag = base->flag; + BKE_scene_base_flag_sync_from_base(base); } } /* also to set active NULL */ -void ED_base_object_activate(bContext *C, Base *base) +void ED_base_object_activate(bContext *C, BaseLegacy *base) { Scene *scene = CTX_data_scene(C); @@ -119,6 +120,33 @@ void ED_base_object_activate(bContext *C, Base *base) WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL); } +void ED_object_base_select(Base *base, short mode) +{ + if (base) { + if (mode == BA_SELECT) { + if ((base->flag & BASE_SELECTABLED) != 0) { + base->flag |= BASE_SELECTED; + } + } + else if (mode == BA_DESELECT) { + base->flag &= ~BASE_SELECTED; + } + } +} + +void ED_object_base_activate(bContext *C, Base *base) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + sl->basact = base; + + if (base) { + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, sl); + } + else { + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL); + } +} + /********************** Selection Operators **********************/ static int objects_selectable_poll(bContext *C) @@ -147,7 +175,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); } CTX_DATA_END; } @@ -155,7 +183,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { if (base->object->type == obtype) { - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); } } CTX_DATA_END; @@ -210,38 +238,15 @@ static EnumPropertyItem prop_select_linked_types[] = { {0, NULL, 0, NULL, NULL} }; -// XXX old animation system -#if 0 -static int object_select_all_by_ipo(bContext *C, Ipo *ipo) -{ - bool changed = false; - - CTX_DATA_BEGIN (C, Base *, base, visible_bases) - { - if (base->object->ipo == ipo) { - base->flag |= SELECT; - base->object->flag = base->flag; - - changed = true; - } - } - CTX_DATA_END; - - return changed; -} -#endif - static bool object_select_all_by_obdata(bContext *C, void *obdata) { bool changed = false; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { if (base->object->data == obdata) { - base->flag |= SELECT; - base->object->flag = base->flag; - + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -257,7 +262,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { Object *ob = base->object; Material *mat1; int a, b; @@ -267,7 +272,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, if (!use_texture) { if (mat1 == mat) { - base->flag |= SELECT; + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -275,7 +280,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, for (b = 0; b < MAX_MTEX; b++) { if (mat1->mtex[b]) { if (tex == mat1->mtex[b]->tex) { - base->flag |= SELECT; + ED_object_base_select(base, BA_SELECT); changed = true; break; } @@ -283,8 +288,6 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, } } } - - base->object->flag = base->flag; } } CTX_DATA_END; @@ -299,12 +302,10 @@ static bool object_select_all_by_dup_group(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL; if (dup_group == dup_group_other) { - base->flag |= SELECT; - base->object->flag = base->flag; - + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -321,23 +322,21 @@ static bool object_select_all_by_particle(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { /* loop through other particles*/ ParticleSystem *psys; for (psys = base->object->particlesystem.first; psys; psys = psys->next) { if (psys->part == psys_act->part) { - base->flag |= SELECT; + ED_object_base_select(base, BA_SELECT); changed = true; break; } - if (base->flag & SELECT) { + if (base->flag & BASE_SELECTED) { break; } } - - base->object->flag = base->flag; } } CTX_DATA_END; @@ -351,11 +350,9 @@ static bool object_select_all_by_library(bContext *C, Library *lib) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { if (lib == base->object->id.lib) { - base->flag |= SELECT; - base->object->flag = base->flag; - + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -371,11 +368,9 @@ static bool object_select_all_by_library_obdata(bContext *C, Library *lib) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if ((base->flag & SELECT) == 0) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { if (base->object->data && lib == ((ID *)base->object->data)->lib) { - base->flag |= SELECT; - base->object->flag = base->flag; - + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -408,6 +403,7 @@ void ED_object_select_linked_by_id(bContext *C, ID *id) static int object_select_linked_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob; int nr = RNA_enum_get(op->ptr, "type"); bool changed = false, extend; @@ -417,12 +413,12 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); } CTX_DATA_END; } - ob = OBACT; + ob = OBACT_NEW; if (ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; @@ -517,7 +513,7 @@ enum { OBJECT_GRPSEL_PARENT = 2, OBJECT_GRPSEL_SIBLINGS = 3, OBJECT_GRPSEL_TYPE = 4, - OBJECT_GRPSEL_LAYER = 5, + /*OBJECT_GRPSEL_LAYER = 5,*/ OBJECT_GRPSEL_GROUP = 6, OBJECT_GRPSEL_HOOK = 7, OBJECT_GRPSEL_PASS = 8, @@ -533,7 +529,6 @@ static EnumPropertyItem prop_select_grouped_types[] = { {OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""}, {OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"}, {OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"}, - {OBJECT_GRPSEL_LAYER, "LAYER", 0, "Layer", "Shared layers"}, {OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"}, {OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""}, {OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"}, @@ -551,13 +546,14 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { if (ob == base->object->parent) { - if (!(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((base->flag & BASE_SELECTED) == 0) { + ED_object_base_select(base, BA_SELECT); changed = true; } - if (recursive) + if (recursive) { changed |= select_grouped_children(C, base->object, 1); + } } } CTX_DATA_END; @@ -566,20 +562,21 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */ { - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); - - bool changed = false; Base *baspar, *basact = CTX_data_active_base(C); + bool changed = false; - if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */ + if (!basact || !(basact->object->parent)) { + return 0; /* we know OBACT is valid */ + } - baspar = BKE_scene_base_find(scene, basact->object->parent); + baspar = BKE_scene_layer_base_find(sl, basact->object->parent); /* can be NULL if parent in other scene */ if (baspar && BASE_SELECTABLE(v3d, baspar)) { - ED_base_object_select(baspar, BA_SELECT); - ED_base_object_activate(C, baspar); + ED_object_base_select(baspar, BA_SELECT); + ED_object_base_activate(C, baspar); changed = true; } return changed; @@ -608,9 +605,11 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in group = ob_groups[0]; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) { - ED_base_object_select(base, BA_SELECT); - changed = true; + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (BKE_group_object_exists(group, base->object)) { + ED_object_base_select(base, BA_SELECT); + changed = true; + } } } CTX_DATA_END; @@ -636,7 +635,7 @@ static bool select_grouped_object_hooks(bContext *C, Object *ob) View3D *v3d = CTX_wm_view3d(C); bool changed = false; - Base *base; + BaseLegacy *base; ModifierData *md; HookModifierData *hmd; @@ -663,8 +662,8 @@ static bool select_grouped_siblings(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if ((base->object->parent == ob->parent) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -681,8 +680,8 @@ static bool select_grouped_lamptype(bContext *C, Object *ob) { if (base->object->type == OB_LAMP) { Lamp *la_test = base->object->data; - if ((la->type == la_test->type) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -696,23 +695,8 @@ static bool select_grouped_type(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if ((base->object->type == ob->type) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); - changed = true; - } - } - CTX_DATA_END; - return changed; -} - -static bool select_grouped_layer(bContext *C, Object *ob) -{ - bool changed = false; - - CTX_DATA_BEGIN (C, Base *, base, selectable_bases) - { - if ((base->lay & ob->lay) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -726,8 +710,8 @@ static bool select_grouped_index_object(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if ((base->object->index == ob->index) && !(base->flag & SELECT)) { - ED_base_object_select(base, BA_SELECT); + if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -741,8 +725,8 @@ static bool select_grouped_color(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) { - ED_base_object_select(base, BA_SELECT); + if (((base->flag & BASE_SELECTED) == 0) && (compare_v3v3(base->object->col, ob->col, 0.005f))) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -768,8 +752,8 @@ static bool select_grouped_gameprops(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) { - ED_base_object_select(base, BA_SELECT); + if (((base->flag & BASE_SELECTED) == 0) && (objects_share_gameprop(base->object, ob))) { + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -807,7 +791,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { /* only check for this object if it isn't selected already, to limit time wasted */ - if ((base->flag & SELECT) == 0) { + if ((base->flag & BASE_SELECTED) == 0) { KS_Path *ksp; /* this is the slow way... we could end up with > 500 items here, @@ -816,7 +800,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList for (ksp = ks->paths.first; ksp; ksp = ksp->next) { /* if id matches, select then stop looping (match found) */ if (ksp->id == (ID *)base->object) { - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); changed = true; break; } @@ -831,6 +815,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList static int object_select_grouped_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob; const int type = RNA_enum_get(op->ptr, "type"); bool changed = false, extend; @@ -840,13 +825,13 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); changed = true; } CTX_DATA_END; } - ob = OBACT; + ob = OBACT_NEW; if (ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; @@ -868,9 +853,6 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) case OBJECT_GRPSEL_TYPE: changed |= select_grouped_type(C, ob); break; - case OBJECT_GRPSEL_LAYER: - changed |= select_grouped_layer(C, ob); - break; case OBJECT_GRPSEL_GROUP: changed |= select_grouped_group(C, ob); break; @@ -928,85 +910,6 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", ""); } -/************************* Select by Layer **********************/ -enum { - OB_SEL_LAYERMATCH_EXACT = 1, - OB_SEL_LAYERMATCH_SHARED = 2, -}; - -static int object_select_by_layer_exec(bContext *C, wmOperator *op) -{ - unsigned int layernum; - bool extend; - int match; - - extend = RNA_boolean_get(op->ptr, "extend"); - layernum = RNA_int_get(op->ptr, "layers"); - match = RNA_enum_get(op->ptr, "match"); - - if (extend == false) { - CTX_DATA_BEGIN (C, Base *, base, visible_bases) - { - ED_base_object_select(base, BA_DESELECT); - } - CTX_DATA_END; - } - - CTX_DATA_BEGIN (C, Base *, base, visible_bases) - { - bool ok = false; - - switch (match) { - case OB_SEL_LAYERMATCH_EXACT: - /* Mask out bits used for local view, only work on real layer ones, see T45783. */ - ok = ((base->lay & ((1 << 20) - 1)) == (1 << (layernum - 1))); - break; - case OB_SEL_LAYERMATCH_SHARED: - ok = (base->lay & (1 << (layernum - 1))) != 0; - break; - default: - break; - } - - if (ok) { - ED_base_object_select(base, BA_SELECT); - } - } - CTX_DATA_END; - - /* undo? */ - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_select_by_layer(wmOperatorType *ot) -{ - static EnumPropertyItem match_items[] = { - {OB_SEL_LAYERMATCH_EXACT, "EXACT", 0, "Exact Match", ""}, - {OB_SEL_LAYERMATCH_SHARED, "SHARED", 0, "Shared Layers", ""}, - {0, NULL, 0, NULL, NULL} - }; - - /* identifiers */ - ot->name = "Select by Layer"; - ot->description = "Select all visible objects on a layer"; - ot->idname = "OBJECT_OT_select_by_layer"; - - /* api callbacks */ - /*ot->invoke = XXX - need a int grid popup*/ - ot->exec = object_select_by_layer_exec; - ot->poll = objects_selectable_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_enum(ot->srna, "match", match_items, OB_SEL_LAYERMATCH_EXACT, "Match", ""); - RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first"); - RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20); -} - /**************************** (De)select All ****************************/ static int object_select_all_exec(bContext *C, wmOperator *op) @@ -1020,7 +923,7 @@ static int object_select_all_exec(bContext *C, wmOperator *op) action = SEL_SELECT; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (base->flag & SELECT) { + if ((base->flag & BASE_SELECTED) != 0) { action = SEL_DESELECT; break; } @@ -1032,17 +935,17 @@ static int object_select_all_exec(bContext *C, wmOperator *op) { switch (action) { case SEL_SELECT: - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); break; case SEL_DESELECT: - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); break; case SEL_INVERT: - if (base->flag & SELECT) { - ED_base_object_select(base, BA_DESELECT); + if ((base->flag & BASE_SELECTED) != 0) { + ED_object_base_select(base, BA_DESELECT); } else { - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); } break; } @@ -1092,8 +995,11 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) - ED_base_object_select(base, BA_SELECT); + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (BKE_group_object_exists(group, base->object)) { + ED_object_base_select(base, BA_SELECT); + } + } } CTX_DATA_END; @@ -1124,6 +1030,7 @@ void OBJECT_OT_select_same_group(wmOperatorType *ot) static int object_select_mirror_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); bool extend; extend = RNA_boolean_get(op->ptr, "extend"); @@ -1137,15 +1044,15 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) if (!STREQ(name_flip, primbase->object->id.name + 2)) { Object *ob = (Object *)BKE_libblock_find_name(ID_OB, name_flip); if (ob) { - Base *secbase = BKE_scene_base_find(scene, ob); + Base *secbase = BKE_scene_layer_base_find(sl, ob); if (secbase) { - ED_base_object_select(secbase, BA_SELECT); + ED_object_base_select(secbase, BA_SELECT); } } } - if (extend == false) ED_base_object_select(primbase, BA_DESELECT); + if (extend == false) ED_object_base_select(primbase, BA_DESELECT); } CTX_DATA_END; @@ -1180,9 +1087,9 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot) static bool object_select_more_less(bContext *C, const bool select) { - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = sl->object_bases.first; base; base = base->next) { Object *ob = base->object; ob->flag &= ~OB_DONE; ob->id.tag &= ~LIB_TAG_DOIT; @@ -1223,7 +1130,7 @@ static bool object_select_more_less(bContext *C, const bool select) Base *base = ctx_base->ptr.data; Object *ob = base->object; if ((ob->id.tag & LIB_TAG_DOIT) && ((ob->flag & SELECT) != select_flag)) { - ED_base_object_select(base, select_mode); + ED_object_base_select(base, select_mode); changed = true; } } @@ -1305,7 +1212,7 @@ static int object_select_random_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { if (BLI_rng_get_float(rng) < randfac) { - ED_base_object_select(base, select); + ED_object_base_select(base, select); } } CTX_DATA_END; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 56f59dca9a1..67ef4515c18 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -363,8 +363,8 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot /* matching index only */ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) { - MDeformVert **dvert_array_from, **dvf; - MDeformVert **dvert_array, **dv; + MDeformVert **dvert_array_from = NULL, **dvf; + MDeformVert **dvert_array = NULL, **dv; int dvert_tot_from; int dvert_tot; int i; @@ -375,26 +375,30 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) if (ob == ob_from) return true; - ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false); - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); - - if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) { + /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */ + if (ob->data != ob_from->data) { + ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false); ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); - new_vgroup = true; - } - if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) { + if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) { + ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); + new_vgroup = true; + } - if (dvert_array) MEM_freeN(dvert_array); - if (dvert_array_from) MEM_freeN(dvert_array_from); + if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) { + if (dvert_array) + MEM_freeN(dvert_array); + if (dvert_array_from) + MEM_freeN(dvert_array_from); - if (new_vgroup == true) { - /* free the newly added vgroup since it wasn't compatible */ - BKE_object_defgroup_remove_all(ob); - } + if (new_vgroup == true) { + /* free the newly added vgroup since it wasn't compatible */ + BKE_object_defgroup_remove_all(ob); + } - /* if true: both are 0 and nothing needs changing, consider this a success */ - return (dvert_tot == dvert_tot_from); + /* if true: both are 0 and nothing needs changing, consider this a success */ + return (dvert_tot == dvert_tot_from); + } } /* do the copy */ @@ -412,22 +416,23 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) MEM_freeN(remap); } - dvf = dvert_array_from; - dv = dvert_array; + if (dvert_array_from != NULL && dvert_array != NULL) { + dvf = dvert_array_from; + dv = dvert_array; - for (i = 0; i < dvert_tot; i++, dvf++, dv++) { - if ((*dv)->dw) - MEM_freeN((*dv)->dw); + for (i = 0; i < dvert_tot; i++, dvf++, dv++) { + MEM_SAFE_FREE((*dv)->dw); + *(*dv) = *(*dvf); - *(*dv) = *(*dvf); + if ((*dv)->dw) { + (*dv)->dw = MEM_dupallocN((*dv)->dw); + } + } - if ((*dv)->dw) - (*dv)->dw = MEM_dupallocN((*dv)->dw); + MEM_freeN(dvert_array); + MEM_freeN(dvert_array_from); } - MEM_freeN(dvert_array); - MEM_freeN(dvert_array_from); - return true; } @@ -3296,7 +3301,7 @@ static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Object *ob = ED_object_context(C); - Base *base; + BaseLegacy *base; int retval = OPERATOR_CANCELLED; for (base = scene->base.first; base; base = base->next) { diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index b5adf38527b..bb3375b91a6 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -329,7 +329,7 @@ static void free_all_fluidobject_channels(ListBase *fobjects) static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects) { Scene *scene = CTX_data_scene(C); - Base *base; + BaseLegacy *base; int i; int length = channels->length; float eval_time; @@ -572,7 +572,7 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDomain) { - Base *base; + BaseLegacy *base; Object *newdomain = NULL; int channelObjCount = 0; int fluidInputCount = 0; diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index e81aa584586..4b19e235d9c 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -254,7 +254,7 @@ static void ptcache_bake_cancel(bContext *C, wmOperator *op) static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene= CTX_data_scene(C); - Base *base; + BaseLegacy *base; PTCacheID *pid; ListBase pidlist; diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index 1bfc162a331..b7be31602d9 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -89,7 +89,7 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE; /* add constraint to rigid body constraint group */ - BKE_group_object_add(rbw->constraints, ob, scene, NULL); + BKE_group_object_add(rbw->constraints, ob); DAG_relations_tag_update(bmain); DAG_id_tag_update(&ob->id, OB_RECALC_OB); @@ -102,7 +102,7 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob) BKE_rigidbody_remove_constraint(scene, ob); if (rbw) - BKE_group_object_unlink(rbw->constraints, ob, scene, NULL); + BKE_group_object_unlink(rbw->constraints, ob); DAG_relations_tag_update(bmain); DAG_id_tag_update(&ob->id, OB_RECALC_OB); diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 30597d95497..c9e32fa5194 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -119,7 +119,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE; /* add object to rigid body group */ - BKE_group_object_add(rbw->group, ob, scene, NULL); + BKE_group_object_add(rbw->group, ob); DAG_relations_tag_update(bmain); DAG_id_tag_update(&ob->id, OB_RECALC_OB); @@ -133,7 +133,7 @@ void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob) BKE_rigidbody_remove_object(scene, ob); if (rbw) - BKE_group_object_unlink(rbw->group, ob, scene, NULL); + BKE_group_object_unlink(rbw->group, ob); DAG_relations_tag_update(bmain); DAG_id_tag_update(&ob->id, OB_RECALC_OB); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 8c5d25ad44d..07f4679a32a 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -784,7 +784,7 @@ static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay) { Object *object; Scene *sce_iter; - Base *base; + BaseLegacy *base; for (object = bmain->object.first; object; object = object->id.next) { object->id.tag |= LIB_TAG_DOIT; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index c48e142f233..cb54f0efd85 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -276,7 +276,7 @@ static Scene *preview_get_scene(Main *pr_main) static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp) { Scene *sce; - Base *base; + BaseLegacy *base; Main *pr_main = sp->pr_main; memcpy(pr_main->name, bmain->name, sizeof(pr_main->name)); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 837573ad175..986e9623fef 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -54,6 +54,7 @@ #include "BKE_font.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_linestyle.h" #include "BKE_main.h" @@ -626,11 +627,11 @@ static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - BKE_scene_add_render_layer(scene, NULL); - scene->r.actlay = BLI_listbase_count(&scene->r.layers) - 1; + BKE_scene_layer_add(scene, NULL); + scene->active_layer = BLI_listbase_count(&scene->render_layers) - 1; DAG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); return OPERATOR_FINISHED; } @@ -652,10 +653,11 @@ void SCENE_OT_render_layer_add(wmOperatorType *ot) static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *rl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *sl = BKE_scene_layer_active(scene); - if (!BKE_scene_remove_render_layer(CTX_data_main(C), scene, rl)) + if (!BKE_scene_layer_remove(CTX_data_main(C), scene, sl)) { return OPERATOR_CANCELLED; + } DAG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 7f91cd42d27..dbecbb974f7 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -373,41 +373,37 @@ static void region_draw_azone_tab_plus(AZone *az) static void region_draw_azone_tab(AZone *az) { - float col[3]; + float col[4], black[4] = {0.0f, 0.0f, 0.0f, 1.0f}; glEnable(GL_BLEND); UI_GetThemeColor3fv(TH_HEADER, col); - glColor4f(col[0], col[1], col[2], 0.5f); - + col[3] = 0.5f; + /* add code to draw region hidden as 'too small' */ switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_RB_ALPHA); - UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f); - glColor4ub(0, 0, 0, 255); - UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f); + UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col); + UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f, black); break; case AE_BOTTOM_TO_TOPLEFT: UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA); - UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f); - glColor4ub(0, 0, 0, 255); - UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f); + UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col); + UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f, black); break; case AE_LEFT_TO_TOPRIGHT: UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA); - UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f); - glColor4ub(0, 0, 0, 255); - UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f); + UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col); + UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, black); break; case AE_RIGHT_TO_TOPLEFT: UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_RB_ALPHA); - UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f); - glColor4ub(0, 0, 0, 255); - UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f); + UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col); + UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, black); break; } @@ -557,7 +553,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar) UI_ThemeClearColor(TH_HEADER); glClear(GL_COLOR_BUFFER_BIT); - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(BLF_default(), TH_TEXT); BLF_draw_default(UI_UNIT_X, 0.4f * UI_UNIT_Y, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX); } else if (at->draw) { @@ -2161,7 +2157,7 @@ void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], con glDisable(GL_BLEND); /* text */ - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(fontid, TH_TEXT_HI); BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(fontid, BLF_CLIPPING); BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit, 0.0f); @@ -2369,7 +2365,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame, BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(blf_mono_font, BLF_CLIPPING); - UI_ThemeColor(TH_METADATA_TEXT); + UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT); metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true); BLF_disable(blf_mono_font, BLF_CLIPPING); @@ -2394,7 +2390,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame, BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(blf_mono_font, BLF_CLIPPING); - UI_ThemeColor(TH_METADATA_TEXT); + UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT); metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false); BLF_disable(blf_mono_font, BLF_CLIPPING); @@ -2547,7 +2543,7 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f); immUnbindProgram(); - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(fontid, TH_TEXT); BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f); BLF_draw(fontid, numstr, sizeof(numstr)); } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 23b3af26f50..14d877a8d69 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -75,6 +75,18 @@ void fdrawbox(float x1, float y1, float x2, float y2) glEnd(); } +void fdrawbox_filled(float x1, float y1, float x2, float y2) +{ + glBegin(GL_POLYGON); + + glVertex2f(x1, y1); + glVertex2f(x1, y2); + glVertex2f(x2, y2); + glVertex2f(x2, y1); + + glEnd(); +} + void fdrawcheckerboard(float x1, float y1, float x2, float y2) /* DEPRECATED */ { unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50}; @@ -323,6 +335,7 @@ static int get_cached_work_texture(int *r_w, int *r_h) return texid; } +/* DEPRECATED: use immDrawPixelsTexScaled_clipping instead */ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY, @@ -458,6 +471,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } +/* DEPRECATED: use immDrawPixelsTexScaled instead */ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY) @@ -466,12 +480,14 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f); } +/* DEPRECATED: use immDrawPixelsTex instead */ void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect) { glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f); } +/* DEPRECATED: use immDrawPixelsTex_clipping instead */ void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y) @@ -585,6 +601,176 @@ void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int t 0.0f, 0.0f, 0.0f, 0.0f); } +/* TODO this is utterly slow and need some love + * but in the meantime it's not using deprecated api */ +void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, + int format, int type, int zoomfilter, void *rect, + float scaleX, float scaleY, + float clip_min_x, float clip_min_y, + float clip_max_x, float clip_max_y, + float xzoom, float yzoom, float color[4]) +{ + unsigned char *uc_rect = (unsigned char *) rect; + const float *f_rect = (float *)rect; + int subpart_x, subpart_y, tex_w, tex_h; + int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y; + int texid = get_cached_work_texture(&tex_w, &tex_h); + int components; + const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y)); + + /* Specify the color outside this function, and tex will modulate it. + * This is useful for changing alpha without using glPixelTransferf() + */ + glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w); + glBindTexture(GL_TEXTURE_2D, texid); + + /* don't want nasty border artifacts */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter); + + /* setup seamless 2=on, 0=off */ + seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0; + + offset_x = tex_w - seamless; + offset_y = tex_h - seamless; + + nsubparts_x = (img_w + (offset_x - 1)) / (offset_x); + nsubparts_y = (img_h + (offset_y - 1)) / (offset_y); + + if (format == GL_RGBA) + components = 4; + else if (format == GL_RGB) + components = 3; + else if (format == GL_RED) + components = 1; + else { + BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled"); + return; + } + + if (type == GL_FLOAT) { + /* need to set internal format to higher range float */ + + /* NOTE: this could fail on some drivers, like mesa, + * but currently this code is only used by color + * management stuff which already checks on whether + * it's possible to use GL_RGBA16F_ARB + */ + + /* TODO viewport : remove extension */ + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL); + } + else { + /* switch to 8bit RGBA for byte buffer */ + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL); + } + + VertexFormat *vert_format = immVertexFormat(); + unsigned int pos = add_attrib(vert_format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned int texco = add_attrib(vert_format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immUniform4fv("color", color); + immUniform1i("image", 0); + + for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) { + for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) { + int remainder_x = img_w - subpart_x * offset_x; + int remainder_y = img_h - subpart_y * offset_y; + int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w; + int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h; + int offset_left = (seamless && subpart_x != 0) ? 1 : 0; + int offset_bot = (seamless && subpart_y != 0) ? 1 : 0; + int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0; + int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0; + float rast_x = x + subpart_x * offset_x * xzoom; + float rast_y = y + subpart_y * offset_y * yzoom; + /* check if we already got these because we always get 2 more when doing seamless */ + if (subpart_w <= seamless || subpart_h <= seamless) + continue; + + if (use_clipping) { + if (rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX < clip_min_x || + rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY < clip_min_y) + { + continue; + } + if (rast_x + (float)offset_left * xzoom > clip_max_x || + rast_y + (float)offset_bot * yzoom > clip_max_y) + { + continue; + } + } + + if (type == GL_FLOAT) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]); + + /* add an extra border of pixels so linear looks ok at edges of full image */ + if (subpart_w < tex_w) + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + if (subpart_h < tex_h) + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); + if (subpart_w < tex_w && subpart_h < tex_h) + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + } + else { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]); + + if (subpart_w < tex_w) + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + if (subpart_h < tex_h) + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); + if (subpart_w < tex_w && subpart_h < tex_h) + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + } + + immBegin(GL_TRIANGLE_FAN, 4); + immAttrib2f(texco, (float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h); + immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom); + + immAttrib2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h); + immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom); + + immAttrib2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h); + immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); + + immAttrib2f(texco, (float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h); + immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); + immEnd(); + } + } + + immUnbindProgram(); + + glBindTexture(GL_TEXTURE_2D, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +} + +void immDrawPixelsTexScaled(float x, float y, int img_w, int img_h, + int format, int type, int zoomfilter, void *rect, + float scaleX, float scaleY, float xzoom, float yzoom, float color[4]) +{ + immDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, + scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color); +} + +void immDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, + float xzoom, float yzoom, float color[4]) +{ + immDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f, + 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color); +} + +void immDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, + int format, int type, int zoomfilter, void *rect, + float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y, + float xzoom, float yzoom, float color[4]) +{ + immDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f, + clip_min_x, clip_min_y, clip_max_x, clip_max_y, xzoom, yzoom, color); +} + /* 2D Drawing Assistance */ void glaDefine2DArea(rcti *screen_rect) diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index c165bbfd301..c82a210725c 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -47,6 +47,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_gpencil.h" +#include "BKE_layer.h" #include "BKE_screen.h" #include "BKE_sequencer.h" @@ -60,20 +61,8 @@ #include "screen_intern.h" -static unsigned int context_layers(bScreen *sc, Scene *scene, ScrArea *sa_ctx) -{ - /* needed for 'USE_ALLSELECT' define, otherwise we end up editing off-screen layers. */ - if (sc && sa_ctx && (sa_ctx->spacetype == SPACE_BUTS)) { - const unsigned int lay = BKE_screen_view3d_layer_all(sc); - if (lay) { - return lay; - } - } - return scene->lay; -} - const char *screen_context_dir[] = { - "scene", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", + "scene", "render_layer", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", "selected_objects", "selected_bases", "editable_objects", "editable_bases", "selected_editable_objects", "selected_editable_bases", @@ -95,17 +84,9 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bScreen *sc = CTX_wm_screen(C); ScrArea *sa = CTX_wm_area(C); Scene *scene = sc->scene; - Base *base; - -#if 0 /* Using the context breaks adding objects in the UI. Need to find out why - campbell */ - Object *obact = CTX_data_active_object(C); - Object *obedit = CTX_data_edit_object(C); - base = CTX_data_active_base(C); -#else + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = scene->obedit; - Object *obact = OBACT; - base = BASACT; -#endif + Object *obact = sl->basact ? sl->basact->object : NULL; if (CTX_data_dir(member)) { CTX_data_dir_set(result, screen_context_dir); @@ -115,84 +96,105 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult CTX_data_id_pointer_set(result, &scene->id); return 1; } - else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool visible_objects = CTX_data_equals(member, "visible_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) { - if (visible_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + else if (CTX_data_equals(member, "visible_objects")) { + Object *ob; + FOREACH_VISIBLE_OBJECT(sl, ob) + { + CTX_data_id_list_add(result, &ob->id); + } + FOREACH_VISIBLE_BASE_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selectable_objects")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + CTX_data_id_list_add(result, &base->object->id); } } CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selectable_objects = CTX_data_equals(member, "selectable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (selectable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } + else if (CTX_data_equals(member, "selected_objects")) { + Object *ob; + FOREACH_SELECTED_OBJECT(sl, ob) + { + CTX_data_id_list_add(result, &ob->id); + } + FOREACH_SELECTED_OBJECT_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_editable_objects")) { + Object *ob; + FOREACH_SELECTED_OBJECT(sl, ob) + { + if (0 == BKE_object_is_libdata(ob)) { + CTX_data_id_list_add(result, &ob->id); } } + FOREACH_SELECTED_OBJECT_END CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selected_objects = CTX_data_equals(member, "selected_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if (selected_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + else if (CTX_data_equals(member, "editable_objects")) { + /* Visible + Editable, but not necessarily selected */ + Object *ob; + FOREACH_VISIBLE_OBJECT(sl, ob) + { + if (0 == BKE_object_is_libdata(ob)) { + CTX_data_id_list_add(result, &ob->id); } } + FOREACH_VISIBLE_OBJECT_END CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (0 == BKE_object_is_libdata(base->object)) { - if (selected_editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } + else if ( CTX_data_equals(member, "visible_bases")) { + Base *base; + FOREACH_VISIBLE_BASE(sl, base) + { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + FOREACH_VISIBLE_BASE_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selectable_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTABLED) != 0) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + } + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTED) != 0) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + } + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_editable_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTED) != 0) { + if (0 == BKE_object_is_libdata(base->object)) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } } } CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "editable_objects") || CTX_data_equals(member, "editable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool editable_objects = CTX_data_equals(member, "editable_objects"); - + else if (CTX_data_equals(member, "editable_bases")) { /* Visible + Editable, but not necessarily selected */ - for (base = scene->base.first; base; base = base->next) { - if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { if (0 == BKE_object_is_libdata(base->object)) { - if (editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } } } @@ -344,8 +346,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } } else if (CTX_data_equals(member, "active_base")) { - if (base) - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, base); + if (sl->basact) + CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact); return 1; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 32b63aca34c..a55d6c2143f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -321,6 +321,10 @@ int ED_operator_info_active(bContext *C) return ed_spacetype_test(C, SPACE_INFO); } +int ED_operator_collections_active(bContext *C) +{ + return ed_spacetype_test(C, SPACE_COLLECTIONS); +} int ED_operator_console_active(bContext *C) { diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index feea9cf5b13..f2707b9399f 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -157,15 +157,12 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - int filter; View2D *v2d = &ar->v2d; bDopeSheet *ads = &saction->ads; AnimData *adt = NULL; float act_start, act_end, y; - size_t items; - int height; unsigned char col1[3], col2[3]; unsigned char col1a[3], col2a[3]; @@ -195,10 +192,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) } /* build list of channels to draw */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac))); + int height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac))); /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ @@ -236,7 +233,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) case ANIMTYPE_SUMMARY: { /* reddish color from NLA */ - UI_ThemeColor4(TH_ANIM_ACTIVE); + immUniformThemeColor(TH_ANIM_ACTIVE); break; } case ANIMTYPE_SCENE: @@ -259,11 +256,11 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) bActionGroup *agrp = ale->data; if (show_group_colors && agrp->customCol) { if (sel) { - unsigned char *cp = agrp->cs.select; + char *cp = agrp->cs.select; immUniformColor4ub(cp[0], cp[1], cp[2], 0x45); } else { - unsigned char *cp = agrp->cs.solid; + char *cp = agrp->cs.solid; immUniformColor4ub(cp[0], cp[1], cp[2], 0x1D); } } @@ -332,18 +329,29 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) y -= ACHANNEL_STEP(ac); } glDisable(GL_BLEND); - - /* Draw keyframes + + /* black line marking 'current frame' for Time-Slide transform mode */ + if (saction->flag & SACTION_MOVING) { + immUniformColor3f(0.0f, 0.0f, 0.0f); + + immBegin(GL_LINES, 2); + immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD); + immVertex2f(pos, saction->timeslide, v2d->cur.ymax); + immEnd(); + } + immUnbindProgram(); + + /* Draw keyframes * 1) Only channels that are visible in the Action Editor get drawn/evaluated. * This is to try to optimize this for heavier data sets * 2) Keyframes which are out of view horizontally are disregarded */ y = (float)(-ACHANNEL_HEIGHT(ac)); - + for (ale = anim_data.first; ale; ale = ale->next) { const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac)); const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac)); - + /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) @@ -351,7 +359,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* check if anything to show for this channel */ if (ale->datatype != ALE_NONE) { adt = ANIM_nla_mapping_get(ac, ale); - + /* draw 'keyframes' for each specific datatype */ switch (ale->datatype) { case ALE_ALL: @@ -381,21 +389,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) } } } - + y -= ACHANNEL_STEP(ac); } - - /* free tempolary channels used for drawing */ - ANIM_animdata_freelist(&anim_data); - /* black line marking 'current frame' for Time-Slide transform mode */ - if (saction->flag & SACTION_MOVING) { - immUniformColor3f(0.0f, 0.0f, 0.0f); - - immBegin(GL_LINES, 2); - immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD); - immVertex2f(pos, saction->timeslide, v2d->cur.ymax); - immEnd(); - } - immUnbindProgram(); + /* free temporary channels used for drawing */ + ANIM_animdata_freelist(&anim_data); } diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 5ff1d758563..8c278c0b3ae 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -96,6 +96,7 @@ void ED_spacetypes_init(void) ED_spacetype_console(); ED_spacetype_userpref(); ED_spacetype_clip(); + ED_spacetype_collections(); // ... /* register operator types for screen and all spaces */ diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index da3364d872d..f53d98a1b59 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -49,6 +49,7 @@ #include "BKE_context.h" #include "BKE_action.h" +#include "BKE_layer.h" #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_paint.h" @@ -180,7 +181,9 @@ static int buttons_context_path_object(ButsContextPath *path) /* if we have a scene, use the scene's active object */ else if (buttons_context_path_scene(path)) { scene = path->ptr[path->len - 1].data; - ob = (scene->basact) ? scene->basact->object : NULL; + TODO_LAYER_CONTEXT; /* use context, not active one */ + SceneLayer *sl = BKE_scene_layer_active(scene); + ob = (sl->basact) ? sl->basact->object : NULL; if (ob) { RNA_id_pointer_create(&ob->id, &path->ptr[path->len]); @@ -553,6 +556,28 @@ static bool buttons_context_linestyle_pinnable(const bContext *C) } #endif +static int buttons_context_path_collection(const bContext *C, ButsContextPath *path) +{ + PointerRNA *ptr = &path->ptr[path->len - 1]; + + /* if we already have a (pinned) Collection, we're done */ + if (RNA_struct_is_a(ptr->type, &RNA_LayerCollection)) { + return 1; + } + + SceneLayer *sl = CTX_data_scene_layer(C); + LayerCollection *sc = BKE_layer_collection_active(sl); + + if (sc) { + RNA_pointer_create(NULL, &RNA_LayerCollection, sc, &path->ptr[path->len]); + path->len++; + return 1; + } + + /* no path to a collection possible */ + return 0; +} + static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag) { SpaceButs *sbuts = CTX_wm_space_buts(C); @@ -627,7 +652,10 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma case BCONTEXT_BONE_CONSTRAINT: found = buttons_context_path_pose_bone(path); break; - default: + case BCONTEXT_COLLECTION: + found = buttons_context_path_collection(C, path); + break; + default: found = 0; break; } @@ -744,7 +772,7 @@ const char *buttons_context_dir[] = { "texture", "texture_user", "texture_user_property", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable", "particle_settings", "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint", - "line_style", NULL + "line_style", "collection", NULL }; int buttons_context(const bContext *C, const char *member, bContextDataResult *result) @@ -1064,6 +1092,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r set_pointer_type(path, result, &RNA_FreestyleLineStyle); return 1; } + else if (CTX_data_equals(member, "collection")) { + set_pointer_type(path, result, &RNA_LayerCollection); + return 1; + } else { return 0; /* not found */ } diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index e4c23ad74f8..608287939bd 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -171,6 +171,8 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, "constraint", sbuts->mainb, vertical); else if (sbuts->mainb == BCONTEXT_BONE_CONSTRAINT) ED_region_panels(C, ar, "bone_constraint", sbuts->mainb, vertical); + else if (sbuts->mainb == BCONTEXT_COLLECTION) + ED_region_panels(C, ar, "collection", sbuts->mainb, vertical); sbuts->re_align = 0; sbuts->mainbo = sbuts->mainb; diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 4bf4c1e7baa..872e62dbc97 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -42,8 +42,6 @@ #include "ED_screen.h" #include "ED_clip.h" -#include "BIF_gl.h" - #include "WM_types.h" #include "UI_interface.h" @@ -54,6 +52,9 @@ #include "RNA_access.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" + #include "clip_intern.h" /* own include */ static void track_channel_color(MovieTrackingTrack *track, float default_color[3], float color[3]) @@ -72,78 +73,25 @@ static void track_channel_color(MovieTrackingTrack *track, float default_color[3 } } -static void draw_keyframe_shape(float x, float y, float xscale, float yscale, bool sel, float alpha) +static void draw_keyframe_shape(float x, float y, bool sel, float alpha, + unsigned int pos_id, unsigned int color_id) { - /* coordinates for diamond shape */ - static const float _unit_diamond_shape[4][2] = { - {0.0f, 1.0f}, /* top vert */ - {1.0f, 0.0f}, /* mid-right */ - {0.0f, -1.0f}, /* bottom vert */ - {-1.0f, 0.0f} /* mid-left */ - }; - static GLuint displist1 = 0; - static GLuint displist2 = 0; - int hsize = STRIP_HEIGHT_HALF; - - /* initialize 2 display lists for diamond shape - one empty, one filled */ - if (displist1 == 0) { - displist1 = glGenLists(1); - glNewList(displist1, GL_COMPILE); - - glBegin(GL_LINE_LOOP); - glVertex2fv(_unit_diamond_shape[0]); - glVertex2fv(_unit_diamond_shape[1]); - glVertex2fv(_unit_diamond_shape[2]); - glVertex2fv(_unit_diamond_shape[3]); - glEnd(); - glEndList(); + float color[4] = { 0.91f, 0.91f, 0.91f, alpha }; + if (sel) { + UI_GetThemeColorShadeAlpha4fv(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha), color); } - if (displist2 == 0) { - displist2 = glGenLists(1); - glNewList(displist2, GL_COMPILE); - - glBegin(GL_QUADS); - glVertex2fv(_unit_diamond_shape[0]); - glVertex2fv(_unit_diamond_shape[1]); - glVertex2fv(_unit_diamond_shape[2]); - glVertex2fv(_unit_diamond_shape[3]); - glEnd(); - glEndList(); - } - - glPushMatrix(); - - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f); - - /* anti-aliased lines for more consistent appearance */ - glEnable(GL_LINE_SMOOTH); - - if (sel) - UI_ThemeColorShadeAlpha(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha)); - else - glColor4f(0.91f, 0.91f, 0.91f, alpha); - - glCallList(displist2); - /* exterior - black frame */ - glColor4f(0.0f, 0.0f, 0.0f, alpha); - glCallList(displist1); - - glDisable(GL_LINE_SMOOTH); - - /* restore view transform */ - glPopMatrix(); + immAttrib4fv(color_id, color); + immVertex2f(pos_id, x, y); } -static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip) +static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip, unsigned int pos_id) { View2D *v2d = &ar->v2d; MovieTracking *tracking = &clip->tracking; MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; MovieTrackingDopesheetCoverageSegment *coverage_segment; - + for (coverage_segment = dopesheet->coverage_segments.first; coverage_segment; coverage_segment = coverage_segment->next) @@ -153,12 +101,13 @@ static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip) int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->end_frame); if (coverage_segment->coverage == TRACKING_COVERAGE_BAD) { - glColor4f(1.0f, 0.0f, 0.0f, 0.07f); + immUniformColor4f(1.0f, 0.0f, 0.0f, 0.07f); + } + else { + immUniformColor4f(1.0f, 1.0f, 0.0f, 0.07f); } - else - glColor4f(1.0f, 1.0f, 0.0f, 0.07f); - glRectf(start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax); + immRectf(pos_id, start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax); } } } @@ -175,18 +124,21 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) MovieTracking *tracking = &clip->tracking; MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; MovieTrackingDopesheetChannel *channel; - float y, xscale, yscale; float strip[4], selected_strip[4]; float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); + unsigned int keyframe_ct = 0; + + VertexFormat *format = immVertexFormat(); + unsigned int pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ v2d->tot.ymin = (float)(-height); - y = (float) CHANNEL_FIRST; - - UI_view2d_scale_get(v2d, &xscale, &yscale); + float y = (float) CHANNEL_FIRST; /* setup colors for regular and selected strips */ UI_GetThemeColor3fv(TH_STRIP, strip); @@ -197,7 +149,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) glEnable(GL_BLEND); - clip_draw_dopesheet_background(ar, clip); + clip_draw_dopesheet_background(ar, clip, pos_id); for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float) (y - CHANNEL_HEIGHT_HALF); @@ -208,7 +160,6 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; - float alpha; int i; bool sel = (track->flag & TRACK_DOPE_SEL) != 0; @@ -218,32 +169,26 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f}; track_channel_color(track, default_color, color); - glColor4fv(color); + immUniformColor4fv(color); - glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, - v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); + immRectf(pos_id, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, + v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); } - alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f; - /* tracked segments */ for (i = 0; i < channel->tot_segment; i++) { int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]); int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]); - if (sel) - glColor4fv(selected_strip); - else - glColor4fv(strip); + immUniformColor4fv(sel ? selected_strip : strip); if (start_frame != end_frame) { - glRectf(start_frame, (float) y - STRIP_HEIGHT_HALF, - end_frame, (float) y + STRIP_HEIGHT_HALF); - draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha); - draw_keyframe_shape(end_frame, y, xscale, yscale, sel, alpha); + immRectf(pos_id, start_frame, (float) y - STRIP_HEIGHT_HALF, + end_frame, (float) y + STRIP_HEIGHT_HALF); + keyframe_ct += 2; } else { - draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha); + keyframe_ct++; } } @@ -253,9 +198,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) MovieTrackingMarker *marker = &track->markers[i]; if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) { - int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); - - draw_keyframe_shape(framenr, y, xscale, yscale, sel, alpha); + keyframe_ct++; } i++; @@ -266,6 +209,76 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) y -= CHANNEL_STEP; } + immUnbindProgram(); + + if (keyframe_ct > 0) { + /* draw keyframe markers */ + format = immVertexFormat(); + pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT); + unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(PRIM_POINTS, keyframe_ct); + + /* all same size with black outline */ + immAttrib1f(size_id, 2.0f * STRIP_HEIGHT_HALF); + immAttrib3ub(outline_color_id, 0, 0, 0); + + y = (float) CHANNEL_FIRST; /* start again at the top */ + for (channel = dopesheet->channels.first; channel; channel = channel->next) { + float yminc = (float) (y - CHANNEL_HEIGHT_HALF); + float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); + + /* check if visible */ + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) + { + MovieTrackingTrack *track = channel->track; + int i; + bool sel = (track->flag & TRACK_DOPE_SEL) != 0; + float alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f; + + /* tracked segments */ + for (i = 0; i < channel->tot_segment; i++) { + int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]); + int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]); + + if (start_frame != end_frame) { + draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id); + draw_keyframe_shape(end_frame, y, sel, alpha, pos_id, color_id); + } + else { + draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id); + } + } + + /* keyframes */ + i = 0; + while (i < track->markersnr) { + MovieTrackingMarker *marker = &track->markers[i]; + + if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) { + int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); + + draw_keyframe_shape(framenr, y, sel, alpha, pos_id, color_id); + } + + i++; + } + } + + /* adjust y-position for next one */ + y -= CHANNEL_STEP; + } + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); + } + glDisable(GL_BLEND); } @@ -279,22 +292,15 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) SpaceClip *sc = CTX_wm_space_clip(C); View2D *v2d = &ar->v2d; MovieClip *clip = ED_space_clip_get_clip(sc); - MovieTracking *tracking; - MovieTrackingDopesheet *dopesheet; - MovieTrackingDopesheetChannel *channel; uiStyle *style = UI_style_get(); - uiBlock *block; int fontid = style->widget.uifont_id; - int height; - float y; - PropertyRNA *chan_prop_lock; - + if (!clip) return; - tracking = &clip->tracking; - dopesheet = &tracking->dopesheet; - height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); + MovieTracking *tracking = &clip->tracking; + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); if (height > BLI_rcti_size_y(&v2d->mask)) { /* don't use totrect set, as the width stays the same @@ -309,6 +315,37 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) /* loop through channels, and set up drawing depending on their type * first pass: just the standard GL-drawing for backdrop + text */ + float y = (float) CHANNEL_FIRST; + + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + MovieTrackingDopesheetChannel *channel; + for (channel = dopesheet->channels.first; channel; channel = channel->next) { + float yminc = (float) (y - CHANNEL_HEIGHT_HALF); + float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); + + /* check if visible */ + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) + { + MovieTrackingTrack *track = channel->track; + float color[3]; + track_channel_color(track, NULL, color); + immUniformColor3fv(color); + + immRectf(pos, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, + v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); + } + + /* adjust y-position for next one */ + y -= CHANNEL_STEP; + } + immUnbindProgram(); + + /* second pass: text */ y = (float) CHANNEL_FIRST; BLF_size(fontid, 11.0f * U.pixelsize, U.dpi); @@ -322,21 +359,11 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; - float font_height, color[3]; bool sel = (track->flag & TRACK_DOPE_SEL) != 0; - track_channel_color(track, NULL, color); - glColor3fv(color); - - glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, - v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); - - if (sel) - UI_ThemeColor(TH_TEXT_HI); - else - UI_ThemeColor(TH_TEXT); + UI_FontThemeColor(fontid, sel ? TH_TEXT_HI : TH_TEXT); - font_height = BLF_height(fontid, channel->name, sizeof(channel->name)); + float font_height = BLF_height(fontid, channel->name, sizeof(channel->name)); BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD, y - font_height / 2.0f, 0.0f); BLF_draw(fontid, channel->name, strlen(channel->name)); @@ -346,12 +373,12 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) y -= CHANNEL_STEP; } - /* second pass: widgets */ - block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + /* third pass: widgets */ + uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); y = (float) CHANNEL_FIRST; /* get RNA properties (once) */ - chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock"); + PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock"); BLI_assert(chan_prop_lock); glEnable(GL_BLEND); diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index 424d25defdd..b373358b49c 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -42,7 +42,10 @@ #include "ED_screen.h" #include "ED_clip.h" -#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "WM_types.h" @@ -53,52 +56,30 @@ #include "clip_intern.h" // own include -static void draw_curve_knot(float x, float y, float xscale, float yscale, float hsize) -{ - static GLuint displist = 0; - - /* initialize round circle shape */ - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0, 0.7, 8, 1); - gluDeleteQuadric(qobj); - - glEndList(); - } - - glPushMatrix(); - - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f); - glCallList(displist); - - glPopMatrix(); -} +typedef struct TrackMotionCurveUserData { + MovieTrackingTrack *act_track; + bool sel; + float xscale, yscale, hsize; + unsigned int pos; +} TrackMotionCurveUserData; -static void tracking_segment_point_cb(void *UNUSED(userdata), MovieTrackingTrack *UNUSED(track), +static void tracking_segment_point_cb(void *userdata, MovieTrackingTrack *UNUSED(track), MovieTrackingMarker *UNUSED(marker), int UNUSED(coord), int scene_framenr, float val) { - glVertex2f(scene_framenr, val); + TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata; + + immVertex2f(data->pos, scene_framenr, val); } static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord) { - const float colors[2][3] = { - {1.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 0.0f}, - }; - float col[4]; + TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata; + float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - copy_v3_v3(col, colors[coord]); + col[coord] = 1.0f; - if (track == userdata) { + if (track == data->act_track) { col[3] = 1.0f; glLineWidth(2.0f); } @@ -107,22 +88,17 @@ static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, glLineWidth(1.0f); } - glColor4fv(col); + immUniformColor4fv(col); - glBegin(GL_LINE_STRIP); + /* Graph can be composed of smaller segments, if any marker is disabled */ + immBeginAtMost(GL_LINE_STRIP, track->markersnr); } static void tracking_segment_end_cb(void *UNUSED(userdata), int UNUSED(coord)) { - glEnd(); + immEnd(); } -typedef struct TrackMotionCurveUserData { - MovieTrackingTrack *act_track; - bool sel; - float xscale, yscale, hsize; -} TrackMotionCurveUserData; - static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float val) { @@ -136,16 +112,20 @@ static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, sel = (marker->flag & sel_flag) ? 1 : 0; if (sel == data->sel) { - if (sel) - UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); - else - UI_ThemeColor(TH_HANDLE_VERTEX); + immUniformThemeColor(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX); + + glPushMatrix(); + glTranslatef(scene_framenr, val, 0.0f); + glScalef(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize, 1.0f); + gpuMatrixUpdate_legacy(); + + imm_draw_lined_circle(data->pos, 0, 0, 0.7, 8); - draw_curve_knot(scene_framenr, val, data->xscale, data->yscale, data->hsize); + glPopMatrix(); } } -static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc) +static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int pos) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; @@ -162,18 +142,21 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc) userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); userdata.sel = false; userdata.act_track = act_track; + userdata.pos = pos; UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale); clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, &userdata, tracking_segment_knot_cb, NULL, NULL); + gpuMatrixUpdate_legacy(); + /* draw graph lines */ glEnable(GL_BLEND); clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, - act_track, tracking_segment_point_cb, tracking_segment_start_cb, + &userdata, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb); glDisable(GL_BLEND); @@ -183,6 +166,8 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc) (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, &userdata, tracking_segment_knot_cb, NULL, NULL); + + gpuMatrixUpdate_legacy(); } typedef struct TrackErrorCurveUserData { @@ -195,6 +180,7 @@ typedef struct TrackErrorCurveUserData { float projection_matrix[4][4]; int width, height; float aspy; + unsigned int pos; } TrackErrorCurveUserData; static void tracking_error_segment_point_cb(void *userdata, @@ -230,7 +216,7 @@ static void tracking_error_segment_point_cb(void *userdata, sub_v2_v2v2(delta, reprojected_position, marker_position); reprojection_error = len_v2(delta) * weight; - glVertex2f(scene_framenr, reprojection_error); + immVertex2f(data->pos, scene_framenr, reprojection_error); } } @@ -249,20 +235,21 @@ static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack * glLineWidth(1.0f); } - glColor4fv(col); + immUniformColor4fv(col); - glBegin(GL_LINE_STRIP); + /* Graph can be composed of smaller segments, if any marker is disabled */ + immBeginAtMost(GL_LINE_STRIP, track->markersnr); } } static void tracking_error_segment_end_cb(void *UNUSED(userdata), int coord) { if (coord == 1) { - glEnd(); + immEnd(); } } -static void draw_tracks_error_curves(SpaceClip *sc) +static void draw_tracks_error_curves(SpaceClip *sc, unsigned int pos) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; @@ -273,6 +260,7 @@ static void draw_tracks_error_curves(SpaceClip *sc) data.tracking_object = BKE_tracking_object_get_active(tracking); data.active_track = BKE_tracking_track_get_active(tracking); data.matrix_initialized = false; + data.pos = pos; BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height); data.aspy = 1.0f / tracking->camera.pixel_aspect; @@ -289,37 +277,38 @@ static void draw_tracks_error_curves(SpaceClip *sc) tracking_error_segment_end_cb); } -static void draw_frame_curves(SpaceClip *sc) +static void draw_frame_curves(SpaceClip *sc, unsigned int pos) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking); int i, lines = 0, prevfra = 0; - glColor3f(0.0f, 0.0f, 1.0f); + immUniformColor3f(0.0f, 0.0f, 1.0f); for (i = 0; i < reconstruction->camnr; i++) { MovieReconstructedCamera *camera = &reconstruction->cameras[i]; int framenr; if (lines && camera->framenr != prevfra + 1) { - glEnd(); + immEnd(); lines = 0; } if (!lines) { - glBegin(GL_LINE_STRIP); + immBeginAtMost(GL_LINE_STRIP, reconstruction->camnr); lines = 1; } framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, camera->framenr); - glVertex2f(framenr, camera->error); + immVertex2f(pos, framenr, camera->error); prevfra = camera->framenr; } - if (lines) - glEnd(); + if (lines) { + immEnd(); + } } void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene) @@ -334,17 +323,26 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene) UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL); UI_view2d_grid_free(grid); + unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + if (clip) { - if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) - draw_tracks_motion_curves(v2d, sc); + if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) { + draw_tracks_motion_curves(v2d, sc, pos); + } - if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) - draw_tracks_error_curves(sc); + if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) { + draw_tracks_error_curves(sc, pos); + } - if (sc->flag & SC_SHOW_GRAPH_FRAMES) - draw_frame_curves(sc); + if (sc->flag & SC_SHOW_GRAPH_FRAMES) { + draw_frame_curves(sc, pos); + } } + immUnbindProgram(); + /* frame range */ clip_draw_sfra_efra(v2d, scene); diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 547c2fba66f..6026036c05d 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -43,8 +43,7 @@ #include "BKE_tracking.h" #include "BKE_depsgraph.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "GPU_immediate.h" #include "WM_api.h" #include "WM_types.h" @@ -52,7 +51,6 @@ #include "ED_screen.h" #include "ED_clip.h" - #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -237,31 +235,35 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y) void clip_draw_cfra(SpaceClip *sc, ARegion *ar, Scene *scene) { + /* Draw a light green line to indicate current frame */ View2D *v2d = &ar->v2d; - float xscale, yscale; + float x = (float)(sc->user.framenr * scene->r.framelen); - /* Draw a light green line to indicate current frame */ - UI_ThemeColor(TH_CFRAME); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); - float x = (float)(sc->user.framenr * scene->r.framelen); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_CFRAME); + glLineWidth(2.0f); - glLineWidth(2.0); + immBegin(GL_LINES, 2); + immVertex2f(pos, x, v2d->cur.ymin); + immVertex2f(pos, x, v2d->cur.ymax); + immEnd(); - glBegin(GL_LINES); - glVertex2f(x, v2d->cur.ymin); - glVertex2f(x, v2d->cur.ymax); - glEnd(); + immUnbindProgram(); UI_view2d_view_orthoSpecial(ar, v2d, 1); /* because the frame number text is subject to the same scaling as the contents of the view */ + float xscale, yscale; UI_view2d_scale_get(v2d, &xscale, &yscale); + glPushMatrix(); glScalef(1.0f / xscale, 1.0f, 1.0f); ED_region_cache_draw_curfra_label(sc->user.framenr, (float)sc->user.framenr * xscale, 18); /* restore view transform */ - glScalef(xscale, 1.0, 1.0); + glPopMatrix(); } void clip_draw_sfra_efra(View2D *v2d, Scene *scene) @@ -271,15 +273,27 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene) /* currently clip editor supposes that editing clip length is equal to scene frame range */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); - glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); - glRectf((float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); + immRectf(pos, (float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + glDisable(GL_BLEND); - UI_ThemeColorShade(TH_BACK, -60); + immUniformThemeColorShade(TH_BACK, -60); /* thin lines where the actual frames are */ - fdrawline((float)SFRA, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax); - fdrawline((float)EFRA, v2d->cur.ymin, (float)EFRA, v2d->cur.ymax); + glLineWidth(1.0f); + + immBegin(GL_LINES, 4); + immVertex2f(pos, (float)SFRA, v2d->cur.ymin); + immVertex2f(pos, (float)SFRA, v2d->cur.ymax); + immVertex2f(pos, (float)EFRA, v2d->cur.ymin); + immVertex2f(pos, (float)EFRA, v2d->cur.ymax); + immEnd(); + + immUnbindProgram(); } diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c index f81180d65a9..12b97504dc7 100644 --- a/source/blender/editors/space_clip/tracking_ops_orient.c +++ b/source/blender/editors/space_clip/tracking_ops_orient.c @@ -44,6 +44,7 @@ #include "BKE_tracking.h" #include "BKE_global.h" #include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "BKE_object.h" #include "BKE_report.h" @@ -69,17 +70,17 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip) return camera; } - for (Base *base = scene->base.first; - base != NULL; - base = base->next) + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) { - if (base->object->type == OB_CAMERA) { - if (BKE_object_movieclip_get(scene, base->object, false) == clip) { - camera = base->object; + if (ob->type == OB_CAMERA) { + if (BKE_object_movieclip_get(scene, ob, false) == clip) { + camera = ob; break; } } } + FOREACH_SCENE_OBJECT_END return camera; } @@ -87,6 +88,7 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip) static Object *get_orientation_object(bContext *C) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; @@ -97,7 +99,7 @@ static Object *get_orientation_object(bContext *C) object = get_camera_with_movieclip(scene, clip); } else { - object = OBACT; + object = OBACT_NEW; } if (object != NULL && object->parent != NULL) { @@ -111,7 +113,7 @@ static int set_orientation_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); if (sc != NULL) { - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); MovieClip *clip = ED_space_clip_get_clip(sc); if (clip != NULL) { MovieTracking *tracking = &clip->tracking; @@ -120,7 +122,7 @@ static int set_orientation_poll(bContext *C) return true; } else { - return OBACT != NULL; + return OBACT_NEW != NULL; } } } diff --git a/source/blender/editors/space_collections/CMakeLists.txt b/source/blender/editors/space_collections/CMakeLists.txt new file mode 100644 index 00000000000..1cc4a40d657 --- /dev/null +++ b/source/blender/editors/space_collections/CMakeLists.txt @@ -0,0 +1,45 @@ +# ***** 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): Jacques Beaurain. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenkernel + ../../blenlib + ../../blentranslation + ../../gpu + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/guardedalloc + ../../../../intern/glew-mx +) + +set(INC_SYS + ${GLEW_INCLUDE_PATH} +) + +set(SRC + collections_ops.c + space_collections.c + + collections_intern.h +) + +blender_add_lib(bf_editor_space_collections "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_collections/collections_intern.h b/source/blender/editors/space_collections/collections_intern.h new file mode 100644 index 00000000000..866f59659c3 --- /dev/null +++ b/source/blender/editors/space_collections/collections_intern.h @@ -0,0 +1,35 @@ +/* + * ***** 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 ***** + */ + +/** \file blender/editors/space_collections/collections_intern.h + * \ingroup spcollections + */ + +#ifndef __COLLECTIONS_INTERN_H__ +#define __COLLECTIONS_INTERN_H__ + +struct wmKeyConfig; + +/* collections_ops.c */ +void collections_operatortypes(void); +void collections_keymap(struct wmKeyConfig *keyconf); + +#endif /* __COLLECTIONS_INTERN_H__ */ + diff --git a/source/blender/editors/space_collections/collections_ops.c b/source/blender/editors/space_collections/collections_ops.c new file mode 100644 index 00000000000..7e1bf8091b0 --- /dev/null +++ b/source/blender/editors/space_collections/collections_ops.c @@ -0,0 +1,340 @@ +/* + * ***** 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 ***** + */ + +/** \file blender/editors/space_collections/collections_ops.c + * \ingroup spcollections + */ + +#include "BKE_context.h" +#include "BKE_layer.h" +#include "BKE_report.h" + +#include "ED_screen.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "collections_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ +/* polls */ + +static SceneCollection *collection_manager_collection_active(bContext *C) +{ + TODO_LAYER_OPERATORS; + /* consider that we may have overrides active + * leading to no active collections */ + return CTX_data_scene_collection(C); +} + +static int operator_not_master_collection_active(bContext *C) +{ + SceneCollection *sc = collection_manager_collection_active(C); + if (sc == NULL) { + return 1; + } + + return (sc == BKE_collection_master(CTX_data_scene(C))) ? 0 : 1; +} + +static int operator_top_collection_active(bContext *C) +{ + SceneCollection *sc = collection_manager_collection_active(C); + if (sc == NULL) { + return 0; + } + + TODO_LAYER_OPERATORS; + /* see if it's a top collection */ + return 1; +} + +static int operator_collection_active(bContext *C) +{ + return collection_manager_collection_active(C) ? 1 : 0; +} + +/* -------------------------------------------------------------------- */ +/* collection manager operators */ + +static int collection_link_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_collection_link not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_collection_link(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Collection"; + ot->idname = "COLLECTIONS_OT_collection_link"; + ot->description = "Link a new collection to the active layer"; + + /* api callbacks */ + ot->invoke = collection_link_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int collection_unlink_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_collection_unlink not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_collection_unlink(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Collection"; + ot->idname = "COLLECTIONS_OT_collection_unlink"; + ot->description = "Link a new collection to the active layer"; + + /* api callbacks */ + ot->invoke = collection_unlink_invoke; + ot->poll = operator_top_collection_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int collection_new_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + + SceneCollection *sc = BKE_collection_add(scene, NULL, NULL); + BKE_collection_link(sl, sc); + + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; +} + +static void COLLECTIONS_OT_collection_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Collection"; + ot->idname = "COLLECTIONS_OT_collection_new"; + ot->description = "Add a new collection to the scene, and link it to the active layer"; + + /* api callbacks */ + ot->exec = collection_new_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + TODO_LAYER_OVERRIDE; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_override_new not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_override_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Override"; + ot->idname = "COLLECTIONS_OT_override_new"; + ot->description = "Add a new override to the active collection"; + + /* api callbacks */ + ot->invoke = override_new_invoke; + ot->poll = operator_collection_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int delete_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_delete not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete"; + ot->idname = "COLLECTIONS_OT_delete"; + ot->description = "Delete active override or collection"; + + /* api callbacks */ + ot->invoke = delete_invoke; + ot->poll = operator_not_master_collection_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int select_exec(bContext *C, wmOperator *op) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + const int collection_index = RNA_int_get(op->ptr, "collection_index"); + sl->active_collection = collection_index; + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; +} + +static void COLLECTIONS_OT_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select"; + ot->idname = "COLLECTIONS_OT_select"; + ot->description = "Change active collection or override"; + + /* api callbacks */ + ot->exec = select_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index", + "Index of collection to select", 0, INT_MAX); +} + +static int rename_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_rename not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_rename(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Rename"; + ot->idname = "COLLECTIONS_OT_rename"; + ot->description = "Rename active collection or override"; + + /* api callbacks */ + ot->invoke = rename_invoke; + ot->poll = operator_not_master_collection_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------------------------------------------------- */ +/* property editor operators */ + +static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_objects_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Objects"; + ot->idname = "COLLECTIONS_OT_objects_add"; + ot->description = "Add selected objects to collection"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static void COLLECTIONS_OT_objects_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Object"; + ot->idname = "COLLECTIONS_OT_objects_remove"; + ot->description = "Remove object from collection"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static void COLLECTIONS_OT_objects_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Objects"; + ot->idname = "COLLECTIONS_OT_objects_select"; + ot->description = "Selected collection objects"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static void COLLECTIONS_OT_objects_deselect(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Deselect Objects"; + ot->idname = "COLLECTIONS_OT_objects_deselect"; + ot->description = "Deselected collection objects"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ************************** registration - operator types **********************************/ + +void collections_operatortypes(void) +{ + WM_operatortype_append(COLLECTIONS_OT_delete); + WM_operatortype_append(COLLECTIONS_OT_select); + WM_operatortype_append(COLLECTIONS_OT_rename); + WM_operatortype_append(COLLECTIONS_OT_collection_link); + WM_operatortype_append(COLLECTIONS_OT_collection_unlink); + WM_operatortype_append(COLLECTIONS_OT_collection_new); + WM_operatortype_append(COLLECTIONS_OT_override_new); + + WM_operatortype_append(COLLECTIONS_OT_objects_add); + WM_operatortype_append(COLLECTIONS_OT_objects_remove); + WM_operatortype_append(COLLECTIONS_OT_objects_select); + WM_operatortype_append(COLLECTIONS_OT_objects_deselect); +} + +void collections_keymap(wmKeyConfig *keyconf) +{ + wmKeyMap *keymap = WM_keymap_find(keyconf, "Collections Manager", SPACE_COLLECTIONS, 0); + + /* selection */ + WM_keymap_add_item(keymap, "COLLECTIONS_OT_select", LEFTMOUSE, KM_CLICK, 0, 0); + + WM_keymap_add_item(keymap, "COLLECTIONS_OT_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); + WM_keymap_add_item(keymap, "COLLECTIONS_OT_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); + + WM_keymap_add_item(keymap, "COLLECTIONS_OT_collection_new", NKEY, KM_PRESS, KM_CTRL, 0); + + WM_keymap_add_item(keymap, "COLLECTIONS_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "COLLECTIONS_OT_delete", DELKEY, KM_PRESS, 0, 0); +} diff --git a/source/blender/editors/space_collections/space_collections.c b/source/blender/editors/space_collections/space_collections.c new file mode 100644 index 00000000000..7dd50e5cbac --- /dev/null +++ b/source/blender/editors/space_collections/space_collections.c @@ -0,0 +1,182 @@ +/* + * ***** 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 ***** + */ + +/** \file blender/editors/space_collections/space_collections.c + * \ingroup spcollections + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BIF_gl.h" + +#include "BKE_context.h" +#include "BKE_screen.h" + +#include "BLI_ghash.h" +#include "BLI_listbase.h" + +#include "ED_screen.h" +#include "ED_space_api.h" + +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "collections_intern.h" /* own include */ + +/* ******************** default callbacks for collection manager space ***************** */ + +static SpaceLink *collections_new(const bContext *UNUSED(C)) +{ + ARegion *ar; + SpaceCollections *scollection; /* hmm, that's actually a good band name... */ + + scollection = MEM_callocN(sizeof(SpaceCollections), __func__); + scollection->spacetype = SPACE_COLLECTIONS; + + /* header */ + ar = MEM_callocN(sizeof(ARegion), "header for collection manager"); + BLI_addtail(&scollection->regionbase, ar); + ar->regiontype = RGN_TYPE_HEADER; + ar->alignment = RGN_ALIGN_BOTTOM; + + /* main region */ + ar = MEM_callocN(sizeof(ARegion), "main region for collection manager"); + BLI_addtail(&scollection->regionbase, ar); + ar->regiontype = RGN_TYPE_WINDOW; + ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE); + ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y); + + return (SpaceLink *)scollection; +} + +static void collections_free(SpaceLink *UNUSED(sl)) +{ +} + +static SpaceLink *collections_duplicate(SpaceLink *sl) +{ + SpaceCollections *scollection = MEM_dupallocN(sl); + + /* clear or remove stuff from old */ + + return (SpaceLink *)scollection; +} + +/* add handlers, stuff you only do once or on area/region changes */ +static void collection_main_region_init(wmWindowManager *wm, ARegion *ar) +{ + UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); + ar->v2d.scroll |= (V2D_SCROLL_VERTICAL_FULLR | V2D_SCROLL_HORIZONTAL_FULLR); + + /* own keymap */ + wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Layer Manager", SPACE_COLLECTIONS, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); +} + +static void collections_main_region_draw(const bContext *C, ARegion *ar) +{ + SpaceCollections *spc = CTX_wm_space_collections(C); + View2D *v2d = &ar->v2d; + + if (spc->flag & SC_COLLECTION_DATA_REFRESH) { + } + + /* v2d has initialized flag, so this call will only set the mask correct */ + UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); + + UI_ThemeClearColor(TH_BACK); + glClear(GL_COLOR_BUFFER_BIT); + + /* reset view matrix */ + UI_view2d_view_restore(C); + + /* scrollers */ + View2DScrollers *scrollers; + scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + UI_view2d_scrollers_draw(C, v2d, scrollers); + UI_view2d_scrollers_free(scrollers); +} + +/* add handlers, stuff you only do once or on area/region changes */ +static void collections_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar) +{ + ED_region_header_init(ar); +} + +static void collections_header_region_draw(const bContext *C, ARegion *ar) +{ + ED_region_header(C, ar); +} + +static void collections_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +{ + switch (wmn->category) { + case NC_SCENE: + if (wmn->data == ND_LAYER) { + ED_region_tag_redraw(ar); + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_COLLECTIONS) { + ED_region_tag_redraw(ar); + } + } +} + +/* only called once, from space/spacetypes.c */ +void ED_spacetype_collections(void) +{ + SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype collections"); + ARegionType *art; + + st->spaceid = SPACE_COLLECTIONS; + strncpy(st->name, "LayerManager", BKE_ST_MAXNAME); + + st->new = collections_new; + st->free = collections_free; + st->duplicate = collections_duplicate; + st->operatortypes = collections_operatortypes; + st->keymap = collections_keymap; + + /* regions: main window */ + art = MEM_callocN(sizeof(ARegionType), "spacetype collections region"); + art->regionid = RGN_TYPE_WINDOW; + art->init = collection_main_region_init; + art->draw = collections_main_region_draw; + art->listener = collections_main_region_listener; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; + BLI_addhead(&st->regiontypes, art); + + /* regions: header */ + art = MEM_callocN(sizeof(ARegionType), "spacetype collections header"); + art->regionid = RGN_TYPE_HEADER; + art->prefsizey = HEADERY; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER; + art->init = collections_header_region_init; + art->draw = collections_header_region_draw; + BLI_addhead(&st->regiontypes, art); + + BKE_spacetype_register(st); +} diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index f049d616aa7..06066372828 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -290,7 +290,8 @@ static void file_draw_icon(uiBlock *block, const char *path, int sx, int sy, int } -static void file_draw_string(int sx, int sy, const char *string, float width, int height, short align) +static void file_draw_string(int sx, int sy, const char *string, float width, int height, short align, + const unsigned char col[4]) { uiStyle *style; uiFontStyle fs; @@ -315,7 +316,7 @@ static void file_draw_string(int sx, int sy, const char *string, float width, in rect.ymin = sy - height; rect.ymax = sy; - UI_fontstyle_draw(&fs, &rect, fname); + UI_fontstyle_draw(&fs, &rect, fname, col); } void file_calc_previews(const bContext *C, ARegion *ar) @@ -537,6 +538,7 @@ void file_draw_list(const bContext *C, ARegion *ar) short align; bool do_drag; int column_space = 0.6f * UI_UNIT_X; + unsigned char text_col[4]; const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size); const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size); const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size)); @@ -645,7 +647,7 @@ void file_draw_list(const bContext *C, ARegion *ar) sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X; } - UI_ThemeColor4(TH_TEXT); + UI_GetThemeColor4ubv(TH_TEXT, text_col); if (file_selflag & FILE_SEL_EDITING) { uiBut *but; @@ -676,7 +678,7 @@ void file_draw_list(const bContext *C, ARegion *ar) if (!(file_selflag& FILE_SEL_EDITING)) { int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : sy; - file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align); + file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col); } sx += (int)layout->column_widths[COLUMN_NAME] + column_space; @@ -688,7 +690,8 @@ void file_draw_list(const bContext *C, ARegion *ar) BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str); } file_draw_string( - sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); + sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, + align, text_col); } sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; } @@ -699,10 +702,12 @@ void file_draw_list(const bContext *C, ARegion *ar) NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str); } file_draw_string( - sx, sy, file->entry->date_str, layout->column_widths[COLUMN_DATE], layout->tile_h, align); + sx, sy, file->entry->date_str, layout->column_widths[COLUMN_DATE], layout->tile_h, + align, text_col); sx += (int)layout->column_widths[COLUMN_DATE] + column_space; file_draw_string( - sx, sy, file->entry->time_str, layout->column_widths[COLUMN_TIME], layout->tile_h, align); + sx, sy, file->entry->time_str, layout->column_widths[COLUMN_TIME], layout->tile_h, + align, text_col); sx += (int)layout->column_widths[COLUMN_TIME] + column_space; } else { @@ -717,7 +722,8 @@ void file_draw_list(const bContext *C, ARegion *ar) BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str); } file_draw_string( - sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); + sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, + align, text_col); } sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; } diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index f12db310856..70d3fad9554 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -53,7 +53,7 @@ #include "ED_anim_api.h" #include "ED_markers.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" #include "WM_api.h" #include "WM_types.h" @@ -265,43 +265,52 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) /* only free grid after drawing data, as we need to use it to determine sampling rate */ UI_view2d_grid_free(grid); - - /* horizontal component of value-cursor (value line before the current frame line) */ - if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) { - float y = sipo->cursorVal; - - /* Draw a green line to indicate the cursor value */ - UI_ThemeColorShadeAlpha(TH_CFRAME, -10, -50); - glEnable(GL_BLEND); - glLineWidth(2.0); + if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) { + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); - glBegin(GL_LINES); - glVertex2f(v2d->cur.xmin, y); - glVertex2f(v2d->cur.xmax, y); - glEnd(); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glDisable(GL_BLEND); - } - - /* current frame or vertical component of vertical component of the cursor */ - if (sipo->mode == SIPO_MODE_DRIVERS) { - /* cursor x-value */ - float x = sipo->cursorTime; - - /* to help differentiate this from the current frame, draw slightly darker like the horizontal one */ - UI_ThemeColorShadeAlpha(TH_CFRAME, -40, -50); - glEnable(GL_BLEND); - glLineWidth(2.0); - - glBegin(GL_LINES); - glVertex2f(x, v2d->cur.ymin); - glVertex2f(x, v2d->cur.ymax); - glEnd(); + /* horizontal component of value-cursor (value line before the current frame line) */ + if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) { + + float y = sipo->cursorVal; + + /* Draw a green line to indicate the cursor value */ + immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50); + glEnable(GL_BLEND); + glLineWidth(2.0); + + immBegin(GL_LINES, 2); + immVertex2f(pos, v2d->cur.xmin, y); + immVertex2f(pos, v2d->cur.xmax, y); + immEnd(); - glDisable(GL_BLEND); + glDisable(GL_BLEND); + } + + /* current frame or vertical component of vertical component of the cursor */ + if (sipo->mode == SIPO_MODE_DRIVERS) { + /* cursor x-value */ + float x = sipo->cursorTime; + + /* to help differentiate this from the current frame, draw slightly darker like the horizontal one */ + immUniformThemeColorShadeAlpha(TH_CFRAME, -40, -50); + glEnable(GL_BLEND); + glLineWidth(2.0); + + immBegin(GL_LINES, 2); + immVertex2f(pos, x, v2d->cur.ymin); + immVertex2f(pos, x, v2d->cur.ymax); + immEnd(); + + glDisable(GL_BLEND); + } + + immUnbindProgram(); } - else { + + if (sipo->mode != SIPO_MODE_DRIVERS) { /* current frame */ if (sipo->flag & SIPO_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS; if ((sipo->flag & SIPO_NODRAWCFRANUM) == 0) flag |= DRAWCFRA_SHOW_NUMBOX; diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 8dc6c4229b2..435d9b2ee26 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -269,9 +269,9 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats) stats->tottri = ob->sculpt->bm->totface; } -static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) +static void stats_dupli_object(BaseLegacy *base, Object *ob, SceneStats *stats) { - if (base->flag & SELECT) stats->totobjsel++; + if (base->flag_legacy & SELECT) stats->totobjsel++; if (ob->transflag & OB_DUPLIPARTS) { /* Dupli Particles */ @@ -300,7 +300,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) } } - stats_object(ob, base->flag & SELECT, 1, stats); + stats_object(ob, base->flag_legacy & SELECT, 1, stats); stats->totobj++; } else if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) { @@ -316,23 +316,23 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) } stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag_legacy & SELECT, tot, stats); } else if (ob->transflag & OB_DUPLIFRAMES) { /* Dupli Frames */ int tot = count_duplilist(ob); stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag_legacy & SELECT, tot, stats); } else if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) { /* Dupli Group */ int tot = count_duplilist(ob); stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag_legacy & SELECT, tot, stats); } else { /* No Dupli */ - stats_object(ob, base->flag & SELECT, 1, stats); + stats_object(ob, base->flag_legacy & SELECT, 1, stats); stats->totobj++; } } @@ -348,7 +348,7 @@ static void stats_update(Scene *scene) { SceneStats stats = {0}; Object *ob = (scene->basact) ? scene->basact->object : NULL; - Base *base; + BaseLegacy *base; if (scene->obedit) { /* Edit Mode */ diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index d3c8fed5fc1..8ee488ac591 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -200,17 +200,15 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str immUnbindProgram(); } - glColor3ubv(fg); - /* last part needs no clipping */ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0); + BLF_color3ubv(cdc->font_id, fg); BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth); if (cdc->sel[0] != cdc->sel[1]) { console_step_sel(cdc, -initial_offset); // glColor4ub(255, 0, 0, 96); // debug console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel); - glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; @@ -226,7 +224,6 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str console_step_sel(cdc, len); // glColor4ub(0, 255, 0, 96); // debug console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel); - glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; @@ -254,8 +251,6 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str immUnbindProgram(); } - glColor3ubv(fg); - BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0); BLF_draw_mono(cdc->font_id, str, str_len, cdc->cwidth); diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 3de44174d6a..f1a08a45c29 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -460,7 +460,7 @@ static void set_sca_ob(Object *ob) static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag) { - Base *base; + BaseLegacy *base; Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); Object *ob, *obt, *obact= CTX_data_active_object(C); @@ -491,7 +491,7 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf base= FIRSTBASE; while (base) { if (base->lay & lay) { - if (base->flag & SELECT) { + if (base->flag_legacy & SELECT) { if (scavisflag & BUTS_SENS_SEL) base->object->scavisflag |= OB_VIS_SENS; if (scavisflag & BUTS_CONT_SEL) base->object->scavisflag |= OB_VIS_CONT; if (scavisflag & BUTS_ACT_SEL) base->object->scavisflag |= OB_VIS_ACT; diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index e9c46e9d04b..48e822ef876 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -45,6 +45,7 @@ #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_report.h" @@ -125,7 +126,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe { bDopeSheet *ads = (bDopeSheet *)ac->data; Scene *sce = (Scene *)ads->source; - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; AnimData *adt = ob->adt; @@ -133,24 +134,24 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ - base->flag ^= SELECT; - ob->flag = base->flag; + base->flag_legacy ^= SELECT; + BKE_scene_base_flag_sync_from_base(base); if (adt) adt->flag ^= ADT_UI_SELECTED; } else { - Base *b; + BaseLegacy *b; /* deselect all */ /* TODO: should this deselect all other types of channels too? */ for (b = sce->base.first; b; b = b->next) { - b->flag &= ~SELECT; - b->object->flag = b->flag; + b->flag_legacy &= ~SELECT; + BKE_scene_base_flag_sync_from_base(b); if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); } /* select object now */ - base->flag |= SELECT; + base->flag_legacy |= SELECT; ob->flag |= SELECT; if (adt) adt->flag |= ADT_UI_SELECTED; } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index a9b8bfd08c8..e744a39fde9 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -54,7 +54,6 @@ #include "ED_anim_api.h" #include "ED_keyframes_draw.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "GPU_immediate.h" @@ -101,50 +100,68 @@ void nla_action_get_color(AnimData *adt, bAction *act, float color[4]) } /* draw the keyframes in the specified Action */ -static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax) +static void nla_action_draw_keyframes(AnimData *adt, bAction *act, float y, float ymin, float ymax) { - DLRBT_Tree keys; - ActKeyColumn *ak; - float xscale, f1, f2; - float color[4]; - /* get a list of the keyframes with NLA-scaling applied */ + DLRBT_Tree keys; BLI_dlrbTree_init(&keys); action_to_keylist(adt, act, &keys, NULL); BLI_dlrbTree_linkedlist_sync(&keys); - - if (ELEM(NULL, act, keys.first)) + + if (!(act && keys.first)) return; - + /* draw a darkened region behind the strips * - get and reset the background color, this time without the alpha to stand out better * (amplified alpha is used instead) */ + float color[4]; nla_action_get_color(adt, act, color); color[3] *= 2.5f; - - glColor4fv(color); + + VertexFormat *format = immVertexFormat(); + unsigned int pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + + immUniformColor4fv(color); + /* - draw a rect from the first to the last frame (no extra overlaps for now) * that is slightly stumpier than the track background (hardcoded 2-units here) */ - f1 = ((ActKeyColumn *)keys.first)->cfra; - f2 = ((ActKeyColumn *)keys.last)->cfra; - - glRectf(f1, ymin + 2, f2, ymax - 2); - - - /* get View2D scaling factor */ - UI_view2d_scale_get(v2d, &xscale, NULL); - - /* for now, color is hardcoded to be black */ - glColor3f(0.0f, 0.0f, 0.0f); - - /* just draw each keyframe as a simple dot (regardless of the selection status) - * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction - */ - for (ak = keys.first; ak; ak = ak->next) - draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f); - + float f1 = ((ActKeyColumn *)keys.first)->cfra; + float f2 = ((ActKeyColumn *)keys.last)->cfra; + + immRectf(pos_id, f1, ymin + 2, f2, ymax - 2); + immUnbindProgram(); + + /* count keys before drawing */ + unsigned int key_ct = 0; + for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) { + key_ct++; + } + + if (key_ct > 0) { + format = immVertexFormat(); + pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT); + unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immBegin(PRIM_POINTS, key_ct); + + /* - disregard the selection status of keyframes so they draw a certain way + * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction + */ + for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) { + draw_keyframe_shape(ak->cfra, y, 3.0f, false, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f, + pos_id, size_id, color_id, outline_color_id); + } + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); + } + /* free icons */ BLI_dlrbTree_free(&keys); } @@ -152,57 +169,55 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d, /* Strip Markers ------------------------ */ /* Markers inside an action strip */ -static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc) +static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc, int shade, unsigned int pos) { - bAction *act = strip->act; - TimeMarker *marker; - - if (ELEM(NULL, strip->act, strip->act->markers.first)) + const bAction *act = strip->act; + + if (!(act && act->markers.first)) return; - - for (marker = act->markers.first; marker; marker = marker->next) { + + immUniformThemeColorShade(TH_STRIP_SELECT, shade); + + immBeginAtMost(PRIM_POINTS, BLI_listbase_count(&act->markers)); + for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) { float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP); - + /* just a simple line for now */ - // XXX: draw a triangle instead... - fdrawline(frame, yminc + 1, frame, ymaxc - 1); + /* XXX: draw a triangle instead... */ + immVertex2f(pos, frame, yminc + 1); + immVertex2f(pos, frame, ymaxc - 1); } } + immEnd(); } /* Markers inside a NLA-Strip */ -static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc) +static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos) { - glLineWidth(2.0); + glLineWidth(2.0f); if (strip->type == NLASTRIP_TYPE_CLIP) { /* try not to be too conspicuous, while being visible enough when transforming */ - if (strip->flag & NLASTRIP_FLAG_SELECT) - UI_ThemeColorShade(TH_STRIP_SELECT, -60); - else - UI_ThemeColorShade(TH_STRIP_SELECT, -40); - + int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40; + setlinestyle(3); /* just draw the markers in this clip */ - nla_actionclip_draw_markers(strip, yminc, ymaxc); + nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, pos); setlinestyle(0); } else if (strip->flag & NLASTRIP_FLAG_TEMP_META) { /* just a solid color, so that it is very easy to spot */ - UI_ThemeColorShade(TH_STRIP_SELECT, 20); - + int shade = 20; /* draw the markers in the first level of strips only (if they are actions) */ for (NlaStrip *nls = strip->strips.first; nls; nls = nls->next) { if (nls->type == NLASTRIP_TYPE_CLIP) { - nla_actionclip_draw_markers(nls, yminc, ymaxc); + nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, pos); } } } - - glLineWidth(1.0); } /* Strips (Proper) ---------------------- */ @@ -270,12 +285,8 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col } /* helper call for drawing influence/time control curves for a given NLA-strip */ -static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc) +static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos) { - - VertexFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformColor4f(0.7f, 0.7f, 0.7f, 1.0f); const float yheight = ymaxc - yminc; @@ -290,13 +301,13 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc) float cfra; /* plot the curve (over the strip's main region) */ - immBegin(GL_LINE_STRIP, abs(strip->end - strip->start + 1)); + immBegin(GL_LINE_STRIP, abs((int)(strip->end - strip->start) + 1)); /* sample at 1 frame intervals, and draw * - min y-val is yminc, max is y-maxc, so clamp in those regions */ for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) { - float y = evaluate_fcurve(fcu, cfra); // assume this to be in 0-1 range + float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */ immVertex2f(pos, cfra, ((y * yheight) + yminc)); } @@ -330,20 +341,20 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc) /* turn off AA'd lines */ glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); - - //Unbind GPU_SHADER_2D_UNIFORM_COLOR - immUnbindProgram(); } /* main call for drawing a single NLA-strip */ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) { const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0); - float color[3]; - + float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + /* get color of strip */ nla_strip_get_color_inside(adt, strip, color); - + + unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draw extrapolation info first (as backdrop) * - but this should only be drawn if track has some contribution */ @@ -351,7 +362,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri /* enable transparency... */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + switch (strip->extendmode) { /* since this does both sides, only do the 'before' side, and leave the rest to the next case */ case NLASTRIP_EXTEND_HOLD: @@ -360,15 +371,10 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri */ if (strip->prev == NULL) { /* set the drawing color to the color of the strip, but with very faint alpha */ - glColor4f(color[0], color[1], color[2], 0.15f); - + immUniformColor3fvAlpha(color, 0.15f); + /* draw the rect to the edge of the screen */ - glBegin(GL_QUADS); - glVertex2f(v2d->cur.xmin, yminc); - glVertex2f(v2d->cur.xmin, ymaxc); - glVertex2f(strip->start, ymaxc); - glVertex2f(strip->start, yminc); - glEnd(); + immRectf(pos, v2d->cur.xmin, yminc, strip->start, ymaxc); } /* fall-through */ @@ -377,118 +383,132 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri /* only need to try and draw if the next strip doesn't occur immediately after */ if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end) == 0)) { /* set the drawing color to the color of the strip, but this time less faint */ - glColor4f(color[0], color[1], color[2], 0.3f); + immUniformColor3fvAlpha(color, 0.3f); /* draw the rect to the next strip or the edge of the screen */ - glBegin(GL_QUADS); - glVertex2f(strip->end, yminc); - glVertex2f(strip->end, ymaxc); - - if (strip->next) { - glVertex2f(strip->next->start, ymaxc); - glVertex2f(strip->next->start, yminc); - } - else { - glVertex2f(v2d->cur.xmax, ymaxc); - glVertex2f(v2d->cur.xmax, yminc); - } - glEnd(); + float x2 = strip->next ? strip->next->start : v2d->cur.xmax; + immRectf(pos, strip->end, yminc, x2, ymaxc); } break; } - + glDisable(GL_BLEND); } - - + + /* draw 'inside' of strip itself */ if (non_solo == 0) { + immUnbindProgram(); + /* strip is in normal track */ - glColor3fv(color); UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */ - - UI_draw_roundbox_shade_x(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1); + UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color); + + /* restore current vertex format & program (roundbox trashes it) */ + pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); } else { /* strip is in disabled track - make less visible */ - glColor4f(color[0], color[1], color[2], 0.1f); + immUniformColor3fvAlpha(color, 0.1f); glEnable(GL_BLEND); - glRectf(strip->start, yminc, strip->end, ymaxc); + immRectf(pos, strip->start, yminc, strip->end, ymaxc); glDisable(GL_BLEND); } - - + + /* draw strip's control 'curves' * - only if user hasn't hidden them... */ if ((snla->flag & SNLA_NOSTRIPCURVES) == 0) - nla_draw_strip_curves(strip, yminc, ymaxc); - - + nla_draw_strip_curves(strip, yminc, ymaxc, pos); + + /* draw markings indicating locations of local markers (useful for lining up different actions) */ if ((snla->flag & SNLA_NOLOCALMARKERS) == 0) - nla_strip_draw_markers(strip, yminc, ymaxc); - - /* draw strip outline + nla_strip_draw_markers(strip, yminc, ymaxc, pos); + + immUnbindProgram(); + + /* draw strip outline * - color used here is to indicate active vs non-active */ if (strip->flag & NLASTRIP_FLAG_ACTIVE) { /* strip should appear 'sunken', so draw a light border around it */ - glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors + color[0] = 0.9f; /* FIXME: hardcoded temp-hack colors */ + color[1] = 1.0f; + color[2] = 0.9f; } else { /* strip should appear to stand out, so draw a dark border around it */ - glColor3f(0.0f, 0.0f, 0.0f); + color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */ } - + /* - line style: dotted for muted */ if ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED)) setlinestyle(4); - + /* draw outline */ - UI_draw_roundbox_shade_x(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1); - + UI_draw_roundbox_shade_x(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color); + + /* restore current vertex format & program (roundbox trashes it) */ + pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor3fv(color); + /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */ if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQF(strip->repeat, 1.0f) == 0) { float repeatLen = (strip->actend - strip->actstart) * strip->scale; - int i; - + /* only draw lines for whole-numbered repeats, starting from the first full-repeat * up to the last full repeat (but not if it lies on the end of the strip) */ - for (i = 1; i < strip->repeat; i++) { + immBeginAtMost(PRIM_LINES, 2 * (strip->repeat - 1)); + for (int i = 1; i < strip->repeat; i++) { float repeatPos = strip->start + (repeatLen * i); - + /* don't draw if line would end up on or after the end of the strip */ - if (repeatPos < strip->end) - fdrawline(repeatPos, yminc + 4, repeatPos, ymaxc - 4); + if (repeatPos < strip->end) { + immVertex2f(pos, repeatPos, yminc + 4); + immVertex2f(pos, repeatPos, ymaxc - 4); + } } + immEnd(); } /* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */ else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) { - NlaStrip *cs; - float y = (ymaxc - yminc) / 2.0f + yminc; - + float y = (ymaxc - yminc) * 0.5f + yminc; + + immBeginAtMost(PRIM_LINES, 4 * BLI_listbase_count(&strip->strips)); /* up to 2 lines per strip */ + /* only draw first-level of child-strips, but don't draw any lines on the endpoints */ - for (cs = strip->strips.first; cs; cs = cs->next) { + for (NlaStrip *cs = strip->strips.first; cs; cs = cs->next) { /* draw start-line if not same as end of previous (and only if not the first strip) * - on upper half of strip */ - if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) - fdrawline(cs->start, y, cs->start, ymaxc); - + if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) { + immVertex2f(pos, cs->start, y); + immVertex2f(pos, cs->start, ymaxc); + } + /* draw end-line if not the last strip * - on lower half of strip */ - if (cs->next) - fdrawline(cs->end, yminc, cs->end, y); + if (cs->next) { + immVertex2f(pos, cs->end, yminc); + immVertex2f(pos, cs->end, y); + } } + + immEnd(); } - + /* reset linestyle */ setlinestyle(0); -} + immUnbindProgram(); +} /* add the relevant text to the cache of text-strings to draw in pixelspace */ static void nla_draw_strip_text( @@ -499,7 +519,6 @@ static void nla_draw_strip_text( char str[256]; size_t str_len; char col[4]; - rctf rect; /* just print the name and the range */ if (strip->flag & NLASTRIP_FLAG_TEMP_META) { @@ -526,12 +545,14 @@ static void nla_draw_strip_text( /* set bounding-box for text * - padding of 2 'units' on either side */ - // TODO: make this centered? - rect.xmin = xminc; - rect.ymin = yminc; - rect.xmax = xmaxc; - rect.ymax = ymaxc; - + /* TODO: make this centered? */ + rctf rect = { + .xmin = xminc, + .ymin = yminc, + .xmax = xmaxc, + .ymax = ymaxc + }; + /* add this string to the cache of texts to draw */ UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col); } @@ -544,9 +565,7 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */ const char col[4] = {220, 220, 220, 255}; /* light gray */ char numstr[32]; - size_t numstr_len; - - + /* Always draw times above the strip, whereas sequencer drew below + above. * However, we should be fine having everything on top, since these tend to be * quite spaced out. @@ -554,9 +573,9 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V * while also preserving some accuracy, since we do use floats */ /* start frame */ - numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start); + size_t numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start); UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col); - + /* end frame */ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end); UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col); @@ -566,20 +585,14 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - View2D *v2d = &ar->v2d; - float y = 0.0f; - size_t items; - int height; const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); const float text_margin_x = (8 * UI_DPI_FAC) * pixelx; /* build list of channels to draw */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + ListBase anim_data = {NULL, NULL}; + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Update max-extent of channels here (taking into account scrollers): * - this is done to allow the channel list to be scrollable, but must be done here @@ -587,16 +600,16 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for * start of list offset, and the second is as a correction for the scrollers. */ - height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); + int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ v2d->tot.ymin = (float)(-height); /* loop through channels, and set up drawing depending on their type */ - y = (float)(-NLACHANNEL_HEIGHT(snla)); + float y = (float)(-NLACHANNEL_HEIGHT(snla)); - for (ale = anim_data.first; ale; ale = ale->next) { + for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) { const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); @@ -610,11 +623,10 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) { AnimData *adt = ale->adt; NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - int index; /* draw each strip in the track (if visible) */ - for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) { + int index = 1; + for (NlaStrip *strip = nlt->strips.first; strip; strip = strip->next, index++) { if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { const float xminc = strip->start + text_margin_x; const float xmaxc = strip->end + text_margin_x; @@ -639,45 +651,60 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) case ANIMTYPE_NLAACTION: { AnimData *adt = ale->adt; - float color[4]; - + + unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, * and a second darker rect within which we draw keyframe indicator dots if there's data */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + /* get colors for drawing */ + float color[4]; nla_action_get_color(adt, ale->data, color); - glColor4fv(color); - + immUniformColor4fv(color); + /* draw slightly shifted up for greater separation from standard channels, * but also slightly shorter for some more contrast when viewing the strips */ - glRectf(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - - /* draw keyframes in the action */ - nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP); + immRectf(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); /* draw 'embossed' lines above and below the strip for effect */ /* white base-lines */ glLineWidth(2.0f); - glColor4f(1.0f, 1.0f, 1.0f, 0.3); - fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); - fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3); + immBegin(PRIM_LINES, 4); + immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); + immEnd(); + /* black top-lines */ glLineWidth(1.0f); - glColor3f(0.0f, 0.0f, 0.0f); - fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); - fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - + immUniformColor3f(0.0f, 0.0f, 0.0f); + immBegin(PRIM_LINES, 4); + immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); + immEnd(); + + /* TODO: these lines but better --^ */ + + immUnbindProgram(); + + /* draw keyframes in the action */ + nla_action_draw_keyframes(adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP); + glDisable(GL_BLEND); break; } } } - + /* adjust y-position for next one */ y -= NLACHANNEL_STEP(snla); } @@ -693,17 +720,14 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - int filter; SpaceNla *snla = (SpaceNla *)ac->sl; View2D *v2d = &ar->v2d; float y = 0.0f; - size_t items; - int height; /* build list of channels to draw */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Update max-extent of channels here (taking into account scrollers): * - this is done to allow the channel list to be scrollable, but must be done here @@ -711,7 +735,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for * start of list offset, and the second is as a correction for the scrollers. */ - height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); + int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); /* 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_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index e02c69ea857..5940ed5f0c1 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3619,27 +3619,27 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) // node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); } -void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border) +void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos) { - glBegin(GL_LINES); + immBegin(GL_LINES, 4); if (border & (NODE_LEFT | NODE_RIGHT)) { - glVertex2f(cent[0], v2d->cur.ymin); - glVertex2f(cent[0], v2d->cur.ymax); + immVertex2f(pos, cent[0], v2d->cur.ymin); + immVertex2f(pos, cent[0], v2d->cur.ymax); } else { - glVertex2f(cent[0], cent[1] - size); - glVertex2f(cent[0], cent[1] + size); + immVertex2f(pos, cent[0], cent[1] - size); + immVertex2f(pos, cent[0], cent[1] + size); } if (border & (NODE_TOP | NODE_BOTTOM)) { - glVertex2f(v2d->cur.xmin, cent[1]); - glVertex2f(v2d->cur.xmax, cent[1]); + immVertex2f(pos, v2d->cur.xmin, cent[1]); + immVertex2f(pos, v2d->cur.xmax, cent[1]); } else { - glVertex2f(cent[0] - size, cent[1]); - glVertex2f(cent[0] + size, cent[1]); + immVertex2f(pos, cent[0] - size, cent[1]); + immVertex2f(pos, cent[0] + size, cent[1]); } - glEnd(); + immEnd(); } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 2a0593e6a0d..80b19176c90 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -1269,7 +1269,7 @@ static void draw_tree_path(SpaceNode *snode) ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info)); - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info)); } @@ -1315,7 +1315,7 @@ static void draw_group_overlay(const bContext *C, ARegion *ar) UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, -70, color); UI_draw_roundbox_corner_set(UI_CNR_NONE); - UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color); + UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color); glDisable(GL_BLEND); /* set the block bounds to clip mouse events from underlying nodes */ diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 998dad6466b..d15c3d67d45 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -51,6 +51,7 @@ #include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_modifier.h" @@ -174,116 +175,6 @@ static void restrictbutton_recursive_bone(Bone *bone_parent, int flag, bool set_ } -static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob_parent, char flag, - bool state, bool deselect, const char *rnapropname) -{ - Main *bmain = CTX_data_main(C); - Object *ob; - - for (ob = bmain->object.first; ob; ob = ob->id.next) { - if (BKE_object_is_child_recursive(ob_parent, ob)) { - /* only do if child object is selectable */ - if ((flag == OB_RESTRICT_SELECT) || (ob->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (state) { - ob->restrictflag |= flag; - if (deselect) { - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - } - else { - ob->restrictflag &= ~flag; - } - } - - if (rnapropname) { - PointerRNA ptr; - PropertyRNA *prop; - ID *id; - bAction *action; - FCurve *fcu; - bool driven, special; - - RNA_id_pointer_create(&ob->id, &ptr); - prop = RNA_struct_find_property(&ptr, rnapropname); - fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, &special); - - if (fcu && !driven) { - id = ptr.id.data; - if (autokeyframe_cfra_can_key(scene, id)) { - ReportList *reports = CTX_wm_reports(C); - ToolSettings *ts = scene->toolsettings; - eInsertKeyFlags key_flag = ANIM_get_keyframing_flags(scene, 1); - - fcu->flag &= ~FCURVE_SELECTED; - insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), - fcu->rna_path, fcu->array_index, CFRA, ts->keyframe_type, key_flag); - /* Assuming this is not necessary here, since 'ancestor' object button will do it anyway. */ - /* WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); */ - } - } - } - } - } -} - -static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2) -{ - Scene *scene = (Scene *)poin; - Object *ob = (Object *)poin2; - - if (!common_restrict_check(C, ob)) return; - - /* deselect objects that are invisible */ - if (ob->restrictflag & OB_RESTRICT_VIEW) { - /* Ouch! There is no backwards pointer from Object to Base, - * so have to do loop to find it. */ - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_VIEW, - (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true, "hide"); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - -} - -static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2) -{ - Scene *scene = (Scene *)poin; - Object *ob = (Object *)poin2; - - if (!common_restrict_check(C, ob)) return; - - /* if select restriction has just been turned on */ - if (ob->restrictflag & OB_RESTRICT_SELECT) { - /* Ouch! There is no backwards pointer from Object to Base, - * so have to do loop to find it. */ - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_SELECT, - (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true, NULL); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - -} - -static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2) -{ - Object *ob = (Object *)poin2; - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, (Scene *)poin, ob, OB_RESTRICT_RENDER, - (ob->restrictflag & OB_RESTRICT_RENDER) != 0, false, "hide_render"); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin); -} - static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2)) { WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin); @@ -357,96 +248,32 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } -static int group_restrict_flag(Group *gr, int flag) +static void restrictbutton_collection_hide_cb(bContext *C, void *poin, void *poin2) { - GroupObject *gob; + Scene *scene = poin; + LayerCollection *collection = poin2; + SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, collection); -#ifdef USE_GROUP_SELECT - for (gob = gr->gobject.first; gob; gob = gob->next) { - if ((gob->ob->restrictflag & flag) == 0) - return 0; - } - return 1; -#else - /* weak but fast */ - if ((gob = gr->gobject.first)) - if ((gob->ob->restrictflag & flag) == 0) - return 0; - return 1; -#endif -} - -static int group_select_flag(Group *gr) -{ - GroupObject *gob; - -#ifdef USE_GROUP_SELECT - for (gob = gr->gobject.first; gob; gob = gob->next) - if ((gob->ob->flag & SELECT)) - return 1; - - return 0; -#else - /* weak but fast */ - if ((gob = gr->gobject.first)) - if (gob->ob->flag & SELECT) - return 1; - return 0; -#endif + /* hide and deselect bases that are directly influenced by this LayerCollection */ + BKE_scene_layer_base_flag_recalculate(sl); + BKE_scene_layer_engine_settings_collection_recalculate(sl, collection); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL); } -void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag) +static void restrictbutton_collection_hide_select_cb(bContext *C, void *poin, void *poin2) { - Scene *scene = (Scene *)poin; - GroupObject *gob; - Group *gr = (Group *)poin2; + Scene *scene = poin; + LayerCollection *collection = poin2; - if (group_restrict_flag(gr, flag)) { - for (gob = gr->gobject.first; gob; gob = gob->next) { - if (ID_IS_LINKED_DATABLOCK(gob->ob)) - continue; + if ((collection->flag & COLLECTION_SELECTABLE) == 0) { + SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, collection); - gob->ob->restrictflag &= ~flag; - - if (flag == OB_RESTRICT_VIEW) - if (gob->ob->flag & SELECT) - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT); - } + /* deselect bases that are directly influenced by this LayerCollection */ + BKE_scene_layer_base_flag_recalculate(sl); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); } - else { - for (gob = gr->gobject.first; gob; gob = gob->next) { - if (ID_IS_LINKED_DATABLOCK(gob->ob)) - continue; - - /* not in editmode */ - if (scene->obedit != gob->ob) { - gob->ob->restrictflag |= flag; - - if (ELEM(flag, OB_RESTRICT_SELECT, OB_RESTRICT_VIEW)) { - if ((gob->ob->flag & SELECT)) { - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT); - } - } - } - } - } -} - -static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2) -{ - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_VIEW); - WM_event_add_notifier(C, NC_GROUP, NULL); - DAG_id_type_tag(CTX_data_main(C), ID_OB); -} -static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2) -{ - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_SELECT); - WM_event_add_notifier(C, NC_GROUP, NULL); -} -static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poin2) -{ - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_RENDER); - WM_event_add_notifier(C, NC_GROUP, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL); } static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2)) @@ -468,6 +295,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) { SpaceOops *soops = CTX_wm_space_outliner(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); BLI_mempool *ts = soops->treestore; TreeStoreElem *tselem = tsep; @@ -529,7 +357,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) BLI_strncpy(newname, ebone->name, sizeof(ebone->name)); BLI_strncpy(ebone->name, oldname, sizeof(ebone->name)); ED_armature_bone_rename(obedit->data, oldname, newname); - WM_event_add_notifier(C, NC_OBJECT | ND_POSE, OBACT); + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, OBACT_NEW); } break; } @@ -541,8 +369,8 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) char newname[sizeof(bone->name)]; /* always make current object active */ - tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, true); - ob = OBACT; + tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, true); + ob = OBACT_NEW; /* restore bone name */ BLI_strncpy(newname, bone->name, sizeof(bone->name)); @@ -558,8 +386,8 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) char newname[sizeof(pchan->name)]; /* always make current pose-bone active */ - tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, true); - ob = OBACT; + tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, true); + ob = OBACT_NEW; BLI_assert(ob->type == OB_ARMATURE); @@ -605,7 +433,6 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar TreeElement *te; TreeStoreElem *tselem; Object *ob = NULL; - Group *gr = NULL; PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render; @@ -619,73 +446,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar for (te = lb->first; te; te = te->next) { tselem = TREESTORE(te); if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { - /* objects have toggle-able restriction flags */ - if (tselem->type == 0 && te->idcode == ID_OB) { - PointerRNA ptr; - - ob = (Object *)tselem->id; - RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr); - - UI_block_emboss_set(block, UI_EMBOSS_NONE); - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide, -1, 0, 0, -1, -1, - TIP_("Restrict viewport visibility (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_view_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide_select, -1, 0, 0, -1, -1, - TIP_("Restrict viewport selection (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_sel_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide_render, -1, 0, 0, -1, -1, - TIP_("Restrict rendering (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_rend_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - UI_block_emboss_set(block, UI_EMBOSS); - - } - if (tselem->type == 0 && te->idcode == ID_GR) { - int restrict_bool; - int but_flag = UI_BUT_DRAG_LOCK; - gr = (Group *)tselem->id; - - if (ID_IS_LINKED_DATABLOCK(gr)) - but_flag |= UI_BUT_DISABLED; - - UI_block_emboss_set(block, UI_EMBOSS_NONE); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View")); - UI_but_func_set(bt, restrictbutton_gr_restrict_view, scene, gr); - UI_but_flag_enable(bt, but_flag); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow selection in the 3D View")); - UI_but_func_set(bt, restrictbutton_gr_restrict_select, scene, gr); - UI_but_flag_enable(bt, but_flag); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow renderability")); - UI_but_func_set(bt, restrictbutton_gr_restrict_render, scene, gr); - UI_but_flag_enable(bt, but_flag); - - UI_block_emboss_set(block, UI_EMBOSS); - } /* scene render layers and passes have toggle-able flags too! */ - else if (tselem->type == TSE_R_LAYER) { + if (tselem->type == TSE_R_LAYER) { UI_block_emboss_set(block, UI_EMBOSS_NONE); bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1, @@ -807,6 +569,27 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar UI_block_emboss_set(block, UI_EMBOSS); } + else if (tselem->type == TSE_COLLECTION) { + LayerCollection *collection = te->directdata; + + UI_block_emboss_set(block, UI_EMBOSS_NONE); + + bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_VISIBLE, 0, ICON_RESTRICT_VIEW_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, + TIP_("Restrict/Allow 3D View visibility of objects in the collection")); + UI_but_func_set(bt, restrictbutton_collection_hide_cb, scene, collection); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, + TIP_("Restrict/Allow 3D View selection of objects in the collection")); + UI_but_func_set(bt, restrictbutton_collection_hide_select_cb, scene, collection); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + UI_block_emboss_set(block, UI_EMBOSS); + } } if (TSELEM_OPEN(tselem, soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree); @@ -1350,7 +1133,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto } } -static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, +static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SceneLayer *sl, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys) { TreeElement *te; @@ -1371,17 +1154,17 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa /* active blocks get white circle */ if (tselem->type == 0) { if (te->idcode == ID_OB) { - active = (OBACT == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE; + active = (OBACT_NEW == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE; } else if (scene->obedit && scene->obedit->data == tselem->id) { active = OL_DRAWSEL_NORMAL; } else { - active = tree_element_active(C, scene, soops, te, OL_SETSEL_NONE, false); + active = tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NONE, false); } } else { - active = tree_element_type_active(NULL, scene, soops, te, tselem, OL_SETSEL_NONE, false); + active = tree_element_type_active(NULL, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false); } if (active != OL_DRAWSEL_NONE) { @@ -1410,7 +1193,7 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa /* this tree element always has same amount of branches, so don't draw */ if (tselem->type != TSE_R_LAYER) - outliner_draw_iconrow(C, block, scene, soops, &te->subtree, level + 1, xmax, offsx, ys); + outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, level + 1, xmax, offsx, ys); } } @@ -1434,7 +1217,7 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta static void outliner_draw_tree_element( - bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ARegion *ar, SpaceOops *soops, + bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, SceneLayer *sl, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty, TreeElement **te_edit) { TreeElement *ten; @@ -1467,26 +1250,16 @@ static void outliner_draw_tree_element( active = OL_DRAWSEL_ACTIVE; } } - else if (te->idcode == ID_GR) { - Group *gr = (Group *)tselem->id; - if (group_select_flag(gr)) { - char col[4]; - UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col); - rgba_float_args_set(color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha); - - active = OL_DRAWSEL_ACTIVE; - } - } else if (te->idcode == ID_OB) { Object *ob = (Object *)tselem->id; - if (ob == OBACT || (ob->flag & SELECT)) { + if (ob == OBACT_NEW || (ob->flag & SELECT)) { char col[4] = {0, 0, 0, 0}; /* outliner active ob: always white text, circle color now similar to view3d */ active = OL_DRAWSEL_ACTIVE; - if (ob == OBACT) { + if (ob == OBACT_NEW) { if (ob->flag & SELECT) { UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col); col[3] = alpha; @@ -1507,14 +1280,14 @@ static void outliner_draw_tree_element( active = OL_DRAWSEL_ACTIVE; } else { - if (tree_element_active(C, scene, soops, te, OL_SETSEL_NONE, false)) { + if (tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NONE, false)) { rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha); active = OL_DRAWSEL_ACTIVE; } } } else { - if (tree_element_type_active(NULL, scene, soops, te, tselem, OL_SETSEL_NONE, false) != OL_DRAWSEL_NONE) { + if (tree_element_type_active(NULL, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false) != OL_DRAWSEL_NONE) { active = OL_DRAWSEL_ACTIVE; } rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha); @@ -1579,17 +1352,20 @@ static void outliner_draw_tree_element( /* name */ if ((tselem->flag & TSE_TEXTBUT) == 0) { + unsigned char text_col[4]; + if (active == OL_DRAWSEL_NORMAL) { - UI_ThemeColor(TH_TEXT_HI); + UI_GetThemeColor4ubv(TH_TEXT_HI, text_col); } else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { - UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f); + UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.75f, text_col); + text_col[3] = 255; } else { - UI_ThemeColor(TH_TEXT); + UI_GetThemeColor4ubv(TH_TEXT, text_col); } - UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name); + UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_col); } offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name)); @@ -1606,16 +1382,23 @@ static void outliner_draw_tree_element( int tempx = startx + offsx; /* divider */ - UI_ThemeColorShade(TH_BACK, -40); - glRecti(tempx - 10.0f * ufac, - *starty + 4.0f * ufac, - tempx - 8.0f * ufac, - *starty + UI_UNIT_Y - 4.0f * ufac); - + { + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + unsigned char col[4]; + UI_GetThemeColorShade4ubv(TH_BACK, -40, col); + immUniformColor4ubv(col); + immRecti(pos, tempx - 10.0f * ufac, + *starty + 4.0f * ufac, + tempx - 8.0f * ufac, + *starty + UI_UNIT_Y - 4.0f * ufac); + immUnbindProgram(); + } glEnable(GL_BLEND); glPixelTransferf(GL_ALPHA_SCALE, 0.5); - outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty); + outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, 0, xmax, &tempx, *starty); glPixelTransferf(GL_ALPHA_SCALE, 1.0); glDisable(GL_BLEND); @@ -1632,7 +1415,7 @@ static void outliner_draw_tree_element( *starty -= UI_UNIT_Y; for (ten = te->subtree.first; ten; ten = ten->next) { - outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit); + outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit); } } else { @@ -1644,14 +1427,14 @@ static void outliner_draw_tree_element( } } -static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty) +static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soops, ListBase *lb, int startx, int *starty) { + if (BLI_listbase_is_empty(lb)) return; + TreeElement *te; TreeStoreElem *tselem; int y1, y2; - - if (BLI_listbase_is_empty(lb)) return; - + y1 = y2 = *starty; /* for vertical lines between objects */ for (te = lb->first; te; te = te->next) { y2 = *starty; @@ -1659,25 +1442,35 @@ static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int st /* horizontal line? */ if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE)) - glRecti(startx, *starty, startx + UI_UNIT_X, *starty - 1); + immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - 1); *starty -= UI_UNIT_Y; if (TSELEM_OPEN(tselem, soops)) - outliner_draw_hierarchy_lines(soops, &te->subtree, startx + UI_UNIT_X, starty); + outliner_draw_hierarchy_lines_recursive(pos, soops, &te->subtree, startx + UI_UNIT_X, starty); } /* vertical line */ te = lb->last; if (te->parent || lb->first != lb->last) { tselem = TREESTORE(te); - if (tselem->type == 0 && te->idcode == ID_OB) { - - glRecti(startx, y1 + UI_UNIT_Y, startx + 1, y2); - } + if (tselem->type == 0 && te->idcode == ID_OB) + immRecti(pos, startx, y1 + UI_UNIT_Y, startx + 1, y2); } } +static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty) +{ + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + unsigned char col[3]; + UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col); + immUniformColor3ubv(col); + outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, starty); + immUnbindProgram(); +} + static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) { TreeElement *te; @@ -1713,7 +1506,7 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase * } static void outliner_draw_highlights_recursive( - const ARegion *ar, const SpaceOops *soops, const ListBase *lb, + unsigned pos, const ARegion *ar, const SpaceOops *soops, const ListBase *lb, const float col_selection[4], const float col_highlight[4], const float col_searchmatch[4], int start_x, int *io_start_y) { @@ -1726,29 +1519,29 @@ static void outliner_draw_highlights_recursive( /* selection status */ if (tselem->flag & TSE_SELECTED) { - glColor4fv(col_selection); - glRecti(0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); + immUniformColor4fv(col_selection); + immRecti(pos, 0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); } /* search match highlights * we don't expand items when searching in the datablocks but we * still want to highlight any filter matches. */ if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) { - glColor4fv(col_searchmatch); - glRecti(start_x, start_y + 1, ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); + immUniformColor4fv(col_searchmatch); + immRecti(pos, start_x, start_y + 1, ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); } /* mouse hover highlights */ if (tselem->flag & TSE_HIGHLIGHTED) { - glColor4fv(col_highlight); - glRecti(0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); + immUniformColor4fv(col_highlight); + immRecti(pos, 0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1); } *io_start_y -= UI_UNIT_Y; if (TSELEM_OPEN(tselem, soops)) { outliner_draw_highlights_recursive( - ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch, - start_x + UI_UNIT_X, io_start_y); + pos, ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch, + start_x + UI_UNIT_X, io_start_y); } } } @@ -1764,13 +1557,17 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx, col_searchmatch[3] = 0.5f; glEnable(GL_BLEND); - outliner_draw_highlights_recursive(ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch, - startx, starty); + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + outliner_draw_highlights_recursive(pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch, + startx, starty); + immUnbindProgram(); glDisable(GL_BLEND); } static void outliner_draw_tree( - bContext *C, uiBlock *block, Scene *scene, ARegion *ar, + bContext *C, uiBlock *block, Scene *scene, SceneLayer *sl, ARegion *ar, SpaceOops *soops, const bool has_restrict_icons, TreeElement **te_edit) { @@ -1801,7 +1598,7 @@ static void outliner_draw_tree( } // gray hierarchy lines - UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f); + starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET; startx = 6; outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty); @@ -1810,7 +1607,7 @@ static void outliner_draw_tree( starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET; startx = 0; for (TreeElement *te = soops->tree.first; te; te = te->next) { - outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, te, startx, &starty, te_edit); + outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, te, startx, &starty, te_edit); } if (has_restrict_icons) { @@ -1882,6 +1679,7 @@ void draw_outliner(const bContext *C) { Main *mainvar = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; SpaceOops *soops = CTX_wm_space_outliner(C); @@ -1890,7 +1688,7 @@ void draw_outliner(const bContext *C) TreeElement *te_edit = NULL; bool has_restrict_icons; - outliner_build_tree(mainvar, scene, soops); // always + outliner_build_tree(mainvar, scene, sl, soops); // always /* get extents of data */ outliner_height(soops, &soops->tree, &sizey); @@ -1940,7 +1738,7 @@ void draw_outliner(const bContext *C) /* draw outliner stuff (background, hierarchy lines and names) */ outliner_back(ar); block = UI_block_begin(C, ar, __func__, UI_EMBOSS); - outliner_draw_tree((bContext *)C, block, scene, ar, soops, has_restrict_icons, &te_edit); + outliner_draw_tree((bContext *)C, block, scene, sl, ar, soops, has_restrict_icons, &te_edit); if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) { /* draw rna buttons */ diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 4dcdcc69d6d..0afaf298264 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -54,6 +54,7 @@ #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idcode.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -882,181 +883,6 @@ int common_restrict_check(bContext *C, Object *ob) } /* =============================================== */ -/* Restriction toggles */ - -/* Toggle Visibility ---------------------------------------- */ - -void object_toggle_visibility_cb( - bContext *C, ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - Object *ob = (Object *)tselem->id; - - if (ID_IS_LINKED_DATABLOCK(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - /* add check for edit mode */ - if (!common_restrict_check(C, ob)) return; - - if (base || (base = BKE_scene_base_find(scene, ob))) { - if ((base->object->restrictflag ^= OB_RESTRICT_VIEW)) { - ED_base_object_select(base, BA_DESELECT); - } - } -} - -void group_toggle_visibility_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_VIEW); -} - -static int outliner_toggle_visibility_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb); - - DAG_id_type_tag(bmain, ID_OB); - WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); - ED_region_tag_redraw(ar); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_visibility_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Visibility"; - ot->idname = "OUTLINER_OT_visibility_toggle"; - ot->description = "Toggle the visibility of selected items"; - - /* callbacks */ - ot->exec = outliner_toggle_visibility_exec; - ot->poll = ED_operator_outliner_active_no_editobject; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* Toggle Selectability ---------------------------------------- */ - -void object_toggle_selectability_cb( - bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - - if (ID_IS_LINKED_DATABLOCK(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { - base->object->restrictflag ^= OB_RESTRICT_SELECT; - } -} - -void group_toggle_selectability_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_SELECT); -} - -static int outliner_toggle_selectability_exec(bContext *C, wmOperator *op) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb); - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - ED_region_tag_redraw(ar); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_selectability_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Selectability"; - ot->idname = "OUTLINER_OT_selectability_toggle"; - ot->description = "Toggle the selectability"; - - /* callbacks */ - ot->exec = outliner_toggle_selectability_exec; - ot->poll = ED_operator_outliner_active_no_editobject; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* Toggle Renderability ---------------------------------------- */ - -void object_toggle_renderability_cb( - bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - - if (ID_IS_LINKED_DATABLOCK(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { - base->object->restrictflag ^= OB_RESTRICT_RENDER; - } -} - -void group_toggle_renderability_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_RENDER); -} - -static int outliner_toggle_renderability_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb); - - DAG_id_type_tag(bmain, ID_OB); - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_renderability_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Renderability"; - ot->idname = "OUTLINER_OT_renderability_toggle"; - ot->description = "Toggle the renderability of selected items"; - - /* callbacks */ - ot->exec = outliner_toggle_renderability_exec; - ot->poll = ED_operator_outliner_active; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* =============================================== */ /* Outliner setting toggles */ /* Toggle Expanded (Outliner) ---------------------------------------- */ @@ -1177,14 +1003,14 @@ static int outliner_open_back(TreeElement *te) static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceOops *so = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; TreeElement *te; int xdelta, ytop; - Object *obact = OBACT; + Object *obact = OBACT_NEW; if (!obact) return OPERATOR_CANCELLED; @@ -2345,8 +2171,6 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) te = outliner_dropzone_find(soops, fmval, false); if (te) { - Base *base; - RNA_string_set(op->ptr, "scene", te->name); scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name); @@ -2357,16 +2181,26 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED; } - base = ED_object_scene_link(scene, ob); - - if (base == NULL) { + if (BKE_scene_has_object(scene, ob)) { return OPERATOR_CANCELLED; } - if (scene == CTX_data_scene(C)) { - /* when linking to an inactive scene don't touch the layer */ - ob->lay = base->lay; - ED_base_object_select(base, BA_SELECT); + SceneCollection *sc; + if (scene != CTX_data_scene(C)) { + /* when linking to an inactive scene link to the master collection */ + sc = BKE_collection_master(scene); + } + else { + sc = CTX_data_scene_collection(C); + } + + BKE_collection_object_add(scene, sc, ob); + + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + Base *base = BKE_scene_layer_base_find(sl, ob); + if (base) { + ED_object_base_select(base, BA_SELECT); + } } DAG_relations_tag_update(bmain); @@ -2461,7 +2295,6 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) Main *bmain = CTX_data_main(C); Group *group = NULL; Object *ob = NULL; - Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); ARegion *ar = CTX_wm_region(C); TreeElement *te = NULL; @@ -2491,7 +2324,7 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED; } - BKE_group_object_add(group, ob, scene, NULL); + BKE_group_object_add(group, ob); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index f23c294c488..768fe4d8551 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -40,6 +40,7 @@ struct wmOperatorType; struct TreeStoreElem; struct bContext; struct Scene; +struct SceneLayer; struct ID; struct Object; struct bPoseChannel; @@ -141,7 +142,7 @@ TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel * TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone); struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode); -void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SpaceOops *soops); +void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops); /* outliner_draw.c ---------------------------------------------- */ @@ -150,9 +151,9 @@ void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag); /* outliner_select.c -------------------------------------------- */ eOLDrawState tree_element_type_active( - struct bContext *C, struct Scene *scene, struct SpaceOops *soops, + struct bContext *C, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive); -eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, SpaceOops *soops, +eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, struct SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set, const bool handle_all_types); int outliner_item_activate_or_toggle_closed(struct bContext *C, int x, int y, bool extend, bool recursive); @@ -239,10 +240,6 @@ void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot); void OUTLINER_OT_scroll_page(struct wmOperatorType *ot); -void OUTLINER_OT_renderability_toggle(struct wmOperatorType *ot); -void OUTLINER_OT_selectability_toggle(struct wmOperatorType *ot); -void OUTLINER_OT_visibility_toggle(struct wmOperatorType *ot); - void OUTLINER_OT_keyingset_add_selected(struct wmOperatorType *ot); void OUTLINER_OT_keyingset_remove_selected(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index f0c2d848f7a..5ddfdddc80d 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -71,10 +71,6 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_selected_toggle); WM_operatortype_append(OUTLINER_OT_expanded_toggle); - WM_operatortype_append(OUTLINER_OT_renderability_toggle); - WM_operatortype_append(OUTLINER_OT_selectability_toggle); - WM_operatortype_append(OUTLINER_OT_visibility_toggle); - WM_operatortype_append(OUTLINER_OT_keyingset_add_selected); WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected); @@ -143,11 +139,6 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OUTLINER_OT_selected_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OUTLINER_OT_expanded_toggle", AKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_renderability_toggle", RKEY, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_selectability_toggle", SKEY, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_visibility_toggle", VKEY, KM_PRESS, 0, 0); - - /* keying sets - only for databrowse */ WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_add_selected", KKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_remove_selected", KKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index a73e160f357..1fad5f26218 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -46,6 +46,7 @@ #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_object.h" +#include "BKE_layer.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_armature.h" @@ -73,7 +74,7 @@ /* Outliner Element Selection/Activation on Click */ static eOLDrawState tree_element_active_renderlayer( - bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) { Scene *sce; @@ -99,7 +100,7 @@ static eOLDrawState tree_element_active_renderlayer( */ static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select) { - Base *base; + BaseLegacy *base; for (base = FIRSTBASE; base; base = base->next) { Object *ob = base->object; @@ -135,7 +136,7 @@ static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_p } static eOLDrawState tree_element_set_active_object( - bContext *C, Scene *scene, SpaceOops *soops, + bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set, bool recursive) { TreeStoreElem *tselem = TREESTORE(te); @@ -149,7 +150,7 @@ static eOLDrawState tree_element_set_active_object( } else { ob = (Object *)outliner_search_back(soops, te, ID_OB); - if (ob == OBACT) { + if (ob == OBACT_NEW) { return OL_DRAWSEL_NONE; } } @@ -169,15 +170,15 @@ static eOLDrawState tree_element_set_active_object( if (base) { if (set == OL_SETSEL_EXTEND) { /* swap select */ - if (base->flag & SELECT) - ED_base_object_select(base, BA_DESELECT); + if (base->flag & BASE_SELECTED) + ED_object_base_select(base, BA_DESELECT); else - ED_base_object_select(base, BA_SELECT); + ED_object_base_select(base, BA_SELECT); } else { /* deleselect all */ - BKE_scene_base_deselect_all(scene); - ED_base_object_select(base, BA_SELECT); + BKE_scene_layer_base_deselect_all(sl); + ED_object_base_select(base, BA_SELECT); } if (recursive) { @@ -186,7 +187,7 @@ static eOLDrawState tree_element_set_active_object( } if (C) { - ED_base_object_activate(C, base); /* adds notifier */ + ED_object_base_activate(C, base); /* adds notifier */ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } } @@ -198,7 +199,7 @@ static eOLDrawState tree_element_set_active_object( } static eOLDrawState tree_element_active_material( - bContext *C, Scene *scene, SpaceOops *soops, + bContext *C, Scene* UNUSED(scene), SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set) { TreeElement *tes; @@ -207,7 +208,7 @@ static eOLDrawState tree_element_active_material( /* we search for the object parent */ ob = (Object *)outliner_search_back(soops, te, ID_OB); // note: ob->matbits can be NULL when a local object points to a library mesh. - if (ob == NULL || ob != OBACT || ob->matbits == NULL) { + if (ob == NULL || ob != OBACT_NEW || ob->matbits == NULL) { return OL_DRAWSEL_NONE; /* just paranoia */ } @@ -251,12 +252,12 @@ static eOLDrawState tree_element_active_material( } static eOLDrawState tree_element_active_texture( - bContext *C, Scene *scene, SpaceOops *UNUSED(soops), + bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *UNUSED(soops), TreeElement *te, const eOLSetState set) { TreeElement *tep; TreeStoreElem /* *tselem,*/ *tselemp; - Object *ob = OBACT; + Object *ob = OBACT_NEW; SpaceButs *sbuts = NULL; if (ob == NULL) { @@ -338,14 +339,14 @@ static eOLDrawState tree_element_active_texture( static eOLDrawState tree_element_active_lamp( - bContext *UNUSED(C), Scene *scene, SpaceOops *soops, + bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set) { Object *ob; /* we search for the object parent */ ob = (Object *)outliner_search_back(soops, te, ID_OB); - if (ob == NULL || ob != OBACT) { + if (ob == NULL || ob != OBACT_NEW) { /* just paranoia */ return OL_DRAWSEL_NONE; } @@ -361,7 +362,7 @@ static eOLDrawState tree_element_active_lamp( } static eOLDrawState tree_element_active_camera( - bContext *UNUSED(C), Scene *scene, SpaceOops *soops, + bContext *UNUSED(C), Scene *scene, SceneLayer *UNUSED(sl), SpaceOops *soops, TreeElement *te, const eOLSetState set) { Object *ob = (Object *)outliner_search_back(soops, te, ID_OB); @@ -374,7 +375,7 @@ static eOLDrawState tree_element_active_camera( } static eOLDrawState tree_element_active_world( - bContext *C, Scene *scene, SpaceOops *UNUSED(soops), + bContext *C, Scene *scene, SceneLayer *UNUSED(sl), SpaceOops *UNUSED(soops), TreeElement *te, const eOLSetState set) { TreeElement *tep; @@ -407,7 +408,7 @@ static eOLDrawState tree_element_active_world( } static eOLDrawState tree_element_active_defgroup( - bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) + bContext *C, SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) { Object *ob; @@ -421,7 +422,7 @@ static eOLDrawState tree_element_active_defgroup( WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); } else { - if (ob == OBACT) + if (ob == OBACT_NEW) if (ob->actdef == te->index + 1) { return OL_DRAWSEL_NORMAL; } @@ -430,7 +431,7 @@ static eOLDrawState tree_element_active_defgroup( } static eOLDrawState tree_element_active_posegroup( - bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *UNUSED(scene), SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) { Object *ob = (Object *)tselem->id; @@ -441,7 +442,7 @@ static eOLDrawState tree_element_active_posegroup( } } else { - if (ob == OBACT && ob->pose) { + if (ob == OBACT_NEW && ob->pose) { if (ob->pose->active_group == te->index + 1) { return OL_DRAWSEL_NORMAL; } @@ -451,7 +452,7 @@ static eOLDrawState tree_element_active_posegroup( } static eOLDrawState tree_element_active_posechannel( - bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) + bContext *C, Scene *UNUSED(scene), SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) { Object *ob = (Object *)tselem->id; bArmature *arm = ob->data; @@ -485,7 +486,7 @@ static eOLDrawState tree_element_active_posechannel( } } else { - if (ob == OBACT && ob->pose) { + if (ob == OBACT_NEW && ob->pose) { if (pchan->bone->flag & BONE_SELECTED) { return OL_DRAWSEL_NORMAL; } @@ -495,14 +496,14 @@ static eOLDrawState tree_element_active_posechannel( } static eOLDrawState tree_element_active_bone( - bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) + bContext *C, SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) { bArmature *arm = (bArmature *)tselem->id; Bone *bone = te->directdata; if (set != OL_SETSEL_NONE) { if (!(bone->flag & BONE_HIDDEN_P)) { - Object *ob = OBACT; + Object *ob = OBACT_NEW; if (ob) { if (set != OL_SETSEL_EXTEND) { /* single select forces all other bones to get unselected */ @@ -531,7 +532,7 @@ static eOLDrawState tree_element_active_bone( } } else { - Object *ob = OBACT; + Object *ob = OBACT_NEW; if (ob && ob->data == arm) { if (bone->flag & BONE_SELECTED) { @@ -604,7 +605,7 @@ static eOLDrawState tree_element_active_ebone( } static eOLDrawState tree_element_active_modifier( - bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) { if (set != OL_SETSEL_NONE) { Object *ob = (Object *)tselem->id; @@ -632,7 +633,7 @@ static eOLDrawState tree_element_active_psys( } static int tree_element_active_constraint( - bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) { if (set != OL_SETSEL_NONE) { Object *ob = (Object *)tselem->id; @@ -645,7 +646,7 @@ static int tree_element_active_constraint( } static eOLDrawState tree_element_active_text( - bContext *UNUSED(C), Scene *UNUSED(scene), SpaceOops *UNUSED(soops), + bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *UNUSED(sl), SpaceOops *UNUSED(soops), TreeElement *UNUSED(te), int UNUSED(set)) { // XXX removed @@ -653,10 +654,10 @@ static eOLDrawState tree_element_active_text( } static eOLDrawState tree_element_active_pose( - bContext *C, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) + bContext *C, Scene *scene, SceneLayer *sl, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) { Object *ob = (Object *)tselem->id; - Base *base = BKE_scene_base_find(scene, ob); + Base *base = BKE_scene_layer_base_find(sl, ob); if (set != OL_SETSEL_NONE) { if (scene->obedit) @@ -737,7 +738,7 @@ static eOLDrawState tree_element_active_sequence_dup( } static eOLDrawState tree_element_active_keymap_item( - bContext *UNUSED(C), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set) + bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set) { wmKeyMapItem *kmi = te->directdata; @@ -753,10 +754,28 @@ static eOLDrawState tree_element_active_keymap_item( return OL_DRAWSEL_NONE; } +static eOLDrawState tree_element_active_collection( + bContext *C, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set) +{ + if (set != OL_SETSEL_NONE) { + Scene *scene = CTX_data_scene(C); + SceneLayer *slayer = BLI_findlink(&scene->render_layers, scene->active_layer); + LayerCollection *collection = te->directdata; + const int collection_index = BKE_layer_collection_findindex(slayer, collection); + + BLI_assert(collection_index >= 0); + slayer->active_collection = collection_index; + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OL_DRAWSEL_ACTIVE; + } + + return OL_DRAWSEL_NONE; +} + /* ---------------------------------------------- */ /* generic call for ID data check or make/check active in UI */ -eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, +eOLDrawState tree_element_active(bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops, TreeElement *te, const eOLSetState set, const bool handle_all_types) { switch (te->idcode) { @@ -764,21 +783,21 @@ eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, Tr * selection. See do_outliner_item_activate. */ case ID_OB: if (handle_all_types) { - return tree_element_set_active_object(C, scene, soops, te, set, false); + return tree_element_set_active_object(C, scene, sl, soops, te, set, false); } break; case ID_MA: - return tree_element_active_material(C, scene, soops, te, set); + return tree_element_active_material(C, scene, sl, soops, te, set); case ID_WO: - return tree_element_active_world(C, scene, soops, te, set); + return tree_element_active_world(C, scene, sl, soops, te, set); case ID_LA: - return tree_element_active_lamp(C, scene, soops, te, set); + return tree_element_active_lamp(C, scene, sl, soops, te, set); case ID_TE: - return tree_element_active_texture(C, scene, soops, te, set); + return tree_element_active_texture(C, scene, sl, soops, te, set); case ID_TXT: - return tree_element_active_text(C, scene, soops, te, set); + return tree_element_active_text(C, scene, sl, soops, te, set); case ID_CA: - return tree_element_active_camera(C, scene, soops, te, set); + return tree_element_active_camera(C, scene, sl, soops, te, set); } return OL_DRAWSEL_NONE; } @@ -789,48 +808,49 @@ eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, Tr * \note Context can be NULL when ``(set == OL_SETSEL_NONE)`` */ eOLDrawState tree_element_type_active( - bContext *C, Scene *scene, SpaceOops *soops, + bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive) { switch (tselem->type) { case TSE_DEFGROUP: - return tree_element_active_defgroup(C, scene, te, tselem, set); + return tree_element_active_defgroup(C, sl, te, tselem, set); case TSE_BONE: - return tree_element_active_bone(C, scene, te, tselem, set, recursive); + return tree_element_active_bone(C, sl, te, tselem, set, recursive); case TSE_EBONE: return tree_element_active_ebone(C, scene, te, tselem, set, recursive); case TSE_MODIFIER: - return tree_element_active_modifier(C, te, tselem, set); + return tree_element_active_modifier(C, scene, sl, te, tselem, set); case TSE_LINKED_OB: if (set != OL_SETSEL_NONE) { - tree_element_set_active_object(C, scene, soops, te, set, false); + tree_element_set_active_object(C, scene, sl, soops, te, set, false); } - else if (tselem->id == (ID *)OBACT) { + else if (tselem->id == (ID *)OBACT_NEW) { return OL_DRAWSEL_NORMAL; } break; case TSE_LINKED_PSYS: return tree_element_active_psys(C, scene, te, tselem, set); case TSE_POSE_BASE: - return tree_element_active_pose(C, scene, te, tselem, set); + return tree_element_active_pose(C, scene, sl, te, tselem, set); case TSE_POSE_CHANNEL: - return tree_element_active_posechannel(C, scene, te, tselem, set, recursive); + return tree_element_active_posechannel(C, scene, sl, te, tselem, set, recursive); case TSE_CONSTRAINT: - return tree_element_active_constraint(C, te, tselem, set); + return tree_element_active_constraint(C, scene, sl, te, tselem, set); case TSE_R_LAYER: - return tree_element_active_renderlayer(C, te, tselem, set); + return tree_element_active_renderlayer(C, scene, sl, te, tselem, set); case TSE_POSEGRP: - return tree_element_active_posegroup(C, scene, te, tselem, set); + return tree_element_active_posegroup(C, scene, sl, te, tselem, set); case TSE_SEQUENCE: return tree_element_active_sequence(C, scene, te, tselem, set); case TSE_SEQUENCE_DUP: return tree_element_active_sequence_dup(scene, te, tselem, set); case TSE_KEYMAP_ITEM: - return tree_element_active_keymap_item(C, te, tselem, set); + return tree_element_active_keymap_item(C, scene, sl, te, tselem, set); case TSE_GP_LAYER: - //return tree_element_active_gplayer(C, scene, te, tselem, set); + //return tree_element_active_gplayer(C, scene, s, te, tselem, set); break; - + case TSE_COLLECTION: + return tree_element_active_collection(C, te, tselem, set); } return OL_DRAWSEL_NONE; } @@ -842,13 +862,14 @@ static void outliner_item_activate( const bool extend, const bool recursive) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); TreeStoreElem *tselem = TREESTORE(te); /* always makes active object, except for some specific types. * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want * to switch out of edit mode (see T48328 for details). */ - if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) { - tree_element_set_active_object(C, scene, soops, te, + if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_COLLECTION)) { + tree_element_set_active_object(C, scene, sl, soops, te, (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, recursive && tselem->type == 0); } @@ -874,15 +895,17 @@ static void outliner_item_activate( } for (gob = gr->gobject.first; gob; gob = gob->next) { - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel); + ED_object_base_select(BKE_scene_layer_base_find(sl, gob->ob), sel); } } else { - BKE_scene_base_deselect_all(scene); + BKE_scene_layer_base_deselect_all(sl); for (gob = gr->gobject.first; gob; gob = gob->next) { - if ((gob->ob->flag & SELECT) == 0) - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT); + Base *base = BKE_scene_layer_base_find(sl, gob->ob); + if ((base->flag & BASE_SELECTED) == 0) { + ED_object_base_select(base, BA_SELECT); + } } } @@ -892,12 +915,12 @@ static void outliner_item_activate( WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL); } else { // rest of types - tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false); + tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, false); } } else { - tree_element_type_active(C, scene, soops, te, tselem, + tree_element_type_active(C, scene, sl, soops, te, tselem, extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, recursive); } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 4560b7cd6e7..550dc63dd3c 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -56,6 +56,7 @@ #include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_group.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -360,15 +361,15 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot) /* ******************************************** */ static void object_select_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base && ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0)) { - base->flag |= SELECT; - base->object->flag |= SELECT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = (Object *)tselem->id; + Base *base = BKE_scene_layer_base_find(sl, ob); + + if (base && ((base->flag & BASE_VISIBLED) != 0)) { + base->flag |= BASE_SELECTED; } } @@ -385,46 +386,43 @@ static void object_select_hierarchy_cb( static void object_deselect_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = (Object *)tselem->id; + Base *base = BKE_scene_layer_base_find(sl, ob); + if (base) { - base->flag &= ~SELECT; - base->object->flag &= ~SELECT; + base->flag &= ~BASE_SELECTED; } } static void object_delete_cb( - bContext *C, ReportList *reports, Scene *scene, TreeElement *te, + bContext *C, ReportList *reports, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) - base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { + Object *ob = (Object *)tselem->id; + if (ob) { Main *bmain = CTX_data_main(C); - if (base->object->id.tag & LIB_TAG_INDIRECT) { - BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2); + if (ob->id.tag & LIB_TAG_INDIRECT) { + BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2); return; } - else if (BKE_library_ID_is_indirectly_used(bmain, base->object) && - ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) + else if (BKE_library_ID_is_indirectly_used(bmain, ob) && + ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { BKE_reportf(reports, RPT_WARNING, "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", - base->object->id.name + 2, scene->id.name + 2); + ob->id.name + 2, scene->id.name + 2); return; } // check also library later - if (scene->obedit == base->object) + if (scene->obedit == ob) ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); - ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + ED_base_object_free_and_unlink(CTX_data_main(C), scene, ob); /* leave for ED_outliner_id_unref to handle */ #if 0 te->directdata = NULL; @@ -520,7 +518,7 @@ static void group_linkobs2scene_cb( { Group *group = (Group *)tselem->id; GroupObject *gob; - Base *base; + BaseLegacy *base; for (gob = group->gobject.first; gob; gob = gob->next) { base = BKE_scene_base_find(scene, gob->ob); @@ -530,7 +528,7 @@ static void group_linkobs2scene_cb( id_us_plus(&gob->ob->id); } base->object->flag |= SELECT; - base->flag |= SELECT; + base->flag_legacy |= SELECT; } } @@ -820,9 +818,9 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li } } -static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, Base *base) +static BaseLegacy *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, BaseLegacy *base) { - Base *child_base, *base_next; + BaseLegacy *child_base, *base_next; Object *parent; if (!base) { @@ -852,7 +850,7 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s base->object->id.name + 2, scene->id.name + 2); return base_next; } - ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + ED_base_object_free_and_unlink(CTX_data_main(C), scene, base->object); return base_next; } @@ -860,6 +858,7 @@ static void object_delete_hierarchy_cb( bContext *C, ReportList *reports, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { +#if 0 Base *base = (Base *)te->directdata; Object *obedit = scene->obedit; @@ -882,6 +881,15 @@ static void object_delete_hierarchy_cb( } WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); +#else + (void) C; + (void) scene; + (void) te; + (void) tselem; + (void) outline_delete_hierarchy; + BKE_reportf(reports, RPT_ERROR, "Delete from outliner not supported at the moment"); + TODO_LAYER_BASE +#endif } /* **************************************** */ @@ -985,21 +993,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb); str = "Localized Objects"; } - else if (event == OL_OP_TOGVIS) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb); - str = "Toggle Visibility"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); - } - else if (event == OL_OP_TOGSEL) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb); - str = "Toggle Selectability"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - else if (event == OL_OP_TOGREN) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb); - str = "Toggle Renderability"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); - } else if (event == OL_OP_RENAME) { outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb); str = "Rename Object"; @@ -1095,15 +1088,6 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) case OL_GROUPOP_REMAP: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); break; - case OL_GROUPOP_TOGVIS: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_visibility_cb, NULL); - break; - case OL_GROUPOP_TOGSEL: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_selectability_cb, NULL); - break; - case OL_GROUPOP_TOGREN: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_renderability_cb, NULL); - break; case OL_GROUPOP_RENAME: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL); break; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index ec46c5df9a0..c96d7f970ed 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -63,6 +63,7 @@ #include "BKE_fcurve.h" #include "BKE_main.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_modifier.h" #include "BKE_sequencer.h" @@ -903,8 +904,8 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i id = TREESTORE(parent)->id; } - /* One exception */ - if (type == TSE_ID_BASE) { + /* exceptions */ + if (ELEM(type, TSE_ID_BASE, TSE_COLLECTION)) { /* pass */ } else if (id == NULL) { @@ -941,6 +942,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i else if (type == TSE_GP_LAYER) { /* pass */ } + else if (type == TSE_COLLECTION) { + /* pass */ + } else if (type == TSE_ID_BASE) { /* pass */ } @@ -1370,6 +1374,24 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops) } } +static void outliner_add_collections_recursive(SpaceOops *soops, ListBase *tree, ListBase *layer_collections, + TreeElement *parent_ten) +{ + for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) { + TreeElement *ten = outliner_add_element(soops, tree, NULL, parent_ten, TSE_COLLECTION, 0); + + ten->name = collection->scene_collection->name; + ten->directdata = collection; + + outliner_add_collections_recursive(soops, &ten->subtree, &collection->layer_collections, ten); + } +} + +static void outliner_add_collections(SpaceOops *soops, SceneLayer *layer) +{ + outliner_add_collections_recursive(soops, &soops->tree, &layer->layer_collections, NULL); +} + /* ======================================================= */ /* Generic Tree Building helpers - order these are called is top to bottom */ @@ -1619,9 +1641,8 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb) /* Main entry point for building the tree data-structure that the outliner represents */ // TODO: split each mode into its own function? -void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) +void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops *soops) { - Base *base; TreeElement *te = NULL, *ten; TreeStoreElem *tselem; int show_opened = !soops->treestore || !BLI_mempool_count(soops->treestore); /* on first view, we open scenes */ @@ -1702,31 +1723,43 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) tselem = TREESTORE(te); if (sce == scene && show_opened) tselem->flag &= ~TSE_CLOSED; - - for (base = sce->base.first; base; base = base->next) { - ten = outliner_add_element(soops, &te->subtree, base->object, te, 0, 0); - ten->directdata = base; + + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) + { + ten = outliner_add_element(soops, &te->subtree, ob, te, 0, 0); } + FOREACH_SCENE_OBJECT_END + outliner_make_hierarchy(&te->subtree); + /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ - for (base = sce->base.first; base; base = base->next) base->object->id.newid = NULL; + FOREACH_SCENE_OBJECT(scene, ob) + { + ob->id.newid = NULL; + } + FOREACH_SCENE_OBJECT_END } } else if (soops->outlinevis == SO_CUR_SCENE) { outliner_add_scene_contents(soops, &soops->tree, scene, NULL); - - for (base = scene->base.first; base; base = base->next) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; + + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) + { + ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } + FOREACH_SCENE_OBJECT_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_VISIBLE) { - for (base = scene->base.first; base; base = base->next) { - if (base->lay & scene->lay) - outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); + Object *ob; + FOREACH_VISIBLE_OBJECT(sl, ob) + { + outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } + FOREACH_VISIBLE_OBJECT_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_GROUPS) { @@ -1739,7 +1772,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) for (go = group->gobject.first; go; go = go->next) { ten = outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0); - ten->directdata = NULL; /* eh, why? */ } outliner_make_hierarchy(&te->subtree); /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ @@ -1748,26 +1780,26 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) } } else if (soops->outlinevis == SO_SAME_TYPE) { - Object *ob = OBACT; - if (ob) { - for (base = scene->base.first; base; base = base->next) { - if (base->object->type == ob->type) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; + Object *ob_active = OBACT_NEW; + if (ob_active) { + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) + { + if (ob->type == ob_active->type) { + ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } } + FOREACH_SCENE_OBJECT_END outliner_make_hierarchy(&soops->tree); } } else if (soops->outlinevis == SO_SELECTED) { - for (base = scene->base.first; base; base = base->next) { - if (base->lay & scene->lay) { - if (base->flag & SELECT) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; - } - } + Object *ob; + FOREACH_SELECTED_OBJECT(sl, ob) + { + ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } + FOREACH_SELECTED_OBJECT_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_SEQUENCE) { @@ -1821,9 +1853,11 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) else if (soops->outlinevis == SO_ID_ORPHANS) { outliner_add_orphaned_datablocks(mainvar, soops); } + else if (soops->outlinevis == SO_COLLECTIONS) { + outliner_add_collections(soops, BLI_findlink(&scene->render_layers, scene->active_layer)); + } else { - ten = outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0); - if (ten) ten->directdata = BASACT; + ten = outliner_add_element(soops, &soops->tree, OBACT_NEW, NULL, 0, 0); } if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) { diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index d7771d06787..b4cc1123176 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -758,6 +758,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg View2D *v2d = &ar->v2d; float x1, x2, y1, y2; unsigned char col[3], background_col[3], is_single_image; + float fcol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; const float handsize_clamped = draw_seq_handle_size_get_clamped(seq, pixelx); /* we need to know if this is a single image/color or not for drawing */ @@ -855,11 +856,11 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x8888); } - - glColor3ubv((GLubyte *)col); - - UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0); - + + rgb_uchar_to_float(fcol, col); + + UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0, fcol); + if (seq->flag & SEQ_MUTE) { glDisable(GL_LINE_STIPPLE); } diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 5e7060d6651..e9306c04cfa 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -402,7 +402,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN; } - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { Object *ob = base->object; ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index f0e65f84205..505ed1fdd3a 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -51,6 +51,8 @@ #include "BIF_gl.h" +#include "GPU_immediate.h" + #include "ED_keyframes_draw.h" @@ -86,10 +88,11 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar) * - User selected color for next frames */ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short sel, int sfra, int efra, - float prev_color[3], float frame_color[3], float next_color[3]) + float prev_color[3], float frame_color[3], float next_color[3], unsigned color) { int frame = sfra + i; int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */ + unsigned char ubcolor[3]; #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min) float intensity; /* how faint */ @@ -97,7 +100,7 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short if (frame < CFRA) { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: previous frames color is darker than current frame */ - glColor3fv(prev_color); + rgb_float_to_uchar(ubcolor, prev_color); } else { /* black - before cfra */ @@ -109,13 +112,14 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short /* intensity = 0.8f; */ intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f); } - UI_ThemeColorBlend(TH_WIRE, blend_base, intensity); + + UI_GetThemeColorBlend3ubv(TH_WIRE, blend_base, intensity, ubcolor); } } else if (frame > CFRA) { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: next frames color is equal to user selected color */ - glColor3fv(next_color); + rgb_float_to_uchar(ubcolor, next_color); } else { /* blue - after cfra */ @@ -127,13 +131,14 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short /* intensity = 0.8f; */ intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f); } - UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity); + + UI_GetThemeColorBlend3ubv(TH_BONE_POSE, blend_base, intensity, ubcolor); } } else { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: current frame color is slightly darker than user selected color */ - glColor3fv(frame_color); + rgb_float_to_uchar(ubcolor, frame_color); } else { /* green - on cfra */ @@ -143,9 +148,12 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short else { intensity = 0.99f; } - UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10); + UI_GetThemeColorBlendShade3ubv(TH_CFRAME, TH_BACK, intensity, 10, ubcolor); } } + + immAttrib3ubv(color, ubcolor); + #undef SET_INTENSITY } @@ -231,42 +239,65 @@ void draw_motion_path_instance(Scene *scene, /* set line thickness */ glLineWidth(mpath->line_thickness); - glBegin(GL_LINE_STRIP); + VertexFormat *format = immVertexFormat(); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + + immBegin(GL_LINE_STRIP, len); + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT); + /* Set color */ - set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color); + set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color, color); + /* draw a vertex with this color */ - glVertex3fv(mpv->co); + immVertex3fv(pos, mpv->co); } - glEnd(); + immEnd(); + + immUnbindProgram(); + /* back to old line thickness */ glLineWidth(old_width); } + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + /* Point must be bigger than line thickness */ glPointSize(mpath->line_thickness + 1.0); - /* draw little black point at each frame - * NOTE: this is not really visible/noticeable - */ - glBegin(GL_POINTS); - for (i = 0, mpv = mpv_start; i < len; i++, mpv++) - glVertex3fv(mpv->co); - glEnd(); - + /* draw little black point at each frame */ + immUniformColor3ub(0, 0, 0); + + immBegin(GL_POINTS, len); + + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { + immVertex3fv(pos, mpv->co); + } + + immEnd(); + /* Draw little white dots at each framestep value or replace with custom color */ if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { - glColor4fv(mpath->color); + immUniformColor3fv(mpath->color); } else { - UI_ThemeColor(TH_TEXT_HI); + immUniformThemeColor(TH_TEXT_HI); } - glBegin(GL_POINTS); - for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) - glVertex3fv(mpv->co); - glEnd(); + + immBegin(GL_POINTS, (len + stepsize - 1) / stepsize); + + for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) { + immVertex3fv(pos, mpv->co); + } + + immEnd(); /* Draw big green dot where the current frame is * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter @@ -274,16 +305,18 @@ void draw_motion_path_instance(Scene *scene, if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) && (sfra < CFRA) && (CFRA <= efra)) { - UI_ThemeColor(TH_CFRAME); - glPointSize(mpath->line_thickness + 5.0); - glBegin(GL_POINTS); + immUniformThemeColor(TH_CFRAME); + + immBegin(GL_POINTS, 1); + mpv = mpv_start + (CFRA - sfra); - glVertex3fv(mpv->co); - glEnd(); - - UI_ThemeColor(TH_TEXT_HI); + immVertex3fv(pos, mpv->co); + + immEnd(); } + + immUnbindProgram(); /* XXX, this isn't up to date but probably should be kept so. */ invert_m4_m4(ob->imat, ob->obmat); @@ -353,24 +386,28 @@ void draw_motion_path_instance(Scene *scene, UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col); col[3] = 255; - /* if custom, point must be bigger than line */ - if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { - glPointSize(mpath->line_thickness + 3.0); - } - else { - glPointSize(4.0f); - } - glColor3ubv(col); + /* point must be bigger than line */ + glPointSize(mpath->line_thickness + 3.0); + + pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(col); - glBegin(GL_POINTS); + immBeginAtMost(GL_POINTS, len); + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { int frame = sfra + i; float mframe = (float)(frame); - if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) - glVertex3fv(mpv->co); + if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) { + immVertex3fv(pos, mpv->co); + } } - glEnd(); + + immEnd(); + + immUnbindProgram(); /* Draw frame numbers of keyframes */ if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) { diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index af041e392c5..a7bff0a8301 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -63,6 +63,8 @@ #include "ED_keyframes_draw.h" #include "GPU_basic_shader.h" +#include "GPU_batch.h" +#include "GPU_matrix.h" #include "UI_resources.h" @@ -74,6 +76,7 @@ /* global here is reset before drawing each bone */ static ThemeWireColor *bcolor = NULL; +static float fcolor[4] = {0.0f}; /* values of colCode for set_pchan_glcolor */ enum { @@ -148,11 +151,12 @@ static void cp_shade_color3ub(unsigned char cp[3], const int offset) /* This function sets the gl-color for coloring a certain bone (based on bcolor) */ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) { + /* TODO remove glColor/UI_ThemeColor functions when no longer needed */ switch (colCode) { case PCHAN_COLOR_NORMAL: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -170,19 +174,24 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) } glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) { UI_ThemeColor(TH_BONE_POSE_ACTIVE); + UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor); } else if (boneflag & BONE_DRAW_ACTIVE) { UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */ + UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor); } else if (boneflag & BONE_SELECTED) { UI_ThemeColor(TH_BONE_POSE); + UI_GetThemeColor4fv(TH_BONE_POSE, fcolor); } else { UI_ThemeColor(TH_WIRE); + UI_GetThemeColor4fv(TH_WIRE, fcolor); } } @@ -192,20 +201,27 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) { if (bcolor) { glColor3ubv((unsigned char *)bcolor->solid); + rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid); } - else + else { UI_ThemeColor(TH_BONE_SOLID); + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } return true; } case PCHAN_COLOR_CONSTS: { if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) { - if (constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80); - else if (constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80); - else if (constflag & PCHAN_HAS_SPLINEIK) glColor4ub(200, 255, 0, 80); - else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80); - + unsigned char cp[4]; + if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 80); + else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 80); + else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80); + else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80); + + glColor4ubv(cp); + rgba_uchar_to_float(fcolor, cp); + return true; } return false; @@ -213,7 +229,7 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_SPHEREBONE_BASE: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -226,11 +242,21 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) } glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { - if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40); - else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE); - else UI_ThemeColor(TH_BONE_SOLID); + if (boneflag & BONE_DRAW_ACTIVE) { + UI_ThemeColorShade(TH_BONE_POSE, 40); + UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_ThemeColor(TH_BONE_POSE); + UI_GetThemeColor4fv(TH_BONE_POSE, fcolor); + } + else { + UI_ThemeColor(TH_BONE_SOLID); + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } } return true; @@ -238,7 +264,7 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_SPHEREBONE_END: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -254,11 +280,21 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) } glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { - if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10); - else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30); - else UI_ThemeColorShade(TH_BONE_SOLID, -30); + if (boneflag & BONE_DRAW_ACTIVE) { + UI_ThemeColorShade(TH_BONE_POSE, 10); + UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_ThemeColorShade(TH_BONE_POSE, -30); + UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor); + } + else { + UI_ThemeColorShade(TH_BONE_SOLID, -30); + UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); + } } break; } @@ -266,19 +302,27 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) { /* inner part in background color or constraint */ if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) { - if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0); - else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0); - else if (constflag & PCHAN_HAS_SPLINEIK) glColor3ub(200, 255, 0); - else if (constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120); - else if (constflag) UI_ThemeColor(TH_BONE_POSE); /* PCHAN_HAS_ACTION */ + unsigned char cp[4]; + if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 255); + else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 255); + else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 255); + else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255); + else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp); /* PCHAN_HAS_ACTION */ + + glColor4ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { if (bcolor) { const char *cp = bcolor->solid; glColor4ub(cp[0], cp[1], cp[2], 204); + rgb_uchar_to_float(fcolor, (unsigned char *)cp); + fcolor[3] = 204.f / 255.f; } - else + else { UI_ThemeColorShade(TH_BACK, -30); + UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor); + } } return true; @@ -290,24 +334,29 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) static void set_ebone_glColor(const unsigned int boneflag) { + /* TODO remove glColor/UI_ThemeColor functions when no longer needed */ if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) { UI_ThemeColor(TH_EDGE_SELECT); + UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor); } else if (boneflag & BONE_DRAW_ACTIVE) { UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f); /* unselected active */ + UI_GetThemeColorBlendShade4fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, fcolor); } else if (boneflag & BONE_SELECTED) { UI_ThemeColorShade(TH_EDGE_SELECT, -20); + UI_GetThemeColorShade4fv(TH_EDGE_SELECT, -20, fcolor); } else { UI_ThemeColor(TH_WIRE_EDIT); + UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor); } } /* *************** Armature drawing, helper calls for parts ******************* */ /* half the cube, in Y */ -static const float cube[8][3] = { +static const float cube_vert[8][3] = { {-1.0, 0.0, -1.0}, {-1.0, 0.0, 1.0}, {-1.0, 1.0, 1.0}, @@ -318,6 +367,12 @@ static const float cube[8][3] = { { 1.0, 1.0, -1.0}, }; +static const float cube_wire[24] = { + 0, 1, 1, 2, 2, 3, 3, 0, + 4, 5, 5, 6, 6, 7, 7, 4, + 0, 4, 1, 5, 2, 6, 3, 7, +}; + static void drawsolidcube_size(float xsize, float ysize, float zsize) { static GLuint displist = 0; @@ -332,26 +387,26 @@ static void drawsolidcube_size(float xsize, float ysize, float zsize) glBegin(GL_QUADS); n[0] = -1.0; glNormal3fv(n); - glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); + glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[1]); glVertex3fv(cube_vert[2]); glVertex3fv(cube_vert[3]); n[0] = 0; n[1] = -1.0; glNormal3fv(n); - glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]); + glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[5]); glVertex3fv(cube_vert[1]); n[1] = 0; n[0] = 1.0; glNormal3fv(n); - glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]); + glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[6]); glVertex3fv(cube_vert[5]); n[0] = 0; n[1] = 1.0; glNormal3fv(n); - glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]); + glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[3]); glVertex3fv(cube_vert[2]); glVertex3fv(cube_vert[6]); n[1] = 0; n[2] = 1.0; glNormal3fv(n); - glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]); + glVertex3fv(cube_vert[1]); glVertex3fv(cube_vert[5]); glVertex3fv(cube_vert[6]); glVertex3fv(cube_vert[2]); n[2] = -1.0; glNormal3fv(n); - glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]); + glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[3]); glEnd(); glEndList(); @@ -362,30 +417,42 @@ static void drawsolidcube_size(float xsize, float ysize, float zsize) static void drawcube_size(float xsize, float ysize, float zsize) { - static GLuint displist = 0; - - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glBegin(GL_LINE_STRIP); - glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); - glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); - glVertex3fv(cube[7]); glVertex3fv(cube[4]); - glEnd(); - - glBegin(GL_LINES); - glVertex3fv(cube[1]); glVertex3fv(cube[5]); - glVertex3fv(cube[2]); glVertex3fv(cube[6]); - glVertex3fv(cube[3]); glVertex3fv(cube[7]); - glEnd(); - - glEndList(); + static VertexFormat format = {0}; + static VertexBuffer vbo = {0}; + static ElementListBuilder elb = {0}; + static ElementList el = {0}; + static Batch batch = {0}; + + if (format.attrib_ct == 0) { + /* Vertex format */ + unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + + /* Elements */ + ElementListBuilder_init(&elb, GL_LINES, 12, 8); + for (int i = 0; i < 12; ++i) { + add_line_vertices(&elb, cube_wire[i*2], cube_wire[i*2+1]); + } + ElementList_build_in_place(&elb, &el); + + /* Vertices */ + VertexBuffer_init_with_format(&vbo, &format); + VertexBuffer_allocate_data(&vbo, 8); + for (int i = 0; i < 8; ++i) { + setAttrib(&vbo, pos, i, cube_vert[i]); + } + + Batch_init(&batch, GL_LINES, &vbo, &el); + Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR); } - glScalef(xsize, ysize, zsize); - glCallList(displist); - + gpuMatrixBegin3D_legacy(); + gpuScale3f(xsize, ysize, zsize); + + Batch_use_program(&batch); + Batch_Uniform4fv(&batch, "color", fcolor); + Batch_draw(&batch); + + gpuMatrixEnd(); } @@ -451,8 +518,11 @@ static const float bone_octahedral_verts[6][3] = { { 0.0f, 1.0f, 0.0f} }; -static const unsigned int bone_octahedral_wire_sides[8] = {0, 1, 5, 3, 0, 4, 5, 2}; -static const unsigned int bone_octahedral_wire_square[8] = {1, 2, 3, 4, 1}; +static const unsigned int bone_octahedral_wire[24] = { + 0, 1, 1, 5, 5, 3, 3, 0, + 0, 4, 4, 5, 5, 2, 2, 0, + 1, 2, 2, 3, 3, 4, 4, 1, +}; static const unsigned int bone_octahedral_solid_tris[8][3] = { {2, 1, 0}, /* bottom */ @@ -480,31 +550,41 @@ static const float bone_octahedral_solid_normals[8][3] = { static void draw_bone_octahedral(void) { - static GLuint displist = 0; - - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); + static VertexFormat format = {0}; + static VertexBuffer vbo = {0}; + static ElementListBuilder elb = {0}; + static ElementList el = {0}; + static Batch batch = {0}; + + if (format.attrib_ct == 0) { + /* Vertex format */ + unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + + /* Elements */ + ElementListBuilder_init(&elb, GL_LINES, 12, 6); + for (int i = 0; i < 12; ++i) { + add_line_vertices(&elb, bone_octahedral_wire[i*2], bone_octahedral_wire[i*2+1]); + } + ElementList_build_in_place(&elb, &el); - /* Section 1, sides */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts); - glDrawElements(GL_LINE_LOOP, - sizeof(bone_octahedral_wire_sides) / sizeof(*bone_octahedral_wire_sides), - GL_UNSIGNED_INT, - bone_octahedral_wire_sides); - - /* Section 1, square */ - glDrawElements(GL_LINE_LOOP, - sizeof(bone_octahedral_wire_square) / sizeof(*bone_octahedral_wire_square), - GL_UNSIGNED_INT, - bone_octahedral_wire_square); - glDisableClientState(GL_VERTEX_ARRAY); - - glEndList(); + /* Vertices */ + VertexBuffer_init_with_format(&vbo, &format); + VertexBuffer_allocate_data(&vbo, 6); + for (int i = 0; i < 6; ++i) { + setAttrib(&vbo, pos, i, bone_octahedral_verts[i]); + } + + Batch_init(&batch, GL_LINES, &vbo, &el); + Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR); } - glCallList(displist); + gpuMatrixBegin3D_legacy(); + + Batch_use_program(&batch); + Batch_Uniform4fv(&batch, "color", fcolor); + Batch_draw(&batch); + + gpuMatrixEnd(); } static void draw_bone_solid_octahedral(void) @@ -1733,7 +1813,7 @@ static void bone_matrix_translate_y(float mat[4][4], float y) } /* assumes object is Armature with pose */ -static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, +static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base, const short dt, const unsigned char ob_wire_col[4], const bool do_const_color, const bool is_outline) { @@ -1753,6 +1833,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, bool draw_wire = false; int flag; bool is_cull_enabled; + + /* TODO find a way to overcome this. + * used in case do_const_color is true */ + glGetFloatv(GL_CURRENT_COLOR, fcolor); /* being set below */ arm->layer_used = 0; @@ -1938,6 +2022,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, set_pchan_colorset(ob, pchan); else { glColor3ubv(ob_wire_col); + rgba_uchar_to_float(fcolor, ob_wire_col); } /* catch exception for bone with hidden parent */ @@ -2106,7 +2191,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* draw DoFs */ if (arm->flag & ARM_POSEMODE) { - if (((base->flag & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) { + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) { draw_pose_dofs(ob); } } @@ -2114,7 +2199,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* finally names and axes */ if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) && (is_outline == 0) && - ((base->flag & OB_FROMDUPLI) == 0)) + ((base->flag_legacy & OB_FROMDUPLI) == 0)) { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ if ((G.f & G_PICKSEL) == 0) { @@ -2445,7 +2530,7 @@ static void ghost_poses_tag_unselected(Object *ob, short unset) /* draw ghosts that occur within a frame range * note: object should be in posemode */ -static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2511,7 +2596,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base /* draw ghosts on keyframes in action within range * - object should be in posemode */ -static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2592,7 +2677,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * /* draw ghosts around current frame * - object is supposed to be armature in posemode */ -static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2686,7 +2771,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) /* called from drawobject.c, return true if nothing was drawn * (ob_wire_col == NULL) when drawing ghost */ -bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, +bool draw_armature(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, const short dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_outline) { @@ -2733,7 +2818,7 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } /* drawing posemode selection indices or colors only in these cases */ - if (!(base->flag & OB_FROMDUPLI)) { + if (!(base->flag_legacy & OB_FROMDUPLI)) { if (G.f & G_PICKSEL) { #if 0 /* nifty but actually confusing to allow bone selection out of posemode */ @@ -2759,10 +2844,10 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, draw_ghost_poses(scene, v3d, ar, base); } if ((dflag & DRAW_SCENESET) == 0) { - if (ob == OBACT) + if (ob == OBACT_NEW) arm->flag |= ARM_POSEMODE; - else if (OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) { - if (ob == modifiers_isDeformedByArmature(OBACT)) + else if (OBACT_NEW && (OBACT_NEW->mode & OB_MODE_WEIGHT_PAINT)) { + if (ob == modifiers_isDeformedByArmature(OBACT_NEW)) arm->flag |= ARM_POSEMODE; } draw_pose_paths(scene, v3d, ar, ob); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 1692d3a7372..5d821734b63 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -323,9 +323,9 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) return false; } -static bool check_alpha_pass(Base *base) +static bool check_alpha_pass(BaseLegacy *base) { - if (base->flag & OB_FROMDUPLI) + if (base->flag_legacy & OB_FROMDUPLI) return false; if (G.f & G_PICKSEL) @@ -787,7 +787,7 @@ void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][ glDisableClientState(GL_VERTEX_ARRAY); } -static void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos) +void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos) { float verts[CIRCLE_RESOL][3]; @@ -1247,7 +1247,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, !(G.f & G_PICKSEL) && (la->type == LA_SPOT) && (la->mode & LA_SHOW_CONE) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #ifdef WITH_GAMEENGINE @@ -1259,7 +1259,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, ((la->mode & LA_SHAD_BUF) || (la->mode & LA_SHAD_RAY)) && (la->mode & LA_SHOW_SHADOW_BOX) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #else const bool drawshadowbox = false; @@ -1309,7 +1309,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, if ((dflag & DRAW_CONSTCOLOR) == 0) { const float *color = curcol; if (ob->id.us > 1) { - if (is_obact || (ob->flag & SELECT)) { + if (is_obact || ((base->flag & BASE_SELECTED) != 0)) { static const float active_color[4] = {0.533f, 1.0f, 1.0f, 1.0f}; color = active_color; } @@ -1690,7 +1690,7 @@ static void draw_bundle_sphere(void) } static void draw_viewport_object_reconstruction( - Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, + Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, MovieTrackingObject *tracking_object, const short dflag, const unsigned char ob_wire_col[4], int *global_track_index, bool draw_selected) @@ -1852,7 +1852,7 @@ static void draw_viewport_object_reconstruction( } static void draw_viewport_reconstruction( - Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, + Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, const short dflag, const unsigned char ob_wire_col[4], const bool draw_selected) { @@ -4188,7 +4188,7 @@ static bool object_is_halo(Scene *scene, Object *ob) return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene)); } -static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { #ifdef WITH_GAMEENGINE @@ -4254,7 +4254,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && (draw_wire == OBDRAW_WIRE_OFF)) { @@ -4325,7 +4325,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* draw outline */ if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { @@ -4349,7 +4349,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { @@ -4451,7 +4451,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } /* returns true if nothing was drawn, for detecting to draw an object center */ -static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; @@ -4541,7 +4541,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 } } - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* GPU_begin_object_materials checked if this is needed */ if (do_alpha_after) { if (ob->dtx & OB_DRAWXRAY) { @@ -4595,7 +4595,7 @@ static void make_color_variations(const unsigned char base_ubyte[4], float low[4 high[3] = base[3]; } -static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit) { if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { @@ -4731,7 +4731,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && (draw_wire == OBDRAW_WIRE_OFF)) { @@ -4798,7 +4798,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi /* TODO: move this into a separate pass */ if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { @@ -4822,7 +4822,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { @@ -4914,7 +4914,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi dm->release(dm); } -static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; @@ -5253,7 +5253,7 @@ static void drawCurveDMWired(Object *ob) } /* return true when nothing was drawn */ -static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) +static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt) { Object *ob = base->object; DerivedMesh *dm = ob->derivedFinal; @@ -5289,7 +5289,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, * Only called by #drawDispList * \return true when nothing was drawn */ -static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -5410,7 +5410,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 return false; } -static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { bool retval; @@ -5697,7 +5697,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv float cfra; float ma_col[3] = {0.0f, 0.0f, 0.0f}; int a, totpart, totpoint = 0, totve = 0, drawn, draw_as, totchild = 0; - bool select = (ob->flag & SELECT) != 0, create_cdata = false, need_v = false; + bool select = (base->flag & BASE_SELECTED) != 0, create_cdata = false, need_v = false; GLint polygonmode[2]; char numstr[32]; unsigned char tcol[4] = {0, 0, 0, 255}; @@ -5768,7 +5768,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv timestep = psys_get_timestep(&sim); - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { + if ((ob->flag & OB_FROMGROUP) != 0) { float mat[4][4]; mul_m4_m4m4(mat, ob->obmat, psys->imat); glMultMatrixf(mat); @@ -6399,7 +6399,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->ma_col = NULL; } - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { + if ((ob->flag & OB_FROMGROUP) != 0) { glLoadMatrixf(rv3d->viewmat); } } @@ -7059,7 +7059,7 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) } static void draw_editnurb( - Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, + Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, Nurb *nurb, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { ToolSettings *ts = scene->toolsettings; @@ -7169,7 +7169,7 @@ static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2]) ED_view3d_polygon_offset(rv3d, 0.0); } -static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -7527,7 +7527,7 @@ static void imm_drawcone(const float vec[3], float radius, float height, float t } /* return true if nothing was drawn */ -static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -7548,7 +7548,7 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ml = mb->editelems->first; } else { - if ((base->flag & OB_FROMDUPLI) == 0) { + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); } ml = mb->elems.first; @@ -7942,7 +7942,7 @@ static void drawtexspace(Object *ob) } /* draws wire outline */ -static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base, +static void drawObjectSelect(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, const unsigned char ob_wire_col[4]) { RegionView3D *rv3d = ar->regiondata; @@ -7982,16 +7982,16 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - if ((base->flag & OB_FROMDUPLI) == 0) { + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); drawDispListwire(&ob->curve_cache->disp, ob->type); } } } else if (ob->type == OB_ARMATURE) { - if (!(ob->mode & OB_MODE_POSE && base == scene->basact)) { + if (!(ob->mode & OB_MODE_POSE && base == sl->basact)) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - draw_armature(scene, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true); + draw_armature(scene, sl, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true); } } @@ -8095,7 +8095,7 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, setlinestyle(0); } -void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4]) +void draw_object_wire_color(Scene *scene, SceneLayer *sl, Base *base, unsigned char r_ob_wire_col[4]) { Object *ob = base->object; int colindex = 0; @@ -8109,19 +8109,19 @@ void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_co if ((scene->obedit == NULL) && (G.moving & G_TRANSFORM_OBJ) && - (base->flag & (SELECT + BA_WAS_SEL))) + ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) { theme_id = TH_TRANSFORM; } else { /* Sets the 'colindex' */ if (ID_IS_LINKED_DATABLOCK(ob)) { - colindex = (base->flag & (SELECT + BA_WAS_SEL)) ? 2 : 1; + colindex = ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) ? 2 : 1; } /* Sets the 'theme_id' or fallback to wire */ else { - if (ob->flag & OB_FROMGROUP) { - if (base->flag & (SELECT + BA_WAS_SEL)) { + if ((ob->flag & OB_FROMGROUP) != 0) { + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { /* uses darker active color for non-active + selected */ theme_id = TH_GROUP_ACTIVE; @@ -8134,8 +8134,8 @@ void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_co } } else { - if (base->flag & (SELECT + BA_WAS_SEL)) { - theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT; + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { + theme_id = sl->basact == base ? TH_ACTIVE : TH_SELECT; } else { if (ob->type == OB_LAMP) theme_id = TH_LAMP; @@ -8233,7 +8233,7 @@ void draw_rigidbody_shape(Object *ob) * main object drawing function, draws in selection * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */ -void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) +void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base, const short dflag) { ModifierData *md = NULL; Object *ob = base->object; @@ -8243,7 +8243,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short unsigned char _ob_wire_col[4]; /* dont initialize this */ const unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */ bool zbufoff = false, is_paint = false, empty_object = false; - const bool is_obact = (ob == OBACT); + const bool is_obact = (ob == OBACT_NEW); const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0; const bool is_picking = (G.f & G_PICKSEL) != 0; const bool has_particles = (ob->particlesystem.first != NULL); @@ -8283,7 +8283,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } - if (((base->flag & OB_FROMDUPLI) == 0) && + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && (md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { @@ -8307,7 +8307,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* xray delay? */ - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* don't do xray in particle mode, need the z-buffer */ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { /* xray and transp are set when it is drawing the 2nd/3rd pass */ @@ -8360,7 +8360,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short ED_view3d_project_base(ar, base); - draw_object_wire_color(scene, base, _ob_wire_col); + draw_object_wire_color(scene, sl, base, _ob_wire_col); ob_wire_col = _ob_wire_col; glColor3ubv(ob_wire_col); @@ -8415,8 +8415,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* draw outline for selected objects, mesh does itself */ if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) { if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) { - if (!(ob->dtx & OB_DRAWWIRE) && (ob->flag & SELECT) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { - drawObjectSelect(scene, v3d, ar, base, ob_wire_col); + if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { + drawObjectSelect(scene, sl, v3d, ar, base, ob_wire_col); } } } @@ -8552,7 +8552,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } else { glLineWidth(1.0f); - empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false); + empty_object = draw_armature(scene, sl, v3d, ar, base, dt, dflag, ob_wire_col, false); } } break; @@ -8598,7 +8598,7 @@ afterdraw: if ((dflag & DRAW_CONSTCOLOR) == 0) { /* for visibility, also while wpaint */ - if (col || (ob->flag & SELECT)) { + if (col || (base->flag & BASE_SELECTED)) { cpack(0xFFFFFF); } } @@ -8805,7 +8805,7 @@ afterdraw: glDisable(GL_DEPTH_TEST); } - if ((base->flag & OB_FROMDUPLI) || render_override) { + if ((base->flag_legacy & OB_FROMDUPLI) || render_override) { ED_view3d_clear_mats_rv3d(rv3d); return; } @@ -8819,7 +8819,7 @@ afterdraw: } else if (is_obact) do_draw_center = ACTIVE; - else if (base->flag & SELECT) + else if (base->flag & BASE_SELECTED) do_draw_center = SELECT; else if (empty_object || (v3d->flag & V3D_DRAW_CENTERS)) do_draw_center = DESELECT; diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 27ecbf83db5..debdcb58d71 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -160,7 +160,7 @@ static GPUTexture *create_field_texture(SmokeDomainSettings *sds) default: return NULL; } - return GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, field); + return GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1, GPU_R8, field, NULL); } typedef struct VolumeSlicer { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 9b65784f52b..046aa40b85d 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -592,6 +592,7 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar) if (rv3d->viewport) { GPU_viewport_free(rv3d->viewport); + MEM_freeN(rv3d->viewport); rv3d->viewport = NULL; } } @@ -653,7 +654,7 @@ static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *eve static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { - Base *base = ED_view3d_give_base_under_cursor(C, event->mval); + BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval); /* either holding and ctrl and no object, or dropping to empty */ if (((base == NULL) && event->ctrl) || @@ -667,7 +668,7 @@ static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent * static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { - Base *base = ED_view3d_give_base_under_cursor(C, event->mval); + BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval); if (base && base->object->type == OB_MESH) return view3d_ima_drop_poll(C, drag, event); @@ -753,6 +754,7 @@ static void view3d_main_region_free(ARegion *ar) } if (rv3d->viewport) { GPU_viewport_free(rv3d->viewport); + MEM_freeN(rv3d->viewport); } MEM_freeN(rv3d); @@ -790,7 +792,7 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene wmWindow *win = wmn->wm->winactive; ScrArea *sa; unsigned int lay_used = 0; - Base *base; + BaseLegacy *base; if (!win) return; @@ -1287,8 +1289,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot } const char *view3d_context_dir[] = { - "selected_objects", "selected_bases", "selected_editable_objects", - "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", "active_base", "active_object", NULL }; @@ -1299,109 +1299,27 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes if (CTX_data_dir(member)) { CTX_data_dir_set(result, view3d_context_dir); } - else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selected_objects = CTX_data_equals(member, "selected_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (selected_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (0 == BKE_object_is_libdata(base->object)) { - if (selected_editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool visible_objects = CTX_data_equals(member, "visible_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (visible_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selectable_objects = CTX_data_equals(member, "selectable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (selectable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } else if (CTX_data_equals(member, "active_base")) { - View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - if (scene->basact && (scene->basact->lay & lay)) { - Object *ob = scene->basact->object; + SceneLayer *sl = CTX_data_scene_layer(C); + if (sl->basact) { + Object *ob = sl->basact->object; /* if hidden but in edit mode, we still display, can happen with animation */ - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact); + if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) { + CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact); + } } return 1; } else if (CTX_data_equals(member, "active_object")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - if (scene->basact && (scene->basact->lay & lay)) { - Object *ob = scene->basact->object; - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) - CTX_data_id_pointer_set(result, &scene->basact->object->id); + SceneLayer *sl = CTX_data_scene_layer(C); + if (sl->basact) { + Object *ob = sl->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) { + CTX_data_id_pointer_set(result, &ob->id); + } } return 1; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 17622d9dbb1..46ffde7f671 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -699,7 +699,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) /* camera name - draw in highlighted text color */ if (ca && (ca->flag & CAM_SHOWNAME)) { - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); BLF_draw_default( x1i, y1i - (0.7f * U.widget_unit), 0.0f, v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2); @@ -1645,11 +1645,11 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect) int i = axis_order[axis_i]; const char axis_text[2] = {'x' + i, '\0'}; - glColor4ubv(axis_col[i]); /* text shader still uses gl_Color */ + BLF_color4ubv(BLF_default(), axis_col[i]); BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1); } - /* BLF_draw_default disabled blending for us */ + /* BLF_draw disabled blending for us */ } #ifdef WITH_INPUT_NDOF @@ -1768,7 +1768,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) /* ******************** non-meshes ***************** */ static void view3d_draw_non_mesh( -Scene *scene, Object *ob, Base *base, View3D *v3d, +Scene *scene, SceneLayer *sl, Object *ob, Base *base, View3D *v3d, RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4]) { glMatrixMode(GL_PROJECTION); @@ -1794,7 +1794,7 @@ RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4]) drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, color); break; case OB_LAMP: - drawlamp(v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, ob == OBACT); + drawlamp(v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, ob == OBACT_NEW); break; case OB_CAMERA: drawcamera(scene, v3d, rv3d, base, DRAW_CONSTCOLOR, color); @@ -1873,6 +1873,7 @@ static void view3d_draw_setup_view(const bContext *C, ARegion *ar) static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); if (only_depth) @@ -1885,13 +1886,13 @@ static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_dep v3d->zbuf = true; } - for (Base *base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { /* dupli drawing */ if (base->object->transflag & OB_DUPLI) - draw_dupli_objects(scene, ar, v3d, base); + draw_dupli_objects(scene, sl, ar, v3d, base); - draw_object(scene, ar, v3d, base, 0); + draw_object(scene, sl, ar, v3d, base, 0); } } @@ -1969,6 +1970,7 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar) * we filter them based on the plates/layers */ Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ar->regiondata; @@ -1982,13 +1984,13 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar) * for now let's avoid writing again to zbuffer to prevent glitches */ - for (Base *base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { Object *ob = base->object; unsigned char ob_wire_col[4]; - draw_object_wire_color(scene, base, ob_wire_col); - view3d_draw_non_mesh(scene, ob, base, v3d, rv3d, is_boundingbox, ob_wire_col); + draw_object_wire_color(scene, sl, base, ob_wire_col); + view3d_draw_non_mesh(scene, sl, ob, base, v3d, rv3d, is_boundingbox, ob_wire_col); } } @@ -2100,12 +2102,42 @@ static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data #endif } +static void view3d_render_pass(const bContext *C, ARegion *UNUSED(ar)) +{ + Scene *scene = CTX_data_scene(C); + RenderEngineType *type = RE_engines_find(scene->r.engine); /* In the future we should get that from Layers */ + + if (type->flag & RE_USE_OGL_PIPELINE) { + type->view_draw(NULL, C); + } + else { + // Offline Render engine + } +} + +static void view3d_draw_view_new(const bContext *C, ARegion *ar, DrawData *UNUSED(draw_data)) +{ + + view3d_draw_setup_view(C, ar); + + /* Only 100% compliant on new spec goes bellow */ + view3d_render_pass(C, ar); + + view3d_draw_grid(C, ar); + view3d_draw_manipulators(C, ar); + view3d_draw_region_info(C, ar); +} + + void view3d_main_region_draw(const bContext *C, ARegion *ar) { + Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ar->regiondata; + /* TODO layers - In the future we should get RE from Layers */ + RenderEngineType *type = RE_engines_find(scene->r.engine); - if (IS_VIEWPORT_LEGACY(v3d)) { + if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_OGL_PIPELINE) == 0)) { view3d_main_region_draw_legacy(C, ar); return; } @@ -2113,12 +2145,20 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar) if (!rv3d->viewport) rv3d->viewport = GPU_viewport_create(); + GPU_viewport_bind(rv3d->viewport, &ar->winrct, scene->r.engine); + /* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c * before we even call the drawing routine, but let's move on for now (dfelinto) * but this is a provisory way to start seeing things in the viewport */ DrawData draw_data; view3d_draw_data_init(C, ar, rv3d, &draw_data); - view3d_draw_view(C, ar, &draw_data); + + if (type->flag & RE_USE_OGL_PIPELINE) + view3d_draw_view_new(C, ar, &draw_data); + else + view3d_draw_view(C, ar, &draw_data); + + GPU_viewport_unbind(rv3d->viewport); v3d->flag |= V3D_INVALID_BACKBUF; } diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 3f78cfdb086..26756a5e410 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -60,6 +60,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_image.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_global.h" @@ -292,7 +293,7 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) name = tmpstr; } - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); #ifdef WITH_INTERNATIONAL BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); #else @@ -310,6 +311,8 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) const char *msg_pin = " (Pinned)"; const char *msg_sep = " : "; + const int font_id = BLF_default(); + char info[300]; char *s = info; short offset = 1.5f * UI_UNIT_X + rect->xmin; @@ -385,18 +388,18 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) /* color depends on whether there is a keyframe */ if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) - UI_ThemeColor(TH_TIME_KEYFRAME); + UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) - UI_ThemeColor(TH_TIME_GP_KEYFRAME); + UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); else - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(font_id, TH_TEXT_HI); } else { /* no object */ if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) - UI_ThemeColor(TH_TIME_GP_KEYFRAME); + UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); else - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(font_id, TH_TEXT_HI); } if (markern) { @@ -411,10 +414,10 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) /* *********************** backdraw for selection *************** */ -static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d) +static void backdrawview3d(Scene *scene, SceneLayer *sl, wmWindow *win, ARegion *ar, View3D *v3d) { RegionView3D *rv3d = ar->regiondata; - struct Base *base = scene->basact; + struct Base *base = sl->basact; int multisample_enabled; BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); @@ -511,7 +514,7 @@ static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d G.f |= G_BACKBUFSEL; - if (base && (base->lay & v3d->lay)) + if (base && ((base->flag & BASE_VISIBLED) != 0)) draw_object_backbufsel(scene, v3d, rv3d, base->object); if (rv3d->gpuoffscreen) @@ -556,7 +559,7 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, void ED_view3d_backbuf_validate(ViewContext *vc) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) - backdrawview3d(vc->scene, vc->win, vc->ar, vc->v3d); + backdrawview3d(vc->scene, vc->sl, vc->win, vc->ar, vc->v3d); } /** @@ -1030,22 +1033,22 @@ static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, typedef struct View3DAfter { struct View3DAfter *next, *prev; - struct Base *base; + struct BaseLegacy *base; short dflag; } View3DAfter; /* temp storage of Objects that need to be drawn as last */ -void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag) +void ED_view3d_after_add(ListBase *lb, BaseLegacy *base, const short dflag) { View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after"); - BLI_assert((base->flag & OB_FROMDUPLI) == 0); + BLI_assert((base->flag_legacy & OB_FROMDUPLI) == 0); BLI_addtail(lb, v3da); v3da->base = base; v3da->dflag = dflag; } /* disables write in zbuffer and draws it over */ -static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d) +static void view3d_draw_transp(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d) { View3DAfter *v3da; @@ -1053,7 +1056,7 @@ static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d) v3d->transp = true; while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); + draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag); MEM_freeN(v3da); } v3d->transp = false; @@ -1063,7 +1066,7 @@ static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d) } /* clears zbuffer and draws it over */ -static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear) +static void view3d_draw_xray(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, bool *clear) { if (*clear && v3d->zbuf) { glClear(GL_DEPTH_BUFFER_BIT); @@ -1073,7 +1076,7 @@ static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear v3d->xray = true; View3DAfter *v3da; while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); + draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag); MEM_freeN(v3da); } v3d->xray = false; @@ -1081,7 +1084,7 @@ static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear /* clears zbuffer and draws it over */ -static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const bool clear) +static void view3d_draw_xraytransp(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, const bool clear) { if (clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT); @@ -1093,7 +1096,7 @@ static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const View3DAfter *v3da; while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); + draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag); MEM_freeN(v3da); } @@ -1132,7 +1135,7 @@ static DupliObject *dupli_step(DupliObject *dob) } static void draw_dupli_objects_color( - Scene *scene, ARegion *ar, View3D *v3d, Base *base, + Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *base, const short dflag, const int color) { RegionView3D *rv3d = ar->regiondata; @@ -1149,7 +1152,7 @@ static void draw_dupli_objects_color( short dtx; DupliApplyData *apply_data; - if (base->object->restrictflag & OB_RESTRICT_VIEW) return; + if ((base->flag & BASE_VISIBLED) == 0) return; if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return; if (dflag & DRAW_CONSTCOLOR) { @@ -1159,7 +1162,8 @@ static void draw_dupli_objects_color( UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb); } - tbase.flag = OB_FROMDUPLI | base->flag; + tbase.flag_legacy = OB_FROMDUPLI | base->flag_legacy; + tbase.flag = base->flag; lb = object_duplilist(G.main->eval_ctx, scene, base->object); // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ @@ -1253,7 +1257,7 @@ static void draw_dupli_objects_color( displist = glGenLists(1); glNewList(displist, GL_COMPILE); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); + draw_object(scene, sl, ar, v3d, &tbase, dflag_dupli); glEndList(); use_displist = true; @@ -1270,7 +1274,7 @@ static void draw_dupli_objects_color( else { copy_m4_m4(dob->ob->obmat, dob->mat); GPU_begin_dupli_object(dob); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); + draw_object(scene, sl, ar, v3d, &tbase, dflag_dupli); GPU_end_dupli_object(); } } @@ -1292,17 +1296,17 @@ static void draw_dupli_objects_color( glDeleteLists(displist, 1); } -void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base) +void draw_dupli_objects(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *base) { /* define the color here so draw_dupli_objects_color can be called * from the set loop */ - int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE; + int color = (base->flag & BASE_SELECTED) ? TH_SELECT : TH_WIRE; /* debug */ if (base->object->dup_group && base->object->dup_group->id.us < 1) color = TH_REDALERT; - draw_dupli_objects_color(scene, ar, v3d, base, 0, color); + draw_dupli_objects_color(scene, sl, ar, v3d, base, 0, color); } /* XXX warning, not using gpu offscreen here */ @@ -1449,10 +1453,11 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover short flag = v3d->flag; float glalphaclip = U.glalphaclip; int obcenter_dia = U.obcenter_dia; + TODO_LAYER_CONTEXT; /* we should pass context, really */ + SceneLayer *sl = BKE_scene_layer_active(scene); /* no need for color when drawing depth buffer */ const short dflag_depth = DRAW_CONSTCOLOR; /* temp set drawtype to solid */ - /* Setting these temporarily is not nice */ v3d->flag &= ~V3D_SELECT_OUTLINE; U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ @@ -1483,21 +1488,21 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover Scene *sce_iter; for (SETLOOPER(scene->set, sce_iter, base)) { if (v3d->lay & base->lay) { - draw_object(scene, ar, v3d, base, 0); + draw_object(scene, sl, ar, v3d, base, 0); if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED); + draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED); } } } } - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { /* dupli drawing */ if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED); + draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED); } - draw_object(scene, ar, v3d, base, dflag_depth); + draw_object(scene, sl, ar, v3d, base, dflag_depth); } } @@ -1518,7 +1523,7 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) { glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */ for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); + draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth); } glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */ } @@ -1527,21 +1532,21 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover v3d->xray = false; v3d->transp = true; while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); + draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth); MEM_freeN(v3da); } v3d->xray = true; v3d->transp = false; while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); + draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth); MEM_freeN(v3da); } v3d->xray = true; v3d->transp = true; while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); + draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth); MEM_freeN(v3da); } @@ -1603,7 +1608,7 @@ static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) { ListBase shadows; Scene *sce_iter; - Base *base; + BaseLegacy *base; World *world = scene->world; SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL; @@ -1737,8 +1742,9 @@ static void view3d_draw_objects( const char **grid_unit, const bool do_bgpic, const bool draw_offscreen, GPUFX *fx) { + SceneLayer *sl = C ? CTX_data_scene_layer(C) : BKE_scene_layer_active(scene); RegionView3D *rv3d = ar->regiondata; - Base *base; + BaseLegacy *base; const bool do_camera_frame = !draw_offscreen; const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); @@ -1798,10 +1804,10 @@ static void view3d_draw_objects( for (SETLOOPER(scene->set, sce_iter, base)) { if (v3d->lay & base->lay) { UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); - draw_object(scene, ar, v3d, base, dflag); + draw_object(scene, sl, ar, v3d, base, dflag); if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag, TH_UNDEFINED); + draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag, TH_UNDEFINED); } } } @@ -1810,13 +1816,13 @@ static void view3d_draw_objects( } if (draw_offscreen) { - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { /* dupli drawing */ if (base->object->transflag & OB_DUPLI) - draw_dupli_objects(scene, ar, v3d, base); + draw_dupli_objects(scene, sl, ar, v3d, base); - draw_object(scene, ar, v3d, base, 0); + draw_object(scene, sl, ar, v3d, base, 0); } } } @@ -1824,18 +1830,18 @@ static void view3d_draw_objects( unsigned int lay_used = 0; /* then draw not selected and the duplis, but skip editmode object */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { lay_used |= base->lay; - if (v3d->lay & base->lay) { + if ((base->flag & BASE_VISIBLED) != 0) { /* dupli drawing */ if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects(scene, ar, v3d, base); + draw_dupli_objects(scene, sl, ar, v3d, base); } - if ((base->flag & SELECT) == 0) { + if ((base->flag & BASE_SELECTED) == 0) { if (base->object != scene->obedit) - draw_object(scene, ar, v3d, base, 0); + draw_object(scene, sl, ar, v3d, base, 0); } } } @@ -1844,10 +1850,10 @@ static void view3d_draw_objects( v3d->lay_used = lay_used & ((1 << 20) - 1); /* draw selected and editmode */ - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { - if (base->object == scene->obedit || (base->flag & SELECT)) { - draw_object(scene, ar, v3d, base, 0); + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + if (base->object == scene->obedit || (base->flag & BASE_SELECTED)) { + draw_object(scene, sl, ar, v3d, base, 0); } } } @@ -1869,7 +1875,7 @@ static void view3d_draw_objects( } /* transp and X-ray afterdraw stuff */ - if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d); + if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, sl, ar, v3d); /* always do that here to cleanup depth buffers if none needed */ if (fx) { @@ -1877,8 +1883,8 @@ static void view3d_draw_objects( GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray); } - if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, &xrayclear); - if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, xrayclear); + if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, sl, ar, v3d, &xrayclear); + if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, sl, ar, v3d, xrayclear); if (fx && do_composite_xray) { GPU_fx_compositor_XRay_resolve(fx); @@ -2345,13 +2351,15 @@ void ED_scene_draw_fps(Scene *scene, const rcti *rect) } #endif + const int font_id = BLF_default(); + /* is this more than half a frame behind? */ if (fps + 0.5f < (float)(FPS)) { - UI_ThemeColor(TH_REDALERT); + UI_FontThemeColor(font_id, TH_REDALERT); BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); } else { - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(font_id, TH_TEXT_HI); BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); } @@ -2533,7 +2541,7 @@ static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion * static void update_lods(Scene *scene, float camera_pos[3]) { Scene *sce_iter; - Base *base; + BaseLegacy *base; for (SETLOOPER(scene, sce_iter, base)) { Object *ob = base->object; @@ -2664,7 +2672,8 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene, draw_view_icon(rv3d, &rect); if (U.uiflag & USER_DRAWVIEWINFO) { - Object *ob = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT_NEW; draw_selected_name(scene, ob, &rect); } } @@ -2685,7 +2694,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene, if (grid_unit) { /* draw below the viewport name */ char numstr[32] = ""; - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); if (v3d->grid != 1.0f) { BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 921042229b0..a27434fdfd7 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -670,7 +670,7 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) { /* object mode use boundbox centers */ View3D *v3d = CTX_wm_view3d(C); - Base *base; + BaseLegacy *base; unsigned int tot = 0; float select_center[3]; @@ -2940,7 +2940,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - Base *base; + BaseLegacy *base; float *curs; const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) || @@ -3045,7 +3045,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) { /* hard-coded exception, we look for the one selected armature */ /* this is weak code this way, we should make a generic active/selection callback interface once... */ - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { if (TESTBASELIB(v3d, base)) { if (base->object->type == OB_ARMATURE) @@ -3091,7 +3091,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) ok_dist = 0; /* don't zoom */ } else { - Base *base; + BaseLegacy *base; for (base = FIRSTBASE; base; base = base->next) { if (TESTBASE(v3d, base)) { diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 92e3fb5946b..fb109e98a7e 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -284,9 +284,10 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ToolSettings *ts = CTX_data_tool_settings(C); PointerRNA v3dptr, toolsptr, sceneptr; - Object *ob = OBACT; + Object *ob = OBACT_NEW; Object *obedit = CTX_data_edit_object(C); bGPdata *gpd = CTX_data_gpencil_data(C); uiBlock *block; @@ -373,11 +374,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) } if (obedit == NULL && v3d->localvd == NULL) { - unsigned int ob_lay = ob ? ob->lay : 0; - - /* Layers */ - uiTemplateLayers(layout, v3d->scenelock ? &sceneptr : &v3dptr, "layers", &v3dptr, "layers_used", ob_lay); - /* Scene lock */ uiItemR(layout, &v3dptr, "lock_camera_and_layers", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 21a3f16c510..5f29e91143a 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -38,6 +38,7 @@ struct ARegion; struct ARegionType; struct BoundBox; +struct Batch; struct DerivedMesh; struct Object; struct SmokeDomainSettings; @@ -46,6 +47,7 @@ struct bContext; struct bMotionPath; struct bPoseChannel; struct Mesh; +struct SceneLayer; struct wmManipulatorGroupType; struct wmOperatorType; struct wmWindowManager; @@ -142,14 +144,14 @@ void draw_motion_paths_cleanup(View3D *v3d); /* drawobject.c */ -void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag); +void draw_object(Scene *scene, struct SceneLayer *sl, struct ARegion *ar, View3D *v3d, BaseLegacy *base, const short dflag); void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm); bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt); void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline); void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); -void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4]); +void draw_object_wire_color(Scene *scene, struct SceneLayer *, Base *base, unsigned char r_ob_wire_col[4]); void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]); void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4], @@ -179,7 +181,7 @@ enum { int view3d_effective_drawtype(const struct View3D *v3d); /* drawarmature.c */ -bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, +bool draw_armature(Scene *scene, struct SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, const short dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_outline); @@ -210,7 +212,7 @@ void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar); void view3d_main_region_draw_legacy(const struct bContext *C, struct ARegion *ar); void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride); void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d); -void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag); +void ED_view3d_after_add(ListBase *lb, BaseLegacy *base, const short dflag); void circ(float x, float y, float rad); void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect); @@ -334,7 +336,7 @@ void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool void VP_legacy_view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]); bool VP_legacy_view3d_stereo3d_active(const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d); void VP_legacy_view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar); -void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base); +void draw_dupli_objects(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *base); bool VP_legacy_use_depth(Scene *scene, View3D *v3d); void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d); void VP_drawrenderborder(ARegion *ar, View3D *v3d); diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index 7540e5ad180..4a4d008f779 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -43,6 +43,8 @@ #include "BIF_gl.h" +#include "GPU_immediate.h" + #include "WM_api.h" #include "WM_types.h" @@ -280,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), CTX_data_scene(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { @@ -456,28 +458,38 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a glEnable(GL_BLEND); - cpack(is_act ? color_act : color_base); - if (ruler_item->flag & RULERITEM_USE_ANGLE) { - glBegin(GL_LINE_STRIP); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + imm_cpack(is_act ? color_act : color_base); + + immBegin(GL_LINE_STRIP, 3); + for (j = 0; j < 3; j++) { - glVertex2fv(co_ss[j]); + immVertex2fv(pos, co_ss[j]); } - glEnd(); - cpack(0xaaaaaa); + + immEnd(); + + imm_cpack(0xaaaaaa); setlinestyle(3); - glBegin(GL_LINE_STRIP); + + immBegin(GL_LINE_STRIP, 3); + for (j = 0; j < 3; j++) { - glVertex2fv(co_ss[j]); + immVertex2fv(pos, co_ss[j]); } - glEnd(); + + immEnd(); + setlinestyle(0); /* arc */ { float dir_tmp[3]; float co_tmp[3]; - float arc_ss_coords[ARC_STEPS + 1][2]; + float arc_ss_coord[2]; float dir_a[3]; float dir_b[3]; @@ -501,45 +513,19 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a copy_v3_v3(dir_tmp, dir_a); - glColor3ubv(color_wire); + immUniformColor3ubv(color_wire); + + immBegin(GL_LINE_STRIP, arc_steps + 1); for (j = 0; j <= arc_steps; j++) { madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); - ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP); mul_qt_v3(quat, dir_tmp); - } - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords); - glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1); - glDisableClientState(GL_VERTEX_ARRAY); - } - - /* text */ - { - char numstr[256]; - float numstr_size[2]; - float pos[2]; - const int prec = 2; /* XXX, todo, make optional */ - - ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); - - BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); - pos[0] = co_ss[1][0] + (cap_size * 2.0f); - pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); + immVertex2fv(pos, arc_ss_coord); + } - /* draw text (bg) */ - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox( - pos[0] - bg_margin, pos[1] - bg_margin, - pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], - bg_radius, color_back); - /* draw text */ - glColor3ubv(color_text); - BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); - BLF_rotation(blf_mono_font, 0.0f); - BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + immEnd(); } /* capping */ @@ -560,74 +546,88 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a glEnable(GL_BLEND); - glColor3ubv(color_wire); + immUniformColor3ubv(color_wire); - glBegin(GL_LINES); + immBegin(GL_LINES, 8); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); - glVertex2fv(cap); + immVertex2fv(pos, cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); - glVertex2fv(cap); + immVertex2fv(pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); - glVertex2fv(cap); + immVertex2fv(pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); - glVertex2fv(cap); + immVertex2fv(pos, cap); /* angle vertex */ - glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); - glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); - glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); - glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); - glEnd(); + immVertex2f(pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); + immVertex2f(pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); + immVertex2f(pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); + immVertex2f(pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); + + immEnd(); glDisable(GL_BLEND); } - } - else { - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j += 2) { - glVertex2fv(co_ss[j]); - } - glEnd(); - cpack(0xaaaaaa); - setlinestyle(3); - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j += 2) { - glVertex2fv(co_ss[j]); - } - glEnd(); - setlinestyle(0); - sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); + immUnbindProgram(); /* text */ { char numstr[256]; float numstr_size[2]; - const int prec = 6; /* XXX, todo, make optional */ - float pos[2]; + float posit[2]; + const int prec = 2; /* XXX, todo, make optional */ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); - mid_v2_v2v2(pos, co_ss[0], co_ss[2]); - - /* center text */ - pos[0] -= numstr_size[0] / 2.0f; - pos[1] -= numstr_size[1] / 2.0f; + posit[0] = co_ss[1][0] + (cap_size * 2.0f); + posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); /* draw text (bg) */ UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox(pos[0] - bg_margin, pos[1] - bg_margin, - pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], - bg_radius, color_back); + UI_draw_roundbox( + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); /* draw text */ - glColor3ubv(color_text); - BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_rotation(blf_mono_font, 0.0f); BLF_draw(blf_mono_font, numstr, sizeof(numstr)); } + } + else { + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + imm_cpack(is_act ? color_act : color_base); + + immBegin(GL_LINE_STRIP, 2); + + for (j = 0; j < 3; j += 2) { + immVertex2fv(pos, co_ss[j]); + } + + immEnd(); + + imm_cpack(0xaaaaaa); + setlinestyle(3); + + immBegin(GL_LINE_STRIP, 2); + + for (j = 0; j < 3; j += 2) { + immVertex2fv(pos, co_ss[j]); + } + + immEnd(); + + setlinestyle(0); + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); /* capping */ { @@ -637,22 +637,55 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a normalize_v2(rot_90_vec); glEnable(GL_BLEND); - glColor3ubv(color_wire); - glBegin(GL_LINES); + immUniformColor3ubv(color_wire); + + immBegin(GL_LINES, 4); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); - glVertex2fv(cap); + immVertex2fv(pos, cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); - glVertex2fv(cap); + immVertex2fv(pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); - glVertex2fv(cap); + immVertex2fv(pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); - glVertex2fv(cap); - glEnd(); + immVertex2fv(pos, cap); + + immEnd(); glDisable(GL_BLEND); } + + immUnbindProgram(); + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + const int prec = 6; /* XXX, todo, make optional */ + float posit[2]; + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + + mid_v2_v2v2(posit, co_ss[0], co_ss[2]); + + /* center text */ + posit[0] -= numstr_size[0] / 2.0f; + posit[1] -= numstr_size[1] / 2.0f; + + /* draw text (bg) */ + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox(posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); + /* draw text */ + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } } } @@ -671,8 +704,14 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a float co_ss[3]; ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP); - cpack(color_act); - circ(co_ss[0], co_ss[1], size * U.pixelsize); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + imm_cpack(color_act); + + imm_draw_lined_circle(pos, co_ss[0], co_ss[1], size * U.pixelsize, 32); + + immUnbindProgram(); } } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 3239d07553f..60bf078acc3 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -64,11 +64,13 @@ #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_editmesh.h" +#include "BKE_scene.h" #include "BKE_tracking.h" #include "BKE_utildefines.h" @@ -109,6 +111,7 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc) memset(vc, 0, sizeof(ViewContext)); vc->ar = CTX_wm_region(C); vc->scene = CTX_data_scene(C); + vc->sl = CTX_data_scene_layer(C); vc->v3d = CTX_wm_view3d(C); vc->win = CTX_wm_window(C); vc->rv3d = CTX_wm_region_view3d(C); @@ -399,13 +402,13 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[] } } -static void object_deselect_all_visible(Scene *scene, View3D *v3d) +static void object_deselect_all_visible(SceneLayer *sl) { Base *base; - for (base = scene->base.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { - ED_base_object_select(base, BA_DESELECT); + for (base = sl->object_bases.first; base; base = base->next) { + if (BASE_SELECTABLE_NEW(base)) { + ED_object_base_select(base, BA_DESELECT); } } } @@ -416,15 +419,14 @@ static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], cons Base *base; if (extend == false && select) - object_deselect_all_visible(vc->scene, vc->v3d); + object_deselect_all_visible(vc->sl); - for (base = vc->scene->base.first; base; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */ + for (base = vc->sl->object_bases.first; base; base = base->next) { + if (BASE_SELECTABLE_NEW(base)) { /* use this to avoid un-needed lasso lookups */ if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) { if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); - base->object->flag = base->flag; + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); } } if (vc->obact == base->object && (base->object->mode & OB_MODE_POSE)) { @@ -1017,8 +1019,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) if (!toggle) { CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (base->flag & SELECT) { - ED_base_object_select(base, BA_DESELECT); + if ((base->flag & BASE_SELECTED) != 0) { + ED_object_base_select(base, BA_DESELECT); changed = true; } } @@ -1029,8 +1031,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) { /* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */ if (STREQ(name, base->object->id.name + 2)) { - ED_base_object_activate(C, base); - ED_base_object_select(base, BA_SELECT); + ED_object_base_activate(C, base); + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -1074,14 +1076,12 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } -static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */ +static void deselectall_except(SceneLayer *sl, Base *b) /* deselect all except b */ { - Base *base; - - for (base = FIRSTBASE; base; base = base->next) { - if (base->flag & SELECT) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (base->flag & BASE_SELECTED) { if (b != base) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); } } } @@ -1092,7 +1092,8 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int short baseCount = 0; bool ok; LinkNode *linklist = NULL; - + + /* handle base->selcol */ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { ok = false; @@ -1278,8 +1279,7 @@ static short mixed_bones_object_selectbuffer( static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, Base *startbase, bool has_bones, bool do_nearest) { - Scene *scene = vc->scene; - View3D *v3d = vc->v3d; + SceneLayer *sl = vc->sl; Base *base, *basact = NULL; int a; @@ -1299,7 +1299,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int } else { /* only exclude active object when it is selected... */ - if (BASACT && (BASACT->flag & SELECT) && hits > 1) notcol = BASACT->selcol; + if (BASACT_NEW && (BASACT_NEW->flag & BASE_SELECTED) && hits > 1) notcol = BASACT_NEW->selcol; for (a = 0; a < hits; a++) { if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) { @@ -1309,9 +1309,9 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int } } - base = FIRSTBASE; + base = FIRSTBASE_NEW; while (base) { - if (BASE_SELECTABLE(v3d, base)) { + if (BASE_SELECTABLE_NEW(base)) { if (base->selcol == selcol) break; } base = base->next; @@ -1324,13 +1324,13 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int while (base) { /* skip objects with select restriction, to prevent prematurely ending this loop * with an un-selectable choice */ - if (base->object->restrictflag & OB_RESTRICT_SELECT) { + if ((base->flag & BASE_SELECTABLED) == 0) { base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE_NEW; if (base == startbase) break; } - if (BASE_SELECTABLE(v3d, base)) { + if (BASE_SELECTABLE_NEW(base)) { for (a = 0; a < hits; a++) { if (has_bones) { /* skip non-bone objects */ @@ -1349,7 +1349,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int if (basact) break; base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE_NEW; if (base == startbase) break; } } @@ -1374,7 +1374,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) if (hits > 0) { const bool has_bones = selectbuffer_has_bones(buffer, hits); - basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene->base.first, has_bones, do_nearest); + basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.sl->object_bases.first, has_bones, do_nearest); } return basact; @@ -1406,8 +1406,8 @@ static bool ed_object_select_pick( { ViewContext vc; ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL; bool is_obedit; float dist = ED_view3d_select_dist_px() * 1.3333f; @@ -1426,8 +1426,8 @@ static bool ed_object_select_pick( } /* always start list from basact in wire mode */ - startbase = FIRSTBASE; - if (BASACT && BASACT->next) startbase = BASACT->next; + startbase = FIRSTBASE_NEW; + if (BASACT_NEW && BASACT_NEW->next) startbase = BASACT_NEW->next; /* This block uses the control key to make the object selected by its center point rather than its contents */ /* in editmode do not activate */ @@ -1440,13 +1440,13 @@ static bool ed_object_select_pick( else { base = startbase; while (base) { - if (BASE_SELECTABLE(v3d, base)) { + if (BASE_SELECTABLE_NEW(base)) { float screen_co[2]; if (ED_view3d_project_float_global(ar, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { float dist_temp = len_manhattan_v2v2(mval_fl, screen_co); - if (base == BASACT) dist_temp += 10.0f; + if (base == BASACT_NEW) dist_temp += 10.0f; if (dist_temp < dist) { dist = dist_temp; basact = base; @@ -1455,7 +1455,7 @@ static bool ed_object_select_pick( } base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE_NEW; if (base == startbase) break; } } @@ -1482,7 +1482,7 @@ static bool ed_object_select_pick( if (has_bones && basact) { if (basact->object->type == OB_CAMERA) { - if (BASACT == basact) { + if (BASACT_NEW == basact) { int i, hitresult; bool changed = false; @@ -1520,8 +1520,8 @@ static bool ed_object_select_pick( changed = true; } - basact->flag |= SELECT; - basact->object->flag = basact->flag; + basact->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(basact); retval = true; @@ -1544,22 +1544,22 @@ static bool ed_object_select_pick( /* we make the armature selected: * not-selected active object in posemode won't work well for tools */ - basact->flag |= SELECT; - basact->object->flag = basact->flag; + basact->flag |= BASE_SELECTED; + BKE_scene_base_flag_sync_from_base(basact); retval = true; WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object); /* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */ - if (BASACT && (BASACT->object->mode & OB_MODE_WEIGHT_PAINT)) { + if (BASACT_NEW && (BASACT_NEW->object->mode & OB_MODE_WEIGHT_PAINT)) { /* prevent activating */ basact = NULL; } } /* prevent bone selecting to pass on to object selecting */ - if (basact == BASACT) + if (basact == BASACT_NEW) basact = NULL; } } @@ -1571,37 +1571,37 @@ static bool ed_object_select_pick( if (vc.obedit) { /* only do select */ - deselectall_except(scene, basact); - ED_base_object_select(basact, BA_SELECT); + deselectall_except(sl, basact); + ED_object_base_select(basact, BA_SELECT); } /* also prevent making it active on mouse selection */ - else if (BASE_SELECTABLE(v3d, basact)) { + else if (BASE_SELECTABLE_NEW(basact)) { - oldbasact = BASACT; + oldbasact = BASACT_NEW; if (extend) { - ED_base_object_select(basact, BA_SELECT); + ED_object_base_select(basact, BA_SELECT); } else if (deselect) { - ED_base_object_select(basact, BA_DESELECT); + ED_object_base_select(basact, BA_DESELECT); } else if (toggle) { - if (basact->flag & SELECT) { + if (basact->flag & BASE_SELECTED) { if (basact == oldbasact) { - ED_base_object_select(basact, BA_DESELECT); + ED_object_base_select(basact, BA_DESELECT); } } else { - ED_base_object_select(basact, BA_SELECT); + ED_object_base_select(basact, BA_SELECT); } } else { - deselectall_except(scene, basact); - ED_base_object_select(basact, BA_SELECT); + deselectall_except(sl, basact); + ED_object_base_select(basact, BA_SELECT); } if ((oldbasact != basact) && (is_obedit == false)) { - ED_base_object_activate(C, basact); /* adds notifier */ + ED_object_base_activate(C, basact); /* adds notifier */ } } @@ -2031,7 +2031,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b CTX_DATA_END; } else { - object_deselect_all_visible(vc->scene, vc->v3d); + object_deselect_all_visible(vc->sl); } } @@ -2051,7 +2051,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b */ if (hits > 0) { /* no need to loop if there's no hit */ - Base *base; + BaseLegacy *base; col = vbuffer + 3; for (base = vc->scene->base.first; base && hits; base = base->next) { @@ -2786,22 +2786,22 @@ static void obedit_circle_select(ViewContext *vc, const bool select, const int m static bool object_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) { - Scene *scene = vc->scene; + SceneLayer *sl = vc->sl; const float radius_squared = rad * rad; const float mval_fl[2] = {mval[0], mval[1]}; bool changed = false; - const int select_flag = select ? SELECT : 0; + const int select_flag = select ? BASE_SELECTED : 0; Base *base; - for (base = FIRSTBASE; base; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) { + for (base = FIRSTBASE_NEW; base; base = base->next) { + if (BASE_SELECTABLE_NEW(base) && ((base->flag & BASE_SELECTED) != select_flag)) { float screen_co[2]; if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); changed = true; } } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 8582952d1a0..53c91936913 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1091,28 +1091,27 @@ void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d) } } -static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, bool use_obedit_skip) +static void view3d_select_loop(ViewContext *vc, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, bool use_obedit_skip) { short code = 1; char dt; short dtx; if (vc->obedit && vc->obedit->type == OB_MBALL) { - draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR); + draw_object(scene, sl, ar, v3d, BASACT_NEW, DRAW_PICKING | DRAW_CONSTCOLOR); } else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) { /* if not drawing sketch, draw bones */ if (!BDR_drawSketchNames(vc)) { - draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR); + draw_object(scene, sl, ar, v3d, BASACT_NEW, DRAW_PICKING | DRAW_CONSTCOLOR); } } else { Base *base; v3d->xray = true; /* otherwise it postpones drawing */ - for (base = scene->base.first; base; base = base->next) { - if (base->lay & v3d->lay) { - + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { if ((base->object->restrictflag & OB_RESTRICT_SELECT) || (use_obedit_skip && (scene->obedit->data == base->object->data))) { @@ -1122,7 +1121,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi base->selcol = code; if (GPU_select_load_id(code)) { - draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR); + draw_object(scene, sl, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR); /* we draw duplicators for selection too */ if ((base->object->transflag & OB_DUPLI)) { @@ -1130,7 +1129,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi DupliObject *dob; Base tbase; - tbase.flag = OB_FROMDUPLI; + tbase.flag_legacy = OB_FROMDUPLI; lb = object_duplilist(G.main->eval_ctx, scene, base->object); for (dob = lb->first; dob; dob = dob->next) { @@ -1145,7 +1144,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; - draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR); + draw_object(scene, sl, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR); tbase.object->dt = dt; tbase.object->dtx = dtx; @@ -1173,6 +1172,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, bool do_nearest) { Scene *scene = vc->scene; + SceneLayer *sl = vc->sl; View3D *v3d = vc->v3d; ARegion *ar = vc->ar; rctf rect; @@ -1209,7 +1209,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b else GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_ALL, 0); - view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip); + view3d_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip); hits = GPU_select_end(); @@ -1217,7 +1217,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b if (do_passes) { GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); - view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip); + view3d_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip); GPU_select_end(); } @@ -1319,7 +1319,7 @@ static bool view3d_localview_init( ReportList *reports) { View3D *v3d = sa->spacedata.first; - Base *base; + BaseLegacy *base; float min[3], max[3], box[3], mid[3]; float size = 0.0f; unsigned int locallay; @@ -1422,7 +1422,7 @@ static bool view3d_localview_init( if (base->lay & locallay) { base->lay -= locallay; if (base->lay == 0) base->lay = v3d->layact; - if (base->object != scene->obedit) base->flag |= SELECT; + if (base->object != scene->obedit) base->flag_legacy |= SELECT; base->object->lay = base->lay; } } @@ -1493,7 +1493,7 @@ static bool view3d_localview_exit( Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx) { View3D *v3d = sa->spacedata.first; - struct Base *base; + struct BaseLegacy *base; unsigned int locallay; if (v3d->localvd) { @@ -1510,7 +1510,7 @@ static bool view3d_localview_exit( base->lay -= locallay; if (base->lay == 0) base->lay = v3d->layact; if (base->object != scene->obedit) { - base->flag |= SELECT; + base->flag_legacy |= SELECT; base->object->flag |= SELECT; } base->object->lay = base->lay; diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 4131a5c33c7..d4e78035b84 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -599,7 +599,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->rv3d->rflag |= RV3D_NAVIGATING; walk->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), walk->scene, SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), walk->scene, 0, walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 5b1dcf92c29..fb1543c5deb 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1852,8 +1852,9 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) int xco, yco; ED_region_visible_rect(ar, &rect); - - BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); + + const int font_id = BLF_default(); + BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; yco = (rect.ymax - U.widget_unit); @@ -1861,7 +1862,9 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) /* warning text (to clarify meaning of overlays) * - original color was red to match the icon, but that clashes badly with a less nasty border */ - UI_ThemeColorShade(TH_TEXT_HI, -50); + unsigned char color[3]; + UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color); + BLF_color3ubv(font_id, color); #ifdef WITH_INTERNATIONAL BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #else @@ -1884,7 +1887,8 @@ static void drawTransformPixel(const struct bContext *UNUSED(C), ARegion *ar, vo { TransInfo *t = arg; Scene *scene = t->scene; - Object *ob = OBACT; + SceneLayer *sl = t->sl; + Object *ob = OBACT_NEW; /* draw autokeyframing hint in the corner * - only draw if enabled (advanced users may be distracted/annoyed), @@ -3721,6 +3725,12 @@ static void initRotation(TransInfo *t) copy_v3_v3(t->axis_orig, t->axis); } +/** + * Applies values of rotation to `td->loc` and `td->ext->quat` + * based on a rotation matrix (mat) and a pivot (center). + * + * Protected axis and other transform settings are taken into account. + */ static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], const float *center) { float vec[3], totmat[3][3], smat[3][3]; @@ -4338,9 +4348,22 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) { TransData *td = t->data; float tvec[3]; - int i; - for (i = 0; i < t->total; i++, td++) { + /* The ideal would be "apply_snap_align_rotation" only when a snap point is found + * so, maybe inside this function is not the best place to apply this rotation. + * but you need "handle snapping rotation before doing the translation" (really?) */ + const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT); + float pivot[3]; + if (apply_snap_align_rotation) { + copy_v3_v3(pivot, t->tsnap.snapTarget); + /* The pivot has to be in local-space (see T49494) */ + if (t->flag & (T_EDIT | T_POSE)) { + Object *ob = t->obedit ? t->obedit : t->poseobj; + mul_m4_v3(ob->imat, pivot); + } + } + + for (int i = 0; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; @@ -4351,7 +4374,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) bool use_rotate_offset = false; /* handle snapping rotation before doing the translation */ - if (usingSnappingNormal(t)) { + if (apply_snap_align_rotation) { float mat[3][3]; if (validSnappingNormal(t)) { @@ -4369,7 +4392,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) unit_m3(mat); } - ElementRotation_ex(t, td, mat, t->tsnap.snapTarget); + ElementRotation_ex(t, td, mat, pivot); if (td->loc) { use_rotate_offset = true; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index f250a7abf7c..31af54c030b 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -84,8 +84,8 @@ typedef struct TransSnap { bool peel; bool snap_spatial_grid; short status; - float snapPoint[3]; /* snapping from this point */ - float snapTarget[3]; /* to this point */ + float snapPoint[3]; /* snapping from this point (in global-space)*/ + float snapTarget[3]; /* to this point (in global-space)*/ float snapNormal[3]; char snapNodeBorder; ListBase points; @@ -461,6 +461,7 @@ typedef struct TransInfo { struct ScrArea *sa; struct ARegion *ar; struct Scene *scene; + struct SceneLayer *sl; struct ToolSettings *settings; struct wmTimer *animtimer; struct wmKeyMap *keymap; /* so we can do lookups for header text */ diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index c4fa84513c3..d123d9eb3c1 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -40,9 +40,10 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" + #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" @@ -715,7 +716,6 @@ void drawConstraint(TransInfo *t) else { if (tc->mode & CON_SELECT) { float vec[3]; - char col2[3] = {255, 255, 255}; int depth_test_enabled; convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1])); @@ -725,19 +725,26 @@ void drawConstraint(TransInfo *t) drawLine(t, t->center_global, tc->mtx[1], 'Y', 0); drawLine(t, t->center_global, tc->mtx[2], 'Z', 0); - glColor3ubv((GLubyte *)col2); - depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); if (depth_test_enabled) glDisable(GL_DEPTH_TEST); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ub(255, 255, 255); + setlinestyle(1); - glBegin(GL_LINES); - glVertex3fv(t->center_global); - glVertex3fv(vec); - glEnd(); + + immBegin(GL_LINES, 2); + immVertex3fv(pos, t->center_global); + immVertex3fv(pos, vec); + immEnd(); + setlinestyle(0); + immUnbindProgram(); + if (depth_test_enabled) glEnable(GL_DEPTH_TEST); } @@ -762,8 +769,6 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) float tmat[4][4], imat[4][4]; int depth_test_enabled; - UI_ThemeColor(TH_GRID); - if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) { copy_m4_m4(tmat, rv3d->viewmat); invert_m4_m4(imat, tmat); @@ -796,10 +801,17 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) if (depth_test_enabled) glDisable(GL_DEPTH_TEST); + unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_GRID); + set_inverted_drawing(1); - drawcircball(GL_LINE_LOOP, t->center_global, t->prop_size, imat); + imm_drawcircball(t->center_global, t->prop_size, imat, pos); set_inverted_drawing(0); + immUnbindProgram(); + if (depth_test_enabled) glEnable(GL_DEPTH_TEST); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 3e355deef33..b68b3365e46 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -72,6 +72,7 @@ #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_gpencil.h" +#include "BKE_layer.h" #include "BKE_key.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -2381,7 +2382,12 @@ static void createTransEditVerts(TransInfo *t) editmesh_set_connectivity_distance(em->bm, mtx, dists); } - if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + /* Only in case of rotation and resize, we want the elements of the edited + * object to behave as groups whose pivot are the individual origins + * + * TODO: use island_info to detect the closest point when the "Snap Target" + * in Blender UI is "Closest" */ + if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) { island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map); } @@ -5346,12 +5352,11 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) /* it deselects Bases, so we have to call the clear function always after */ static void set_trans_object_base_flags(TransInfo *t) { - Scene *scene = t->scene; - View3D *v3d = t->view; + SceneLayer *sl = t->sl; /* * if Base selected and has parent selected: - * base->flag = BA_WAS_SEL + * base->flag_legacy = BA_WAS_SEL */ Base *base; @@ -5360,32 +5365,32 @@ static void set_trans_object_base_flags(TransInfo *t) return; /* makes sure base flags and object flags are identical */ - BKE_scene_base_flag_to_objects(t->scene); + BKE_scene_base_flag_to_objects(t->sl); /* Make sure depsgraph is here. */ DAG_scene_relations_update(G.main, t->scene); /* handle pending update events, otherwise they got copied below */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { if (base->object->recalc & OB_RECALC_ALL) { /* TODO(sergey): Ideally, it's not needed. */ BKE_object_handle_update(G.main->eval_ctx, t->scene, base->object); } } - for (base = scene->base.first; base; base = base->next) { - base->flag &= ~BA_WAS_SEL; + for (base = sl->object_bases.first; base; base = base->next) { + base->flag_legacy &= ~BA_WAS_SEL; - if (TESTBASELIB_BGMODE(v3d, scene, base)) { + if (TESTBASELIB_BGMODE_NEW(base)) { Object *ob = base->object; Object *parsel = ob->parent; /* if parent selected, deselect */ while (parsel) { - if (parsel->flag & SELECT) { - Base *parbase = BKE_scene_base_find(scene, parsel); + Base *parbase = BKE_scene_layer_base_find(sl, parsel); + if (parbase->flag & BASE_SELECTED) { if (parbase) { /* in rare cases this can fail */ - if (TESTBASELIB_BGMODE(v3d, scene, parbase)) { + if (TESTBASELIB_BGMODE_NEW(parbase)) { break; } } @@ -5398,11 +5403,11 @@ static void set_trans_object_base_flags(TransInfo *t) if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)) { - base->flag |= BA_TRANSFORM_CHILD; + base->flag_legacy |= BA_TRANSFORM_CHILD; } else { - base->flag &= ~SELECT; - base->flag |= BA_WAS_SEL; + base->flag &= ~BASE_SELECTED; + base->flag_legacy |= BA_WAS_SEL; } } DAG_id_tag_update(&ob->id, OB_RECALC_OB); @@ -5411,11 +5416,11 @@ static void set_trans_object_base_flags(TransInfo *t) /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { if (base->object->recalc & OB_RECALC_OB) - base->flag |= BA_HAS_RECALC_OB; + base->flag_legacy |= BA_HAS_RECALC_OB; if (base->object->recalc & OB_RECALC_DATA) - base->flag |= BA_HAS_RECALC_DATA; + base->flag_legacy |= BA_HAS_RECALC_DATA; } } @@ -5437,8 +5442,7 @@ static bool mark_children(Object *ob) static int count_proportional_objects(TransInfo *t) { int total = 0; - Scene *scene = t->scene; - View3D *v3d = t->view; + SceneLayer *sl = t->sl; Base *base; /* rotations around local centers are allowed to propagate, so we take all objects */ @@ -5446,8 +5450,8 @@ static int count_proportional_objects(TransInfo *t) (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))) { /* mark all parents */ - for (base = scene->base.first; base; base = base->next) { - if (TESTBASELIB_BGMODE(v3d, scene, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (TESTBASELIB_BGMODE_NEW(base)) { Object *parent = base->object->parent; /* flag all parents */ @@ -5459,22 +5463,24 @@ static int count_proportional_objects(TransInfo *t) } /* mark all children */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { /* all base not already selected or marked that is editable */ - if ((base->object->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && - (BASE_EDITABLE_BGMODE(v3d, scene, base))) + if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && + (base->flag & BASE_SELECTED) == 0 && + (BASE_EDITABLE_BGMODE_NEW(base))) { mark_children(base->object); } } } - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { Object *ob = base->object; /* if base is not selected, not a parent of selection or not a child of selection and it is editable */ - if ((ob->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && - (BASE_EDITABLE_BGMODE(v3d, scene, base))) + if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && + (base->flag & BASE_SELECTED) == 0 && + (BASE_EDITABLE_BGMODE_NEW(base))) { DAG_id_tag_update(&ob->id, OB_RECALC_OB); @@ -5489,11 +5495,11 @@ static int count_proportional_objects(TransInfo *t) /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { if (base->object->recalc & OB_RECALC_OB) - base->flag |= BA_HAS_RECALC_OB; + base->flag_legacy |= BA_HAS_RECALC_OB; if (base->object->recalc & OB_RECALC_DATA) - base->flag |= BA_HAS_RECALC_DATA; + base->flag_legacy |= BA_HAS_RECALC_DATA; } return total; @@ -5501,14 +5507,15 @@ static int count_proportional_objects(TransInfo *t) static void clear_trans_object_base_flags(TransInfo *t) { - Scene *sce = t->scene; + SceneLayer *sl = t->sl; Base *base; - for (base = sce->base.first; base; base = base->next) { - if (base->flag & BA_WAS_SEL) - base->flag |= SELECT; + for (base = sl->object_bases.first; base; base = base->next) { + if (base->flag_legacy & BA_WAS_SEL) { + base->flag |= BASE_SELECTED; + } - base->flag &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT); + base->flag_legacy &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT); } } @@ -6426,7 +6433,7 @@ static void createTransObject(bContext *C, TransInfo *t) if (is_prop_edit) { View3D *v3d = t->view; - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; @@ -7880,7 +7887,8 @@ static void createTransGPencil(bContext *C, TransInfo *t) void createTransData(bContext *C, TransInfo *t) { Scene *scene = t->scene; - Object *ob = OBACT; + SceneLayer *sl = t->sl; + Object *ob = OBACT_NEW; /* if tests must match recalcData for correct updates */ if (t->options & CTX_TEXTURE) { @@ -8040,10 +8048,9 @@ void createTransData(bContext *C, TransInfo *t) * lines below just check is also visible */ Object *ob_armature = modifiers_isDeformedByArmature(ob); if (ob_armature && ob_armature->mode & OB_MODE_POSE) { - Base *base_arm = BKE_scene_base_find(t->scene, ob_armature); + Base *base_arm = BKE_scene_layer_base_find(t->sl, ob_armature); if (base_arm) { - View3D *v3d = t->view; - if (BASE_VISIBLE(v3d, base_arm)) { + if (BASE_VISIBLE_NEW(base_arm)) { createTransPose(t, ob_armature); } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 6de5cf112d2..2c10ee61466 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -62,8 +62,7 @@ #include "RNA_access.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "GPU_immediate.h" #include "BIK_api.h" @@ -315,7 +314,7 @@ static bool fcu_test_selected(FCurve *fcu) /* helper for recalcData() - for Action Editor transforms */ static void recalcData_actedit(TransInfo *t) { - Scene *scene = t->scene; + SceneLayer *sl= t->sl; SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; bAnimContext ac = {NULL}; @@ -326,7 +325,7 @@ static void recalcData_actedit(TransInfo *t) /* initialize relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ ac.scene = t->scene; - ac.obact = OBACT; + ac.obact = OBACT_NEW; ac.sa = t->sa; ac.ar = t->ar; ac.sl = (t->sa) ? t->sa->spacedata.first : NULL; @@ -363,7 +362,7 @@ static void recalcData_actedit(TransInfo *t) static void recalcData_graphedit(TransInfo *t) { SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; - Scene *scene; + SceneLayer *sl = t->sl; ListBase anim_data = {NULL, NULL}; bAnimContext ac = {NULL}; @@ -374,8 +373,8 @@ static void recalcData_graphedit(TransInfo *t) /* initialize relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ - scene = ac.scene = t->scene; - ac.obact = OBACT; + ac.scene = t->scene; + ac.obact = OBACT_NEW; ac.sa = t->sa; ac.ar = t->ar; ac.sl = (t->sa) ? t->sa->spacedata.first : NULL; @@ -709,7 +708,7 @@ static void recalcData_spaceclip(TransInfo *t) /* helper for recalcData() - for object transforms, typically in the 3D view */ static void recalcData_objects(TransInfo *t) { - Base *base = t->scene->basact; + BaseLegacy *base = t->scene->basact; if (t->obedit) { if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) { @@ -1050,14 +1049,19 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis UI_GetThemeColor3ubv(TH_GRID, col); } UI_make_axis_color(col, col2, axis); - glColor3ubv(col2); - - setlinestyle(0); - glBegin(GL_LINES); - glVertex3fv(v1); - glVertex3fv(v2); - glEnd(); - + + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(col2); + + immBegin(GL_LINES, 2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immEnd(); + + immUnbindProgram(); + glPopMatrix(); } } @@ -1104,6 +1108,7 @@ static int initTransInfo_edit_pet_to_flag(const int proportional) void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event) { Scene *sce = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ToolSettings *ts = CTX_data_tool_settings(C); ARegion *ar = CTX_wm_region(C); ScrArea *sa = CTX_wm_area(C); @@ -1113,6 +1118,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve PropertyRNA *prop; t->scene = sce; + t->sl = sl; t->sa = sa; t->ar = ar; t->obedit = obedit; @@ -1768,8 +1774,8 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } } else if (t->flag & T_POSE) { - Scene *scene = t->scene; - Object *ob = OBACT; + SceneLayer *sl = t->sl; + Object *ob = OBACT_NEW; if (ob) { bPoseChannel *pchan = BKE_pose_channel_active(ob); if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) { @@ -1788,9 +1794,10 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } else { /* object mode */ - Scene *scene = t->scene; - Object *ob = OBACT; - if (ob && (!select_only || (ob->flag & SELECT))) { + SceneLayer *sl = t->sl; + Object *ob = OBACT_NEW; + Base *base = BASACT_NEW; + if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) { copy_v3_v3(r_center, ob->obmat[3]); ok = true; } diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index c730afe9e60..efc5517f3e5 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -688,10 +688,10 @@ static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const int getLocalTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around) { - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); Base *base; - Object *ob = OBACT; + Object *ob = OBACT_NEW; int result = ORIENTATION_NONE; const bool activeOnly = (around == V3D_AROUND_ACTIVE); @@ -1118,16 +1118,16 @@ int getLocalTransformOrientation_ex(const bContext *C, float normal[3], float pl } else { /* we need the one selected object, if its not active */ - View3D *v3d = CTX_wm_view3d(C); - ob = OBACT; - if (ob && (ob->flag & SELECT)) { + base = BASACT_NEW; + ob = OBACT_NEW; + if (base && ((base->flag & BASE_SELECTED) != 0)) { /* pass */ } else { /* first selected */ ob = NULL; - for (base = scene->base.first; base; base = base->next) { - if (TESTBASELIB(v3d, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (TESTBASELIB_NEW(base)) { ob = base->object; break; } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index f8bb124e943..bd640463da2 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -49,7 +49,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" @@ -163,36 +163,42 @@ void drawSnapping(const struct bContext *C, TransInfo *t) size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); invert_m4_m4(imat, rv3d->viewmat); - + + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + for (p = t->tsnap.points.first; p; p = p->next) { if (p == t->tsnap.selectedPoint) { - glColor4ubv(selectedCol); + immUniformColor4ubv(selectedCol); } else { - glColor4ubv(col); + immUniformColor4ubv(col); } - drawcircball(GL_LINE_LOOP, p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat); + imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos); } if (t->tsnap.status & POINT_INIT) { - glColor4ubv(activeCol); + immUniformColor4ubv(activeCol); - drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat); + imm_drawcircball(t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos); } /* draw normal if needed */ if (usingSnappingNormal(t) && validSnappingNormal(t)) { - glColor4ubv(activeCol); + immUniformColor4ubv(activeCol); - glBegin(GL_LINES); - glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); - glVertex3f(t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0], - t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1], - t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]); - glEnd(); + immBegin(GL_LINES, 2); + immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); + immVertex3f(pos, t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0], + t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1], + t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]); + immEnd(); } - + + immUnbindProgram(); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -241,23 +247,29 @@ void drawSnapping(const struct bContext *C, TransInfo *t) glEnable(GL_BLEND); + unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + for (p = t->tsnap.points.first; p; p = p->next) { if (p == t->tsnap.selectedPoint) { - glColor4ubv(selectedCol); + immUniformColor4ubv(selectedCol); } else { - glColor4ubv(col); + immUniformColor4ubv(col); } - ED_node_draw_snap(&ar->v2d, p->co, size, 0); + ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos); } if (t->tsnap.status & POINT_INIT) { - glColor4ubv(activeCol); + immUniformColor4ubv(activeCol); - ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder); + ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos); } - + + immUnbindProgram(); + glDisable(GL_BLEND); } } @@ -520,7 +532,7 @@ static void initSnappingMode(TransInfo *t) ToolSettings *ts = t->settings; Object *obedit = t->obedit; Scene *scene = t->scene; - Base *base_act = scene->basact; + BaseLegacy *base_act = scene->basact; if (t->spacetype == SPACE_NODE) { /* force project off when not supported */ @@ -569,7 +581,9 @@ static void initSnappingMode(TransInfo *t) else if (t->tsnap.applySnap != NULL && // A snapping function actually exist (obedit == NULL) ) // Object Mode { - t->tsnap.modeSelect = SNAP_NOT_SELECTED; + /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632) + * TODO: perform self snap in gpencil_strokes */ + t->tsnap.modeSelect = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_ALL : SNAP_NOT_SELECTED; } else { /* Grid if snap is not possible */ @@ -599,7 +613,7 @@ static void initSnappingMode(TransInfo *t) if (t->spacetype == SPACE_VIEW3D) { if (t->tsnap.object_context == NULL) { t->tsnap.object_context = ED_transform_snap_object_context_create_view3d( - G.main, t->scene, SNAP_OBJECT_USE_CACHE, + G.main, t->scene, 0, t->ar, t->view); ED_transform_snap_object_context_set_editmesh_callbacks( @@ -1214,7 +1228,7 @@ bool snapObjectsTransform( t->tsnap.object_context, t->scene->toolsettings->snap_mode, &(const struct SnapObjectParams){ - .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect, + .snap_select = t->tsnap.modeSelect, .use_object_edit_cage = (t->flag & T_EDIT) != 0, }, mval, dist_px, NULL, @@ -1304,7 +1318,7 @@ bool peelObjectsTransform( t->tsnap.object_context, mval, &(const struct SnapObjectParams){ - .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect, + .snap_select = t->tsnap.modeSelect, .use_object_edit_cage = (t->flag & T_EDIT) != 0, }, use_peel_object, diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 02900d7022c..2e95b67d508 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -59,6 +59,24 @@ #include "transform.h" +enum eViewProj { + VIEW_PROJ_NONE = -1, + VIEW_PROJ_ORTHO = 0, + VIEW_PROJ_PERSP = -1, +}; + +typedef struct SnapData { + short snap_to; + float mval[2]; + float ray_origin[3]; + float ray_start[3]; + float ray_dir[3]; + float pmat[4][4]; /* perspective matrix */ + float win_half[2];/* win x and y */ + enum eViewProj view_proj; + float depth_range[2]; +} SnapData; + typedef struct SnapObjectData { enum { SNAP_MESH = 1, @@ -110,12 +128,6 @@ struct SnapObjectContext { }; -enum eViewProj { - VIEW_PROJ_NONE = -1, - VIEW_PROJ_ORTHO = 0, - VIEW_PROJ_PERSP = -1, -}; - static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt); @@ -223,200 +235,87 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH /** \Common utilities * \{ */ - -/** - * Struct that kepts basic information about a BVHTree build from a editmesh. - */ -typedef struct BVHTreeFromMeshType { - void *userdata; - char type; -} BVHTreeFromMeshType; - -typedef struct PreDefProject { - float pmat[4][4]; /* perspective matrix multiplied by object matrix */ - float win_half[2]; - float dist_px_sq; -} PreDefProject; - -static void precalc_project( - PreDefProject *projectdefs, const ARegion *ar, - const float dist_px, float obmat[4][4]) -{ - float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat; - if (obmat) { - mul_m4_m4m4(projectdefs->pmat, pmat, obmat); - } - else { - copy_m4_m4(projectdefs->pmat, pmat); - } - projectdefs->win_half[0] = ar->winx / 2; - projectdefs->win_half[1] = ar->winy / 2; - projectdefs->dist_px_sq = SQUARE(dist_px); -} - /** - * From a threshold (maximum distance to snap in pixels) returns: + * Generates a struct with the immutable parameters that will be used on all objects. * - * - The *real* distance (3D) if you are in orthographic-view. - * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view. + * \param snap_to: Element to snap, Vertice, Edge or Face. + * \param view_proj: ORTHO or PERSP. + * Currently only works one at a time, but can eventually operate as flag. + * + * \param mval: Mouse coords. + * (When NULL, ray-casting is handled without any projection matrix correction.) + * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. + * \param ray_start: ray_origin moved for the start clipping plane (clip_min). + * \param ray_direction: Unit length direction of the ray. + * \param depth_range: distances of clipe plane min and clip plane max; */ -static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px) +static void snap_data_set( + SnapData *snapdata, + const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj, + const float mval[2], const float ray_origin[3], const float ray_start[3], + const float ray_direction[3], const float depth_range[2]) { - const RegionView3D *rv3d = ar->regiondata; - if (ar->winx >= ar->winy) - return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0]; - else - return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1]; + if (ar) { + copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat); + snapdata->win_half[0] = ar->winx / 2; + snapdata->win_half[1] = ar->winy / 2; + } + if (mval) { + copy_v2_v2(snapdata->mval, mval); + } + snapdata->snap_to = snap_to; + copy_v3_v3(snapdata->ray_origin, ray_origin); + copy_v3_v3(snapdata->ray_start, ray_start); + copy_v3_v3(snapdata->ray_dir, ray_direction); + snapdata->view_proj = view_proj; + copy_v2_v2(snapdata->depth_range, depth_range); } -static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index) +MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) { - switch (meshdata->type) { - case SNAP_MESH: - { - BVHTreeFromMesh *data = meshdata->userdata; - const MVert *vert = data->vert; - return vert[index].co; - } - case SNAP_EDIT_MESH: - { - BVHTreeFromEditMesh *data = meshdata->userdata; - BMVert *eve = BM_vert_at_index(data->em->bm, index); - return eve->co; - } - } - return NULL; + float dvec[3]; + sub_v3_v3v3(dvec, co, ray_start); + return dot_v3v3(dvec, ray_dir); } -static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3]) +static void copy_dm_vert_no(const int index, float r_no[3], const BVHTreeFromMesh *data) { - switch (meshdata->type) { - case SNAP_MESH: - { - BVHTreeFromMesh *data = meshdata->userdata; - const MVert *vert = data->vert + index; - normal_short_to_float_v3(r_no, vert->no); - break; - } - case SNAP_EDIT_MESH: - { - BVHTreeFromEditMesh *data = meshdata->userdata; - BMVert *eve = BM_vert_at_index(data->em->bm, index); - copy_v3_v3(r_no, eve->no); - break; - } - } + const MVert *vert = data->vert + index; + + normal_short_to_float_v3(r_no, vert->no); } -static void get_edge_verts( - const BVHTreeFromMeshType *meshdata, const int index, - const float *v_pair[2]) +static void copy_bvert_no(const int index, float r_no[3], const BVHTreeFromEditMesh *data) { - switch (meshdata->type) { - case SNAP_MESH: - { - BVHTreeFromMesh *data = meshdata->userdata; - - const MVert *vert = data->vert; - const MEdge *edge = data->edge + index; + BMVert *eve = BM_vert_at_index(data->em->bm, index); - v_pair[0] = vert[edge->v1].co; - v_pair[1] = vert[edge->v2].co; - break; - } - case SNAP_EDIT_MESH: - { - BVHTreeFromEditMesh *data = meshdata->userdata; - BMEdge *eed = BM_edge_at_index(data->em->bm, index); - - v_pair[0] = eed->v1->co; - v_pair[1] = eed->v2->co; - break; - } - } + copy_v3_v3(r_no, eve->no); } -#define V3_MUL_ELEM(a, b) \ - (a)[0] * (b)[0], \ - (a)[1] * (b)[1], \ - (a)[2] * (b)[2] - -static bool test_vert_dist( - const float vco[3], const float ray_co[3], const float ray_dir[3], - const float ray_depth_range[2], const float scale[3], - /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, - /* return args */ - float r_co[3]) +static void get_dm_edge_verts(const int index, const float *v_pair[2], const BVHTreeFromMesh *data) { - const float vco_sc[3] = {V3_MUL_ELEM(vco, scale)}; - const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; - const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)}; - - float depth, dist_sq; - dist_sq = dist_squared_to_ray_v3(origin_sc, dir_sc, vco_sc, &depth); - - if (depth < ray_depth_range[0]) { - return false; - } - - if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) { - *dist_to_ray_sq = dist_sq; - - copy_v3_v3(r_co, vco); + const MVert *vert = data->vert; + const MEdge *edge = data->edge + index; - *ray_depth = depth; - return true; - } - return false; + v_pair[0] = vert[edge->v1].co; + v_pair[1] = vert[edge->v2].co; } -static bool test_edge_dist( - const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3], - const float ray_depth_range[2], const float scale[3], - /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, - /* return args */ - float r_co[3]) +static void get_bedge_verts(const int index, const float *v_pair[2], const BVHTreeFromEditMesh *data) { - const float v1_sc[3] = {V3_MUL_ELEM(v1, scale)}; - const float v2_sc[3] = {V3_MUL_ELEM(v2, scale)}; - const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; - const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)}; - - float tmp_co[3], depth, dist_sq; - dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth); + BMEdge *eed = BM_edge_at_index(data->em->bm, index); - if (depth < ray_depth_range[0]) { - return false; - } - - if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) { - *dist_to_ray_sq = dist_sq; - - tmp_co[0] /= scale[0]; - tmp_co[1] /= scale[1]; - tmp_co[2] /= scale[2]; - - copy_v3_v3(r_co, tmp_co); - - *ray_depth = depth; - return true; - } - return false; + v_pair[0] = eed->v1->co; + v_pair[1] = eed->v2->co; } -#undef V3_MUL_ELEM - static bool test_projected_vert_dist( - PreDefProject *projectdefs, - const float co[3], const enum eViewProj view_proj, - const float mval[2], const float depth_range[2], - float r_co[3]) + const float depth_range[2], const float mval[2], const float co[3], + float pmat[4][4], const float win_half[2], const bool is_persp, + float *dist_px_sq, float r_co[3]) { float depth; - float(*pmat)[4] = projectdefs->pmat; - if (view_proj == VIEW_PROJ_PERSP) { + if (is_persp) { depth = mul_project_m4_v3_zfac(pmat, co); if (depth < depth_range[0] || depth > depth_range[1]) { return false; @@ -428,109 +327,106 @@ static bool test_projected_vert_dist( (dot_m4_v3_row_y(pmat, co) + pmat[3][1]), }; - if (view_proj == VIEW_PROJ_PERSP) { + if (is_persp) { mul_v2_fl(co2d, 1 / depth); } co2d[0] += 1.0f; co2d[1] += 1.0f; - co2d[0] *= projectdefs->win_half[0]; - co2d[1] *= projectdefs->win_half[1]; + co2d[0] *= win_half[0]; + co2d[1] *= win_half[1]; const float dist_sq = len_squared_v2v2(mval, co2d); - if (dist_sq < projectdefs->dist_px_sq) { + if (dist_sq < *dist_px_sq) { copy_v3_v3(r_co, co); - projectdefs->dist_px_sq = dist_sq; + *dist_px_sq = dist_sq; return true; } return false; } static bool test_projected_edge_dist( - PreDefProject *projectdefs, - const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3], - const enum eViewProj view_proj, const float mval[2], const float depth_range[2], - float r_co[3]) + const float depth_range[2], const float mval[2], + float pmat[4][4], const float win_half[2], const bool is_persp, + const float ray_start[3], const float ray_dir[3], + const float va[3], const float vb[3], + float *dist_px_sq, float r_co[3]) { float tmp_co[3], depth; - dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth); - return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co); + dist_squared_ray_to_seg_v3(ray_start, ray_dir, va, vb, tmp_co, &depth); + return test_projected_vert_dist(depth_range, mval, tmp_co, pmat, win_half, is_persp, dist_px_sq, r_co); } - -/** \} */ - - -/* -------------------------------------------------------------------- */ - -/** \Walk DFS - * \{ */ -typedef struct Object_Nearest2dPrecalc { +typedef struct Nearest2dPrecalc { float ray_origin_local[3]; float ray_direction_local[3]; float ray_inv_dir[3]; - PreDefProject projectdefs; + float ray_min_dist; + float pmat[4][4]; /* perspective matrix multiplied by object matrix */ + bool is_persp; + float win_half[2]; + float mval[2]; bool sign[3]; - bool r_axis_closest[3]; - float depth_range[2]; - - void *userdata; - int index; - float co[3]; - float no[3]; -} Object_Nearest2dPrecalc; +} Nearest2dPrecalc; - -static void nearest2d_precalc( - Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar, - const float dist_px, float obmat[4][4], - const float ray_origin_local[3], const float ray_direction_local[3], - const float mval[2], const float depth_range[2]) +/** + * \param lpmat: Perspective matrix multiplied by object matrix + */ +static void dist_squared_to_projected_aabb_precalc( + struct Nearest2dPrecalc *neasrest_precalc, + float lpmat[4][4], bool is_persp, const float win_half[2], + const float ray_min_dist, const float mval[2], + const float ray_origin_local[3], const float ray_direction_local[3]) { - precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat); + copy_m4_m4(neasrest_precalc->pmat, lpmat); + neasrest_precalc->is_persp = is_persp; + copy_v2_v2(neasrest_precalc->win_half, win_half); + neasrest_precalc->ray_min_dist = ray_min_dist; + copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local); copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local); copy_v2_v2(neasrest_precalc->mval, mval); - copy_v2_v2(neasrest_precalc->depth_range, depth_range); for (int i = 0; i < 3; i++) { - neasrest_precalc->ray_inv_dir[i] = + neasrest_precalc->ray_inv_dir[i] = (neasrest_precalc->ray_direction_local[i] != 0.0f) ? (1.0f / neasrest_precalc->ray_direction_local[i]) : FLT_MAX; neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f); - neasrest_precalc->r_axis_closest[i] = true; } } -static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data) +/* Returns the distance from a 2d coordinate to a BoundBox (Projected) */ +static float dist_squared_to_projected_aabb( + struct Nearest2dPrecalc *data, + const float bbmin[3], const float bbmax[3], + bool r_axis_closest[3]) { - Object_Nearest2dPrecalc *data = user_data; float local_bvmin[3], local_bvmax[3]; if (data->sign[0]) { - local_bvmin[0] = bounds[0].max; - local_bvmax[0] = bounds[0].min; + local_bvmin[0] = bbmax[0]; + local_bvmax[0] = bbmin[0]; } else { - local_bvmin[0] = bounds[0].min; - local_bvmax[0] = bounds[0].max; + local_bvmin[0] = bbmin[0]; + local_bvmax[0] = bbmax[0]; } if (data->sign[1]) { - local_bvmin[1] = bounds[1].max; - local_bvmax[1] = bounds[1].min; + local_bvmin[1] = bbmax[1]; + local_bvmax[1] = bbmin[1]; } else { - local_bvmin[1] = bounds[1].min; - local_bvmax[1] = bounds[1].max; + local_bvmin[1] = bbmin[1]; + local_bvmax[1] = bbmax[1]; } if (data->sign[2]) { - local_bvmin[2] = bounds[2].max; - local_bvmax[2] = bounds[2].min; + local_bvmin[2] = bbmax[2]; + local_bvmax[2] = bbmin[2]; } else { - local_bvmin[2] = bounds[2].min; - local_bvmax[2] = bounds[2].max; + local_bvmin[2] = bbmin[2]; + local_bvmax[2] = bbmax[2]; } const float tmin[3] = { @@ -543,7 +439,9 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us (local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1], (local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2], }; + /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */ float va[3], vb[3]; + /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */ float rtmin, rtmax; int main_axis; @@ -551,38 +449,38 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us rtmax = tmax[0]; va[0] = vb[0] = local_bvmax[0]; main_axis = 3; - data->r_axis_closest[0] = data->sign[0]; + r_axis_closest[0] = data->sign[0]; } else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { rtmax = tmax[1]; va[1] = vb[1] = local_bvmax[1]; main_axis = 2; - data->r_axis_closest[1] = data->sign[1]; + r_axis_closest[1] = data->sign[1]; } else { rtmax = tmax[2]; va[2] = vb[2] = local_bvmax[2]; main_axis = 1; - data->r_axis_closest[2] = data->sign[2]; + r_axis_closest[2] = data->sign[2]; } if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { rtmin = tmin[0]; va[0] = vb[0] = local_bvmin[0]; main_axis -= 3; - data->r_axis_closest[0] = !data->sign[0]; + r_axis_closest[0] = !data->sign[0]; } else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { rtmin = tmin[1]; va[1] = vb[1] = local_bvmin[1]; main_axis -= 1; - data->r_axis_closest[1] = !data->sign[1]; + r_axis_closest[1] = !data->sign[1]; } else { rtmin = tmin[2]; va[2] = vb[2] = local_bvmin[2]; main_axis -= 2; - data->r_axis_closest[2] = !data->sign[2]; + r_axis_closest[2] = !data->sign[2]; } if (main_axis < 0) { main_axis += 3; @@ -590,22 +488,34 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us /* if rtmin < rtmax, ray intersect `AABB` */ if (rtmin <= rtmax) { +#define IGNORE_BEHIND_RAY #ifdef IGNORE_BEHIND_RAY - /* `if rtmax < depth_min`, the whole `AABB` is behind us */ - if (rtmax < min_depth) { - return fallback; + /* `if rtmax < depth_min`, the hit is behind us */ + if (rtmax < data->ray_min_dist) { + /* Test if the entire AABB is behind us */ + float depth = depth_get( + local_bvmax, data->ray_origin_local, data->ray_direction_local); + if (depth < (data->ray_min_dist)) { + return FLT_MAX; + } } #endif const float proj = rtmin * data->ray_direction_local[main_axis]; - data->r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj); - return true; + r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj); + return 0.0f; } #ifdef IGNORE_BEHIND_RAY - /* `if rtmin < depth_min`, the whole `AABB` is behing us */ - else if (rtmin < min_depth) { - return fallback; + /* `if rtmin < depth_min`, the hit is behing us */ + else if (rtmin < data->ray_min_dist) { + /* Test if the entire AABB is behind us */ + float depth = depth_get( + local_bvmax, data->ray_origin_local, data->ray_direction_local); + if (depth < (data->ray_min_dist)) { + return FLT_MAX; + } } #endif +#undef IGNORE_BEHIND_RAY if (data->sign[main_axis]) { va[main_axis] = local_bvmax[main_axis]; vb[main_axis] = local_bvmin[main_axis]; @@ -616,31 +526,35 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us } float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]); - float (*pmat)[4] = data->projectdefs.pmat; - float depth_a = mul_project_m4_v3_zfac(pmat, va); - float depth_b = depth_a + pmat[main_axis][3] * scale; + float (*pmat)[4] = data->pmat; float va2d[2] = { (dot_m4_v3_row_x(pmat, va) + pmat[3][0]), (dot_m4_v3_row_y(pmat, va) + pmat[3][1]), }; float vb2d[2] = { - (va2d[0] + pmat[main_axis][0] * scale) / depth_b, - (va2d[1] + pmat[main_axis][1] * scale) / depth_b, + (va2d[0] + pmat[main_axis][0] * scale), + (va2d[1] + pmat[main_axis][1] * scale), }; - va2d[0] /= depth_a; - va2d[1] /= depth_a; + if (data->is_persp) { + float depth_a = mul_project_m4_v3_zfac(pmat, va); + float depth_b = depth_a + pmat[main_axis][3] * scale; + va2d[0] /= depth_a; + va2d[1] /= depth_a; + vb2d[0] /= depth_b; + vb2d[1] /= depth_b; + } va2d[0] += 1.0f; va2d[1] += 1.0f; vb2d[0] += 1.0f; vb2d[1] += 1.0f; - va2d[0] *= data->projectdefs.win_half[0]; - va2d[1] *= data->projectdefs.win_half[1]; - vb2d[0] *= data->projectdefs.win_half[0]; - vb2d[1] *= data->projectdefs.win_half[1]; + va2d[0] *= data->win_half[0]; + va2d[1] *= data->win_half[1]; + vb2d[0] *= data->win_half[0]; + vb2d[1] *= data->win_half[1]; //float dvec[2], edge[2], rdist; //sub_v2_v2v2(dvec, data->mval, va2d); @@ -653,73 +567,146 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us lambda /= edge[0] * edge[0] + edge[1] * edge[1]; if (lambda <= 0.0f) { rdist = len_squared_v2v2(data->mval, va2d); - data->r_axis_closest[main_axis] = true; + r_axis_closest[main_axis] = true; } else if (lambda >= 1.0f) { rdist = len_squared_v2v2(data->mval, vb2d); - data->r_axis_closest[main_axis] = false; + r_axis_closest[main_axis] = false; } else { va2d[0] += edge[0] * lambda; va2d[1] += edge[1] * lambda; rdist = len_squared_v2v2(data->mval, va2d); - data->r_axis_closest[main_axis] = lambda < 0.5f; + r_axis_closest[main_axis] = lambda < 0.5f; } } else { rdist = len_squared_v2v2(data->mval, va2d); } - return rdist < data->projectdefs.dist_px_sq; + return rdist; +} + +static float dist_squared_to_projected_aabb_simple( + float lpmat[4][4], const float win_half[2], + const float ray_min_dist, const float mval[2], + const float ray_origin_local[3], const float ray_direction_local[3], + const float bbmin[3], const float bbmax[3]) +{ + struct Nearest2dPrecalc data; + dist_squared_to_projected_aabb_precalc( + &data, lpmat, true, win_half, ray_min_dist, + mval, ray_origin_local, ray_direction_local); + + bool dummy[3] = {true, true, true}; + return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy); +} + +static float dist_aabb_to_plane( + const float bbmin[3], const float bbmax[3], + const float plane_co[3], const float plane_no[3]) +{ + const float local_bvmin[3] = { + (plane_no[0] < 0) ? bbmax[0] : bbmin[0], + (plane_no[1] < 0) ? bbmax[1] : bbmin[1], + (plane_no[2] < 0) ? bbmax[2] : bbmin[2], + }; + return depth_get(local_bvmin, plane_co, plane_no); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \Walk DFS + * \{ */ + +typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data); +typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data); + +typedef struct Nearest2dUserData { + struct Nearest2dPrecalc data_precalc; + + float dist_px_sq; + + bool r_axis_closest[3]; + + float depth_range[2]; + + void *userdata; + Nearest2DGetEdgeVertsCallback get_edge_verts; + Nearest2DCopyVertNoCallback copy_vert_no; + + int index; + float co[3]; + float no[3]; +} Nearest2dUserData; + + +static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data) +{ + Nearest2dUserData *data = user_data; + const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min}; + const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max}; + const float rdist = dist_squared_to_projected_aabb( + &data->data_precalc, bbmin, bbmax, data->r_axis_closest); + return rdist < data->dist_px_sq; } static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata) { - struct Object_Nearest2dPrecalc *neasrest_precalc = userdata; + struct Nearest2dUserData *data = userdata; + struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc; const float co[3] = { (bounds[0].min + bounds[0].max) / 2, (bounds[1].min + bounds[1].max) / 2, (bounds[2].min + bounds[2].max) / 2, }; - /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP) - * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO), - * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/ if (test_projected_vert_dist( - &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP, - neasrest_precalc->mval, neasrest_precalc->depth_range, - neasrest_precalc->co)) + data->depth_range, + neasrest_precalc->mval, co, + neasrest_precalc->pmat, + neasrest_precalc->win_half, + neasrest_precalc->is_persp, + &data->dist_px_sq, + data->co)) { - copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no); - neasrest_precalc->index = index; + data->copy_vert_no(index, data->no, data->userdata); + data->index = index; } return true; } static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata) { - struct Object_Nearest2dPrecalc *neasrest_precalc = userdata; + struct Nearest2dUserData *data = userdata; + struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc; const float *v_pair[2]; - get_edge_verts(neasrest_precalc->userdata, index, v_pair); + data->get_edge_verts(index, v_pair, data->userdata); - /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP) - * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO), - * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/ if (test_projected_edge_dist( - &neasrest_precalc->projectdefs, v_pair[0], v_pair[1], - neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local, - VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range, - neasrest_precalc->co)) + data->depth_range, + neasrest_precalc->mval, + neasrest_precalc->pmat, + neasrest_precalc->win_half, + neasrest_precalc->is_persp, + neasrest_precalc->ray_origin_local, + neasrest_precalc->ray_direction_local, + v_pair[0], v_pair[1], + &data->dist_px_sq, + data->co)) { - sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]); - neasrest_precalc->index = index; + sub_v3_v3v3(data->no, v_pair[0], v_pair[1]); + data->index = index; } return true; } static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata) { - const bool *r_axis_closest = ((struct Object_Nearest2dPrecalc *)userdata)->r_axis_closest; + const bool *r_axis_closest = ((struct Nearest2dUserData *)userdata)->r_axis_closest; return r_axis_closest[axis]; } @@ -731,46 +718,56 @@ static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char a * \{ */ static bool snapArmature( - const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], - const short snap_to, const float origin[3], const float dir[3], - const float mval[2], const enum eViewProj view_proj, const float depth_range[2], + SnapData *snapdata, + Object *ob, bArmature *arm, float obmat[4][4], /* read/write args */ - float *dist_px, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { bool retval = false; - float ray_start_local[3], ray_normal_local[3]; - if (snap_to != SCE_SNAP_MODE_VERTEX) { + float ray_start_local[3], ray_normal_local[3]; /* Used only in the snap to edges */ + if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { float imat[4][4]; invert_m4_m4(imat, obmat); - copy_v3_v3(ray_start_local, origin); - copy_v3_v3(ray_normal_local, dir); + copy_v3_v3(ray_start_local, snapdata->ray_origin); + copy_v3_v3(ray_normal_local, snapdata->ray_dir); mul_m4_v3(imat, ray_start_local); mul_mat3_m4_v3(imat, ray_normal_local); } + else if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { /* Currently only edge and vert */ + return retval; + } - PreDefProject projectdefs; - precalc_project(&projectdefs, ar, *dist_px, obmat); + bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + float lpmat[4][4], dist_px_sq; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_px_sq = SQUARE(*dist_px); if (arm->edbo) { for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) { if (eBone->layer & arm->layer) { /* skip hidden or moving (selected) bones */ if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) { - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: retval |= test_projected_vert_dist( - &projectdefs, eBone->head, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, eBone->head, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); retval |= test_projected_vert_dist( - &projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, eBone->tail, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); break; case SCE_SNAP_MODE_EDGE: retval |= test_projected_edge_dist( - &projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local, - view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, lpmat, + snapdata->win_half, is_persp, ray_start_local, ray_normal_local, + eBone->head, eBone->tail, + &dist_px_sq, r_loc); break; } } @@ -785,52 +782,60 @@ static bool snapArmature( const float *head_vec = pchan->pose_head; const float *tail_vec = pchan->pose_tail; - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: retval |= test_projected_vert_dist( - &projectdefs, head_vec, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, head_vec, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); retval |= test_projected_vert_dist( - &projectdefs, tail_vec, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, tail_vec, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); break; case SCE_SNAP_MODE_EDGE: retval |= test_projected_edge_dist( - &projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local, - view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, lpmat, + snapdata->win_half, is_persp, ray_start_local, ray_normal_local, + head_vec, tail_vec, + &dist_px_sq, r_loc); break; } } } } if (retval) { - *dist_px = sqrtf(projectdefs.dist_px_sq); + *dist_px = sqrtf(dist_px_sq); mul_m4_v3(obmat, r_loc); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); return true; } return false; } static bool snapCurve( - const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4], - const short snap_to, const float mval[2], const enum eViewProj view_proj, - const float depth_range[2], + SnapData *snapdata, + Object *ob, Curve *cu, float obmat[4][4], /* read/write args */ - float *dist_px, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { bool retval = false; /* only vertex snapping mode (eg control points and handles) supported for now) */ - if (snap_to != SCE_SNAP_MODE_VERTEX) { + if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { return retval; } - PreDefProject projectdefs; - precalc_project(&projectdefs, ar, *dist_px, obmat); + bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + float lpmat[4][4], dist_px_sq; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_px_sq = SQUARE(*dist_px); for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { for (int u = 0; u < nu->pntsu; u++) { - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: { if (ob->mode == OB_MODE_EDIT) { @@ -840,19 +845,25 @@ static bool snapCurve( break; } retval |= test_projected_vert_dist( - &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1], + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */ if (!(nu->bezt[u].f1 & SELECT) && !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) { retval |= test_projected_vert_dist( - &projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[0], + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } if (!(nu->bezt[u].f3 & SELECT) && !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) { retval |= test_projected_vert_dist( - &projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[2], + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } } else { @@ -861,7 +872,9 @@ static bool snapCurve( break; } retval |= test_projected_vert_dist( - &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bp[u].vec, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } } else { @@ -869,11 +882,15 @@ static bool snapCurve( if (nu->pntsu > 1) { if (nu->bezt) { retval |= test_projected_vert_dist( - &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1], + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } else { retval |= test_projected_vert_dist( - &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bp[u].vec, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } } } @@ -885,8 +902,9 @@ static bool snapCurve( } } if (retval) { - *dist_px = sqrtf(projectdefs.dist_px_sq); + *dist_px = sqrtf(dist_px_sq); mul_m4_v3(obmat, r_loc); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); return true; } return false; @@ -894,11 +912,10 @@ static bool snapCurve( /* may extend later (for now just snaps to empty center) */ static bool snapEmpty( - const ARegion *ar, Object *ob, float obmat[4][4], - const short snap_to, const float mval[2], const enum eViewProj view_proj, - const float depth_range[2], + SnapData *snapdata, + Object *ob, float obmat[4][4], /* read/write args */ - float *dist_px, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { @@ -909,15 +926,19 @@ static bool snapEmpty( } /* for now only vertex supported */ - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: { - PreDefProject projectdefs; - precalc_project(&projectdefs, ar, *dist_px, NULL); + bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + float dist_px_sq = SQUARE(*dist_px); float tmp_co[3]; copy_v3_v3(tmp_co, obmat[3]); - if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) { - *dist_px = sqrtf(projectdefs.dist_px_sq); + if (test_projected_vert_dist( + snapdata->depth_range, snapdata->mval, tmp_co, + snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc)) { + *dist_px = sqrtf(dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); retval = true; } break; @@ -930,18 +951,17 @@ static bool snapEmpty( } static bool snapCamera( - const SnapObjectContext *sctx, Object *object, float obmat[4][4], - const short snap_to, const float mval[2], const enum eViewProj view_proj, - const float depth_range[2], + const SnapObjectContext *sctx, SnapData *snapdata, + Object *object, float obmat[4][4], /* read/write args */ - float *dist_px, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { Scene *scene = sctx->scene; - PreDefProject projectdefs; - precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL); + bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + float dist_px_sq = SQUARE(*dist_px); float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4]; bool retval = false; @@ -962,7 +982,7 @@ static bool snapCamera( invert_m4_m4(orig_camera_imat, orig_camera_mat); invert_m4_m4(imat, obmat); - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: { MovieTrackingObject *tracking_object; @@ -1002,7 +1022,9 @@ static bool snapCamera( mul_m4_v3(vertex_obmat, bundle_pos); retval |= test_projected_vert_dist( - &projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, bundle_pos, + snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } } @@ -1013,7 +1035,8 @@ static bool snapCamera( } if (retval) { - *dist_px = sqrtf(projectdefs.dist_px_sq); + *dist_px = sqrtf(dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); return true; } return false; @@ -1025,57 +1048,10 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly; } -struct NearestDM_Data { - void *bvhdata; - const float *depth_range; - float *ray_depth; -}; - -static void test_vert_ray_dist_cb( - void *userdata, const float origin[3], const float dir[3], - const float scale[3], int index, BVHTreeNearest *nearest) -{ - struct NearestDM_Data *ndata = userdata; - const struct BVHTreeFromMeshType *data = ndata->bvhdata; - - const float *co = get_vert_co(data, index); - - if (test_vert_dist( - co, origin, dir, ndata->depth_range, - scale, ndata->ray_depth, &nearest->dist_sq, - nearest->co)) - { - copy_vert_no(data, index, nearest->no); - nearest->index = index; - } -} - -static void test_edge_ray_dist_cb( - void *userdata, const float origin[3], const float dir[3], - const float scale[3], int index, BVHTreeNearest *nearest) -{ - struct NearestDM_Data *ndata = userdata; - BVHTreeFromMeshType *data = ndata->bvhdata; - - const float *v_pair[2]; - get_edge_verts(data, index, v_pair); - - if (test_edge_dist( - v_pair[0], v_pair[1], origin, dir, ndata->depth_range, - scale, ndata->ray_depth, &nearest->dist_sq, - nearest->co)) - { - sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]); - nearest->index = index; - } -} - static bool snapDerivedMesh( - SnapObjectContext *sctx, + SnapObjectContext *sctx, SnapData *snapdata, Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index, - const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], - const float depth_range[2], + bool do_bb, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1084,12 +1060,12 @@ static bool snapDerivedMesh( { bool retval = false; - if (snap_to == SCE_SNAP_MODE_FACE) { + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { if (dm->getNumPolys(dm) == 0) { return retval; } } - else if (snap_to == SCE_SNAP_MODE_EDGE) { + else if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { if (dm->getNumEdges(dm) == 0) { return retval; } @@ -1100,289 +1076,259 @@ static bool snapDerivedMesh( } } - { - bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO); + bool need_ray_start_correction_init = + (snapdata->snap_to == SCE_SNAP_MODE_FACE) && + (snapdata->view_proj == VIEW_PROJ_ORTHO); - float imat[4][4]; - float timat[3][3]; /* transpose inverse matrix for normals */ - float ray_start_local[3], ray_normal_local[3]; - float local_scale, local_depth, len_diff; + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_start_local[3], ray_normal_local[3]; + float local_scale, local_depth, len_diff; - invert_m4_m4(imat, obmat); - transpose_m3_m4(timat, imat); + invert_m4_m4(imat, obmat); + transpose_m3_m4(timat, imat); - copy_v3_v3(ray_start_local, ray_start); - copy_v3_v3(ray_normal_local, ray_normal); + copy_v3_v3(ray_start_local, snapdata->ray_start); + copy_v3_v3(ray_normal_local, snapdata->ray_dir); - mul_m4_v3(imat, ray_start_local); - mul_mat3_m4_v3(imat, ray_normal_local); + mul_m4_v3(imat, ray_start_local); + mul_mat3_m4_v3(imat, ray_normal_local); - /* local scale in normal direction */ - local_scale = normalize_v3(ray_normal_local); - local_depth = *ray_depth; - if (local_depth != BVH_RAYCAST_DIST_MAX) { - local_depth *= local_scale; - } + /* local scale in normal direction */ + local_scale = normalize_v3(ray_normal_local); + local_depth = *ray_depth; + if (local_depth != BVH_RAYCAST_DIST_MAX) { + local_depth *= local_scale; + } - if (do_bb) { - BoundBox *bb = BKE_object_boundbox_get(ob); + float lpmat[4][4]; + float ray_org_local[3]; + float ray_min_dist; + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + ray_min_dist = snapdata->depth_range[0] * local_scale; + } - if (bb) { - BoundBox bb_temp; + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); - /* We cannot afford a bounding box with some null dimension, which may happen in some cases... - * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ - bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); + if (do_bb) { + BoundBox *bb = BKE_object_boundbox_get(ob); - /* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'dist_px'), - * scale up so we can snap against verts & edges on the boundbox, see T46816. */ - if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { - BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f); - bb = &bb_temp; - } + if (bb) { + BoundBox bb_temp; - /* was local_depth, see: T47838 */ - len_diff = BVH_RAYCAST_DIST_MAX; + /* We cannot afford a bounding box with some null dimension, which may happen in some cases... + * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ + bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); - if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) { + /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */ + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + float dist_px_sq = dist_squared_to_projected_aabb_simple( + lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, + ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); + if (dist_px_sq > SQUARE(*dist_px)) + { return retval; } - need_ray_start_correction_init = false; - } - } - - SnapObjectData_Mesh *sod = NULL; - BVHTreeFromMesh *treedata = NULL, treedata_stack; - - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { - sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_MESH; - } - - int tree_index = -1; - switch (snap_to) { - case SCE_SNAP_MODE_FACE: - tree_index = 2; - break; - case SCE_SNAP_MODE_EDGE: - tree_index = 1; - break; - case SCE_SNAP_MODE_VERTEX: - tree_index = 0; - break; - } - if (tree_index != -1) { - if (sod->bvh_trees[tree_index] == NULL) { - sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); - } - treedata = sod->bvh_trees[tree_index]; - - /* the tree is owned by the DM and may have been freed since we last used! */ - if (treedata && treedata->tree) { - if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) { - free_bvhtree_from_mesh(treedata); - } + /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ + if (!isect_ray_aabb_v3_simple( + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) + { + return retval; } } + /* was local_depth, see: T47838 */ + len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); + if (len_diff < 0) len_diff = 0.0f; + need_ray_start_correction_init = false; } - else { - treedata = &treedata_stack; - memset(treedata, 0, sizeof(*treedata)); + } + + SnapObjectData_Mesh *sod = NULL; + BVHTreeFromMesh *treedata = NULL; + + void **sod_p; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + sod = *sod_p; + } + else { + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_MESH; + } + + int tree_index = -1; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + tree_index = 2; + break; + case SCE_SNAP_MODE_EDGE: + tree_index = 1; + break; + case SCE_SNAP_MODE_VERTEX: + tree_index = 0; + break; + } + if (tree_index != -1) { + if (sod->bvh_trees[tree_index] == NULL) { + sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); } + treedata = sod->bvh_trees[tree_index]; - if (treedata && treedata->tree == NULL) { - switch (snap_to) { - case SCE_SNAP_MODE_FACE: - bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); - break; - case SCE_SNAP_MODE_EDGE: - bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6); - break; - case SCE_SNAP_MODE_VERTEX: - bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6); - break; + /* the tree is owned by the DM and may have been freed since we last used! */ + if (treedata && treedata->tree) { + if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) { + free_bvhtree_from_mesh(treedata); } } + } - if (!treedata || !treedata->tree) { - return retval; + if (treedata && treedata->tree == NULL) { + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); + break; + case SCE_SNAP_MODE_EDGE: + bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6); + break; + case SCE_SNAP_MODE_VERTEX: + bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6); + break; } + } + if (!treedata || !treedata->tree) { + return retval; + } - if (snap_to == SCE_SNAP_MODE_FACE) { - /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already - * been *inside* boundbox, leading to snap failures (see T38409). - * Note also ar might be null (see T38435), in this case we assume ray_start is ok! - */ - if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ - if (need_ray_start_correction_init) { - /* We *need* a reasonably valid len_diff in this case. - * Use BHVTree to find the closest face from ray_start_local. - */ - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); - if (nearest.index != -1) { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - } + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { + /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already + * been *inside* boundbox, leading to snap failures (see T38409). + * Note also ar might be null (see T38435), in this case we assume ray_start is ok! + */ + if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ + if (need_ray_start_correction_init) { + /* We *need* a reasonably valid len_diff in this case. + * Use BHVTree to find the closest face from ray_start_local. + */ + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); + if (nearest.index != -1) { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); } - float ray_org_local[3]; - - copy_v3_v3(ray_org_local, ray_origin); - mul_m4_v3(imat, ray_org_local); - - /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far - * away ray_start values (as returned in case of ortho view3d), see T38358. + } + /* You need to make sure that ray_start is really far away, + * because even in the Orthografic view, in some cases, + * the ray can start inside the object (see T50486) */ + if (len_diff > 400.0f) { + /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with + * very far away ray_start values (as returned in case of ortho view3d), see T38358. */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale); + ray_start_local, ray_org_local, ray_normal_local, + len_diff + snapdata->depth_range[0] * local_scale); local_depth -= len_diff; } - else { - len_diff = 0.0f; - } - if (r_hit_list) { - struct RayCastAll_Data data; - - data.bvhdata = treedata; - data.raycast_callback = treedata->raycast_callback; - data.obmat = obmat; - data.timat = timat; - data.len_diff = len_diff; - data.local_scale = local_scale; - data.ob = ob; - data.ob_uuid = ob_index; - data.hit_list = r_hit_list; - data.retval = retval; - - BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); - - retval = data.retval; - } - else { - BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - - if (BLI_bvhtree_ray_cast( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - &hit, treedata->raycast_callback, treedata) != -1) - { - hit.dist += len_diff; - hit.dist /= local_scale; - if (hit.dist <= *ray_depth) { - *ray_depth = hit.dist; - copy_v3_v3(r_loc, hit.co); - - /* back to worldspace */ - mul_m4_v3(obmat, r_loc); - - if (r_no) { - copy_v3_v3(r_no, hit.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } - - retval = true; - - if (r_index) { - *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]); - } - } - } - } + else len_diff = 0.0f; } - /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ else { - const ARegion *ar = sctx->v3d_data.ar; - - float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); - mul_m4_v3(imat, ray_org_local); - - BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; - - if (view_proj == VIEW_PROJ_PERSP) { - Object_Nearest2dPrecalc neasrest_precalc; - neasrest_precalc.userdata = &treedata_type; - neasrest_precalc.index = -1; - - nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat, - ray_org_local, ray_normal_local, mval, depth_range); - - BVHTree_WalkLeafCallback cb_walk_leaf = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; + len_diff = 0.0f; + } + if (r_hit_list) { + struct RayCastAll_Data data; + + data.bvhdata = treedata; + data.raycast_callback = treedata->raycast_callback; + data.obmat = obmat; + data.timat = timat; + data.len_diff = len_diff; + data.local_scale = local_scale; + data.ob = ob; + data.ob_uuid = ob_index; + data.hit_list = r_hit_list; + data.retval = retval; + + BLI_bvhtree_ray_cast_all( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); + + retval = data.retval; + } + else { + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - BLI_bvhtree_walk_dfs( - treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); + if (BLI_bvhtree_ray_cast( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + &hit, treedata->raycast_callback, treedata) != -1) + { + hit.dist += len_diff; + hit.dist /= local_scale; + if (hit.dist <= *ray_depth) { + *ray_depth = hit.dist; + copy_v3_v3(r_loc, hit.co); - if (neasrest_precalc.index != -1) { - copy_v3_v3(r_loc, neasrest_precalc.co); + /* back to worldspace */ mul_m4_v3(obmat, r_loc); + if (r_no) { - copy_v3_v3(r_no, neasrest_precalc.no); + copy_v3_v3(r_no, hit.no); mul_m3_v3(timat, r_no); normalize_v3(r_no); } - *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); retval = true; - } - } - else { - BVHTreeNearest nearest; - - nearest.index = -1; - float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px); - nearest.dist_sq = SQUARE(dist_3d); - - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); - - struct NearestDM_Data userdata; - userdata.bvhdata = &treedata_type; - userdata.depth_range = depth_range; - userdata.ray_depth = ray_depth; - - BVHTree_NearestToRayCallback cb_test_ray_dist = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - test_vert_ray_dist_cb : test_edge_ray_dist_cb; - - if (BLI_bvhtree_find_nearest_to_ray( - treedata->tree, ray_org_local, ray_normal_local, - true, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1) - { - copy_v3_v3(r_loc, nearest.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, nearest.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + if (r_index) { + *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]); } - *dist_px *= sqrtf(nearest.dist_sq) / dist_3d; - - retval = true; } } } - - if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) { - if (treedata) { - free_bvhtree_from_mesh(treedata); + } + /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ + else { + Nearest2dUserData neasrest2d = { + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .userdata = treedata, + .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts, + .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no, + .index = -1}; + + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, + ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local); + + BVHTree_WalkLeafCallback cb_walk_leaf = + (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; + + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); + + if (neasrest2d.index != -1) { + copy_v3_v3(r_loc, neasrest2d.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest2d.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); } + *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + + retval = true; } } @@ -1390,11 +1336,8 @@ static bool snapDerivedMesh( } static bool snapEditMesh( - SnapObjectContext *sctx, + SnapObjectContext *sctx, SnapData *snapdata, Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index, - const short snap_to, const float mval[2], const enum eViewProj view_proj, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], - const float depth_range[2], /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1403,12 +1346,12 @@ static bool snapEditMesh( { bool retval = false; - if (snap_to == SCE_SNAP_MODE_FACE) { + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { if (em->bm->totface == 0) { return retval; } } - if (snap_to == SCE_SNAP_MODE_EDGE) { + if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { if (em->bm->totedge == 0) { return retval; } @@ -1419,292 +1362,246 @@ static bool snapEditMesh( } } - { - float imat[4][4]; - float timat[3][3]; /* transpose inverse matrix for normals */ - float ray_normal_local[3]; + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_normal_local[3]; - invert_m4_m4(imat, obmat); - transpose_m3_m4(timat, imat); + invert_m4_m4(imat, obmat); + transpose_m3_m4(timat, imat); - copy_v3_v3(ray_normal_local, ray_normal); + copy_v3_v3(ray_normal_local, snapdata->ray_dir); - mul_mat3_m4_v3(imat, ray_normal_local); + mul_mat3_m4_v3(imat, ray_normal_local); - SnapObjectData_EditMesh *sod = NULL; + /* local scale in normal direction */ + float local_scale = normalize_v3(ray_normal_local); + float local_depth = *ray_depth; + if (local_depth != BVH_RAYCAST_DIST_MAX) { + local_depth *= local_scale; + } - BVHTreeFromEditMesh *treedata = NULL, treedata_stack; + SnapObjectData_EditMesh *sod = NULL; - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { - sod = *sod_p; - } - else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_EDIT_MESH; - } + BVHTreeFromEditMesh *treedata = NULL; - int tree_index = -1; - switch (snap_to) { - case SCE_SNAP_MODE_FACE: - tree_index = 2; - break; - case SCE_SNAP_MODE_EDGE: - tree_index = 1; - break; - case SCE_SNAP_MODE_VERTEX: - tree_index = 0; - break; - } - if (tree_index != -1) { - if (sod->bvh_trees[tree_index] == NULL) { - sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); - } - treedata = sod->bvh_trees[tree_index]; - } - } - else { - treedata = &treedata_stack; - memset(treedata, 0, sizeof(*treedata)); + void **sod_p; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + sod = *sod_p; + } + else { + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_EDIT_MESH; + } + + int tree_index = -1; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + tree_index = 2; + break; + case SCE_SNAP_MODE_EDGE: + tree_index = 1; + break; + case SCE_SNAP_MODE_VERTEX: + tree_index = 0; + break; + } + if (tree_index != -1) { + if (sod->bvh_trees[tree_index] == NULL) { + sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); } + treedata = sod->bvh_trees[tree_index]; + } - if (treedata && treedata->tree == NULL) { - switch (snap_to) { - case SCE_SNAP_MODE_FACE: - { - BLI_bitmap *looptri_mask = NULL; - int looptri_num_active = -1; - if (sctx->callbacks.edit_mesh.test_face_fn) { - looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__); - looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( - em->bm, looptri_mask, - sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_looptri_ex(treedata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6, NULL); - if (looptri_mask) { - MEM_freeN(looptri_mask); - } - break; + if (treedata && treedata->tree == NULL) { + BLI_bitmap *elem_mask = NULL; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + { + int looptri_num_active = -1; + if (sctx->callbacks.edit_mesh.test_face_fn) { + elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); + looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( + em->bm, elem_mask, + sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); } - case SCE_SNAP_MODE_EDGE: - { - BLI_bitmap *edges_mask = NULL; - int edges_num_active = -1; - if (sctx->callbacks.edit_mesh.test_edge_fn) { - edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); - edges_num_active = BM_iter_mesh_bitmap_from_filter( - BM_EDGES_OF_MESH, em->bm, edges_mask, - (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, - sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_edges_ex(treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6); - if (edges_mask) { - MEM_freeN(edges_mask); - } - break; + bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL); + break; + } + case SCE_SNAP_MODE_EDGE: + { + int edges_num_active = -1; + if (sctx->callbacks.edit_mesh.test_edge_fn) { + elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); + edges_num_active = BM_iter_mesh_bitmap_from_filter( + BM_EDGES_OF_MESH, em->bm, elem_mask, + (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, + sctx->callbacks.edit_mesh.user_data); } - case SCE_SNAP_MODE_VERTEX: - { - BLI_bitmap *verts_mask = NULL; - int verts_num_active = -1; - if (sctx->callbacks.edit_mesh.test_vert_fn) { - verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); - verts_num_active = BM_iter_mesh_bitmap_from_filter( - BM_VERTS_OF_MESH, em->bm, verts_mask, - (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, - sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_verts_ex(treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6); - if (verts_mask) { - MEM_freeN(verts_mask); - } - break; + bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6); + break; + } + case SCE_SNAP_MODE_VERTEX: + { + int verts_num_active = -1; + if (sctx->callbacks.edit_mesh.test_vert_fn) { + elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + verts_num_active = BM_iter_mesh_bitmap_from_filter( + BM_VERTS_OF_MESH, em->bm, elem_mask, + (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, + sctx->callbacks.edit_mesh.user_data); } + bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6); + break; } } - - if (!treedata || !treedata->tree) { - return retval; + if (elem_mask) { + MEM_freeN(elem_mask); } + } - if (snap_to == SCE_SNAP_MODE_FACE) { - float ray_start_local[3]; - copy_v3_v3(ray_start_local, ray_start); - mul_m4_v3(imat, ray_start_local); + if (!treedata || !treedata->tree) { + return retval; + } - /* local scale in normal direction */ - float local_scale = normalize_v3(ray_normal_local); - float local_depth = *ray_depth; - if (local_depth != BVH_RAYCAST_DIST_MAX) { - local_depth *= local_scale; - } + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { + float ray_start_local[3]; + copy_v3_v3(ray_start_local, snapdata->ray_start); + mul_m4_v3(imat, ray_start_local); - /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already - * been *inside* boundbox, leading to snap failures (see T38409). - * Note also ar might be null (see T38435), in this case we assume ray_start is ok! + /* Only use closer ray_start in case of ortho view! In perspective one, ray_start + * may already been *inside* boundbox, leading to snap failures (see T38409). + * Note also ar might be null (see T38435), in this case we assume ray_start is ok! + */ + float len_diff = 0.0f; + if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ + /* We *need* a reasonably valid len_diff in this case. + * Use BHVTree to find the closest face from ray_start_local. */ - float len_diff = 0.0f; - if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ - /* We *need* a reasonably valid len_diff in this case. - * Use BHVTree to find the closest face from ray_start_local. - */ - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - if (BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) - { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + if (BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) + { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); + /* You need to make sure that ray_start is really far away, + * because even in the Orthografic view, in some cases, + * the ray can start inside the object (see T50486) */ + if (len_diff > 400.0f) { float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); + copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); /* We pass a temp ray_start, set from object's boundbox, * to avoid precision issues with very far away ray_start values * (as returned in case of ortho view3d), see T38358. */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale); + ray_start_local, ray_org_local, ray_normal_local, + len_diff + snapdata->depth_range[0] * local_scale); local_depth -= len_diff; } + else len_diff = 0.0f; } - if (r_hit_list) { - struct RayCastAll_Data data; - - data.bvhdata = treedata; - data.raycast_callback = treedata->raycast_callback; - data.obmat = obmat; - data.timat = timat; - data.len_diff = len_diff; - data.local_scale = local_scale; - data.ob = ob; - data.ob_uuid = ob_index; - data.hit_list = r_hit_list; - data.retval = retval; - - BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); - - retval = data.retval; - } - else { - BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - - if (BLI_bvhtree_ray_cast( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - &hit, treedata->raycast_callback, treedata) != -1) - { - hit.dist += len_diff; - hit.dist /= local_scale; - if (hit.dist <= *ray_depth) { - *ray_depth = hit.dist; - copy_v3_v3(r_loc, hit.co); - - /* back to worldspace */ - mul_m4_v3(obmat, r_loc); - - if (r_no) { - copy_v3_v3(r_no, hit.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } - - retval = true; - - if (r_index) { - *r_index = hit.index; - } - } - } - } + } + if (r_hit_list) { + struct RayCastAll_Data data; + + data.bvhdata = treedata; + data.raycast_callback = treedata->raycast_callback; + data.obmat = obmat; + data.timat = timat; + data.len_diff = len_diff; + data.local_scale = local_scale; + data.ob = ob; + data.ob_uuid = ob_index; + data.hit_list = r_hit_list; + data.retval = retval; + + BLI_bvhtree_ray_cast_all( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); + + retval = data.retval; } else { - const ARegion *ar = sctx->v3d_data.ar; - - float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); - mul_m4_v3(imat, ray_org_local); + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; - - if (view_proj == VIEW_PROJ_PERSP) { - Object_Nearest2dPrecalc neasrest_precalc; - neasrest_precalc.userdata = &treedata_type; - neasrest_precalc.index = -1; - - nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat, - ray_org_local, ray_normal_local, mval, depth_range); - - BVHTree_WalkLeafCallback cb_walk_leaf = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - - BLI_bvhtree_walk_dfs( - treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); + if (BLI_bvhtree_ray_cast( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + &hit, treedata->raycast_callback, treedata) != -1) + { + hit.dist += len_diff; + hit.dist /= local_scale; + if (hit.dist <= *ray_depth) { + *ray_depth = hit.dist; + copy_v3_v3(r_loc, hit.co); - if (neasrest_precalc.index != -1) { - copy_v3_v3(r_loc, neasrest_precalc.co); + /* back to worldspace */ mul_m4_v3(obmat, r_loc); + if (r_no) { - copy_v3_v3(r_no, neasrest_precalc.no); + copy_v3_v3(r_no, hit.no); mul_m3_v3(timat, r_no); normalize_v3(r_no); } - *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); retval = true; - } - } - else { - BVHTreeNearest nearest; - - nearest.index = -1; - float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px); - nearest.dist_sq = SQUARE(dist_3d); - - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); - - struct NearestDM_Data userdata; - userdata.bvhdata = &treedata_type; - userdata.depth_range = depth_range; - userdata.ray_depth = ray_depth; - - BVHTree_NearestToRayCallback cb_test_ray_dist = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - test_vert_ray_dist_cb : test_edge_ray_dist_cb; - - if (BLI_bvhtree_find_nearest_to_ray( - treedata->tree, ray_org_local, ray_normal_local, - false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1) - { - copy_v3_v3(r_loc, nearest.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, nearest.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + if (r_index) { + *r_index = hit.index; } - *dist_px *= sqrtf(nearest.dist_sq) / dist_3d; - - retval = true; } } } - - if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) { - if (treedata) { - free_bvhtree_from_editmesh(treedata); + } + else { + float ray_org_local[3]; + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); + + Nearest2dUserData neasrest2d = { + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .userdata = treedata, + .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts, + .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no, + .index = -1}; + + float lpmat[4][4]; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, + (snapdata->depth_range[0] * local_scale), snapdata->mval, + ray_org_local, ray_normal_local); + + BVHTree_WalkLeafCallback cb_walk_leaf = + (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; + + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); + + if (neasrest2d.index != -1) { + copy_v3_v3(r_loc, neasrest2d.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest2d.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); } + *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + + retval = true; } } @@ -1717,11 +1614,9 @@ static bool snapEditMesh( * \note Duplicate args here are documented at #snapObjectsRay */ static bool snapObject( - SnapObjectContext *sctx, + SnapObjectContext *sctx, SnapData *snapdata, Object *ob, float obmat[4][4], const unsigned int ob_index, - bool use_obedit, const short snap_to, const float mval[2], - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], - const float depth_range[2], + bool use_obedit, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1729,12 +1624,6 @@ static bool snapObject( Object **r_ob, float r_obmat[4][4], ListBase *r_hit_list) { - const enum eViewProj view_proj = - ((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE : - (((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO); - - const ARegion *ar = sctx->v3d_data.ar; - bool retval = false; if (ob->type == OB_MESH) { @@ -1743,9 +1632,7 @@ static bool snapObject( if (use_obedit) { em = BKE_editmesh_from_object(ob); retval = snapEditMesh( - sctx, ob, em, obmat, ob_index, - snap_to, mval, view_proj, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, ob, em, obmat, ob_index, ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); @@ -1762,9 +1649,8 @@ static bool snapObject( dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH); } retval = snapDerivedMesh( - sctx, ob, dm, obmat, ob_index, - snap_to, mval, view_proj, true, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, ob, dm, obmat, ob_index, + true, ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); @@ -1772,32 +1658,32 @@ static bool snapObject( dm->release(dm); } } - else if (snap_to != SCE_SNAP_MODE_FACE) { + else if (snapdata->snap_to != SCE_SNAP_MODE_FACE) { if (ob->type == OB_ARMATURE) { retval = snapArmature( - ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal, - mval, view_proj, depth_range, dist_px, + snapdata, + ob, ob->data, obmat, + ray_depth, dist_px, r_loc, r_no); } else if (ob->type == OB_CURVE) { retval = snapCurve( - ar, ob, ob->data, obmat, snap_to, mval, view_proj, - depth_range, - dist_px, + snapdata, + ob, ob->data, obmat, + ray_depth, dist_px, r_loc, r_no); } else if (ob->type == OB_EMPTY) { retval = snapEmpty( - ar, ob, obmat, snap_to, mval, view_proj, - depth_range, - dist_px, + snapdata, + ob, obmat, + ray_depth, dist_px, r_loc, r_no); } else if (ob->type == OB_CAMERA) { retval = snapCamera( - sctx, ob, obmat, snap_to, mval, view_proj, - depth_range, - dist_px, + sctx, snapdata, ob, obmat, + ray_depth, dist_px, r_loc, r_no); } } @@ -1819,18 +1705,9 @@ static bool snapObject( * Walks through all objects in the scene to find the closest snap element ray. * * \param sctx: Snap context to store data. - * \param snap_to: Element to snap, Vertice, Edge or Face. - * Currently only works one at a time, but can eventually operate as flag. - * + * \param snapdata: struct generated in `get_snapdata`. * \param snap_select: from enum SnapSelect. - * * \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping. - * \param mval: Mouse coords. - * When NULL, ray-casting is handled without any projection matrix correction. - * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. - * \param ray_start: ray_origin moved for the start clipping plane (clip_min). - * \param ray_normal: Unit length direction of the ray. - * \param depth_range: distances of clipe plane min and clip plane max; * * Read/Write Args * --------------- @@ -1851,11 +1728,9 @@ static bool snapObject( * */ static bool snapObjectsRay( - SnapObjectContext *sctx, - const unsigned short snap_to, const SnapSelect snap_select, - const bool use_object_edit_cage, const float mval[2], - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], - const float depth_range[2], + SnapObjectContext *sctx, SnapData *snapdata, + const SnapSelect snap_select, + const bool use_object_edit_cage, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1873,14 +1748,12 @@ static bool snapObjectsRay( * * To solve that problem, we do it first as an exception. * */ - Base *base_act = sctx->scene->basact; + BaseLegacy *base_act = sctx->scene->basact; if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) { Object *ob = base_act->object; retval |= snapObject( - sctx, ob, ob->obmat, ob_index++, - false, snap_to, mval, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, ob, ob->obmat, ob_index++, false, ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1896,11 +1769,11 @@ static bool snapObjectsRay( ignore_object_active = true; break; } - for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) { + for (BaseLegacy *base = sctx->scene->base.first; base != NULL; base = base->next) { if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) && - (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && + (base->flag_legacy & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && - !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) || + !((ignore_object_selected && (base->flag_legacy & (SELECT | BA_WAS_SEL))) || (ignore_object_active && base == base_act))) { Object *ob = base->object; @@ -1914,9 +1787,8 @@ static bool snapObjectsRay( Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob; retval |= snapObject( - sctx, dupli_snap, dupli_ob->mat, ob_index++, - use_obedit_dupli, snap_to, mval, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, dupli_snap, dupli_ob->mat, + ob_index++, use_obedit_dupli, ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1928,9 +1800,7 @@ static bool snapObjectsRay( Object *ob_snap = use_obedit ? obedit : ob; retval |= snapObject( - sctx, ob_snap, ob->obmat, ob_index++, - use_obedit, snap_to, mval, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, ob_snap, ob->obmat, ob_index++, use_obedit, ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1957,6 +1827,9 @@ SnapObjectContext *ED_transform_snap_object_context_create( sctx->bmain = bmain; sctx->scene = scene; + sctx->cache.object_map = BLI_ghash_ptr_new(__func__); + sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + return sctx; } @@ -1971,11 +1844,6 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d( sctx->v3d_data.ar = ar; sctx->v3d_data.v3d = v3d; - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - sctx->cache.object_map = BLI_ghash_ptr_new(__func__); - sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - } - return sctx; } @@ -2007,10 +1875,8 @@ static void snap_object_data_free(void *sod_v) void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) { - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); - BLI_memarena_free(sctx->cache.mem_arena); - } + BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); + BLI_memarena_free(sctx->cache.mem_arena); MEM_freeN(sctx); } @@ -2039,10 +1905,15 @@ bool ED_transform_snap_object_project_ray_ex( Object **r_ob, float r_obmat[4][4]) { const float depth_range[2] = {0.0f, FLT_MAX}; + + SnapData snapdata; + snap_data_set( + &snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, + NULL, ray_start, ray_start, ray_normal, depth_range); + return snapObjectsRay( - sctx, - snap_to, params->snap_select, params->use_object_edit_cage, NULL, - ray_start, ray_start, ray_normal, depth_range, + sctx, &snapdata, + params->snap_select, params->use_object_edit_cage, ray_depth, NULL, r_loc, r_no, r_index, r_ob, r_obmat, NULL); } @@ -2071,10 +1942,13 @@ bool ED_transform_snap_object_project_ray_all( float ray_depth_prev = ray_depth; #endif + SnapData snapdata; + snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, + ray_start, ray_start, ray_normal, depth_range); + bool retval = snapObjectsRay( - sctx, - snap_to, params->snap_select, params->use_object_edit_cage, NULL, - ray_start, ray_start, ray_normal, depth_range, + sctx, &snapdata, + params->snap_select, params->use_object_edit_cage, &ray_depth, NULL, NULL, NULL, NULL, NULL, NULL, r_hit_list); @@ -2153,19 +2027,40 @@ static bool transform_snap_context_project_view3d_mixed_impl( BLI_assert(snap_to_flag != 0); BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0); - for (int i = 0; i < 3; i++) { - if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) { - if (use_depth == false) { - ray_depth = BVH_RAYCAST_DIST_MAX; + if (use_depth) { + const float dist_px_orig = dist_px ? *dist_px : 0; + for (int i = 2; i >= 0; i--) { + if (snap_to_flag & (1 << i)) { + if (i == 0) { + BLI_assert(dist_px != NULL); + *dist_px = dist_px_orig; + } + if (ED_transform_snap_object_project_view3d( + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) + { + /* 0.01 is a random but small value to prioritizing + * the first elements of the loop */ + ray_depth += 0.01f; + is_hit = true; + } } - - if (ED_transform_snap_object_project_view3d( - sctx, - elem_type[i], params, - mval, dist_px, &ray_depth, - r_co, r_no)) - { - is_hit = true; + } + } + else { + for (int i = 0; i < 3; i++) { + if (snap_to_flag & (1 << i)) { + if (ED_transform_snap_object_project_view3d( + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) + { + is_hit = true; + break; + } } } } @@ -2234,10 +2129,14 @@ bool ED_transform_snap_object_project_view3d_ex( ray_depth = &ray_depth_fallback; } + SnapData snapdata; + const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; + snap_data_set(&snapdata, ar, snap_to, view_proj, mval, + ray_origin, ray_start, ray_normal, depth_range); + return snapObjectsRay( - sctx, - snap_to, params->snap_select, params->use_object_edit_cage, - mval, ray_origin, ray_start, ray_normal, depth_range, + sctx, &snapdata, + params->snap_select, params->use_object_edit_cage, ray_depth, dist_px, r_loc, r_no, r_index, NULL, NULL, NULL); } diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 5c5e84ee5f0..3510e1e7088 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -55,6 +55,8 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" + #include "ED_image.h" #include "ED_mesh.h" #include "ED_uvedit.h" @@ -70,7 +72,7 @@ /* use editmesh tessface */ #define USE_EDBM_LOOPTRIS -static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset); +static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, unsigned int pos); void ED_image_draw_cursor(ARegion *ar, const float cursor[2]) { @@ -81,35 +83,67 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2]) mul_v2_fl(zoom, 256.0f * UI_DPI_FAC); x_fac = zoom[0]; y_fac = zoom[1]; - - cpack(0xFFFFFF); + glTranslate2fv(cursor); - fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac); - fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f); - fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac); - fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f); - setlinestyle(4); - cpack(0xFF); - fdrawline(-0.05f * x_fac, 0.0f, 0.0f, 0.05f * y_fac); - fdrawline(0.0f, 0.05f * y_fac, 0.05f * x_fac, 0.0f); - fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac); - fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f); + unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - setlinestyle(0.0f); - cpack(0x0); - fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f); - fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f); - fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac); - fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac); + imm_cpack(0xFFFFFF); + + immBegin(GL_LINE_LOOP, 4); + immVertex2f(pos, -0.05f * x_fac, 0.0f); + immVertex2f(pos, 0.0f, 0.05f * y_fac); + immVertex2f(pos, 0.05f * x_fac, 0.0f); + immVertex2f(pos, 0.0f, -0.05f * y_fac); + immEnd(); + + setlinestyle(4); + imm_cpack(0xFF); + + /* drawing individual segments, because the stipple pattern + * gets messed up when drawing a continuous loop */ + immBegin(GL_LINES, 8); + immVertex2f(pos, -0.05f * x_fac, 0.0f); + immVertex2f(pos, 0.0f, 0.05f * y_fac); + immVertex2f(pos, 0.0f, 0.05f * y_fac); + immVertex2f(pos, 0.05f * x_fac, 0.0f); + immVertex2f(pos, 0.05f * x_fac, 0.0f); + immVertex2f(pos, 0.0f, -0.05f * y_fac); + immVertex2f(pos, 0.0f, -0.05f * y_fac); + immVertex2f(pos, -0.05f * x_fac, 0.0f); + immEnd(); + + setlinestyle(0); + imm_cpack(0x0); + + immBegin(GL_LINES, 8); + immVertex2f(pos, -0.020f * x_fac, 0.0f); + immVertex2f(pos, -0.1f * x_fac, 0.0f); + immVertex2f(pos, 0.1f * x_fac, 0.0f); + immVertex2f(pos, 0.020f * x_fac, 0.0f); + immVertex2f(pos, 0.0f, -0.020f * y_fac); + immVertex2f(pos, 0.0f, -0.1f * y_fac); + immVertex2f(pos, 0.0f, 0.1f * y_fac); + immVertex2f(pos, 0.0f, 0.020f * y_fac); + immEnd(); setlinestyle(1); - cpack(0xFFFFFF); - fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f); - fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f); - fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac); - fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac); + imm_cpack(0xFFFFFF); + + immBegin(GL_LINES, 8); + immVertex2f(pos, -0.020f * x_fac, 0.0f); + immVertex2f(pos, -0.1f * x_fac, 0.0f); + immVertex2f(pos, 0.1f * x_fac, 0.0f); + immVertex2f(pos, 0.020f * x_fac, 0.0f); + immVertex2f(pos, 0.0f, -0.020f * y_fac); + immVertex2f(pos, 0.0f, -0.1f * y_fac); + immVertex2f(pos, 0.0f, 0.1f * y_fac); + immVertex2f(pos, 0.0f, 0.020f * y_fac); + immEnd(); + + immUnbindProgram(); glTranslatef(-cursor[0], -cursor[1], 0.0); setlinestyle(0); @@ -141,12 +175,18 @@ static void draw_uvs_shadow(Object *obedit) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* draws the mesh when painting */ - UI_ThemeColor(TH_UV_SHADOW); + immUniformThemeColor(TH_UV_SHADOW); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); } + + immUnbindProgram(); } static int draw_uvs_dm_shadow(DerivedMesh *dm) @@ -212,19 +252,27 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BM_elem_flag_disable(efa, BM_ELEM_TAG); } } - + + unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + if (totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) { col[0] = 1.0; col[1] = col[2] = 0.0; - glColor3fv(col); + + immUniformColor3fv(col); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - glBegin(GL_POLYGON); + immBegin(GL_TRIANGLE_FAN, efa->len); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } } } @@ -254,18 +302,23 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe areadiff = 1.0f - (area / uvarea); weight_to_rgb(col, areadiff); - glColor3fv(col); + immUniformColor3fv(col); /* TODO: USE_EDBM_LOOPTRIS */ - glBegin(GL_POLYGON); + immBegin(GL_TRIANGLE_FAN, efa->len); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } } } + + immUnbindProgram(); + break; } case SI_UVDT_STRETCH_ANGLE: @@ -278,7 +331,13 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BLI_buffer_declare_static(vec2f, auv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); col[3] = 0.5f; /* hard coded alpha, not that nice */ - + + VertexFormat* format = immVertexFormat(); + unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned int color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); @@ -320,15 +379,15 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe } /* TODO: USE_EDBM_LOOPTRIS */ - glBegin(GL_POLYGON); + immBegin(GL_TRIANGLE_FAN, efa->len); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); a = fabsf(uvang[i] - ang[i]) / (float)M_PI; weight_to_rgb(col, 1.0f - pow2f(1.0f - a)); - glColor3fv(col); - glVertex2fv(luv->uv); + immAttrib3fv(color, col); + immVertex2fv(pos, luv->uv); } - glEnd(); + immEnd(); } else { if (tf == activetf) @@ -337,6 +396,8 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe } } + immUnbindProgram(); + BLI_buffer_free(&uvang_buf); BLI_buffer_free(&ang_buf); BLI_buffer_free(&av_buf); @@ -350,34 +411,38 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BLI_buffer_free(&tf_uvorig_buf); } -static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset) +static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, unsigned int pos) { BMIter liter; BMLoop *l; MLoopUV *luv; - glBegin(GL_LINE_LOOP); + immBegin(GL_LINE_LOOP, efa->len); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } -static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly) +static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly, unsigned int pos) { MLoopUV *mloopuv; int i; - glBegin(GL_LINE_LOOP); + immBegin(GL_LINE_LOOP, mpoly->totloop); + mloopuv = &me->mloopuv[mpoly->loopstart]; for (i = mpoly->totloop; i != 0; i--, mloopuv++) { - glVertex2fv(mloopuv->uv); + immVertex2fv(pos, mloopuv->uv); } - glEnd(); + + immEnd(); } -static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const int other_uv_filter) +static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const int other_uv_filter, unsigned int pos) { Mesh *me = ob->data; MPoly *mpoly = me->mpoly; @@ -398,10 +463,10 @@ static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const } } - draw_uvs_lineloop_mpoly(me, mpoly); + draw_uvs_lineloop_mpoly(me, mpoly, pos); } } -static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, const int other_uv_filter) +static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, const int other_uv_filter, unsigned int pos) { Mesh *me = ob->data; MPoly *mpoly = me->mpoly; @@ -453,38 +518,44 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, c } } - draw_uvs_lineloop_mpoly(me, mpoly); + draw_uvs_lineloop_mpoly(me, mpoly, pos); } } static void draw_uvs_other_mesh(Object *ob, const Image *curimage, const bool new_shading_nodes, - const int other_uv_filter) + const int other_uv_filter, unsigned int pos) { if (new_shading_nodes) { - draw_uvs_other_mesh_new_shading(ob, curimage, other_uv_filter); + draw_uvs_other_mesh_new_shading(ob, curimage, other_uv_filter, pos); } else { - draw_uvs_other_mesh_texface(ob, curimage, other_uv_filter); + draw_uvs_other_mesh_texface(ob, curimage, other_uv_filter, pos); } } static void draw_uvs_other(Scene *scene, Object *obedit, const Image *curimage, const bool new_shading_nodes, const int other_uv_filter) { - Base *base; + BaseLegacy *base; + + unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - UI_ThemeColor(TH_UV_OTHERS); + immUniformThemeColor(TH_UV_OTHERS); for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; - if (!(base->flag & SELECT)) continue; + if (!(base->flag_legacy & SELECT)) continue; if (!(base->lay & scene->lay)) continue; if (ob->restrictflag & OB_RESTRICT_VIEW) continue; if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) { - draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter); + draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter, pos); } } + + immUnbindProgram(); } static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) @@ -498,8 +569,6 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) draw_uvs_other(scene, ob, curimage, new_shading_nodes, sima->other_uv_filter); } - UI_ThemeColor(TH_UV_SHADOW); - ma = give_current_material(ob, ob->actcol); if (me->mtpoly) { @@ -512,24 +581,34 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) mloopuv = me->mloopuv; } + unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_UV_SHADOW); + mloopuv_base = mloopuv; for (a = me->totpoly; a > 0; a--, mpoly++) { if ((scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE) && mpoly->mat_nr != ob->actcol - 1) continue; - glBegin(GL_LINE_LOOP); + + immBegin(GL_LINE_LOOP, mpoly->totloop); mloopuv = mloopuv_base + mpoly->loopstart; for (b = 0; b < mpoly->totloop; b++, mloopuv++) { - glVertex2fv(mloopuv->uv); + immVertex2fv(pos, mloopuv->uv); } - glEnd(); + + immEnd(); } + + immUnbindProgram(); } } #ifdef USE_EDBM_LOOPTRIS -static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset) +static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset, unsigned int pos) { unsigned int i = *r_loop_index; BMFace *f = em->looptris[i][0]->f; @@ -537,7 +616,7 @@ static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const i unsigned int j; for (j = 0; j < 3; j++) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(em->looptris[i][j], cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } i++; } while (i != em->tottri && (f == em->looptris[i][0]->f)); @@ -570,6 +649,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); + unsigned int pos; + activetf = EDBM_mtexpoly_active_get(em, &efa_act, false, false); /* will be set to NULL if hidden */ #ifndef USE_EDBM_LOOPTRIS activef = BM_mesh_active_face_get(bm, false, false); @@ -622,7 +703,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) finaldm->release(finaldm); } } - + /* 2. draw colored faces */ if (sima->flag & SI_DRAW_STRETCH) { @@ -638,6 +719,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) #ifdef USE_EDBM_LOOPTRIS { unsigned int i; + + pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + for (i = 0; i < em->tottri; i++) { efa = em->looptris[i][0]->f; tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); @@ -647,26 +733,22 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) if (tf == activetf) { /* only once */ - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - UI_ThemeColor4(TH_EDITMESH_ACTIVE); + immUniformThemeColor(TH_EDITMESH_ACTIVE); } else { - glColor4ubv((GLubyte *)(is_select ? col2 : col1)); + immUniformColor4ubv(is_select ? col2 : col1); } - glBegin(GL_TRIANGLES); - draw_uvs_looptri(em, &i, cd_loop_uv_offset); - glEnd(); - - if (tf == activetf) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } + immBegin(GL_TRIANGLES, (em->looptris[i][0]->f->len - 2) * 3); + draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos); + immEnd(); } else { BM_elem_flag_disable(efa, BM_ELEM_TAG); } } + + immUnbindProgram(); } #else BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { @@ -751,104 +833,152 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) switch (sima->dt_uv) { case SI_UVDT_DASH: + pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (tf) { - cpack(0x111111); + imm_cpack(0x111111); - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); setlinestyle(2); - cpack(0x909090); + imm_cpack(0x909090); - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); setlinestyle(0); } } + + immUnbindProgram(); + break; case SI_UVDT_BLACK: /* black/white */ - case SI_UVDT_WHITE: - if (sima->dt_uv == SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f); - else glColor3f(0.0f, 0.0f, 0.0f); + case SI_UVDT_WHITE: + pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + if (sima->dt_uv == SI_UVDT_WHITE) { + immUniformColor3f(1.0f, 1.0f, 1.0f); + } + else { + immUniformColor3f(0.0f, 0.0f, 0.0f); + } BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); } + + immUnbindProgram(); + break; case SI_UVDT_OUTLINE: + pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + glLineWidth(3); - cpack(0x0); - + imm_cpack(0x0); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); } - + + immUnbindProgram(); + glLineWidth(1); UI_GetThemeColor4ubv(TH_WIRE_EDIT, col2); - glColor4ubv((unsigned char *)col2); if (me->drawflag & ME_DRAWEDGES) { - int sel, lastsel = -1; + int sel; UI_GetThemeColor4ubv(TH_EDGE_SELECT, col1); + VertexFormat* format = immVertexFormat(); + pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT); + if (interpedges) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - glBegin(GL_LINE_LOOP); + immBegin(GL_LINE_LOOP, efa->len); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); - glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); + immAttrib4ubv(color, sel ? (GLubyte *)col1 : (GLubyte *)col2); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } + + immUnbindProgram(); } else { + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + int lastsel = -1; + if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - glBegin(GL_LINES); + immBegin(GL_LINES, efa->len * 2); + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { sel = uvedit_edge_select_test(scene, l, cd_loop_uv_offset); if (sel != lastsel) { - glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); + immAttrib4ubv(color, sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } - glEnd(); + + immEnd(); } + + immUnbindProgram(); } } else { + pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4ubv(col2); + /* no nice edges */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset); + draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos); } + + immUnbindProgram(); } - + break; } @@ -861,50 +991,80 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) if (drawfaces) { float cent[2]; - + bool col_set = false; + + VertexFormat* format = immVertexFormat(); + pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE); glPointSize(pointsize); - glBegin(GL_POINTS); + immBeginAtMost(GL_POINTS, bm->totface); /* unselected faces */ - UI_ThemeColor(TH_WIRE); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + /* Only set color for the first face */ + if (!col_set) { + UI_GetThemeColor3ubv(TH_WIRE, col1); + immAttrib3ubv(color, col1); + + col_set = true; + } + uv_poly_center(efa, cent, cd_loop_uv_offset); - glVertex2fv(cent); + immVertex2fv(pos, cent); } } + col_set = false; + /* selected faces */ - UI_ThemeColor(TH_FACE_DOT); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + /* Only set color for the first face */ + if (!col_set) { + UI_GetThemeColor3ubv(TH_FACE_DOT, col1); + immAttrib3ubv(color, col1); + + col_set = true; + } + uv_poly_center(efa, cent, cd_loop_uv_offset); - glVertex2fv(cent); + immVertex2fv(pos, cent); } } - glEnd(); + immEnd(); + + immUnbindProgram(); } /* 6. draw uv vertices */ if (drawfaces != 2) { /* 2 means Mesh Face Mode */ + pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* unselected uvs */ - UI_ThemeColor(TH_VERTEX); + immUniformThemeColor(TH_VERTEX); pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE); glPointSize(pointsize); - - glBegin(GL_POINTS); + + immBeginAtMost(GL_POINTS, bm->totloop); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; @@ -912,17 +1072,19 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } } - glEnd(); + + immEnd(); /* pinned uvs */ /* give odd pointsizes odd pin pointsizes */ glPointSize(pointsize * 2 + (((int)pointsize % 2) ? (-1) : 0)); - cpack(0xFF); + imm_cpack(0xFF); - glBegin(GL_POINTS); + immBeginAtMost(GL_POINTS, bm->totloop); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; @@ -931,16 +1093,18 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_PINNED) - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } } - glEnd(); + + immEnd(); /* selected uvs */ - UI_ThemeColor(TH_VERTEX_SELECT); + immUniformThemeColor(TH_VERTEX_SELECT); glPointSize(pointsize); - glBegin(GL_POINTS); + immBeginAtMost(GL_POINTS, bm->totloop); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; @@ -949,10 +1113,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) - glVertex2fv(luv->uv); + immVertex2fv(pos, luv->uv); } } - glEnd(); + + immEnd(); + + immUnbindProgram(); } } diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index f63cf771120..0e03ab84a47 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -127,7 +127,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str BKE_scene_set_background(freestyle_bmain, freestyle_scene); // Camera - Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL); + Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, (SceneLayer *)freestyle_scene->render_layers.first, OB_CAMERA, NULL); DAG_relations_tag_update(freestyle_bmain); Camera *camera = (Camera *)object_camera->data; @@ -166,7 +166,7 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer() // compositor has finished. // release objects and data blocks - for (Base *b = (Base *)freestyle_scene->base.first; b; b = b->next) { + for (BaseLegacy *b = (BaseLegacy *)freestyle_scene->base.first; b; b = b->next) { Object *ob = b->object; void *data = ob->data; char *name = ob->id.name; @@ -674,7 +674,7 @@ int BlenderStrokeRenderer::get_stroke_count() const void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) { #if 0 - Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, OB_MESH); + Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, (SceneLayer *)freestyle_scene->render_layers.first, OB_MESH); DAG_relations_tag_update(freestyle_bmain); #else Object *object_mesh = NewMesh(); @@ -922,7 +922,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) Object *BlenderStrokeRenderer::NewMesh() const { Object *ob; - Base *base; + BaseLegacy *base; char name[MAX_ID_NAME]; unsigned int mesh_id = get_stroke_mesh_id(); diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 76b76bb636a..7573985baa8 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../imbuf ../makesdna ../makesrna + ../draw ../editors/include @@ -64,6 +65,7 @@ set(SRC intern/gpu_select.c intern/gpu_shader.c intern/gpu_texture.c + intern/gpu_uniformbuffer.c intern/gpu_viewport.c gawain/attrib_binding.c @@ -122,6 +124,7 @@ set(SRC GPU_select.h GPU_shader.h GPU_texture.h + GPU_uniformbuffer.h GPU_viewport.h intern/gpu_codegen.h @@ -130,6 +133,8 @@ set(SRC data_to_c_simple(shaders/gpu_shader_depth_only_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_uniform_color_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_checker_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_simple_lighting_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC) @@ -148,8 +153,16 @@ data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_passthrough_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl SRC) + +data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC) + data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_point_uniform_color_smooth_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl SRC) @@ -175,6 +188,8 @@ data_to_c_simple(shaders/gpu_shader_edges_overlay_simple_geom.glsl SRC) data_to_c_simple(shaders/gpu_shader_edges_overlay_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_keyframe_diamond_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC) data_to_c_simple(shaders/gpu_shader_fire_frag.glsl SRC) diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index bc3017e2784..066bc9eeba7 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -35,3 +35,9 @@ /* Extend Batch_set_program to use Blender’s library of built-in shader programs. */ void Batch_set_builtin_program(Batch*, GPUBuiltinShader); + +/* Replacement for gluSphere */ +Batch *Batch_get_sphere(int lod); + +void gpu_batch_init(void); +void gpu_batch_exit(void); diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 31ad8243c4b..ff00a83d00b 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -53,6 +53,8 @@ int GPU_max_textures(void); float GPU_max_texture_anisotropy(void); int GPU_max_color_texture_samples(void); int GPU_max_cube_map_size(void); +int GPU_max_ubo_binds(void); +int GPU_max_ubo_size(void); int GPU_color_depth(void); void GPU_get_dfdy_factors(float fac[2]); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index 989b874fd38..9611a6f0577 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -52,6 +52,7 @@ void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex); GPUFrameBuffer *GPU_framebuffer_create(void); bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot); void GPU_framebuffer_texture_detach(struct GPUTexture *tex); +void GPU_framebuffer_bind(GPUFrameBuffer *fb); void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot); void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex); void GPU_framebuffer_free(GPUFrameBuffer *fb); diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h index 4390b62379e..43a03f8e4b6 100644 --- a/source/blender/gpu/GPU_matrix.h +++ b/source/blender/gpu/GPU_matrix.h @@ -133,6 +133,9 @@ const float *gpuGetNormalMatrixInverse(float m[3][3]); #if SUPPORT_LEGACY_MATRIX /* copy top matrix from each legacy stack into new fresh stack */ void gpuMatrixBegin3D_legacy(void); + +/* call after using glScale, glTranslate, etc. between draw calls */ +void gpuMatrixUpdate_legacy(void); #endif diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index e528089850c..fcf070890ea 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -38,6 +38,7 @@ extern "C" { typedef struct GPUShader GPUShader; struct GPUTexture; +struct GPUUniformBuffer; /* GPU Shader * - only for fragment shaders now @@ -69,14 +70,17 @@ void GPU_shader_free(GPUShader *shader); void GPU_shader_bind(GPUShader *shader); void GPU_shader_unbind(void); +int GPU_shader_get_program(GPUShader *shader); void *GPU_shader_get_interface(GPUShader *shader); void GPU_shader_set_interface(GPUShader *shader, void *interface); int GPU_shader_get_uniform(GPUShader *shader, const char *name); +int GPU_shader_get_uniform_block(GPUShader *shader, const char *name); void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, const float *value); void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length, int arraysize, const int *value); +void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo); void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex); void GPU_shader_uniform_int(GPUShader *shader, int location, int value); void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number); @@ -97,13 +101,17 @@ typedef enum GPUBuiltinShader { GPU_SHADER_EDGES_FRONT_BACK_ORTHO, GPU_SHADER_EDGES_OVERLAY_SIMPLE, GPU_SHADER_EDGES_OVERLAY, + GPU_SHADER_KEYFRAME_DIAMOND, + GPU_SHADER_SIMPLE_LIGHTING, /* for simple 2D drawing */ GPU_SHADER_2D_UNIFORM_COLOR, GPU_SHADER_2D_FLAT_COLOR, GPU_SHADER_2D_SMOOTH_COLOR, GPU_SHADER_2D_IMAGE_COLOR, + GPU_SHADER_2D_CHECKER, /* for simple 3D drawing */ GPU_SHADER_3D_UNIFORM_COLOR, + GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE, GPU_SHADER_3D_FLAT_COLOR, GPU_SHADER_3D_SMOOTH_COLOR, GPU_SHADER_3D_DEPTH_ONLY, @@ -127,6 +135,13 @@ typedef enum GPUBuiltinShader { GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH, GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR, GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR, + /* lamp drawing */ + GPU_SHADER_3D_GROUNDPOINT, + GPU_SHADER_3D_GROUNDLINE, + GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, + /* instance */ + GPU_SHADER_INSTANCE_UNIFORM_COLOR, + GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */ } GPUBuiltinShader; diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 756fe79151b..a8df80cd626 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -55,25 +55,112 @@ typedef struct GPUTexture GPUTexture; * - if created with from_blender, will not free the texture */ -typedef enum GPUHDRType { - GPU_HDR_NONE = 0, - GPU_HDR_HALF_FLOAT = 1, - GPU_HDR_FULL_FLOAT = (1 << 1), -} GPUHDRType; +/* Wrapper to supported OpenGL/Vulkan texture internal storage + * If you need a type just uncomment it. Be aware that some formats + * are not supported by renderbuffers. All of the following formats + * are part of the OpenGL 3.3 core + * specification. */ +typedef enum GPUTextureFormat { + /* Formats texture & renderbuffer */ + GPU_RGBA16F, + GPU_RGBA8, + GPU_RG32F, + GPU_RG16F, + GPU_R8, +#if 0 + GPU_RGBA32F, + GPU_RGBA32I, + GPU_RGBA32UI, + GPU_RGBA16, + GPU_RGBA16I, + GPU_RGBA16UI, + GPU_RGBA8I, + GPU_RGBA8UI, + GPU_RG32I, + GPU_RG32UI, + GPU_RG16, + GPU_RG16I, + GPU_RG16UI, + GPU_RG8, + GPU_RG8I, + GPU_RG8UI, + GPU_R32F, + GPU_R32I, + GPU_R32UI, + GPU_R16F, + GPU_R16I, + GPU_R16UI, + GPU_R16, + GPU_R8I, + GPU_R8UI, +#endif + + /* Special formats texture & renderbuffer */ +#if 0 + GPU_R11F_G11F_B10F, + GPU_RGB10_A2, + GPU_RGB10_A2UI, + GPU_DEPTH32F_STENCIL8, + GPU_DEPTH24_STENCIL8, +#endif + + /* Texture only format */ +#if 0 + GPU_RGBA16_SNORM, + GPU_RGBA8_SNORM, + GPU_RGB32F, + GPU_RGB32I, + GPU_RGB32UI, + GPU_RGB16_SNORM, + GPU_RGB16F, + GPU_RGB16I, + GPU_RGB16UI, + GPU_RGB16, + GPU_RGB8_SNORM, + GPU_RGB8, + GPU_RGB8I, + GPU_RGB8UI, + GPU_RG16_SNORM, + GPU_RG8_SNORM, + GPU_R16_SNORM, + GPU_R8_SNORM, +#endif + + /* Special formats texture only */ +#if 0 + GPU_SRGB8_A8, + GPU_SRGB8, + GPU_RGB9_E5, + GPU_COMPRESSED_RG_RGTC2, + GPU_COMPRESSED_SIGNED_RG_RGTC2, + GPU_COMPRESSED_RED_RGTC1, + GPU_COMPRESSED_SIGNED_RED_RGTC1, +#endif + + /* Depth Formats */ + GPU_DEPTH_COMPONENT32F, + GPU_DEPTH_COMPONENT24, + GPU_DEPTH_COMPONENT16, +} GPUTextureFormat; GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]); -GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]); -GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels); +GPUTexture *GPU_texture_create_1D_custom( + int w, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2D_custom( + int w, int h, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, int samples, char err_out[256]); +GPUTexture *GPU_texture_create_2D_array(int w, int h, int d, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_3D_custom( + int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]); GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); -GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); -GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]); -GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]); -GPUTexture *GPU_texture_create_2D_multisample( - int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]); GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]); + GPUTexture *GPU_texture_from_blender( struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); + void GPU_invalid_tex_init(void); void GPU_invalid_tex_bind(int mode); void GPU_invalid_tex_free(void); @@ -81,12 +168,13 @@ void GPU_invalid_tex_free(void); void GPU_texture_free(GPUTexture *tex); void GPU_texture_ref(GPUTexture *tex); - void GPU_texture_bind(GPUTexture *tex, int number); void GPU_texture_unbind(GPUTexture *tex); int GPU_texture_bound_number(GPUTexture *tex); -void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter); +void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare); +void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter); +void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat); struct GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex); int GPU_texture_framebuffer_attachment(GPUTexture *tex); diff --git a/source/blender/gpu/GPU_uniformbuffer.h b/source/blender/gpu/GPU_uniformbuffer.h new file mode 100644 index 00000000000..bcb6e1077b7 --- /dev/null +++ b/source/blender/gpu/GPU_uniformbuffer.h @@ -0,0 +1,44 @@ +/* + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Clement Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file GPU_uniformbuffer.h + * \ingroup gpu + */ + +typedef struct GPUUniformBuffer GPUUniformBuffer; + +GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]); +void GPU_uniformbuffer_free(GPUUniformBuffer *ubo); + +void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data); + +void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number); +#if 0 +void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo); +#endif + +int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo); diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index fce509377ab..9de16f64ca1 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -34,12 +34,57 @@ #include <stdbool.h> +#include "DNA_vec_types.h" + +#include "GPU_framebuffer.h" +#include "GPU_texture.h" + typedef struct GPUViewport GPUViewport; -GPUViewport *GPU_viewport_create(void); +#define MAX_BUFFERS 8 +#define MAX_TEXTURES 16 +#define MAX_PASSES 16 +#define MAX_STORAGE 2 /* extend if needed */ + +/* All FramebufferLists are just the same pointers with different names */ +typedef struct FramebufferList { + struct GPUFrameBuffer *framebuffers[MAX_BUFFERS]; +} FramebufferList; + +typedef struct TextureList { + struct GPUTexture *textures[MAX_TEXTURES]; +} TextureList; + +typedef struct PassList { + struct DRWPass *passes[MAX_TEXTURES]; +} PassList; +typedef struct StorageList { + void *storage[MAX_STORAGE]; /* custom structs from the engine */ +} StorageList; + +/* Buffer and textures used by the viewport by default */ +typedef struct DefaultFramebufferList { + struct GPUFrameBuffer *default_fb; +} DefaultFramebufferList; + +typedef struct DefaultTextureList { + struct GPUTexture *color; + struct GPUTexture *depth; +} DefaultTextureList; + +typedef struct DefaultPassList { + struct DRWPass *non_meshes_pass; + struct DRWPass *ob_center_pass; +} DefaultPassList; + +GPUViewport *GPU_viewport_create(void); +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine); +void GPU_viewport_unbind(GPUViewport *viewport); void GPU_viewport_free(GPUViewport *viewport); +void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss, void **str); + /* debug */ bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]); void GPU_viewport_debug_depth_free(GPUViewport *viewport); diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c index a60865d41d2..55ccd94a555 100644 --- a/source/blender/gpu/gawain/batch.c +++ b/source/blender/gpu/gawain/batch.c @@ -19,20 +19,25 @@ extern bool gpuMatricesDirty(void); // how best to use this here? Batch* Batch_create(PrimitiveType prim_type, VertexBuffer* verts, ElementList* elem) { + Batch* batch = calloc(1, sizeof(Batch)); + + Batch_init(batch, prim_type, verts, elem); + + return batch; + } + +void Batch_init(Batch* batch, PrimitiveType prim_type, VertexBuffer* verts, ElementList* elem) + { #if TRUST_NO_ONE assert(verts != NULL); assert(prim_type == PRIM_POINTS || prim_type == PRIM_LINES || prim_type == PRIM_TRIANGLES); // we will allow other primitive types in a future update #endif - Batch* batch = calloc(1, sizeof(Batch)); - batch->verts = verts; batch->elem = elem; batch->prim_type = prim_type; batch->phase = READY_TO_DRAW; - - return batch; } void Batch_discard(Batch* batch) @@ -247,3 +252,89 @@ void Batch_draw(Batch* batch) Batch_done_using_program(batch); glBindVertexArray(0); } + + + +// clement : temp stuff +void Batch_draw_stupid(Batch* batch) +{ + if (batch->vao_id) + glBindVertexArray(batch->vao_id); + else + Batch_prime(batch); + + if (batch->program_dirty) + Batch_update_program_bindings(batch); + + // Batch_use_program(batch); + + //gpuBindMatrices(batch->program); + + if (batch->elem) + { + const ElementList* el = batch->elem; + +#if TRACK_INDEX_RANGE + if (el->base_index) + glDrawRangeElementsBaseVertex(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0, el->base_index); + else + glDrawRangeElements(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0); +#else + glDrawElements(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0); +#endif + } + else + glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct); + + // Batch_done_using_program(batch); + glBindVertexArray(0); +} + +// clement : temp stuff +void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count, + int attrib_nbr, int attrib_stride, int attrib_size[16], int attrib_loc[16]) +{ + if (batch->vao_id) + glBindVertexArray(batch->vao_id); + else + Batch_prime(batch); + + if (batch->program_dirty) + Batch_update_program_bindings(batch); + + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo); + int ptr_ofs = 0; + for (int i = 0; i < attrib_nbr; ++i) { + int size = attrib_size[i]; + int loc = attrib_loc[i]; + int atr_ofs = 0; + + while (size > 0) { + glEnableVertexAttribArray(loc + atr_ofs); + glVertexAttribPointer(loc + atr_ofs, (size > 4) ? 4 : size, GL_FLOAT, GL_FALSE, + sizeof(float) * attrib_stride, (GLvoid*)(sizeof(float) * ptr_ofs)); + glVertexAttribDivisor(loc + atr_ofs, 1); + atr_ofs++; + ptr_ofs += (size > 4) ? 4 : size; + size -= 4; + } + } + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // Batch_use_program(batch); + + //gpuBindMatrices(batch->program); + + if (batch->elem) + { + const ElementList* el = batch->elem; + + glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count); + } + else + glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count); + + // Batch_done_using_program(batch); + glBindVertexArray(0); +} + diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h index 932ee182703..660ed9eb762 100644 --- a/source/blender/gpu/gawain/batch.h +++ b/source/blender/gpu/gawain/batch.h @@ -38,6 +38,7 @@ typedef struct Batch{ } Batch; Batch* Batch_create(PrimitiveType, VertexBuffer*, ElementList*); +void Batch_init(Batch*, PrimitiveType, VertexBuffer*, ElementList*); void Batch_discard(Batch*); // verts & elem are not discarded void Batch_discard_all(Batch*); // including verts & elem @@ -59,6 +60,12 @@ void Batch_Uniform4fv(Batch*, const char* name, const float data[4]); void Batch_draw(Batch*); +// clement : temp stuff +void Batch_draw_stupid(Batch*); +void Batch_draw_stupid_instanced(Batch*, unsigned int instance_vbo, int instance_count, + int attrib_nbr, int attrib_stride, int attrib_loc[16], int attrib_size[16]); + + diff --git a/source/blender/gpu/gawain/buffer_id.cpp b/source/blender/gpu/gawain/buffer_id.cpp index a7b8d7a394a..450656c4ebf 100644 --- a/source/blender/gpu/gawain/buffer_id.cpp +++ b/source/blender/gpu/gawain/buffer_id.cpp @@ -53,7 +53,7 @@ GLuint buffer_id_alloc() } orphan_mutex.unlock(); - GLuint new_buffer_id; + GLuint new_buffer_id = 0; glGenBuffers(1, &new_buffer_id); return new_buffer_id; } @@ -80,8 +80,6 @@ GLuint vao_id_alloc() assert(thread_is_main()); #endif - GLuint new_vao_id; - // delete orphaned IDs orphan_mutex.lock(); if (!orphaned_vao_ids.empty()) @@ -95,6 +93,7 @@ GLuint vao_id_alloc() } orphan_mutex.unlock(); + GLuint new_vao_id = 0; glGenVertexArrays(1, &new_vao_id); return new_vao_id; } diff --git a/source/blender/gpu/gawain/immediate.c b/source/blender/gpu/gawain/immediate.c index 3806b0f304a..b7aad530620 100644 --- a/source/blender/gpu/gawain/immediate.c +++ b/source/blender/gpu/gawain/immediate.c @@ -54,7 +54,7 @@ typedef struct { static PER_THREAD bool initialized = false; static PER_THREAD Immediate imm; -void immInit() +void immInit(void) { #if TRUST_NO_ONE assert(!initialized); @@ -80,7 +80,7 @@ void immInit() immActivate(); } -void immActivate() +void immActivate(void) { #if TRUST_NO_ONE assert(initialized); @@ -91,7 +91,7 @@ void immActivate() imm.vao_id = vao_id_alloc(); } -void immDeactivate() +void immDeactivate(void) { #if TRUST_NO_ONE assert(initialized); @@ -104,14 +104,14 @@ void immDeactivate() imm.prev_enabled_attrib_bits = 0; } -void immDestroy() +void immDestroy(void) { immDeactivate(); buffer_id_free(imm.vbo_id); initialized = false; } -VertexFormat* immVertexFormat() +VertexFormat* immVertexFormat(void) { VertexFormat_clear(&imm.vertex_format); return &imm.vertex_format; @@ -134,7 +134,7 @@ void immBindProgram(GLuint program) gpuBindMatrices(program); } -void immUnbindProgram() +void immUnbindProgram(void) { #if TRUST_NO_ONE assert(imm.bound_program != 0); @@ -339,7 +339,7 @@ static void immDrawSetup(void) gpuBindMatrices(imm.bound_program); } -void immEnd() +void immEnd(void) { #if TRUST_NO_ONE assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair @@ -727,6 +727,50 @@ void immUniform1f(const char* name, float x) glUniform1f(loc, x); } +void immUniform2f(const char* name, float x, float y) +{ + int loc = glGetUniformLocation(imm.bound_program, name); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif + + glUniform2f(loc, x, y); +} + +void immUniform2fv(const char* name, const float data[2]) +{ + int loc = glGetUniformLocation(imm.bound_program, name); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif + + glUniform2fv(loc, 1, data); +} + +void immUniform3f(const char* name, float x, float y, float z) + { + int loc = glGetUniformLocation(imm.bound_program, name); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif + + glUniform3f(loc, x, y, z); + } + +void immUniform3fv(const char* name, const float data[3]) + { + int loc = glGetUniformLocation(imm.bound_program, name); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif + + glUniform3fv(loc, 1, data); + } + void immUniform4f(const char* name, float x, float y, float z, float w) { int loc = glGetUniformLocation(imm.bound_program, name); diff --git a/source/blender/gpu/gawain/immediate.h b/source/blender/gpu/gawain/immediate.h index 23d7413aaf8..53f9e6c46e1 100644 --- a/source/blender/gpu/gawain/immediate.h +++ b/source/blender/gpu/gawain/immediate.h @@ -79,6 +79,10 @@ void immVertex2iv(unsigned attrib_id, const int data[2]); // provide uniform values that don't change for the entire draw call void immUniform1i(const char* name, int x); void immUniform1f(const char* name, float x); +void immUniform2f(const char* name, float x, float y); +void immUniform2fv(const char* name, const float data[2]); +void immUniform3f(const char* name, float x, float y, float z); +void immUniform3fv(const char* name, const float data[3]); void immUniform4f(const char* name, float x, float y, float z, float w); void immUniform4fv(const char* name, const float data[4]); void immUniformMat4(const char* name, const float data[4][4]); diff --git a/source/blender/gpu/gawain/vertex_buffer.c b/source/blender/gpu/gawain/vertex_buffer.c index 5f2da60067d..827703403e3 100644 --- a/source/blender/gpu/gawain/vertex_buffer.c +++ b/source/blender/gpu/gawain/vertex_buffer.c @@ -16,7 +16,7 @@ #define KEEP_SINGLE_COPY 1 -VertexBuffer* VertexBuffer_create() +VertexBuffer* VertexBuffer_create(void) { VertexBuffer* verts = malloc(sizeof(VertexBuffer)); VertexBuffer_init(verts); diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 23f9f68f1aa..716c5e55b3c 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -25,6 +25,9 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "BLI_utildefines.h" +#include "BLI_math.h" + #include "GPU_batch.h" #include "gpu_shader_private.h" @@ -33,3 +36,87 @@ void Batch_set_builtin_program(Batch* batch, GPUBuiltinShader shader_id) GPUShader *shader = GPU_shader_get_builtin_shader(shader_id); Batch_set_program(batch, shader->program); } + +static Batch *sphere_high = NULL; +static Batch *sphere_med = NULL; +static Batch *sphere_low = NULL; + +static VertexBuffer *vbo; +static VertexFormat format = {0}; +static unsigned int pos_id, nor_id; +static unsigned int vert; + +static void batch_sphere_lat_lon_vert(float lat, float lon) +{ + float pos[3]; + pos[0] = sinf(lat) * cosf(lon); + pos[1] = cosf(lat); + pos[2] = sinf(lat) * sinf(lon); + + setAttrib(vbo, nor_id, vert, pos); + setAttrib(vbo, pos_id, vert++, pos); +} + +/* Replacement for gluSphere */ +static Batch *batch_sphere(int lat_res, int lon_res) +{ + const float lon_inc = 2 * M_PI / lon_res; + const float lat_inc = M_PI / lat_res; + float lon, lat; + + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT); + } + + vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, (lat_res-1) * lon_res * 6); + vert = 0; + + lon = 0.0f; + for(int i = 0; i < lon_res; i++, lon += lon_inc) { + lat = 0.0f; + for(int j = 0; j < lat_res; j++, lat += lat_inc) { + if (j != lat_res - 1) { /* Pole */ + batch_sphere_lat_lon_vert(lat, lon); + batch_sphere_lat_lon_vert(lat+lat_inc, lon); + batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc); + } + + if (j != 0) { /* Pole */ + batch_sphere_lat_lon_vert(lat, lon); + batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc); + batch_sphere_lat_lon_vert(lat, lon+lon_inc); + } + } + } + + return Batch_create(GL_TRIANGLES, vbo, NULL); +} + +Batch *Batch_get_sphere(int lod) +{ + BLI_assert(lod >= 0 && lod <= 2); + + if (lod == 0) + return sphere_low; + else if (lod == 1) + return sphere_med; + else + return sphere_high; +} + +void gpu_batch_init(void) +{ + /* Hard coded resolution */ + sphere_low = batch_sphere(8, 8); + sphere_med = batch_sphere(16, 10); + sphere_high = batch_sphere(32, 24); +} + +void gpu_batch_exit(void) +{ + Batch_discard_all(sphere_low); + Batch_discard_all(sphere_med); + Batch_discard_all(sphere_high); +} diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 211394e7932..4223ec54f74 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -1192,7 +1192,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType #if 0 input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL); #endif - input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL); + input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL); input->textarget = GL_TEXTURE_2D; MEM_freeN(link->ptr1); diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 13596f2a0de..528bdefc209 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -225,7 +225,13 @@ static GPUTexture * create_concentric_sample_texture(int side) } } - tex = GPU_texture_create_1D_procedural(side * side, texels, NULL); + tex = GPU_texture_create_1D_custom(side * side, 2, GPU_RG16F, (float *)texels, NULL); + + /* Set parameters */ + GPU_texture_bind(tex, 0); + GPU_texture_filter_mode(tex, false); + GPU_texture_unbind(tex); + MEM_freeN(texels); return tex; } @@ -247,7 +253,13 @@ static GPUTexture *create_spiral_sample_texture(int numsaples) texels[i][1] = r * sinf(phi); } - tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL); + tex = GPU_texture_create_1D_custom(numsaples, 2, GPU_RG16F, (float *)texels, NULL); + + /* Set parameters */ + GPU_texture_bind(tex, 0); + GPU_texture_filter_mode(tex, false); + GPU_texture_unbind(tex); + MEM_freeN(texels); return tex; } @@ -358,6 +370,7 @@ void GPU_fx_compositor_destroy(GPUFX *fx) static GPUTexture * create_jitter_texture(void) { + GPUTexture *tex; float jitter[64 * 64][2]; int i; @@ -367,7 +380,15 @@ static GPUTexture * create_jitter_texture(void) normalize_v2(jitter[i]); } - return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, NULL); + tex = GPU_texture_create_2D_custom(64, 64, 2, GPU_RG16F, &jitter[0][0], NULL); + + /* Set parameters */ + GPU_texture_bind(tex, 0); + GPU_texture_filter_mode(tex, false); + GPU_texture_wrap_mode(tex, true); + GPU_texture_unbind(tex); + + return tex; } @@ -433,7 +454,7 @@ bool GPU_fx_compositor_initialize_passes( if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) { cleanup_fx_gl_data(fx, false); - if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) { + if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, err_out))) { printf(".256%s\n", err_out); cleanup_fx_gl_data(fx, true); return false; @@ -485,38 +506,42 @@ bool GPU_fx_compositor_initialize_passes( { if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } - if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out))) + + if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_custom( + fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RG16F, NULL, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } + GPU_texture_bind(fx->dof_nearfar_coc, 0); + GPU_texture_filter_mode(fx->dof_nearfar_coc, false); + GPU_texture_wrap_mode(fx->dof_nearfar_coc, false); + GPU_texture_unbind(fx->dof_nearfar_coc); - - if (!(fx->dof_near_blur = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out))) + if (!(fx->dof_near_blur = GPU_texture_create_2D_custom( + fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RGBA16F, NULL, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } - if (!(fx->dof_far_blur = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out))) + if (!(fx->dof_far_blur = GPU_texture_create_2D_custom( + fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RGBA16F, NULL, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); @@ -531,21 +556,21 @@ bool GPU_fx_compositor_initialize_passes( if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) { if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); @@ -564,7 +589,7 @@ bool GPU_fx_compositor_initialize_passes( /* we need to pass data between shader stages, allocate an extra color buffer */ if (num_passes > 1) { if (!fx->color_buffer_sec) { - if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) { + if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, err_out))) { printf(".256%s\n", err_out); cleanup_fx_gl_data(fx, true); return false; @@ -692,14 +717,16 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) GPU_shader_bind(depth_resolve_shader); GPU_texture_bind(fx->depth_buffer_xray, 0); - GPU_texture_filter_mode(fx->depth_buffer_xray, false, true); + GPU_texture_compare_mode(fx->depth_buffer_xray, false); + GPU_texture_filter_mode(fx->depth_buffer_xray, true); GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray); /* draw */ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ - GPU_texture_filter_mode(fx->depth_buffer_xray, true, false); + GPU_texture_compare_mode(fx->depth_buffer_xray, true); + GPU_texture_filter_mode(fx->depth_buffer_xray, false); GPU_texture_unbind(fx->depth_buffer_xray); GPU_shader_unbind(); @@ -814,7 +841,8 @@ bool GPU_fx_do_composite_pass( GPU_shader_uniform_texture(ssao_shader, interface->color_uniform, src); GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_texture_filter_mode(fx->depth_buffer, false, true); + GPU_texture_compare_mode(fx->depth_buffer, false); + GPU_texture_filter_mode(fx->depth_buffer, true); GPU_shader_uniform_texture(ssao_shader, interface->depth_uniform, fx->depth_buffer); GPU_texture_bind(fx->jitter_buffer, numslots++); @@ -830,7 +858,8 @@ bool GPU_fx_do_composite_pass( /* disable bindings */ GPU_texture_unbind(src); - GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_compare_mode(fx->depth_buffer, true); + GPU_texture_filter_mode(fx->depth_buffer, false); GPU_texture_unbind(fx->depth_buffer); GPU_texture_unbind(fx->jitter_buffer); GPU_texture_unbind(fx->ssao_spiral_samples_tex); @@ -906,12 +935,13 @@ bool GPU_fx_do_composite_pass( GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim); GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_texture_filter_mode(fx->depth_buffer, false, false); + GPU_texture_compare_mode(fx->depth_buffer, false); + GPU_texture_filter_mode(fx->depth_buffer, false); GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer); GPU_texture_bind(src, numslots++); /* disable filtering for the texture so custom downsample can do the right thing */ - GPU_texture_filter_mode(src, false, false); + GPU_texture_filter_mode(src, false); GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, src); /* target is the downsampled coc buffer */ @@ -925,9 +955,10 @@ bool GPU_fx_do_composite_pass( glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ - GPU_texture_filter_mode(src, false, true); + GPU_texture_filter_mode(src, true); GPU_texture_unbind(src); - GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_compare_mode(fx->depth_buffer, true); + GPU_texture_filter_mode(fx->depth_buffer, false); GPU_texture_unbind(fx->depth_buffer); GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near); @@ -958,7 +989,7 @@ bool GPU_fx_do_composite_pass( GPU_texture_bind(fx->dof_half_downsampled_far, numslots++); GPU_texture_bind(fx->dof_half_downsampled_near, numslots++); GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far); - GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false); + GPU_texture_filter_mode(fx->dof_half_downsampled_far, false); /* target is the downsampled coc buffer */ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0); @@ -978,7 +1009,7 @@ bool GPU_fx_do_composite_pass( GPU_framebuffer_texture_detach(fx->dof_far_blur); GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near); - GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false); + GPU_texture_filter_mode(fx->dof_half_downsampled_near, false); selection[0] = 1.0f; selection[1] = 0.0f; @@ -1018,14 +1049,15 @@ bool GPU_fx_do_composite_pass( GPU_texture_bind(fx->dof_near_blur, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, interface->near_uniform, fx->dof_near_blur); - GPU_texture_filter_mode(fx->dof_near_blur, false, true); + GPU_texture_filter_mode(fx->dof_near_blur, true); GPU_texture_bind(fx->dof_far_blur, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, interface->far_uniform, fx->dof_far_blur); - GPU_texture_filter_mode(fx->dof_far_blur, false, true); + GPU_texture_filter_mode(fx->dof_far_blur, true); GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_texture_filter_mode(fx->depth_buffer, false, false); + GPU_texture_compare_mode(fx->depth_buffer, false); + GPU_texture_filter_mode(fx->depth_buffer, false); GPU_shader_uniform_texture(dof_shader_pass3, interface->depth_uniform, fx->depth_buffer); GPU_texture_bind(src, numslots++); @@ -1040,7 +1072,7 @@ bool GPU_fx_do_composite_pass( GPU_texture_unbind(fx->dof_near_blur); GPU_texture_unbind(fx->dof_far_blur); GPU_texture_unbind(src); - GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_compare_mode(fx->depth_buffer, true); GPU_texture_unbind(fx->depth_buffer); /* may not be attached, in that case this just returns */ @@ -1100,7 +1132,8 @@ bool GPU_fx_do_composite_pass( GPU_shader_uniform_texture(dof_shader_pass1, interface->color_uniform, src); GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_texture_filter_mode(fx->depth_buffer, false, true); + GPU_texture_compare_mode(fx->depth_buffer, false); + GPU_texture_filter_mode(fx->depth_buffer, true); GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer); /* target is the downsampled coc buffer */ @@ -1111,7 +1144,8 @@ bool GPU_fx_do_composite_pass( glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_unbind(src); - GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_compare_mode(fx->depth_buffer, true); + GPU_texture_filter_mode(fx->depth_buffer, false); GPU_texture_unbind(fx->depth_buffer); GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer); @@ -1137,7 +1171,8 @@ bool GPU_fx_do_composite_pass( GPU_shader_uniform_vector(dof_shader_pass2, interface->viewvecs_uniform, 4, 3, viewvecs[0]); GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_texture_filter_mode(fx->depth_buffer, false, true); + GPU_texture_compare_mode(fx->depth_buffer, false); + GPU_texture_filter_mode(fx->depth_buffer, true); GPU_shader_uniform_texture(dof_shader_pass2, interface->depth_uniform, fx->depth_buffer); GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); @@ -1165,7 +1200,8 @@ bool GPU_fx_do_composite_pass( glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* *unbind/detach */ - GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_compare_mode(fx->depth_buffer, true); + GPU_texture_filter_mode(fx->depth_buffer, false); GPU_texture_unbind(fx->depth_buffer); GPU_texture_unbind(fx->dof_near_coc_final_buffer); @@ -1249,7 +1285,8 @@ bool GPU_fx_do_composite_pass( GPU_shader_uniform_texture(dof_shader_pass5, interface->medium_blurred_uniform, fx->dof_near_coc_buffer); GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_texture_filter_mode(fx->depth_buffer, false, true); + GPU_texture_compare_mode(fx->depth_buffer, false); + GPU_texture_filter_mode(fx->depth_buffer, true); GPU_shader_uniform_texture(dof_shader_pass5, interface->depth_uniform, fx->depth_buffer); /* if this is the last pass, prepare for rendering on the frambuffer */ @@ -1260,7 +1297,8 @@ bool GPU_fx_do_composite_pass( GPU_texture_unbind(fx->dof_near_coc_buffer); GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); GPU_texture_unbind(src); - GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_compare_mode(fx->depth_buffer, true); + GPU_texture_filter_mode(fx->depth_buffer, false); GPU_texture_unbind(fx->depth_buffer); /* may not be attached, in that case this just returns */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index c8d5d92b66b..1fb1e239310 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -38,8 +38,6 @@ #include <string.h> -#include "GPU_glew.h" - #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_math.h" @@ -853,32 +851,6 @@ void GPU_create_gl_tex( int tpx = rectw; int tpy = recth; -#if 0 /* NPOT support should be a compile-time check */ - /* scale if not a power of two. this is not strictly necessary for newer - * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures - * Then don't bother scaling for hardware that supports NPOT textures! */ - if (textarget == GL_TEXTURE_2D && - ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) || - is_over_resolution_limit(textarget, rectw, recth))) - { - rectw = smaller_power_of_2_limit(rectw); - recth = smaller_power_of_2_limit(recth); - - if (use_high_bit_depth) { - ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); - IMB_scaleImBuf(ibuf, rectw, recth); - - frect = ibuf->rect_float; - } - else { - ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy); - IMB_scaleImBuf(ibuf, rectw, recth); - - rect = ibuf->rect; - } - } -#endif - /* create image */ glGenTextures(1, (GLuint *)bind); glBindTexture(textarget, *bind); @@ -1203,13 +1175,7 @@ void GPU_paint_set_mipmap(bool mipmap) /* check if image has been downscaled and do scaled partial update */ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h) { -#if 0 /* NPOT suport should be a compile-time check */ - if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) || - is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) -#else - if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) -#endif - { + if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) { int x_limit = smaller_power_of_2_limit(ibuf->x); int y_limit = smaller_power_of_2_limit(ibuf->y); @@ -1438,31 +1404,40 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres) if (smoke_has_colors(sds->fluid)) { float *data = MEM_callocN(sizeof(float) * sds->total_cells * 4, "smokeColorTexture"); smoke_get_rgba(sds->fluid, data, 0); - sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data); + sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], data, NULL); MEM_freeN(data); } /* density only */ else { - sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_density(sds->fluid)); + sds->tex = GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1, + GPU_R8, smoke_get_density(sds->fluid), NULL); } - sds->tex_flame = (smoke_has_fuel(sds->fluid)) ? GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_flame(sds->fluid)) : NULL; + sds->tex_flame = (smoke_has_fuel(sds->fluid)) ? + GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1, + GPU_R8, smoke_get_flame(sds->fluid), NULL) : + NULL; } else if (!sds->tex && highres) { /* rgba texture for color + density */ if (smoke_turbulence_has_colors(sds->wt)) { float *data = MEM_callocN(sizeof(float) * smoke_turbulence_get_cells(sds->wt) * 4, "smokeColorTexture"); smoke_turbulence_get_rgba(sds->wt, data, 0); - sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data); + sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], data, NULL); MEM_freeN(data); } /* density only */ else { - sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_density(sds->wt)); + sds->tex = GPU_texture_create_3D_custom(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, + GPU_R8, smoke_turbulence_get_density(sds->wt), NULL); } - sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ? GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_flame(sds->wt)) : NULL; + sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ? + GPU_texture_create_3D_custom(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, + GPU_R8, smoke_turbulence_get_flame(sds->wt), NULL): + NULL; } - sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, sds->shadow); + sds->tex_shadow = GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1, + GPU_R8, sds->shadow, NULL); } #else // WITH_SMOKE (void)highres; @@ -2184,7 +2159,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ int count = 0; - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { if (base->object->type != OB_LAMP) continue; @@ -2343,7 +2318,7 @@ void GPU_state_init(void) GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); } -void GPU_enable_program_point_size() +void GPU_enable_program_point_size(void) { #ifdef __APPLE__ /* TODO: remove this when we switch to core profile */ @@ -2353,7 +2328,7 @@ void GPU_enable_program_point_size() #endif } -void GPU_disable_program_point_size() +void GPU_disable_program_point_size(void) { #ifdef __APPLE__ /* TODO: remove this when we switch to core profile */ diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index e8fd4b8b8b1..d7ed65e853e 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -69,6 +69,8 @@ static struct GPUGlobal { GLint maxtexsize; GLint maxcubemapsize; GLint maxtextures; + GLint maxubosize; + GLint maxubobinds; bool extdisabled; int colordepth; int samples_color_texture_max; @@ -121,6 +123,16 @@ int GPU_max_cube_map_size(void) return GG.maxcubemapsize; } +int GPU_max_ubo_binds(void) +{ + return GG.maxubobinds; +} + +int GPU_max_ubo_size(void) +{ + return GG.maxubosize; +} + void GPU_get_dfdy_factors(float fac[2]) { copy_v2_v2(fac, GG.dfdyfactors); @@ -154,6 +166,9 @@ void gpu_extensions_init(void) else GG.max_anisotropy = 1.0f; + glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &GG.maxubobinds); + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize); + GLint r, g, b; glGetIntegerv(GL_RED_BITS, &r); glGetIntegerv(GL_GREEN_BITS, &g); diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index ec1471744fa..1efc451f4a8 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -54,7 +54,7 @@ struct GPUFrameBuffer { static void GPU_print_framebuffer_error(GLenum status, char err_out[256]) { - const char *format = "GPUFrameBuffer: framebuffer status %s"; + const char *format = "GPUFrameBuffer: framebuffer status %s\n"; const char *err = "unknown"; #define format_status(X) \ @@ -260,6 +260,43 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot) glPushMatrix(); } +void GPU_framebuffer_bind(GPUFrameBuffer *fb) +{ + int numslots = 0, i; + GLenum attachments[4]; + GLenum readattachement = 0; + GPUTexture *tex; + + for (i = 0; i < 4; i++) { + if (fb->colortex[i]) { + attachments[numslots] = GL_COLOR_ATTACHMENT0 + i; + tex = fb->colortex[i]; + + if (!readattachement) + readattachement = GL_COLOR_ATTACHMENT0 + i; + + numslots++; + } + } + + /* bind framebuffer */ + glBindFramebuffer(GL_FRAMEBUFFER, fb->object); + + if (numslots == 0) { + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + tex = fb->depthtex; + } + else { + /* last bound prevails here, better allow explicit control here too */ + glDrawBuffers(numslots, attachments); + glReadBuffer(readattachement); + } + + glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex)); + GG.currentfb = fb->object; +} + void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex)) { @@ -283,7 +320,6 @@ void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot) /* push matrices and set default viewport and matrix */ glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot])); GG.currentfb = fb->object; - GG.currentfb = fb->object; } bool GPU_framebuffer_bound(GPUFrameBuffer *fb) @@ -453,7 +489,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_ return NULL; } - ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out); + ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, samples, err_out); if (!ofs->color) { GPU_offscreen_free(ofs); return NULL; diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c index 817756a3088..7a6b1ff6c70 100644 --- a/source/blender/gpu/intern/gpu_init_exit.c +++ b/source/blender/gpu/intern/gpu_init_exit.c @@ -32,6 +32,7 @@ #include "BLI_sys_types.h" #include "GPU_init_exit.h" /* interface */ #include "GPU_immediate.h" +#include "GPU_batch.h" #include "BKE_global.h" #include "intern/gpu_codegen.h" @@ -59,6 +60,8 @@ void GPU_init(void) if (G.debug & G_DEBUG_GPU) gpu_debug_init(); + gpu_batch_init(); + immInit(); } @@ -68,6 +71,8 @@ void GPU_exit(void) { immDestroy(); + gpu_batch_exit(); + if (G.debug & G_DEBUG_GPU) gpu_debug_exit(); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 56b7af787e7..9e08f629bcb 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -609,7 +609,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode GPU_link(mat, "lamp_visibility_spot", GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), - GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), + GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTBLEND, lamp->ob), inpr, visifac, &visifac); } @@ -1016,7 +1016,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) { - Base *base; + BaseLegacy *base; Scene *sce_iter; for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) { @@ -2369,6 +2369,11 @@ static void gpu_lamp_shadow_free(GPULamp *lamp) } } +static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size) +{ + return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL); +} + GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) { Lamp *la; @@ -2415,7 +2420,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) } /* Shadow color map */ - lamp->tex = GPU_texture_create_vsm_shadow_map(lamp->size, NULL); + lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size); if (!lamp->tex) { gpu_lamp_shadow_free(lamp); return lamp; @@ -2438,7 +2443,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) return lamp; } - lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL); + lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5); if (!lamp->blurtex) { gpu_lamp_shadow_free(lamp); return lamp; diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c index 19ff856b688..855ccaa4999 100644 --- a/source/blender/gpu/intern/gpu_matrix.c +++ b/source/blender/gpu/intern/gpu_matrix.c @@ -70,12 +70,12 @@ static MatrixState state; /* TODO(merwin): make part of GPUContext, alongside im #define Projection3D state.ProjectionMatrix3D #define Projection2D state.ProjectionMatrix2D -void gpuMatrixInit() +void gpuMatrixInit(void) { memset(&state, 0, sizeof(MatrixState)); } -void gpuMatrixBegin2D() +void gpuMatrixBegin2D(void) { state.mode = MATRIX_MODE_2D; state.top = 0; @@ -83,7 +83,7 @@ void gpuMatrixBegin2D() gpuOrtho2D(-1.0f, +1.0f, -1.0f, +1.0f); // or identity? } -void gpuMatrixBegin3D() +void gpuMatrixBegin3D(void) { state.mode = MATRIX_MODE_3D; state.top = 0; @@ -92,7 +92,7 @@ void gpuMatrixBegin3D() } #if SUPPORT_LEGACY_MATRIX -void gpuMatrixBegin3D_legacy() +void gpuMatrixBegin3D_legacy(void) { /* copy top matrix from each legacy stack into new fresh stack */ state.mode = MATRIX_MODE_3D; @@ -103,7 +103,7 @@ void gpuMatrixBegin3D_legacy() } #endif -void gpuMatrixEnd() +void gpuMatrixEnd(void) { state.mode = MATRIX_MODE_INACTIVE; } @@ -133,7 +133,7 @@ static void checkmat(cosnt float *m) #endif -void gpuPushMatrix() +void gpuPushMatrix(void) { BLI_assert(state.mode != MATRIX_MODE_INACTIVE); BLI_assert(state.top < MATRIX_STACK_DEPTH); @@ -144,7 +144,7 @@ void gpuPushMatrix() copy_m3_m3(ModelView2D, state.ModelViewStack2D[state.top - 1]); } -void gpuPopMatrix() +void gpuPopMatrix(void) { BLI_assert(state.mode != MATRIX_MODE_INACTIVE); BLI_assert(state.top > 0); @@ -168,7 +168,7 @@ void gpuLoadMatrix2D(const float m[3][3]) state.dirty = true; } -void gpuLoadIdentity() +void gpuLoadIdentity(void) { switch (state.mode) { case MATRIX_MODE_3D: @@ -281,7 +281,7 @@ void gpuScale3fv(const float vec[3]) void gpuMultMatrix3D(const float m[4][4]) { BLI_assert(state.mode == MATRIX_MODE_3D); - mul_m4_m4_pre(ModelView3D, m); + mul_m4_m4_post(ModelView3D, m); CHECKMAT(ModelView3D); state.dirty = true; } @@ -289,7 +289,7 @@ void gpuMultMatrix3D(const float m[4][4]) void gpuMultMatrix2D(const float m[3][3]) { BLI_assert(state.mode == MATRIX_MODE_2D); - mul_m3_m3_pre(ModelView2D, m); + mul_m3_m3_post(ModelView2D, m); CHECKMAT(ModelView2D); state.dirty = true; } @@ -622,7 +622,7 @@ const float *gpuGetNormalMatrix(float m[3][3]) m = temp3; } - copy_m3_m4(m, gpuGetModelViewMatrix3D(NULL)); + copy_m3_m4(m, (const float (*)[4])gpuGetModelViewMatrix3D(NULL)); invert_m3(m); transpose_m3(m); @@ -695,7 +695,15 @@ void gpuBindMatrices(GLuint program) state.dirty = false; } -bool gpuMatricesDirty() +bool gpuMatricesDirty(void) { return state.dirty; } + +#if SUPPORT_LEGACY_MATRIX +void gpuMatrixUpdate_legacy(void) +{ + BLI_assert(state.mode == MATRIX_MODE_INACTIVE); + state.dirty = true; +} +#endif diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 4fd8ab0d8b4..295182b3153 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -37,6 +37,7 @@ #include "GPU_debug.h" #include "GPU_extensions.h" #include "GPU_shader.h" +#include "GPU_uniformbuffer.h" #include "GPU_texture.h" #include "gpu_shader_private.h" @@ -48,6 +49,8 @@ /* Non-generated shaders */ extern char datatoc_gpu_shader_depth_only_frag_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_checker_frag_glsl[]; +extern char datatoc_gpu_shader_simple_lighting_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[]; extern char datatoc_gpu_shader_2D_vert_glsl[]; @@ -67,8 +70,16 @@ extern char datatoc_gpu_shader_3D_vert_glsl[]; extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; +extern char datatoc_gpu_shader_3D_passthrough_vert_glsl[]; extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[]; +extern char datatoc_gpu_shader_instance_vert_glsl[]; +extern char datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl[]; +extern char datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl[]; + +extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[]; +extern char datatoc_gpu_shader_3D_groundline_geom_glsl[]; + extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl[]; extern char datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl[]; @@ -94,6 +105,8 @@ extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[]; extern char datatoc_gpu_shader_edges_overlay_frag_glsl[]; extern char datatoc_gpu_shader_text_vert_glsl[]; extern char datatoc_gpu_shader_text_frag_glsl[]; +extern char datatoc_gpu_shader_keyframe_diamond_vert_glsl[]; +extern char datatoc_gpu_shader_keyframe_diamond_frag_glsl[]; extern char datatoc_gpu_shader_fire_frag_glsl[]; extern char datatoc_gpu_shader_smoke_vert_glsl[]; @@ -512,11 +525,24 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name) return glGetUniformLocation(shader->program, name); } +int GPU_shader_get_uniform_block(GPUShader *shader, const char *name) +{ + BLI_assert(shader && shader->program); + + return glGetUniformBlockIndex(shader->program, name); +} + void *GPU_shader_get_interface(GPUShader *shader) { return shader->uniform_interface; } +/* Clement : Temp */ +int GPU_shader_get_program(GPUShader *shader) +{ + return (int)shader->program; +} + void GPU_shader_set_interface(GPUShader *shader, void *interface) { shader->uniform_interface = interface; @@ -564,6 +590,17 @@ void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int ou } } +void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo) +{ + int bindpoint = GPU_uniformbuffer_bindpoint(ubo); + + if (location == -1) { + return; + } + + glUniformBlockBinding(shader->program, location, bindpoint); +} + void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex) { int number = GPU_texture_bound_number(tex); @@ -615,6 +652,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_SMOKE_COBA] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl }, [GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl, datatoc_gpu_shader_text_frag_glsl }, + [GPU_SHADER_KEYFRAME_DIAMOND] = { datatoc_gpu_shader_keyframe_diamond_vert_glsl, + datatoc_gpu_shader_keyframe_diamond_frag_glsl }, [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = { datatoc_gpu_shader_edges_front_back_persp_vert_glsl, /* this version is */ datatoc_gpu_shader_flat_color_frag_glsl, /* magical but slooow */ datatoc_gpu_shader_edges_front_back_persp_geom_glsl }, @@ -625,6 +664,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_EDGES_OVERLAY] = { datatoc_gpu_shader_edges_overlay_vert_glsl, datatoc_gpu_shader_edges_overlay_frag_glsl, datatoc_gpu_shader_edges_overlay_geom_glsl }, + [GPU_SHADER_SIMPLE_LIGHTING] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_simple_lighting_frag_glsl }, [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_image_vert_glsl, datatoc_gpu_shader_image_mask_uniform_color_frag_glsl }, @@ -635,8 +675,9 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_3D_IMAGE_DEPTH] = { datatoc_gpu_shader_3D_image_vert_glsl, datatoc_gpu_shader_image_depth_linear_frag_glsl }, - [GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_interlace_frag_glsl }, + [GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_interlace_frag_glsl }, + [GPU_SHADER_2D_CHECKER] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_checker_frag_glsl }, [GPU_SHADER_2D_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, [GPU_SHADER_2D_FLAT_COLOR] = { datatoc_gpu_shader_2D_flat_color_vert_glsl, @@ -651,9 +692,17 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl, datatoc_gpu_shader_3D_smooth_color_frag_glsl }, [GPU_SHADER_3D_DEPTH_ONLY] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_depth_only_frag_glsl }, + + [GPU_SHADER_3D_GROUNDPOINT] = { datatoc_gpu_shader_3D_groundpoint_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl }, + [GPU_SHADER_3D_GROUNDLINE] = { datatoc_gpu_shader_3D_passthrough_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, + datatoc_gpu_shader_3D_groundline_geom_glsl }, [GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl }, [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] = @@ -683,11 +732,17 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH] = { datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl, datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl }, + + [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = { datatoc_gpu_shader_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] = + { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, }; if (builtin_shaders[shader] == NULL) { /* just a few special cases */ - const char *defines = (shader == GPU_SHADER_SMOKE_COBA) ? "#define USE_COBA;\n" : NULL; + const char *defines = (shader == GPU_SHADER_SMOKE_COBA) ? "#define USE_COBA;\n" : + (shader == GPU_SHADER_SIMPLE_LIGHTING) ? "#define USE_NORMALS;\n" : NULL; const GPUShaderStages *stages = builtin_shader_stages + shader; @@ -699,6 +754,14 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) stages = &legacy_fancy_edges; } + if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP && !GLEW_VERSION_3_2) { + /* TODO: remove after switch to core profile (maybe) */ + static const GPUShaderStages legacy_fancy_edges = + { datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl, + datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl }; + stages = &legacy_fancy_edges; + } + /* common case */ builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, defines, 0, 0, 0); diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 6956a815ac5..3513250993e 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -49,9 +49,8 @@ static struct GPUTextureGlobal { } GG = {NULL, NULL, NULL}; /* GPUTexture */ - struct GPUTexture { - int w, h; /* width/height */ + int w, h, d; /* width/height/depth */ int number; /* number for multitexture binding */ int refcount; /* reference count */ GLenum target; /* GL_TEXTURE_* */ @@ -62,42 +61,162 @@ struct GPUTexture { GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */ int fb_attachment; /* slot the texture is attached to */ - int depth; /* is a depth texture? if 3D how deep? */ + bool depth; /* is a depth texture? */ }; -static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels) +static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, GLenum *format, bool *is_depth) { - unsigned char *pixels, *p; - const float *fp = fpixels; - const int len = 4 * length; + if (data_type == GPU_DEPTH_COMPONENT24 || + data_type == GPU_DEPTH_COMPONENT16 || + data_type == GPU_DEPTH_COMPONENT32F) + { + *is_depth = true; + *format = GL_DEPTH_COMPONENT; + } + else { + *is_depth = false; + + switch (components) { + case 1: *format = GL_RED; break; + case 2: *format = GL_RG; break; + case 3: *format = GL_RGB; break; + case 4: *format = GL_RGBA; break; + default: break; + } + } - p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels"); + /* You can add any of the available type to this list + * For available types see GPU_texture.h */ + switch (data_type) { + /* Formats texture & renderbuffer */ + case GPU_RGBA16F: return GL_RGBA16F; + case GPU_RG32F: return GL_RG32F; + case GPU_RG16F: return GL_RG16F; + case GPU_RGBA8: return GL_RGBA8; + case GPU_R8: return GL_R8; + /* Special formats texture & renderbuffer */ + /* ** Add Format here **/ + /* Texture only format */ + /* ** Add Format here **/ + /* Special formats texture only */ + /* ** Add Format here **/ + /* Depth Formats */ + case GPU_DEPTH_COMPONENT32F: return GL_DEPTH_COMPONENT32F; + case GPU_DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT24; + case GPU_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT16; + default: + fprintf(stderr, "Texture format incorrect or unsupported\n"); + return 0; + } +} - for (int a = 0; a < len; a++, p++, fp++) - *p = FTOCHAR((*fp)); +static float *GPU_texture_3D_rescale(GPUTexture *tex, int w, int h, int d, int channels, const float *fpixels) +{ + const unsigned int xf = w / tex->w, yf = h / tex->h, zf = d / tex->d; + float *nfpixels = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->d, "GPUTexture Rescaled 3Dtex"); - return pixels; + if (nfpixels) { + GPU_print_error_debug("You need to scale a 3D texture, feel the pain!"); + + for (unsigned k = 0; k < tex->d; k++) { + for (unsigned j = 0; j < tex->h; j++) { + for (unsigned i = 0; i < tex->w; i++) { + /* obviously doing nearest filtering here, + * it's going to be slow in any case, let's not make it worse */ + float xb = i * xf; + float yb = j * yf; + float zb = k * zf; + unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j; + unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb); + + if (channels == 4) { + nfpixels[offset * 4] = fpixels[offset_orig * 4]; + nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1]; + nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2]; + nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3]; + } + else + nfpixels[offset] = fpixels[offset_orig]; + } + } + } + } + + return nfpixels; } -static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h) +/* This tries to allocate video memory for a given texture + * If alloc fails, lower the resolution until it fits. */ +static bool GPU_texture_try_alloc( + GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum format, int channels, + bool try_rescale, const float *fpixels, float **rescaled_fpixels) { - void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels"); + int r_width; - if (target == GL_TEXTURE_1D) - glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels); - else - glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels); - - MEM_freeN(pixels); + switch (proxy) { + case GL_PROXY_TEXTURE_1D: + glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL); + break; + case GL_PROXY_TEXTURE_2D: + glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL); + break; + case GL_PROXY_TEXTURE_3D: + glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL); + break; + } + + glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &r_width); + + if (r_width == 0 && try_rescale) { + const int w = tex->w, h = tex->h, d = tex->d; + + /* Find largest texture possible */ + while (r_width == 0) { + tex->w /= 2; + tex->h /= 2; + tex->d /= 2; + + /* really unlikely to happen but keep this just in case */ + if (tex->w == 0) break; + if (tex->h == 0 && proxy != GL_PROXY_TEXTURE_1D) break; + if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) break; + + if (proxy == GL_PROXY_TEXTURE_1D) + glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL); + else if (proxy == GL_PROXY_TEXTURE_2D) + glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL); + else if (proxy == GL_PROXY_TEXTURE_3D) + glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL); + + glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); + } + + /* Rescale */ + if (r_width > 0) { + switch (proxy) { + case GL_PROXY_TEXTURE_1D: + case GL_PROXY_TEXTURE_2D: + /* Do nothing for now */ + return false; + case GL_PROXY_TEXTURE_3D: + *rescaled_fpixels = GPU_texture_3D_rescale(tex, w, h, d, channels, fpixels); + return (bool)*rescaled_fpixels; + } + } + } + + return (r_width > 0); } static GPUTexture *GPU_texture_create_nD( - int w, int h, int n, const float *fpixels, int depth, - GPUHDRType hdr_type, int components, int samples, - char err_out[256]) + int w, int h, int d, int n, const float *fpixels, + GPUTextureFormat data_type, int components, int samples, + const bool can_rescale, char err_out[256]) { - GLenum type, format, internalformat; - void *pixels = NULL; + GLenum format, internalformat, proxy; + float *rescaled_fpixels = NULL; + const float *pix; + bool valid; if (samples) { CLAMP_MAX(samples, GPU_max_color_texture_samples()); @@ -106,121 +225,99 @@ static GPUTexture *GPU_texture_create_nD( GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->w = w; tex->h = h; + tex->d = d; tex->number = -1; tex->refcount = 1; - tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D); - tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D; - tex->depth = depth; + + if (n == 1) { + if (h == 0) + tex->target_base = tex->target = GL_TEXTURE_1D; + else + tex->target_base = tex->target = GL_TEXTURE_1D_ARRAY; + } + else if (n == 2) { + if (d == 0) + tex->target_base = tex->target = GL_TEXTURE_2D; + else + tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY; + } + else if (n == 3) { + tex->target_base = tex->target = GL_TEXTURE_3D; + } + tex->fb_attachment = -1; + if (samples && n == 2 && d == 0) + tex->target = GL_TEXTURE_2D_MULTISAMPLE; + + internalformat = GPU_texture_get_format(components, data_type, &format, &tex->depth); + + /* Generate Texture object */ glGenTextures(1, &tex->bindcode); if (!tex->bindcode) { - if (err_out) { + if (err_out) BLI_snprintf(err_out, 256, "GPUTexture: texture create failed"); - } - else { + else fprintf(stderr, "GPUTexture: texture create failed"); - } GPU_texture_free(tex); return NULL; } -#if 0 /* this should be a compile-time check */ - if (!GPU_full_non_power_of_two_support()) { - tex->w = power_of_2_max_i(tex->w); - tex->h = power_of_2_max_i(tex->h); - } -#endif - tex->number = 0; glBindTexture(tex->target, tex->bindcode); - if (depth) { - type = GL_UNSIGNED_BYTE; - format = GL_DEPTH_COMPONENT; - internalformat = GL_DEPTH_COMPONENT; + /* Check if texture fit in VRAM */ + if (d > 0) { + proxy = GL_PROXY_TEXTURE_3D; + } + else if (h > 0) { + proxy = GL_PROXY_TEXTURE_2D; } else { - type = GL_FLOAT; - - if (components == 4) { - format = GL_RGBA; - switch (hdr_type) { - case GPU_HDR_NONE: - internalformat = GL_RGBA8; - break; - /* the following formats rely on ARB_texture_float or OpenGL 3.0 */ - case GPU_HDR_HALF_FLOAT: - internalformat = GL_RGBA16F_ARB; - break; - case GPU_HDR_FULL_FLOAT: - internalformat = GL_RGBA32F_ARB; - break; - default: - break; - } - } - else if (components == 2) { - /* these formats rely on ARB_texture_rg or OpenGL 3.0 */ - format = GL_RG; - switch (hdr_type) { - case GPU_HDR_NONE: - internalformat = GL_RG8; - break; - case GPU_HDR_HALF_FLOAT: - internalformat = GL_RG16F; - break; - case GPU_HDR_FULL_FLOAT: - internalformat = GL_RG32F; - break; - default: - break; - } - } - - if (fpixels && hdr_type == GPU_HDR_NONE) { - type = GL_UNSIGNED_BYTE; - pixels = GPU_texture_convert_pixels(w * h, fpixels); - } + proxy = GL_PROXY_TEXTURE_1D; } - if (tex->target == GL_TEXTURE_1D) { - glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL); + valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, components, can_rescale, fpixels, + &rescaled_fpixels); - if (fpixels) { - glTexSubImage1D(tex->target, 0, 0, w, format, type, - pixels ? pixels : fpixels); + if (!valid) { + if (err_out) + BLI_snprintf(err_out, 256, "GPUTexture: texture alloc failed"); + else + fprintf(stderr, "GPUTexture: texture alloc failed. Not enough Video Memory."); + GPU_texture_free(tex); + return NULL; + } - if (tex->w > w) { - GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1); - } - } + /* Upload Texture */ + pix = (rescaled_fpixels) ? rescaled_fpixels : fpixels; + + if (tex->target == GL_TEXTURE_1D) { + glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, GL_FLOAT, pix); } - else { + else if (tex->target == GL_TEXTURE_1D_ARRAY || + tex->target == GL_TEXTURE_2D || + tex->target == GL_TEXTURE_2D_MULTISAMPLE) + { if (samples) { glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true); + if (pix) + glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, GL_FLOAT, pix); } else { - glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, - format, type, NULL); - } - - if (fpixels) { - glTexSubImage2D(tex->target, 0, 0, 0, w, h, - format, type, pixels ? pixels : fpixels); - - if (tex->w > w) - GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h); - if (tex->h > h) - GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h); + glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, pix); } } + else { + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, pix); + } - if (pixels) - MEM_freeN(pixels); + if (rescaled_fpixels) + MEM_freeN(rescaled_fpixels); - if (depth) { + /* Texture Parameters */ + if (tex->depth) { glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); @@ -232,128 +329,14 @@ static GPUTexture *GPU_texture_create_nD( glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } - if (tex->target_base != GL_TEXTURE_1D) { - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + if (n > 1) { glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - else - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - - return tex; -} - - -GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels) -{ - GLenum type, format, internalformat; - void *pixels = NULL; - - GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); - tex->w = w; - tex->h = h; - tex->depth = depth; - tex->number = -1; - tex->refcount = 1; - tex->target = GL_TEXTURE_3D; - tex->target_base = GL_TEXTURE_3D; - - glGenTextures(1, &tex->bindcode); - - if (!tex->bindcode) { - fprintf(stderr, "GPUTexture: texture create failed"); - GPU_texture_free(tex); - return NULL; - } - - tex->number = 0; - glBindTexture(tex->target, tex->bindcode); - - type = GL_FLOAT; - if (channels == 4) { - format = GL_RGBA; - internalformat = GL_RGBA8; - } - else { - format = GL_RED; - internalformat = GL_INTENSITY8; + if (n > 2) { + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); } - /* 3D textures are quite heavy, test if it's possible to create them first */ - glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); - - bool rescale = false; - int r_width; - - glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); - - while (r_width == 0) { - rescale = true; - tex->w /= 2; - tex->h /= 2; - tex->depth /= 2; - glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); - glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); - } - - /* really unlikely to happen but keep this just in case */ - tex->w = max_ii(tex->w, 1); - tex->h = max_ii(tex->h, 1); - tex->depth = max_ii(tex->depth, 1); - -#if 0 - if (fpixels) - pixels = GPU_texture_convert_pixels(w*h*depth, fpixels); -#endif - - /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it - * for gooseberry */ - if (rescale && fpixels) { - /* FIXME: should these be floating point? */ - const unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth; - float *tex3d = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->depth, "tex3d"); - - GPU_print_error_debug("You need to scale a 3D texture, feel the pain!"); - - for (unsigned k = 0; k < tex->depth; k++) { - for (unsigned j = 0; j < tex->h; j++) { - for (unsigned i = 0; i < tex->w; i++) { - /* obviously doing nearest filtering here, - * it's going to be slow in any case, let's not make it worse */ - float xb = i * xf; - float yb = j * yf; - float zb = k * zf; - unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j; - unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb); - - if (channels == 4) { - tex3d[offset * 4] = fpixels[offset_orig * 4]; - tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1]; - tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2]; - tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3]; - } - else - tex3d[offset] = fpixels[offset_orig]; - } - } - } - - glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d); - - MEM_freeN(tex3d); - } - else if (fpixels) { - glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels); - } - - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - if (pixels) - MEM_freeN(pixels); - GPU_texture_unbind(tex); return tex; @@ -464,114 +447,64 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap) } -GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256]) +GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]) { - GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out); - - if (tex) - GPU_texture_unbind(tex); - - return tex; + return GPU_texture_create_nD(w, 0, 0, 1, pixels, GPU_RGBA8, 4, 0, false, err_out); } -GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256]) +GPUTexture *GPU_texture_create_1D_custom( + int w, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]) { - GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out); - - if (tex) - GPU_texture_unbind(tex); - - return tex; + return GPU_texture_create_nD(w, 0, 0, 1, pixels, data_type, channels, 0, false, err_out); } -GPUTexture *GPU_texture_create_2D_multisample( - int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256]) -{ - GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out); - if (tex) - GPU_texture_unbind(tex); - - return tex; +GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, char err_out[256]) +{ + return GPU_texture_create_nD(w, h, 0, 2, pixels, GPU_RGBA8, 4, 0, false, err_out); } -GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]) +GPUTexture *GPU_texture_create_2D_custom( + int w, int h, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]) { - GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out); - - if (tex) - GPU_texture_unbind(tex); - - return tex; + return GPU_texture_create_nD(w, h, 0, 2, pixels, data_type, channels, 0, false, err_out); } -GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]) -{ - GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out); - - if (tex) - GPU_texture_unbind(tex); - return tex; +GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, int samples, char err_out[256]) +{ + return GPU_texture_create_nD(w, h, 0, 2, pixels, GPU_RGBA8, 4, samples, false, err_out); } -/** - * A shadow map for VSM needs two components (depth and depth^2) - */ -GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]) +GPUTexture *GPU_texture_create_2D_array(int w, int h, int d, const float *pixels, char err_out[256]) { - GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out); - - if (tex) { - /* Now we tweak some of the settings */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - GPU_texture_unbind(tex); - } - - return tex; + return GPU_texture_create_nD(w, h, d, 2, pixels, GPU_RGBA8, 4, 0, false, err_out); } -GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]) +GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char err_out[256]) { - GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out); - - if (tex) { - /* Now we tweak some of the settings */ - if (repeat) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - GPU_texture_unbind(tex); - } - - return tex; + return GPU_texture_create_nD(w, h, d, 3, pixels, GPU_RGBA8, 4, 0, true, err_out); } -GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]) +GPUTexture *GPU_texture_create_3D_custom(int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]) { - GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out); - - if (tex) { - /* Now we tweak some of the settings */ - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + return GPU_texture_create_nD(w, h, d, 3, pixels, data_type, channels, 0, true, err_out); +} - GPU_texture_unbind(tex); - } +GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]) +{ + return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, 0, false, err_out); +} - return tex; +GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]) +{ + return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, samples, false, err_out); } void GPU_invalid_tex_init(void) { const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL); - GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL); - GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color); + GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, NULL); + GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, color, NULL); } void GPU_invalid_tex_bind(int mode) @@ -624,7 +557,13 @@ void GPU_texture_bind(GPUTexture *tex, int number) else GPU_invalid_tex_bind(tex->target_base); - glEnable(tex->target_base); /* TODO: remove this line once we're using GLSL everywhere */ + /* TODO: remove this lines once we're using GLSL everywhere */ + GLenum target = tex->target_base; + if (tex->target_base == GL_TEXTURE_1D_ARRAY) + target = GL_TEXTURE_2D; + if (tex->target_base == GL_TEXTURE_2D_ARRAY) + target = GL_TEXTURE_3D; + glEnable(target); if (number != 0) glActiveTexture(GL_TEXTURE0); @@ -646,7 +585,14 @@ void GPU_texture_unbind(GPUTexture *tex) glActiveTexture(GL_TEXTURE0 + tex->number); glBindTexture(tex->target_base, 0); - glDisable(tex->target_base); /* TODO: remove this line */ + + /* TODO: remove this lines */ + GLenum target = tex->target_base; + if (tex->target_base == GL_TEXTURE_1D_ARRAY) + target = GL_TEXTURE_2D; + if (tex->target_base == GL_TEXTURE_2D_ARRAY) + target = GL_TEXTURE_3D; + glDisable(target); if (tex->number != 0) glActiveTexture(GL_TEXTURE0); @@ -659,7 +605,7 @@ int GPU_texture_bound_number(GPUTexture *tex) return tex->number; } -void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter) +void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare) { if (tex->number >= GPU_max_textures()) { fprintf(stderr, "Not enough texture slots.\n"); @@ -672,13 +618,54 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter) if (tex->number != 0) glActiveTexture(GL_TEXTURE0 + tex->number); - if (tex->depth) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE); + /* TODO viewport: use GL_COMPARE_REF_TO_TEXTURE after we switch to core profile */ + if (tex->depth) + glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, use_compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE); + + if (tex->number != 0) + glActiveTexture(GL_TEXTURE0); +} + +void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter) +{ + if (tex->number >= GPU_max_textures()) { + fprintf(stderr, "Not enough texture slots.\n"); + return; } + if (tex->number == -1) + return; + + if (tex->number != 0) + glActiveTexture(GL_TEXTURE0 + tex->number); + GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter); + + if (tex->number != 0) + glActiveTexture(GL_TEXTURE0); +} + +void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat) +{ + if (tex->number >= GPU_max_textures()) { + fprintf(stderr, "Not enough texture slots.\n"); + return; + } + + if (tex->number == -1) + return; + + if (tex->number != 0) + glActiveTexture(GL_TEXTURE0 + tex->number); + + GLenum repeat = use_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE; + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat); + if (tex->target_base != GL_TEXTURE_1D) + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat); + if (tex->target_base == GL_TEXTURE_3D) + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat); if (tex->number != 0) glActiveTexture(GL_TEXTURE0); diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c new file mode 100644 index 00000000000..76aa1a8226f --- /dev/null +++ b/source/blender/gpu/intern/gpu_uniformbuffer.c @@ -0,0 +1,105 @@ +/* + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Clement Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file gpu_uniformbuffer.c + * \ingroup gpu + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "GPU_extensions.h" +#include "GPU_glew.h" +#include "GPU_uniformbuffer.h" + +struct GPUUniformBuffer { + int size; /* in bytes */ + GLuint bindcode; /* opengl identifier for UBO */ + int bindpoint; /* current binding point */ +}; + +GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]) +{ + GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBuffer), "GPUUniformBuffer"); + ubo->size = size; + + /* Generate Buffer object */ + glGenBuffers(1, &ubo->bindcode); + + if (!ubo->bindcode) { + if (err_out) + BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed"); + GPU_uniformbuffer_free(ubo); + return NULL; + } + + if (ubo->size > GPU_max_ubo_size()) { + if (err_out) + BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big"); + GPU_uniformbuffer_free(ubo); + return NULL; + } + + glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode); + glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + return ubo; +} + +void GPU_uniformbuffer_free(GPUUniformBuffer *ubo) +{ + glDeleteBuffers(1, &ubo->bindcode); + MEM_freeN(ubo); +} + +void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data) +{ + glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode); + glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo->size, data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); +} + +void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number) +{ + if (number >= GPU_max_ubo_binds()) { + fprintf(stderr, "Not enough UBO slots.\n"); + return; + } + + if (ubo->bindcode != 0) { + glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode); + } + + ubo->bindpoint = number; +} + +int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo) +{ + return ubo->bindpoint; +}
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 2f91adde133..62ba06b7a0a 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -31,10 +31,20 @@ * System that manages viewport drawing. */ +#include <string.h> + +#include "BLI_rect.h" +#include "BLI_string.h" + +#include "DNA_vec_types.h" + +#include "GPU_framebuffer.h" #include "GPU_glew.h" #include "GPU_immediate.h" -#include "GPU_viewport.h" #include "GPU_texture.h" +#include "GPU_viewport.h" + +#include "DRW_engine.h" #include "MEM_guardedalloc.h" @@ -43,26 +53,235 @@ struct GPUViewport { /* debug */ GPUTexture *debug_depth; - int debug_width, debug_height; + int size[2]; + + /* Viewport Buffer Storage */ + /* TODO indentify to what engine conf are theses buffers */ + DefaultFramebufferList *fbl; + DefaultTextureList *txl; + DefaultPassList *psl; + StorageList *stl; + + char engine_name[32]; }; +static void GPU_viewport_buffers_free(GPUViewport *viewport); +static void GPU_viewport_passes_free(GPUViewport *viewport); +static void GPU_viewport_storage_free(GPUViewport *viewport); + GPUViewport *GPU_viewport_create(void) { GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport"); + viewport->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList"); + viewport->txl = MEM_callocN(sizeof(TextureList), "TextureList"); + viewport->psl = MEM_callocN(sizeof(PassList), "PassList"); + viewport->stl = MEM_callocN(sizeof(StorageList), "StorageList"); + viewport->size[0] = viewport->size[1] = -1; + return viewport; } +void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss, void **str) +{ + *fbs = viewport->fbl; + *txs = viewport->txl; + *pss = viewport->psl; + *str = viewport->stl; +} + +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine) +{ + /* add one pixel because of scissor test */ + int rect_w = BLI_rcti_size_x(rect) + 1, rect_h = BLI_rcti_size_y(rect) + 1; + +#ifndef WITH_VIEWPORT_CACHE_TEST + /* TODO for testing only, we need proper cache invalidation */ + GPU_viewport_passes_free(viewport); +#endif + + if (!STREQ(engine, viewport->engine_name)) { + GPU_viewport_storage_free(viewport); + GPU_viewport_buffers_free(viewport); + + BLI_strncpy(viewport->engine_name, engine, 32); + } + + if (viewport->fbl->default_fb) { + if (rect_w != viewport->size[0] || rect_h != viewport->size[1]) { + GPU_viewport_buffers_free(viewport); + } + } + + if (!viewport->fbl->default_fb) { + bool ok = true; + viewport->size[0] = rect_w; + viewport->size[1] = rect_h; + + viewport->fbl->default_fb = GPU_framebuffer_create(); + if (!viewport->fbl->default_fb) { + ok = false; + goto cleanup; + } + + /* Color */ + /* No multi samples for now */ + viewport->txl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL); + if (!viewport->txl->color) { + ok = false; + goto cleanup; + } + + if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->color, 0)) { + ok = false; + goto cleanup; + } + + /* Depth */ + viewport->txl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL); + if (!viewport->txl->depth) { + ok = false; + goto cleanup; + } + else if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->depth, 0)) { + ok = false; + goto cleanup; + } + else if (!GPU_framebuffer_check_valid(viewport->fbl->default_fb, NULL)) { + ok = false; + goto cleanup; + } + +cleanup: + if (!ok) { + GPU_viewport_free(viewport); + MEM_freeN(viewport); + return; + } + + GPU_framebuffer_restore(); + } + + GPU_framebuffer_slots_bind(viewport->fbl->default_fb, 0); +} + +static void draw_ofs_to_screen(GPUViewport *viewport) +{ + GPUTexture *color = viewport->txl->color; + + const float w = (float)GPU_texture_width(color); + const float h = (float)GPU_texture_height(color); + + VertexFormat *format = immVertexFormat(); + unsigned texcoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); + + GPU_texture_bind(color, 0); + + immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ + + immBegin(GL_QUADS, 4); + + immAttrib2f(texcoord, 0.0f, 0.0f); + immVertex2f(pos, 0.0f, 0.0f); + + immAttrib2f(texcoord, 1.0f, 0.0f); + immVertex2f(pos, w, 0.0f); + + immAttrib2f(texcoord, 1.0f, 1.0f); + immVertex2f(pos, w, h); + + immAttrib2f(texcoord, 0.0f, 1.0f); + immVertex2f(pos, 0.0f, h); + + immEnd(); + + GPU_texture_unbind(color); + + immUnbindProgram(); +} + +void GPU_viewport_unbind(GPUViewport *viewport) +{ + if (viewport->fbl->default_fb) { + GPU_framebuffer_texture_unbind(NULL, NULL); + GPU_framebuffer_restore(); + + glEnable(GL_SCISSOR_TEST); + + /* This might be bandwidth limiting */ + draw_ofs_to_screen(viewport); + } +} + +static void GPU_viewport_buffers_free(GPUViewport *viewport) +{ + FramebufferList *fbl = (FramebufferList *)viewport->fbl; + TextureList *txl = (TextureList *)viewport->txl; + int i; + for (i = MAX_BUFFERS - 1; i > -1; --i) { + GPUFrameBuffer *fb = fbl->framebuffers[i]; + if (fb) { + GPU_framebuffer_free(fb); + fbl->framebuffers[i] = NULL; + } + } + for (i = MAX_TEXTURES - 1; i > -1; --i) { + GPUTexture *tex = txl->textures[i]; + if (tex) { + GPU_texture_free(tex); + txl->textures[i] = NULL; + } + } +} + +static void GPU_viewport_storage_free(GPUViewport *viewport) +{ + StorageList *stl = (StorageList *)viewport->stl; + + for (int i = MAX_STORAGE - 1; i > -1; --i) { + void *storage = stl->storage[i]; + if (storage) { + MEM_freeN(storage); + stl->storage[i] = NULL; + } + } +} + +static void GPU_viewport_passes_free(GPUViewport *viewport) +{ + PassList *psl = (PassList *)viewport->psl; + int i; + + for (i = MAX_PASSES - 1; i > -1; --i) { + struct DRWPass *pass = psl->passes[i]; + if (pass) { + DRW_pass_free(pass); + MEM_freeN(pass); + psl->passes[i] = NULL; + } + } +} + void GPU_viewport_free(GPUViewport *viewport) { GPU_viewport_debug_depth_free(viewport); - MEM_freeN(viewport); + GPU_viewport_buffers_free(viewport); + GPU_viewport_passes_free(viewport); + GPU_viewport_storage_free(viewport); + + MEM_freeN(viewport->fbl); + MEM_freeN(viewport->txl); + MEM_freeN(viewport->psl); + MEM_freeN(viewport->stl); } /****************** debug ********************/ bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]) { - viewport->debug_depth = GPU_texture_create_2D(width, height, NULL, GPU_HDR_HALF_FLOAT, err_out); + viewport->debug_depth = GPU_texture_create_2D_custom(width, height, 4, GPU_RGBA16F, NULL, err_out); return (viewport->debug_depth != NULL); } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl new file mode 100644 index 00000000000..f16fa21b342 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl @@ -0,0 +1,16 @@ + +/* Make to be used with dynamic batching so no Model Matrix needed */ +uniform mat4 ViewProjectionMatrix; + +layout(points) in; +layout(line_strip, max_vertices = 2) out; + +void main() +{ + vec3 vert = gl_in[0].gl_Position.xyz; + gl_Position = ViewProjectionMatrix * vec4(vert.xyz, 1.0); + EmitVertex(); + gl_Position = ViewProjectionMatrix * vec4(vert.xy, 0.0, 1.0); + EmitVertex(); + EndPrimitive(); +} diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl new file mode 100644 index 00000000000..55f410eb25d --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl @@ -0,0 +1,11 @@ + +/* Made to be used with dynamic batching so no Model Matrix needed */ +uniform mat4 ViewProjectionMatrix; + +in vec3 pos; + +void main() +{ + gl_Position = ViewProjectionMatrix * vec4(pos.xy, 0.0, 1.0); + gl_PointSize = 2.0; +} diff --git a/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl new file mode 100644 index 00000000000..60793bf56b6 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl @@ -0,0 +1,8 @@ + +/* Does Nothing */ +in vec3 pos; + +void main() +{ + gl_Position = vec4(pos, 1.0); +} diff --git a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl index 32da3a99c63..58150c004e5 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl @@ -1,13 +1,27 @@ uniform mat4 ModelViewProjectionMatrix; +#ifdef USE_NORMALS +uniform mat3 NormalMatrix; +#endif #if __VERSION__ == 120 attribute vec3 pos; +#ifdef USE_NORMALS + attribute vec3 nor; + varying vec3 normal; +#endif #else in vec3 pos; +#ifdef USE_NORMALS + in vec3 nor; + out vec3 normal; +#endif #endif void main() { +#ifdef USE_NORMALS + normal = normalize(NormalMatrix * nor); +#endif gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); } diff --git a/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl new file mode 100644 index 00000000000..3b24af916a0 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl @@ -0,0 +1,24 @@ + +uniform vec4 color1; +uniform vec4 color2; +uniform int size; + +#if __VERSION__ == 120 + #define fragColor gl_FragColor +#else + out vec4 fragColor; +#endif + +void main() +{ + vec2 phase = mod(gl_FragCoord.xy, (size*2)); + + if ((phase.x > size && phase.y < size) || + (phase.x < size && phase.y > size)) + { + fragColor = color1; + } + else { + fragColor = color2; + } +} diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl new file mode 100644 index 00000000000..ba0ac29fb79 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl @@ -0,0 +1,29 @@ + +uniform mat4 ViewProjectionMatrix; +uniform vec3 screen_vecs[2]; +uniform float size; +uniform float pixel_size; + +/* ---- Instanciated Attribs ---- */ +in vec2 pos; + +/* ---- Per instance Attribs ---- */ +in vec3 world_pos; +in vec3 color; + +flat out vec4 finalColor; + +float mul_project_m4_v3_zfac(in vec3 co) +{ + return (ViewProjectionMatrix[0][3] * co.x) + + (ViewProjectionMatrix[1][3] * co.y) + + (ViewProjectionMatrix[2][3] * co.z) + ViewProjectionMatrix[3][3]; +} + +void main() +{ + float pix_size = mul_project_m4_v3_zfac(world_pos) * pixel_size; + vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; + gl_Position = ViewProjectionMatrix * vec4(world_pos + screen_pos * size * pix_size, 1.0); + finalColor = vec4(color, 1.0); +} diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl new file mode 100644 index 00000000000..9ade68644fe --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl @@ -0,0 +1,18 @@ + +uniform mat4 ViewProjectionMatrix; + +/* ---- Instanciated Attribs ---- */ +in vec3 pos; + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec3 color; +in float size; + +flat out vec4 finalColor; + +void main() +{ + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * size, 1.0); + finalColor = vec4(color, 1.0); +} diff --git a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl new file mode 100644 index 00000000000..eac167e8045 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl @@ -0,0 +1,13 @@ + +uniform mat4 ViewProjectionMatrix; + +/* ---- Instanciated Attribs ---- */ +in vec3 pos; + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; + +void main() +{ + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0); +} diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl new file mode 100644 index 00000000000..43a7e42153a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl @@ -0,0 +1,38 @@ + +#if __VERSION__ == 120 + varying vec4 radii; + varying vec4 finalColor; + varying vec4 finalOutlineColor; + #define fragColor gl_FragColor +#else + in vec4 radii; + in vec4 finalColor; + in vec4 finalOutlineColor; + out vec4 fragColor; +#endif + +void main() { + vec2 quad = abs(gl_PointCoord - vec2(0.5)); + float dist = quad.x + quad.y; + +// transparent outside of point +// --- 0 --- +// smooth transition +// --- 1 --- +// pure outline color +// --- 2 --- +// smooth transition +// --- 3 --- +// pure point color +// ... +// dist = 0 at center of point + + float mid_stroke = 0.5 * (radii[1] + radii[2]); + + vec4 backgroundColor = vec4(finalColor.rgb, 0.0); + + if (dist > mid_stroke) + fragColor = mix(finalOutlineColor, backgroundColor, smoothstep(radii[1], radii[0], dist)); + else + fragColor = mix(finalColor, finalOutlineColor, smoothstep(radii[3], radii[2], dist)); +} diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl new file mode 100644 index 00000000000..69afefa685f --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl @@ -0,0 +1,44 @@ + +uniform mat4 ModelViewProjectionMatrix; + +const float pixel_fudge = sqrt(2.0); +const float outline_width = 1.25 * pixel_fudge; + +#if __VERSION__ == 120 + attribute vec2 pos; + attribute float size; + attribute vec4 color; + attribute vec4 outlineColor; + varying vec4 finalColor; + varying vec4 finalOutlineColor; + varying vec4 radii; +#else + in vec2 pos; + in float size; + in vec4 color; + in vec4 outlineColor; + out vec4 finalColor; + out vec4 finalOutlineColor; + out vec4 radii; +#endif + +void main() { + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + + // pass through unchanged + gl_PointSize = size; + finalColor = color; + finalOutlineColor = outlineColor; + + // calculate concentric radii in pixels + float radius = 0.5 * gl_PointSize; + + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - pixel_fudge; + radii[2] = radius - outline_width; + radii[3] = radius - outline_width - pixel_fudge; + + // convert to PointCoord units + radii /= size; +} diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index aa583c5ecf8..0f3ffa8244b 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -3536,6 +3536,8 @@ void node_light_path( out float is_transmission_ray, out float ray_length, out float ray_depth, + out float diffuse_depth, + out float glossy_depth, out float transparent_depth, out float transmission_depth) { @@ -3548,6 +3550,8 @@ void node_light_path( is_transmission_ray = 0.0; ray_length = 1.0; ray_depth = 1.0; + diffuse_depth = 1.0; + glossy_depth = 1.0; transparent_depth = 1.0; transmission_depth = 1.0; } diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl new file mode 100644 index 00000000000..9828787fb04 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl @@ -0,0 +1,16 @@ + +uniform vec4 color; +uniform vec3 light; + +#if __VERSION__ == 120 + varying vec3 normal; + #define fragColor gl_FragColor +#else + in vec3 normal; + out vec4 fragColor; +#endif + +void main() +{ + fragColor = color * max(0.0, dot(normalize(normal), light)); +} diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 52febe642a0..4164f5fa75d 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -77,6 +77,16 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha const char *from_colorspace, const char *to_colorspace, bool predivide); void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide); +void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace); void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace); @@ -185,6 +195,8 @@ void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_proc void IMB_colormanagement_processor_apply_pixel(struct ColormanageProcessor *cm_processor, float *pixel, int channels); void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height, int channels, bool predivide); +void IMB_colormanagement_processor_apply_byte(struct ColormanageProcessor *cm_processor, + unsigned char *buffer, int width, int height, int channels); void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor); /* ** OpenGL drawing routines using GLSL for color space transform ** */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index a45346279d9..48cba3e0800 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1555,21 +1555,25 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ typedef struct ProcessorTransformThread { ColormanageProcessor *cm_processor; - float *buffer; + unsigned char *byte_buffer; + float *float_buffer; int width; int start_line; int tot_line; int channels; bool predivide; + bool float_from_byte; } ProcessorTransformThread; typedef struct ProcessorTransformInit { ColormanageProcessor *cm_processor; - float *buffer; + unsigned char *byte_buffer; + float *float_buffer; int width; int height; int channels; bool predivide; + bool float_from_byte; } ProcessorTransformInitData; static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) @@ -1577,17 +1581,24 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; ProcessorTransformInitData *init_data = (ProcessorTransformInitData *) init_data_v; - int channels = init_data->channels; - int width = init_data->width; - bool predivide = init_data->predivide; + const int channels = init_data->channels; + const int width = init_data->width; + const bool predivide = init_data->predivide; + const bool float_from_byte = init_data->float_from_byte; - size_t offset = ((size_t)channels) * start_line * width; + const size_t offset = ((size_t)channels) * start_line * width; memset(handle, 0, sizeof(ProcessorTransformThread)); handle->cm_processor = init_data->cm_processor; - handle->buffer = init_data->buffer + offset; + if (init_data->byte_buffer != NULL) { + /* TODO(serge): Offset might be different for byte and float buffers. */ + handle->byte_buffer = init_data->byte_buffer + offset; + } + if (init_data->float_buffer != NULL) { + handle->float_buffer = init_data->float_buffer + offset; + } handle->width = width; @@ -1596,33 +1607,62 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int handle->channels = channels; handle->predivide = predivide; + handle->float_from_byte = float_from_byte; } static void *do_processor_transform_thread(void *handle_v) { ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; - float *buffer = handle->buffer; - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - bool predivide = handle->predivide; - - IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide); + unsigned char *byte_buffer = handle->byte_buffer; + float *float_buffer = handle->float_buffer; + const int channels = handle->channels; + const int width = handle->width; + const int height = handle->tot_line; + const bool predivide = handle->predivide; + const bool float_from_byte = handle->float_from_byte; + + if (float_from_byte) { + IMB_buffer_float_from_byte(float_buffer, byte_buffer, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, + true, + width, height, width, width); + IMB_colormanagement_processor_apply(handle->cm_processor, + float_buffer, + width, height, channels, + predivide); + } + else { + if (byte_buffer != NULL) { + IMB_colormanagement_processor_apply_byte(handle->cm_processor, + byte_buffer, + width, height, channels); + } + if (float_buffer != NULL) { + IMB_colormanagement_processor_apply(handle->cm_processor, + float_buffer, + width, height, channels, + predivide); + } + } return NULL; } -static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels, - ColormanageProcessor *cm_processor, bool predivide) +static void processor_transform_apply_threaded(unsigned char *byte_buffer, float *float_buffer, + const int width, const int height, const int channels, + ColormanageProcessor *cm_processor, + const bool predivide, const bool float_from_byte) { ProcessorTransformInitData init_data; init_data.cm_processor = cm_processor; - init_data.buffer = buffer; + init_data.byte_buffer = byte_buffer; + init_data.float_buffer = float_buffer; init_data.width = width; init_data.height = height; init_data.channels = channels; init_data.predivide = predivide; + init_data.float_from_byte = float_from_byte; IMB_processor_apply_threaded(height, sizeof(ProcessorTransformThread), &init_data, processor_transform_init_handle, do_processor_transform_thread); @@ -1631,8 +1671,10 @@ static void processor_transform_apply_threaded(float *buffer, int width, int hei /*********************** Color space transformation functions *************************/ /* convert the whole buffer from specified by name color space to another - internal implementation */ -static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace, - const char *to_colorspace, bool predivide, bool do_threaded) +static void colormanagement_transform_ex(unsigned char *byte_buffer, float *float_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace, + bool predivide, bool do_threaded) { ColormanageProcessor *cm_processor; @@ -1649,10 +1691,19 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); - if (do_threaded) - processor_transform_apply_threaded(buffer, width, height, channels, cm_processor, predivide); - else - IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide); + if (do_threaded) { + processor_transform_apply_threaded(byte_buffer, float_buffer, + width, height, channels, + cm_processor, predivide, false); + } + else { + if (byte_buffer != NULL) { + IMB_colormanagement_processor_apply_byte(cm_processor, byte_buffer, width, height, channels); + } + if (float_buffer != NULL) { + IMB_colormanagement_processor_apply(cm_processor, float_buffer, width, height, channels, predivide); + } + } IMB_colormanagement_processor_free(cm_processor); } @@ -1661,7 +1712,7 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide) { - colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); + colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); } /* convert the whole buffer from specified by name color space to another @@ -1670,7 +1721,54 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide) { - colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); + colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); +} + +/* Similar to functions above, but operates on byte buffer. */ +void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, false); +} +void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, true); +} + +/* Similar to above, but gets float buffer from display one. */ +void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + IMB_buffer_float_from_byte(float_buffer, byte_buffer, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, + true, + width, height, width, width); + IMB_colormanagement_transform(float_buffer, + width, height, channels, + from_colorspace, to_colorspace, + true); +} +void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + ColormanageProcessor *cm_processor; + if (from_colorspace == NULL || from_colorspace[0] == '\0') { + return; + } + if (STREQ(from_colorspace, to_colorspace)) { + /* If source and destination color spaces are identical, skip + * threading overhead and simply do nothing + */ + return; + } + cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); + processor_transform_apply_threaded(byte_buffer, float_buffer, + width, height, channels, + cm_processor, true, true); + IMB_colormanagement_processor_free(cm_processor); } void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace) @@ -1974,12 +2072,14 @@ void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float); float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space"); + /* TODO(sergey): Convert float directly to byte buffer. */ + memcpy(display_buffer_float, buffer, float_buffer_size); cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - processor_transform_apply_threaded(display_buffer_float, width, height, channels, - cm_processor, true); + processor_transform_apply_threaded(NULL, display_buffer_float, width, height, channels, + cm_processor, true, false); IMB_buffer_byte_from_float(display_buffer, display_buffer_float, channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, @@ -3100,6 +3200,25 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo } } +void IMB_colormanagement_processor_apply_byte(ColormanageProcessor *cm_processor, + unsigned char *buffer, + int width, int height, int channels) +{ + /* TODO(sergey): Would be nice to support arbitrary channels configurations, + * but for now it's not so important. + */ + BLI_assert(channels == 4); + float pixel[4]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + size_t offset = channels * (((size_t)y) * width + x); + rgba_uchar_to_float(pixel, buffer + offset); + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + rgba_float_to_uchar(buffer + offset, pixel); + } + } +} + void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) { if (cm_processor->curve_mapping) diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h new file mode 100644 index 00000000000..bd456b526c7 --- /dev/null +++ b/source/blender/makesdna/DNA_layer_types.h @@ -0,0 +1,160 @@ +/* + * ***** 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): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file DNA_layer_types.h + * \ingroup DNA + */ + +#ifndef __DNA_LAYER_TYPES_H__ +#define __DNA_LAYER_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "DNA_listBase.h" + +typedef struct Base { + struct Base *next, *prev; + short flag; + short refcount; + short sx, sy; + struct Object *object; + unsigned int selcol; + unsigned int lay; + int flag_legacy; + int pad; +} Base; + +typedef struct CollectionOverride { + struct CollectionOverride *next, *prev; + char name[64]; /* MAX_NAME */ + /* TODO proper data */ +} CollectionOverride; + +typedef struct LayerCollection { + struct LayerCollection *next, *prev; + struct SceneCollection *scene_collection; + short flag; + short pad[3]; + ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects and collection->filter_objects */ + ListBase overrides; + ListBase layer_collections; /* synced with collection->collections */ + ListBase engine_settings; /* CollectionEngineSettings */ +} LayerCollection; + +typedef struct SceneLayer { + struct SceneLayer *next, *prev; + char name[64]; /* MAX_NAME */ + char engine[32]; /* render engine */ + short active_collection; + short flag; + short pad[2]; + ListBase object_bases; /* ObjectBase */ + struct Base *basact; + ListBase layer_collections; /* LayerCollection */ +} SceneLayer; + +typedef struct SceneCollection { + struct SceneCollection *next, *prev; + char name[64]; /* MAX_NAME */ + char filter[64]; /* MAX_NAME */ + int active_object_index; /* for UI */ + int pad; + ListBase objects; /* (Object *)LinkData->data */ + ListBase filter_objects; /* (Object *)LinkData->data */ + ListBase scene_collections; /* nested collections */ +} SceneCollection; + +/* Base->flag */ +enum { + BASE_SELECTED = (1 << 0), + BASE_VISIBLED = (1 << 1), + BASE_SELECTABLED = (1 << 2), + BASE_FROMDUPLI = (1 << 3), + BASE_DIRTY_ENGINE_SETTINGS = (1 << 4), +}; + +/* LayerCollection->flag */ +enum { + COLLECTION_VISIBLE = (1 << 0), + COLLECTION_SELECTABLE = (1 << 1), + COLLECTION_FOLDED = (1 << 2), +}; + +/* SceneLayer->flag */ +enum { + SCENE_LAYER_RENDER = (1 << 0), + SCENE_LAYER_ENGINE_DIRTY = (1 << 1), +}; + + +/* *************************************************************** */ +/* Engine Settings */ + +typedef struct CollectionEngineProperty { + struct CollectionEngineProperty *next, *prev; + char name[64]; /* MAX_NAME */ + short type; + short pad; + char flag; + char pad2[3]; +} CollectionEngineProperty; + +typedef struct CollectionEnginePropertyInt { + struct CollectionEngineProperty data; + int value; + int pad; +} CollectionEnginePropertyInt; + +typedef struct CollectionEnginePropertyFloat { + struct CollectionEngineProperty data; + float value; + float pad; +} CollectionEnginePropertyFloat; + +typedef struct CollectionEngineSettings { + struct CollectionEngineSettings *next, *prev; + char name[32]; /* engine name - MAX_NAME */ + ListBase properties; /* CollectionProperty */ +} CollectionEngineSettings; + +/* CollectionEngineProperty->flag */ +enum { + COLLECTION_PROP_USE = (1 << 0), +}; + +/* CollectionEntineProperty.type */ +typedef enum CollectionEnginePropertyType { + COLLECTION_PROP_TYPE_FLOAT = 0, + COLLECTION_PROP_TYPE_INT = 1, +} CollectionEnginePropertyType; + +/* *************************************************************** */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __DNA_LAYER_TYPES_H__ */ + diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 0c500e366a7..bd8278f897a 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -90,6 +90,43 @@ typedef struct TexPaintSlot { int pad; } TexPaintSlot; +/* Material Engine Settings */ +typedef struct MaterialEngineSettings { + struct MaterialEngineSettings *next, *prev; + char name[32]; /* engine name - MAX_NAME */ + void *data; +} MaterialEngineSettings; + +/* Clay engine */ + +/* MaterialRuntimeClay.flag */ +#define CLAY_OUTDATED 1 + +typedef struct MaterialEngineSettingsClay { + short type; + short matcap_icon; /* Icon ID */ + + float matcap_rot; + float matcap_hue; + float matcap_sat; + float matcap_val; + + float ssao_distance; + float ssao_attenuation; + float ssao_factor_cavity; + float ssao_factor_edge; + + /* Runtime */ + short flag; + short pad; + int ubo_index; +} MaterialEngineSettingsClay; + +/* MaterialEngineSettingsClay.type */ +#define CLAY_MATCAP_NONE 0 +#define CLAY_MATCAP_SIMPLE 1 +#define CLAY_MATCAP_COMPLETE 2 + typedef struct Material { ID id; struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */ @@ -203,6 +240,9 @@ typedef struct Material { struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use * with refresh_texpaint_image_cache */ + /* Engine Settings */ + ListBase engines_settings; /* MaterialEngineSettings */ + ListBase gpumaterial; /* runtime */ } Material; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index d24c7faa9f5..b92d2cd1573 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -46,6 +46,7 @@ struct Object; struct AnimData; struct Ipo; struct BoundBox; +struct CollectionEngineSettings; struct Path; struct Material; struct PartDeflect; @@ -223,7 +224,10 @@ typedef struct Object { float jump_speed; float fall_speed; unsigned char max_jumps; - char pad2[3]; + char pad2; + + /* Depsgraph */ + short base_flag; /* used by depsgraph, flushed from base */ /** Collision mask settings */ unsigned short col_group, col_mask; @@ -299,6 +303,8 @@ typedef struct Object { LodLevel *currentlod; struct PreviewImage *preview; + + struct CollectionEngineSettings *collection_settings; /* used by depsgraph, flushed from collection-tree */ } Object; /* Warning, this is not used anymore because hooks are now modifiers */ diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h index 8310856510c..8c9de0665c4 100644 --- a/source/blender/makesdna/DNA_outliner_types.h +++ b/source/blender/makesdna/DNA_outliner_types.h @@ -99,6 +99,7 @@ enum { #define TSE_KEYMAP_ITEM 35 /* NO ID */ #define TSE_ID_BASE 36 /* NO ID */ #define TSE_GP_LAYER 37 /* NO ID */ +#define TSE_COLLECTION 38 /* NO ID */ /* Check whether given TreeStoreElem should have a real ID in its ->id member. */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 5c7d5ed7397..8eb1d3f5da8 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -47,6 +47,8 @@ extern "C" { #include "DNA_ID.h" #include "DNA_freestyle_types.h" #include "DNA_gpu_types.h" +#include "DNA_layer_types.h" +#include "DNA_material_types.h" #include "DNA_userdef_types.h" struct CurveMapping; @@ -65,18 +67,13 @@ struct bGPdata; struct bGPDbrush; struct MovieClip; struct ColorSpace; +struct SceneCollection; /* ************************************************************* */ /* Scene Data */ /* Base - Wrapper for referencing Objects in a Scene */ -typedef struct Base { - struct Base *next, *prev; - unsigned int lay, selcol; - int flag; - short sx, sy; - struct Object *object; -} Base; +#define BaseLegacy Base /* ************************************************************* */ /* Output Format Data */ @@ -543,6 +540,50 @@ typedef enum BakePassFilter { #define R_BAKE_PASS_FILTER_ALL (~0) /* *************************************************************** */ +/* Engine Settings */ + +typedef struct RenderEngineSettings { + struct RenderEngineSettings *next, *prev; + char name[32]; /* engine name */ + void *data; +} RenderEngineSettings; + +/* Render Data */ +typedef struct RenderEngineSettingsClay { + /* Use same layout as MaterialEngineSettingsClay so this struct + * can be used as Material Settings. */ + short type; + short matcap_icon; /* Icon ID */ + + float matcap_rot; + float matcap_hue; + float matcap_sat; + float matcap_val; + + float ssao_distance; + float ssao_attenuation; + float ssao_factor_cavity; + float ssao_factor_edge; + + short flag; + short pad; + int ubo_index; + /* end of MaterialEngineSettingsClay */ + + /* Global Settings */ + short options; + short pad1; + int ssao_samples; + int pad2[2]; +} RenderEngineSettingsClay; + +/* RenderEngineSettingsClay.options */ +typedef enum ClayFlagSettings { + CLAY_USE_AO = (1 << 0), + CLAY_USE_HSV = (1 << 1), +} ClayFlagSettings; + +/* *************************************************************** */ /* Render Data */ typedef struct RenderData { @@ -1628,7 +1669,7 @@ typedef struct Scene { struct Scene *set; ListBase base; - struct Base *basact; /* active base */ + struct BaseLegacy *basact; /* active base */ struct Object *obedit; /* name replaces old G.obedit */ float cursor[3]; /* 3d cursor location */ @@ -1704,6 +1745,14 @@ typedef struct Scene { struct RigidBodyWorld *rigidbody_world; struct PreviewImage *preview; + + ListBase render_layers; + struct SceneCollection *collection; + int active_layer; + int pad4; + + ListBase engines_settings; /* RenderEngineSettings */ + int pad5[2]; } Scene; /* **************** RENDERDATA ********************* */ @@ -1892,6 +1941,7 @@ enum { /* scene->r.engine (scene.c) */ extern const char *RE_engine_id_BLENDER_RENDER; extern const char *RE_engine_id_BLENDER_GAME; +extern const char *RE_engine_id_BLENDER_CLAY; extern const char *RE_engine_id_CYCLES; /* **************** SCENE ********************* */ @@ -1910,16 +1960,16 @@ extern const char *RE_engine_id_CYCLES; /* depricate this! */ #define TESTBASE(v3d, base) ( \ - ((base)->flag & SELECT) && \ + ((base)->flag_legacy & SELECT) && \ ((base)->lay & v3d->lay) && \ (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define TESTBASELIB(v3d, base) ( \ - ((base)->flag & SELECT) && \ + ((base)->flag_legacy & SELECT) && \ ((base)->lay & v3d->lay) && \ ((base)->object->id.lib == NULL) && \ (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define TESTBASELIB_BGMODE(v3d, scene, base) ( \ - ((base)->flag & SELECT) && \ + ((base)->flag_legacy & SELECT) && \ ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \ ((base)->object->id.lib == NULL) && \ (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) @@ -1928,7 +1978,7 @@ extern const char *RE_engine_id_CYCLES; ((base)->object->id.lib == NULL) && \ (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define BASE_SELECTABLE(v3d, base) ( \ - (base->lay & v3d->lay) && \ + (v3d != NULL) && \ (base->object->restrictflag & (OB_RESTRICT_SELECT | OB_RESTRICT_VIEW)) == 0) #define BASE_VISIBLE(v3d, base) ( \ (base->lay & v3d->lay) && \ @@ -1937,11 +1987,32 @@ extern const char *RE_engine_id_CYCLES; (base->lay & (v3d ? v3d->lay : scene->lay)) && \ (base->object->restrictflag & OB_RESTRICT_VIEW) == 0) +#define TESTBASELIB_NEW(base) ( \ + ((base->flag & BASE_SELECTED) != 0) && \ + ((base)->object->id.lib == NULL) && \ + ((base->flag & BASE_VISIBLED) != 0)) +#define TESTBASELIB_BGMODE_NEW(base) ( \ + ((base->flag & BASE_SELECTED) != 0) && \ + (base->object->id.lib == NULL) && \ + ((base->flag & BASE_VISIBLED) != 0)) +#define BASE_EDITABLE_BGMODE_NEW(base) ( \ + ((base)->object->id.lib == NULL) && \ + ((base->flag & BASE_VISIBLED) != 0)) +#define BASE_SELECTABLE_NEW(base) \ + ((base->flag & BASE_SELECTABLED) != 0) +#define BASE_VISIBLE_NEW(base) ( \ + (base->flag & BASE_VISIBLED) != 0) + #define FIRSTBASE scene->base.first #define LASTBASE scene->base.last #define BASACT (scene->basact) #define OBACT (BASACT ? BASACT->object: NULL) +#define FIRSTBASE_NEW sl->object_bases.first +#define LASTBASE_NEW sl->object_bases.last +#define BASACT_NEW (sl->basact) +#define OBACT_NEW (BASACT_NEW ? BASACT_NEW->object: NULL) + #define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL) #define V3D_CAMERA_SCENE(scene, v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : (scene)->camera) @@ -1956,7 +2027,7 @@ extern const char *RE_engine_id_CYCLES; #define TIME2FRA(a) ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base) #define FPS (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base) -/* base->flag is in DNA_object_types.h */ +/* base->legacy_flag is in DNA_object_types.h */ /* toolsettings->snap_flag */ #define SCE_SNAP 1 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 5e015544dc9..3524c041069 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -181,7 +181,8 @@ typedef enum eSpaceButtons_Context { BCONTEXT_CONSTRAINT = 11, BCONTEXT_BONE_CONSTRAINT = 12, BCONTEXT_RENDER_LAYER = 13, - + BCONTEXT_COLLECTION = 14, + /* always as last... */ BCONTEXT_TOT } eSpaceButtons_Context; @@ -273,21 +274,22 @@ typedef enum eSpaceOutliner_Flag { /* SpaceOops->outlinevis */ typedef enum eSpaceOutliner_Mode { - SO_ALL_SCENES = 0, - SO_CUR_SCENE = 1, - SO_VISIBLE = 2, - SO_SELECTED = 3, - SO_ACTIVE = 4, - SO_SAME_TYPE = 5, - SO_GROUPS = 6, - SO_LIBRARIES = 7, - /* SO_VERSE_SESSION = 8, */ /* deprecated! */ - /* SO_VERSE_MS = 9, */ /* deprecated! */ - SO_SEQUENCE = 10, - SO_DATABLOCKS = 11, - SO_USERDEF = 12, - /* SO_KEYMAP = 13, */ /* deprecated! */ - SO_ID_ORPHANS = 14, + SO_ALL_SCENES = 0, + SO_CUR_SCENE = 1, + SO_VISIBLE = 2, + SO_SELECTED = 3, + SO_ACTIVE = 4, + SO_SAME_TYPE = 5, + SO_GROUPS = 6, + SO_LIBRARIES = 7, + /* SO_VERSE_SESSION = 8, */ /* deprecated! */ + /* SO_VERSE_MS = 9, */ /* deprecated! */ + SO_SEQUENCE = 10, + SO_DATABLOCKS = 11, + SO_USERDEF = 12, + /* SO_KEYMAP = 13, */ /* deprecated! */ + SO_ID_ORPHANS = 14, + SO_COLLECTIONS = 15, } eSpaceOutliner_Mode; /* SpaceOops->storeflag */ @@ -1343,6 +1345,20 @@ typedef enum eSpaceClip_GPencil_Source { SC_GPENCIL_SRC_TRACK = 1, } eSpaceClip_GPencil_Source; +/* Collection Manager ======================================= */ + +typedef struct SpaceCollections { + SpaceLink *next, *prev; + ListBase regionbase; /* storage of regions for inactive spaces */ + int spacetype; + int flag; /* eSpaceCollections_Flag */ +} SpaceCollections; + +/* SpaceClip->flag */ +typedef enum eSpaceCollections_Flag { + SC_COLLECTION_DATA_REFRESH = (1 << 0), /* recreate/update SpaceCollections layer data, needed for undo/read/write */ +} eSpaceCollections_Flag; + /* **************** SPACE DEFINES ********************* */ /* space types, moved from DNA_screen_types.h */ @@ -1372,8 +1388,9 @@ typedef enum eSpace_Type { SPACE_CONSOLE = 18, SPACE_USERPREF = 19, SPACE_CLIP = 20, - - SPACEICONMAX = SPACE_CLIP + SPACE_COLLECTIONS = 21, + + SPACEICONMAX = SPACE_COLLECTIONS } eSpace_Type; /* use for function args */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 1dc6c7ab578..6cc24f74cee 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -390,7 +390,8 @@ typedef struct bTheme { ThemeSpace tuserpref; ThemeSpace tconsole; ThemeSpace tclip; - + ThemeSpace tcollections; + /* 20 sets of bone colors for this theme */ ThemeWireColor tarm[20]; /*ThemeWireColor tobj[20];*/ diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 2cea8715a65..b6cf3d555fa 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -130,6 +130,7 @@ static const char *includefiles[] = { "DNA_freestyle_types.h", "DNA_linestyle_types.h", "DNA_cachefile_types.h", + "DNA_layer_types.h", /* see comment above before editing! */ /* empty string to indicate end of includefiles */ @@ -1342,4 +1343,5 @@ int main(int argc, char **argv) #include "DNA_freestyle_types.h" #include "DNA_linestyle_types.h" #include "DNA_cachefile_types.h" +#include "DNA_layer_types.h" /* end of list */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 66e6f30feeb..2221526fa8b 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -106,6 +106,7 @@ extern StructRNA RNA_ClothCollisionSettings; extern StructRNA RNA_ClothModifier; extern StructRNA RNA_ClothSettings; extern StructRNA RNA_CloudsTexture; +extern StructRNA RNA_CollectionEngineSettings; extern StructRNA RNA_CollectionProperty; extern StructRNA RNA_CollisionModifier; extern StructRNA RNA_CollisionSensor; @@ -317,6 +318,8 @@ extern StructRNA RNA_LaplacianSmoothModifier; extern StructRNA RNA_Lattice; extern StructRNA RNA_LatticeModifier; extern StructRNA RNA_LatticePoint; +extern StructRNA RNA_LayerCollection; +extern StructRNA RNA_LayerCollectionOverride; extern StructRNA RNA_Library; extern StructRNA RNA_LimitDistanceConstraint; extern StructRNA RNA_LimitLocationConstraint; @@ -383,6 +386,8 @@ extern StructRNA RNA_MaterialStrand; extern StructRNA RNA_MaterialSubsurfaceScattering; extern StructRNA RNA_MaterialTextureSlot; extern StructRNA RNA_MaterialVolume; +extern StructRNA RNA_MaterialEngineSettings; +extern StructRNA RNA_MaterialEngineSettingsClay; extern StructRNA RNA_Mask; extern StructRNA RNA_MaskLayer; extern StructRNA RNA_Menu; @@ -498,12 +503,15 @@ extern StructRNA RNA_RenderLayer; extern StructRNA RNA_RenderPass; extern StructRNA RNA_RenderResult; extern StructRNA RNA_RenderSettings; +extern StructRNA RNA_RenderEngineSettings; +extern StructRNA RNA_RenderEngineSettingsClay; extern StructRNA RNA_RigidBodyWorld; extern StructRNA RNA_RigidBodyObject; extern StructRNA RNA_RigidBodyJointConstraint; extern StructRNA RNA_SPHFluidSettings; extern StructRNA RNA_Scene; extern StructRNA RNA_SceneGameData; +extern StructRNA RNA_SceneLayer; extern StructRNA RNA_SceneRenderLayer; extern StructRNA RNA_SceneSequence; extern StructRNA RNA_SceneObjects; @@ -573,6 +581,7 @@ extern StructRNA RNA_SpaceFileBrowser; extern StructRNA RNA_SpaceGraphEditor; extern StructRNA RNA_SpaceImageEditor; extern StructRNA RNA_SpaceInfo; +extern StructRNA RNA_SpaceCollectionManager; extern StructRNA RNA_SpaceLogicEditor; extern StructRNA RNA_SpaceNLA; extern StructRNA RNA_SpaceNodeEditor; @@ -641,6 +650,7 @@ extern StructRNA RNA_ThemeFontStyle; extern StructRNA RNA_ThemeGraphEditor; extern StructRNA RNA_ThemeImageEditor; extern StructRNA RNA_ThemeInfo; +extern StructRNA RNA_ThemeCollectionManager; extern StructRNA RNA_ThemeLogicEditor; extern StructRNA RNA_ThemeNLAEditor; extern StructRNA RNA_ThemeNodeEditor; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 0f3ea27a7f9..0bf2bbb6109 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -192,6 +192,10 @@ if(WITH_GAMEENGINE) add_definitions(-DWITH_GAMEENGINE) endif() +if(WITH_CLAY_ENGINE) + add_definitions(-DWITH_CLAY_ENGINE) +endif() + if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() @@ -341,6 +345,7 @@ blender_include_dirs( ../../bmesh ../../blentranslation ../../depsgraph + ../../draw ../../gpu ../../imbuf ../../ikplugin diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c index d7a679e9702..27e88f592ab 100644 --- a/source/blender/makesrna/intern/rna_context.c +++ b/source/blender/makesrna/intern/rna_context.c @@ -107,6 +107,26 @@ static PointerRNA rna_Context_scene_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Scene, CTX_data_scene(C)); } +static PointerRNA rna_Context_scene_layer_get(PointerRNA *ptr) +{ + bContext *C = (bContext *)ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_SceneLayer, CTX_data_scene_layer(C)); +} + +static PointerRNA rna_Context_scene_collection_get(PointerRNA *ptr) +{ + bContext *C = (bContext *)ptr->data; + ptr->id.data = CTX_data_scene(C); + return rna_pointer_inherit_refine(ptr, &RNA_SceneCollection, CTX_data_scene_collection(C)); +} + +static PointerRNA rna_Context_layer_collection_get(PointerRNA *ptr) +{ + bContext *C = (bContext *)ptr->data; + ptr->id.data = CTX_data_scene(C); + return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, CTX_data_layer_collection(C)); +} + static PointerRNA rna_Context_tool_settings_get(PointerRNA *ptr) { bContext *C = (bContext *)ptr->data; @@ -203,6 +223,21 @@ void RNA_def_context(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_pointer_funcs(prop, "rna_Context_scene_get", NULL, NULL, NULL); + prop = RNA_def_property(srna, "render_layer", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "SceneLayer"); + RNA_def_property_pointer_funcs(prop, "rna_Context_scene_layer_get", NULL, NULL, NULL); + + prop = RNA_def_property(srna, "scene_collection", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "SceneCollection"); + RNA_def_property_pointer_funcs(prop, "rna_Context_scene_collection_get", NULL, NULL, NULL); + + prop = RNA_def_property(srna, "layer_collection", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_pointer_funcs(prop, "rna_Context_layer_collection_get", NULL, NULL, NULL); + prop = RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "ToolSettings"); diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index aa02a3c159d..2a5a0011279 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -53,9 +53,9 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter) return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((GroupObject *)internal->link)->ob); } -static void rna_Group_objects_link(Group *group, bContext *C, ReportList *reports, Object *object) +static void rna_Group_objects_link(Group *group, ReportList *reports, Object *object) { - if (!BKE_group_object_add(group, object, CTX_data_scene(C), NULL)) { + if (!BKE_group_object_add(group, object)) { BKE_reportf(reports, RPT_ERROR, "Object '%s' already in group '%s'", object->id.name + 2, group->id.name + 2); return; } @@ -63,9 +63,9 @@ static void rna_Group_objects_link(Group *group, bContext *C, ReportList *report WM_main_add_notifier(NC_OBJECT | ND_DRAW, &object->id); } -static void rna_Group_objects_unlink(Group *group, bContext *C, ReportList *reports, Object *object) +static void rna_Group_objects_unlink(Group *group, ReportList *reports, Object *object) { - if (!BKE_group_object_unlink(group, object, CTX_data_scene(C), NULL)) { + if (!BKE_group_object_unlink(group, object)) { BKE_reportf(reports, RPT_ERROR, "Object '%s' not in group '%s'", object->id.name + 2, group->id.name + 2); return; } @@ -91,7 +91,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop) /* add object */ func = RNA_def_function(srna, "link", "rna_Group_objects_link"); - RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Add this object to a group"); /* object to add */ parm = RNA_def_pointer(func, "object", "Object", "", "Object to add"); @@ -100,7 +100,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop) /* remove object */ func = RNA_def_function(srna, "unlink", "rna_Group_objects_unlink"); RNA_def_function_ui_description(func, "Remove this object to a group"); - RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_REPORTS); /* object to remove */ parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 76455adbc78..b904b65a37a 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -279,7 +279,7 @@ void RNA_api_material(StructRNA *srna); void RNA_api_mesh(struct StructRNA *srna); void RNA_api_meta(struct StructRNA *srna); void RNA_api_object(struct StructRNA *srna); -void RNA_api_object_base(struct StructRNA *srna); +void RNA_api_object_base_legacy(struct StructRNA *srna); void RNA_api_pose(struct StructRNA *srna); void RNA_api_pose_channel(struct StructRNA *srna); void RNA_api_scene(struct StructRNA *srna); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index b293f20dd95..4d3e3ffca26 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -313,6 +313,31 @@ static void rna_MaterialTextureSlot_use_set(PointerRNA *ptr, int value) } } +static StructRNA *rna_MaterialEngineSettings_refine(PointerRNA *ptr) +{ +#ifdef WITH_CLAY_ENGINE + MaterialEngineSettings *mes = (MaterialEngineSettings *)ptr->data; + if (STREQ(mes->name, RE_engine_id_BLENDER_CLAY)) { + return &RNA_MaterialEngineSettingsClay; + } +#endif + return &RNA_MaterialEngineSettings; +} + +static void rna_Material_update_engine_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) +{ +#if 0 + Material *ma = (Material *)ptr->data; + RenderEngineSettings *ed = DRW_material_settings_get(ma, sce->r.engine, NULL); + + if (ed->runtime) { + MEM_freeN(ed->runtime); + ed->runtime = NULL; + } +#endif + WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL); +} + static void rna_Material_use_diffuse_ramp_set(PointerRNA *ptr, int value) { Material *ma = (Material *)ptr->data; @@ -824,6 +849,118 @@ static void rna_def_material_mtex(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Material_update"); } +static void rna_def_material_settings_clay(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem clay_matcap_items[] = { + {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""}, + {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""}, + {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""}, + {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""}, + {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""}, + {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""}, + {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""}, + {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""}, + {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""}, + {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""}, + {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""}, + {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""}, + {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""}, + {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""}, + {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""}, + {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""}, + {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""}, + {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""}, + {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""}, + {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""}, + {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""}, + {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""}, + {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""}, + {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem clay_matcap_type[] = { + {CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"}, + {CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"}, + {CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "MaterialEngineSettingsClay", "MaterialEngineSettings"); + RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block"); + RNA_def_struct_sdna_from(srna, "MaterialEngineSettingsClay", "data"); + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, clay_matcap_type); + RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material"); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, clay_matcap_items); + RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material"); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "matcap_rot"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model"); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap"); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "matcap_sat"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap"); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "matcap_val"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap"); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect"); + RNA_def_property_range(prop, 0.0f, 250.0f); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect"); + RNA_def_property_range(prop, 0.0f, 250.0f); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect"); + RNA_def_property_range(prop, 0.0f, 100000.0f); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); + + prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant"); + RNA_def_property_range(prop, 1.0f, 100000.0f); + RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3); + RNA_def_property_update(prop, 0, "rna_Material_update_engine_data"); +} + +static void rna_def_material_engine_settings(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "MaterialEngineSettings", NULL); + RNA_def_struct_ui_text(srna, "Engine Settings", "Engine specific settings"); + RNA_def_struct_sdna(srna, "MaterialEngineSettings"); + RNA_def_struct_refine_func(srna, "rna_MaterialEngineSettings_refine"); + + rna_def_material_settings_clay(brna); +} + static void rna_def_material_gamesettings(BlenderRNA *brna) { StructRNA *srna; @@ -2087,6 +2224,11 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_struct_type(prop, "MaterialGameSettings"); RNA_def_property_ui_text(prop, "Game Settings", "Game material settings"); + /* Engine settings */ + prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "MaterialEngineSettings"); + RNA_def_property_ui_text(prop, "Material Engine Settings", "Engine specific settings"); + /* nodetree */ prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "nodetree"); @@ -2136,6 +2278,7 @@ void RNA_def_material(BlenderRNA *brna) rna_def_material_strand(brna); rna_def_material_physics(brna); rna_def_material_gamesettings(brna); + rna_def_material_engine_settings(brna); RNA_api_material(srna); } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 0cffba47f16..f8b3bdd62e9 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -297,23 +297,14 @@ static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin } /* when changing the selection flag the scene needs updating */ -static void rna_Object_select_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) -{ - if (scene) { - Object *ob = (Object *)ptr->id.data; - short mode = (ob->flag & SELECT) ? BA_SELECT : BA_DESELECT; - ED_base_object_select(BKE_scene_base_find(scene, ob), mode); - } -} - static void rna_Base_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Base *base = (Base *)ptr->data; - short mode = (base->flag & BA_SELECT) ? BA_SELECT : BA_DESELECT; + BaseLegacy *base = (BaseLegacy *)ptr->data; + short mode = (base->flag_legacy & BA_SELECT) ? BA_SELECT : BA_DESELECT; ED_base_object_select(base, mode); } -static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, Base *base, Object *ob) +static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, BaseLegacy *base, Object *ob) { /* try to avoid scene sort */ if (scene == NULL) { @@ -335,7 +326,7 @@ static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, Base *b static void rna_Object_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; - Base *base; + BaseLegacy *base; base = scene ? BKE_scene_base_find(scene, ob) : NULL; if (!base) @@ -351,7 +342,7 @@ static void rna_Object_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_Base_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Base *base = (Base *)ptr->data; + BaseLegacy *base = (BaseLegacy *)ptr->data; Object *ob = (Object *)base->object; rna_Object_layer_update__internal(bmain, scene, base, ob); @@ -1120,7 +1111,7 @@ static void rna_Object_layer_set(PointerRNA *ptr, const int *values) static void rna_Base_layer_set(PointerRNA *ptr, const int *values) { - Base *base = (Base *)ptr->data; + BaseLegacy *base = (BaseLegacy *)ptr->data; unsigned int lay; lay = rna_Object_layer_validate__internal(values, base->lay); @@ -2246,11 +2237,6 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Local View Layers", "3D local view layers the object is on"); - prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); - RNA_def_property_ui_text(prop, "Select", "Object selection state"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_select_update"); - /* for data access */ prop = RNA_def_property(srna, "bound_box", PROP_FLOAT, PROP_NONE); RNA_def_property_multi_array(prop, 2, boundbox_dimsize); @@ -2895,14 +2881,14 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object"); } -static void rna_def_object_base(BlenderRNA *brna) +static void rna_def_object_base_legacy(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - srna = RNA_def_struct(brna, "ObjectBase", NULL); + srna = RNA_def_struct(brna, "ObjectBaseLegacy", NULL); RNA_def_struct_sdna(srna, "Base"); - RNA_def_struct_ui_text(srna, "Object Base", "An object instance in a scene"); + RNA_def_struct_ui_text(srna, "Object Base Legacy", "An object instance in a scene (deprecated)"); RNA_def_struct_ui_icon(srna, ICON_OBJECT_DATA); prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); @@ -2922,13 +2908,13 @@ static void rna_def_object_base(BlenderRNA *brna) RNA_def_property_array(prop, 8); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Local View Layers", "3D local view layers the object base is on"); - + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", BA_SELECT); + RNA_def_property_boolean_sdna(prop, NULL, "flag_legacy", BA_SELECT); RNA_def_property_ui_text(prop, "Select", "Object base selection state"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Base_select_update"); - - RNA_api_object_base(srna); + + RNA_api_object_base_legacy(srna); } void RNA_def_object(BlenderRNA *brna) @@ -2937,7 +2923,7 @@ void RNA_def_object(BlenderRNA *brna) RNA_define_animate_sdna(false); rna_def_object_game_settings(brna); - rna_def_object_base(brna); + rna_def_object_base_legacy(brna); rna_def_vertex_group(brna); rna_def_material_slot(brna); rna_def_dupli_object(brna); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index c680abe71a4..c93f72e798f 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -40,10 +40,12 @@ #include "RNA_define.h" #include "DNA_constraint_types.h" +#include "DNA_layer_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "rna_internal.h" /* own include */ @@ -90,6 +92,49 @@ static EnumPropertyItem space_items[] = { #include "DEG_depsgraph.h" +static void rna_Object_select_set(Object *ob, bContext *C, ReportList *reports, int action) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + Base *base = BKE_scene_layer_base_find(sl, ob); + + if (!base) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, sl->name); + return; + } + + if (action == 2) { /* TOGGLE */ + if ((base->flag & BASE_SELECTED) != 0) { + action = 1; /* DESELECT */ + } + else { + action = 0; /* SELECT */ + } + } + + switch (action) { + case 1: /* DESELECT */ + base->flag &= ~BASE_SELECTED; + break; + case 0: /* SELECT */ + default: + BKE_scene_layer_base_select(sl, base); + break; + } +} + +static int rna_Object_select_get(Object *ob, bContext *C, ReportList *reports) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + Base *base = BKE_scene_layer_base_find(sl, ob); + + if (!base) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, sl->name); + return -1; + } + + return ((base->flag & BASE_SELECTED) != 0) ? 1 : 0; +} + /* Convert a given matrix from a space to another (using the object and/or a bone as reference). */ static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan, float *mat, float *mat_ret, int from, int to) @@ -413,9 +458,9 @@ finally: free_bvhtree_from_mesh(&treeData); } -/* ObjectBase */ +/* ObjectBaseLegacy */ -static void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d) +static void rna_ObjectBaseLegacy_layers_from_view(BaseLegacy *base, View3D *v3d) { base->lay = base->object->lay = v3d->lay; } @@ -504,6 +549,26 @@ void RNA_api_object(StructRNA *srna) }; #endif + static EnumPropertyItem object_select_items[] = { + {0, "SELECT", 0, "Select", "Select object from the active render layer"}, + {1, "DESELECT", 0, "Deselect", "Deselect object from the active render layer"}, + {2, "TOGGLE", 0, "Toggle", "Toggle object selection from the active render layer"}, + {0, NULL, 0, NULL, NULL} + }; + + /* Special wrapper to access the base selection value */ + func = RNA_def_function(srna, "select_set", "rna_Object_select_set"); + RNA_def_function_ui_description(func, "Select the object (for the active render layer)"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + parm = RNA_def_enum(func, "action", object_select_items, 0, "Action", "Select mode"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + + func = RNA_def_function(srna, "select_get", "rna_Object_select_get"); + RNA_def_function_ui_description(func, "Get the object selection for the active render layer"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + parm = RNA_def_boolean(func, "result", 0, "", "Object selected"); + RNA_def_function_return(func, parm); + /* Matrix space conversion */ func = RNA_def_function(srna, "convert_space", "rna_Scene_mat_convert_space"); RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another"); @@ -707,12 +772,12 @@ void RNA_api_object(StructRNA *srna) } -void RNA_api_object_base(StructRNA *srna) +void RNA_api_object_base_legacy(StructRNA *srna) { FunctionRNA *func; PropertyRNA *parm; - func = RNA_def_function(srna, "layers_from_view", "rna_ObjectBase_layers_from_view"); + func = RNA_def_function(srna, "layers_from_view", "rna_ObjectBaseLegacy_layers_from_view"); RNA_def_function_ui_description(func, "Sets the object layers from a 3D View (use when adding an object in local view)"); parm = RNA_def_pointer(func, "view", "SpaceView3D", "", ""); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 1d89f7535c4..5fd4762e5be 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -605,7 +605,7 @@ static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene), if (id && GS(id->name) == ID_SCE) { Scene *scene = (Scene *)id; - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 518c7efd915..5f796261c73 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -261,6 +261,24 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt RNA_parameter_list_free(&list); } +static void engine_collection_settings_create(RenderEngine *engine, struct CollectionEngineSettings *ces) +{ + extern FunctionRNA rna_RenderEngine_collection_settings_create_func; + PointerRNA ptr,cesptr; + ParameterList list; + FunctionRNA *func; + + RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr); + RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &cesptr); + func = &rna_RenderEngine_collection_settings_create_func; + + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "collection_settings", &cesptr); + engine->type->ext.call(NULL, &ptr, func, &list); + + RNA_parameter_list_free(&list); +} + /* RenderEngine registration */ static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type) @@ -281,7 +299,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo RenderEngineType *et, dummyet = {NULL}; RenderEngine dummyengine = {NULL}; PointerRNA dummyptr; - int have_function[6]; + int have_function[7]; /* setup dummy engine & engine type to store static properties in */ dummyengine.type = &dummyet; @@ -323,8 +341,9 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo et->view_update = (have_function[3]) ? engine_view_update : NULL; et->view_draw = (have_function[4]) ? engine_view_draw : NULL; et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL; + et->collection_settings_create = (have_function[6]) ? engine_collection_settings_create : NULL; - BLI_addtail(&R_engines, et); + RE_engines_register(bmain, et); return et->ext.srna; } @@ -489,6 +508,13 @@ static void rna_def_render_engine(BlenderRNA *brna) parm = RNA_def_pointer(func, "node", "Node", "", ""); RNA_def_parameter_flags(parm, 0, PARM_RNAPTR); + /* per-collection engine settings initialization */ + func = RNA_def_function(srna, "collection_settings_create", NULL); + RNA_def_function_ui_description(func, "Create the per collection settings for the engine"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); + parm = RNA_def_pointer(func, "collection_settings", "CollectionEngineSettings", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_RNAPTR); + /* tag for redraw */ func = RNA_def_function(srna, "tag_redraw", "engine_tag_redraw"); RNA_def_function_ui_description(func, "Request redraw for viewport rendering"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 1166fb89a0a..2fb1fa9c8d6 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -32,6 +32,7 @@ #include "DNA_particle_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" +#include "DNA_layer_types.h" #include "DNA_linestyle_types.h" #include "DNA_userdef_types.h" #include "DNA_world_types.h" @@ -47,8 +48,12 @@ #include "BKE_editmesh.h" #include "BKE_paint.h" +#include "ED_object.h" + #include "GPU_extensions.h" +#include "DRW_engine.h" + #include "RNA_define.h" #include "RNA_enum_types.h" @@ -77,6 +82,8 @@ #include "BLI_threads.h" +#define NO_ENGINE "NO_ENGINE" + #ifdef WITH_OPENEXR EnumPropertyItem rna_enum_exr_codec_items[] = { {R_IMF_EXR_CODEC_NONE, "NONE", 0, "None", ""}, @@ -445,10 +452,12 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = { #include "MEM_guardedalloc.h" #include "BKE_brush.h" +#include "BKE_collection.h" #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_pointcache.h" @@ -606,11 +615,11 @@ static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, Poi static int rna_Scene_object_bases_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) { Scene *scene = (Scene *)ptr->data; - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { if (STREQLEN(base->object->id.name + 2, key, sizeof(base->object->id.name) - 2)) { - *r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ObjectBase, base); + *r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ObjectBaseLegacy, base); return true; } } @@ -623,13 +632,13 @@ static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter) ListBaseIterator *internal = &iter->internal.listbase; /* we are actually iterating a Base list, so override get */ - return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((Base *)internal->link)->object); + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((BaseLegacy *)internal->link)->object); } -static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *reports, Object *ob) +static BaseLegacy *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *reports, Object *ob) { Scene *scene_act = CTX_data_scene(C); - Base *base; + BaseLegacy *base; if (BKE_scene_base_find(scene, ob)) { BKE_reportf(reports, RPT_ERROR, "Object '%s' is already in scene '%s'", ob->id.name + 2, scene->id.name + 2); @@ -660,7 +669,7 @@ static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *report static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *ob) { - Base *base = BKE_scene_base_find(scene, ob); + BaseLegacy *base = BKE_scene_base_find(scene, ob); if (!base) { BKE_reportf(reports, RPT_ERROR, "Object '%s' is not in this scene '%s'", ob->id.name + 2, scene->id.name + 2); return; @@ -1707,7 +1716,7 @@ static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr) static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH); @@ -1778,7 +1787,7 @@ static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), Poi { Scene *sce = ptr->id.data; Scene *sce_iter; - Base *base; + BaseLegacy *base; BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); for (SETLOOPER(sce, sce_iter, base)) @@ -1867,6 +1876,43 @@ static void rna_GameSettings_exit_key_set(PointerRNA *ptr, int value) gm->exitkey = value; } +static StructRNA *rna_RenderEngineSettings_refine(PointerRNA *ptr) +{ +#ifdef WITH_CLAY_ENGINE + RenderEngineSettings *res = (RenderEngineSettings *)ptr->data; + + if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) { + return &RNA_RenderEngineSettingsClay; + } +#endif + return &RNA_RenderEngineSettings; +} + +static PointerRNA rna_RenderEngineSettings_active_get(PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->data; + RenderEngineSettings *res; + + /* Ensure settings exists */ + DRW_render_settings_get(scene, scene->r.engine); + + res = BLI_findstring(&scene->engines_settings, scene->r.engine, offsetof(RenderEngineSettings, name)); + + return rna_pointer_inherit_refine(ptr, &RNA_RenderEngineSettings, res); +} + +static void rna_RenderEngineSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Scene *sce = (Scene *)ptr->id.data; + MaterialEngineSettingsClay *res; + + res = (MaterialEngineSettingsClay *)DRW_render_settings_get(sce, sce->r.engine); + + res->flag = CLAY_OUTDATED; + + WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL); +} + static TimeMarker *rna_TimeLine_add(Scene *scene, const char name[], int frame) { TimeMarker *marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); @@ -2185,6 +2231,540 @@ static int rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr)) return GPU_instanced_drawing_support() && GPU_geometry_shader_support(); } +static void rna_SceneCollection_name_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneCollection *sc = (SceneCollection *)ptr->data; + SceneCollection *sc_master = BKE_collection_master(scene); + + BLI_strncpy_utf8(sc->name, value, sizeof(sc->name)); + BLI_uniquename(&sc_master->scene_collections, sc, DATA_("SceneCollection"), '.', offsetof(SceneCollection, name), sizeof(sc->name)); +} + +static void rna_SceneCollection_filter_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneCollection *sc = (SceneCollection *)ptr->data; + BLI_strncpy_utf8(sc->filter, value, sizeof(sc->filter)); + + TODO_LAYER_SYNC_FILTER; + (void)scene; +} + +static PointerRNA rna_SceneCollection_objects_get(CollectionPropertyIterator *iter) +{ + ListBaseIterator *internal = &iter->internal.listbase; + + /* we are actually iterating a LinkData list, so override get */ + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((LinkData *)internal->link)->data); +} + +static SceneCollection *rna_SceneCollection_new(ID *id, SceneCollection *sc_parent, const char *name) +{ + Scene *scene = (Scene *)id; + SceneCollection *sc = BKE_collection_add(scene, sc_parent, name); + + DAG_id_tag_update(&scene->id, 0); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + + return sc; +} + +static void rna_SceneCollection_remove( + ID *id, SceneCollection *sc_parent, ReportList *reports, PointerRNA *sc_ptr) +{ + Scene *scene = (Scene *)id; + SceneCollection *sc = sc_ptr->data; + + const int index = BLI_findindex(&sc_parent->scene_collections, sc); + if (index == -1) { + BKE_reportf(reports, RPT_ERROR, "Collection '%s' is not a sub-collection of '%s'", + sc->name, sc_parent->name); + return; + } + + if (!BKE_collection_remove(scene, sc)) { + BKE_reportf(reports, RPT_ERROR, "Collection '%s' could not be removed from collection '%s'", + sc->name, sc_parent->name); + return; + } + + RNA_POINTER_INVALIDATE(sc_ptr); + + DAG_id_tag_update(&scene->id, 0); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); +} + +static int rna_SceneCollection_objects_active_index_get(PointerRNA *ptr) +{ + SceneCollection *sc = (SceneCollection *)ptr->data; + return sc->active_object_index; +} + +static void rna_SceneCollection_objects_active_index_set(PointerRNA *ptr, int value) +{ + SceneCollection *sc = (SceneCollection *)ptr->data; + sc->active_object_index = value; +} + +static void rna_SceneCollection_objects_active_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + SceneCollection *sc = (SceneCollection *)ptr->data; + *min = 0; + *max = max_ii(0, BLI_listbase_count(&sc->objects) - 1); +} + +void rna_SceneCollection_object_link( + ID *id, SceneCollection *sc, Main *bmain, ReportList *reports, Object *ob) +{ + Scene *scene = (Scene *)id; + + if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' is already in collection '%s'", ob->id.name + 2, sc->name); + return; + } + + BKE_collection_object_add(scene, sc, ob); + + /* TODO(sergey): Only update relations for the current scene. */ + DAG_relations_tag_update(bmain); + DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + + WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene); +} + +static void rna_SceneCollection_object_unlink( + ID *id, SceneCollection *sc, Main *bmain, ReportList *reports, Object *ob) +{ + Scene *scene = (Scene *)id; + + if (!BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' is not in collection '%s'", ob->id.name + 2, sc->name); + return; + } + + BKE_collection_object_remove(bmain, scene, sc, ob, false); + + /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */ + DAG_relations_tag_update(bmain); + + WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene); +} + +/****** layer collection engine settings *******/ + +static StructRNA *rna_CollectionEngineSettings_refine(struct PointerRNA *ptr) +{ + CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; + + if (STREQ(ces->name, "BLENDER_CLAY")) { + return &RNA_CollectionEngineSettingsClay; + } + + /* TODO - handle other engines */ + TODO_LAYER; + (void) ces; + + return &RNA_CollectionEngineSettings; +} + +/****** clay engine settings *******/ + +#define RNA_LAYER_ENGINE_USE_GET_SET(_NAME_) \ + static int rna_LayerEngineSettings_##_NAME_##_use_get(PointerRNA *ptr) \ + { \ + CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \ + return BKE_collection_engine_property_use_get(ces, #_NAME_) ? 1 : 0; \ + } \ + \ + static void rna_LayerEngineSettings_##_NAME_##_use_set(PointerRNA *ptr, int value) \ + { \ + CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \ + BKE_collection_engine_property_use_set(ces, #_NAME_, value? true : false); \ + } + +#define RNA_LAYER_ENGINE_GET_SET(_TYPE_, _NAME_) \ +static _TYPE_ rna_LayerEngineSettings_##_NAME_##_get(PointerRNA *ptr) \ +{ \ + CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \ + return BKE_collection_engine_property_value_get_##_TYPE_(ces, #_NAME_); \ +} \ + \ +static void rna_LayerEngineSettings_##_NAME_##_set(PointerRNA *ptr, _TYPE_ value) \ +{ \ + CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \ + BKE_collection_engine_property_value_set_##_TYPE_(ces, #_NAME_, value); \ +} \ + RNA_LAYER_ENGINE_USE_GET_SET(_NAME_) + +#define RNA_LAYER_ENGINE_GET_SET_FLOAT(_NAME_) \ + RNA_LAYER_ENGINE_GET_SET(float, _NAME_) + +#define RNA_LAYER_ENGINE_GET_SET_INT(_NAME_) \ + RNA_LAYER_ENGINE_GET_SET(int, _NAME_) + + +RNA_LAYER_ENGINE_GET_SET_INT(type) +RNA_LAYER_ENGINE_GET_SET_INT(matcap_icon) +RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_rotation) +RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_hue) +RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_saturation) +RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_value) +RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_cavity) +RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_edge) +RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_distance) +RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_attenuation) + +#undef RNA_LAYER_ENGINE_GET_SET_INT +#undef RNA_LAYER_ENGINE_GET_SET_FLOAT +#undef RNA_LAYER_ENGINE_GET_SET +#undef RNA_LAYER_ENGINE_USE_GET_SET + +static void rna_CollectionEngineSettings_update(bContext *C, PointerRNA *UNUSED(ptr)) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + LayerCollection *lc = CTX_data_layer_collection(C); + BKE_scene_layer_engine_settings_collection_recalculate(sl, lc); +} + +/***********************************/ + +static void rna_LayerCollection_name_get(PointerRNA *ptr, char *value) +{ + SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection; + strcpy(value, sc->name); +} + +static int rna_LayerCollection_name_length(PointerRNA *ptr) +{ + SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection; + return strnlen(sc->name, sizeof(sc->name)); +} + +static void rna_LayerCollection_name_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection; + SceneCollection *sc_master = BKE_collection_master(scene); + + BLI_strncpy_utf8(sc->name, value, sizeof(sc->name)); + BLI_uniquename(&sc_master->scene_collections, sc, DATA_("SceneCollection"), '.', offsetof(SceneCollection, name), sizeof(sc->name)); +} + +static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *iter) +{ + ListBaseIterator *internal = &iter->internal.listbase; + Base *base = ((LinkData *)internal->link)->data; + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object); +} + +static PointerRNA rna_LayerCollection_engine_settings_get(ID *UNUSED(id), LayerCollection *lc, bContext *C, const char *engine) +{ + Scene *scene = CTX_data_scene(C); + const char *engine_name; + + if (STREQ(engine, NO_ENGINE)) { + RenderData *rd = &scene->r; + engine_name = rd->engine; + } + else { + engine_name = engine; + } + + PointerRNA ptr; + CollectionEngineSettings *ces = BKE_layer_collection_engine_get(lc, engine_name); + RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &ptr); + return rna_pointer_inherit_refine(&ptr, &RNA_CollectionEngineSettings, ces); +} + +static void rna_LayerCollection_hide_update(bContext *C, PointerRNA *ptr) +{ + Scene *scene = CTX_data_scene(C); + LayerCollection *lc = ptr->data; + SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc); + + /* hide and deselect bases that are directly influenced by this LayerCollection */ + BKE_scene_layer_base_flag_recalculate(sl); + BKE_scene_layer_engine_settings_collection_recalculate(sl, lc); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); +} + +static void rna_LayerCollection_hide_select_update(bContext *C, PointerRNA *ptr) +{ + LayerCollection *lc = ptr->data; + + if ((lc->flag & COLLECTION_SELECTABLE) == 0) { + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc); + + /* deselect bases that are directly influenced by this LayerCollection */ + BKE_scene_layer_base_flag_recalculate(sl); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + } +} + +static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + return sl->active_collection; +} + +static void rna_LayerCollections_active_collection_index_set(PointerRNA *ptr, int value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + int num_collections = BKE_layer_collection_count(sl); + sl->active_collection = min_ff(value, num_collections - 1); +} + +static void rna_LayerCollections_active_collection_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + *min = 0; + *max = max_ii(0, BKE_layer_collection_count(sl) - 1); +} + +static PointerRNA rna_LayerCollections_active_collection_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + LayerCollection *lc = BKE_layer_collection_active(sl); + return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, lc); +} + +static void rna_LayerCollections_active_collection_set(PointerRNA *ptr, PointerRNA value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + LayerCollection *lc = (LayerCollection *)value.data; + const int index = BKE_layer_collection_findindex(sl, lc); + if (index != -1) sl->active_collection = index; +} + +LayerCollection * rna_SceneLayer_collection_link( + ID *id, SceneLayer *sl, Main *bmain, SceneCollection *sc) +{ + Scene *scene = (Scene *)id; + LayerCollection *lc = BKE_collection_link(sl, sc); + + /* TODO(sergey/dfelinto): Only update relations for the current scenelayer. */ + DAG_relations_tag_update(bmain); + WM_main_add_notifier(NC_SCENE | ND_LAYER, scene); + + return lc; +} + +static void rna_SceneLayer_collection_unlink( + ID *id, SceneLayer *sl, Main *bmain, ReportList *reports, LayerCollection *lc) +{ + Scene *scene = (Scene *)id; + + if (BLI_findindex(&sl->layer_collections, lc) == -1) { + BKE_reportf(reports, RPT_ERROR, "Layer collection '%s' is not in '%s'", lc->scene_collection->name, sl->name); + return; + } + + BKE_collection_unlink(sl, lc); + + /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */ + /* TODO(sergey/dfelinto): Only update relations for the current scenelayer. */ + DAG_relations_tag_update(bmain); + + WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene); +} + +static PointerRNA rna_LayerObjects_active_object_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_Object, sl->basact ? sl->basact->object : NULL); +} + +static void rna_LayerObjects_active_object_set(PointerRNA *ptr, PointerRNA value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + if (value.data) + sl->basact = BKE_scene_layer_base_find(sl, (Object *)value.data); + else + sl->basact = NULL; +} + +static void rna_SceneLayer_name_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneLayer *sl = (SceneLayer *)ptr->data; + char oldname[sizeof(sl->name)]; + + BLI_strncpy(oldname, sl->name, sizeof(sl->name)); + + BLI_strncpy_utf8(sl->name, value, sizeof(sl->name)); + BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name)); + + if (scene->nodetree) { + bNode *node; + int index = BLI_findindex(&scene->render_layers, sl); + + for (node = scene->nodetree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS && node->id == NULL) { + if (node->custom1 == index) + BLI_strncpy(node->name, sl->name, NODE_MAXSTR); + } + } + } +} + +static PointerRNA rna_SceneLayer_objects_get(CollectionPropertyIterator *iter) +{ + ListBaseIterator *internal = &iter->internal.listbase; + + /* we are actually iterating a ObjectBase list, so override get */ + Base *base = (Base *)internal->link; + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object); +} + +static int rna_SceneLayer_objects_selected_skip(CollectionPropertyIterator *iter, void *UNUSED(data)) +{ + ListBaseIterator *internal = &iter->internal.listbase; + Base *base = (Base *)internal->link; + + if ((base->flag & BASE_SELECTED) != 0) { + return 0; + } + + return 1; +}; + +static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + rna_iterator_listbase_begin(iter, &sl->object_bases, rna_SceneLayer_objects_selected_skip); +} + +static void rna_SceneLayer_engine_set(PointerRNA *ptr, int value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + RenderEngineType *type = BLI_findlink(&R_engines, value); + + if (type) + BKE_scene_layer_engine_set(sl, type->idname); +} + +static EnumPropertyItem *rna_SceneLayer_engine_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +{ + RenderEngineType *type; + EnumPropertyItem *item = NULL; + EnumPropertyItem tmp = {0, "", 0, "", ""}; + int a = 0, totitem = 0; + + for (type = R_engines.first; type; type = type->next, a++) { + tmp.value = a; + tmp.identifier = type->idname; + tmp.name = type->name; + RNA_enum_item_add(&item, &totitem, &tmp); + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; +} + +static int rna_SceneLayer_engine_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + RenderEngineType *type; + int a = 0; + + for (type = R_engines.first; type; type = type->next, a++) + if (STREQ(type->idname, sl->engine)) + return a; + + return 0; +} + +static void rna_SceneLayer_engine_update(Main *bmain, Scene *UNUSED(unused), PointerRNA *UNUSED(ptr)) +{ + ED_render_engine_changed(bmain); +} + +static int rna_SceneLayer_multiple_engines_get(PointerRNA *UNUSED(ptr)) +{ + return (BLI_listbase_count(&R_engines) > 1); +} + +static int rna_SceneLayer_active_layer_index_get(PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->data; + return scene->active_layer; +} + +static void rna_SceneLayer_active_layer_index_set(PointerRNA *ptr, int value) +{ + Scene *scene = (Scene *)ptr->data; + int num_layers = BLI_listbase_count(&scene->render_layers); + scene->active_layer = min_ff(value, num_layers - 1); +} + +static void rna_SceneLayer_active_layer_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + Scene *scene = (Scene *)ptr->data; + + *min = 0; + *max = max_ii(0, BLI_listbase_count(&scene->render_layers) - 1); +} + +static PointerRNA rna_SceneLayer_active_layer_get(PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->data; + SceneLayer *sl = BLI_findlink(&scene->render_layers, scene->active_layer); + + return rna_pointer_inherit_refine(ptr, &RNA_SceneLayer, sl); +} + +static void rna_SceneLayer_active_layer_set(PointerRNA *ptr, PointerRNA value) +{ + Scene *scene = (Scene *)ptr->data; + SceneLayer *sl = (SceneLayer *)value.data; + const int index = BLI_findindex(&scene->render_layers, sl); + if (index != -1) scene->active_layer = index; +} + +static SceneLayer *rna_SceneLayer_new(ID *id, Scene *UNUSED(sce), const char *name) +{ + Scene *scene = (Scene *)id; + SceneLayer *sl = BKE_scene_layer_add(scene, name); + + DAG_id_tag_update(&scene->id, 0); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + + return sl; +} + +static void rna_SceneLayer_remove( + ID *id, Scene *UNUSED(sce), Main *bmain, ReportList *reports, PointerRNA *sl_ptr) +{ + Scene *scene = (Scene *)id; + SceneLayer *sl = sl_ptr->data; + + if (!BKE_scene_layer_remove(bmain, scene, sl)) { + BKE_reportf(reports, RPT_ERROR, "Render layer '%s' could not be removed from scene '%s'", + sl->name, scene->id.name + 2); + return; + } + + RNA_POINTER_INVALIDATE(sl_ptr); + + DAG_id_tag_update(&scene->id, 0); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); +} + +static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Base *base = (Base *)ptr->data; + short mode = (base->flag & BASE_SELECTED) ? BA_SELECT : BA_DESELECT; + ED_object_base_select(base, mode); +} + #else /* Grease Pencil Interpolation tool settings */ @@ -5046,6 +5626,545 @@ static void rna_def_gpu_fx(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update"); } +/* Render Layers and Collections */ + +static void rna_def_scene_collections(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "SceneCollections"); + srna = RNA_def_struct(brna, "SceneCollections", NULL); + RNA_def_struct_sdna(srna, "SceneCollection"); + RNA_def_struct_ui_text(srna, "Scene Collection", "Collection of scene collections"); + + func = RNA_def_function(srna, "new", "rna_SceneCollection_new"); + RNA_def_function_ui_description(func, "Add a collection to scene"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_string(func, "name", "SceneCollection", 0, "", "New name for the collection (not unique)"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_SceneCollection_remove"); + RNA_def_function_ui_description(func, "Remove a collection layer"); + RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); + parm = RNA_def_pointer(func, "layer", "SceneCollection", "", "Collection to remove"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); +} + +static void rna_def_collection_objects(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + PropertyRNA *prop; + + RNA_def_property_srna(cprop, "CollectionObjects"); + srna = RNA_def_struct(brna, "CollectionObjects", NULL); + RNA_def_struct_sdna(srna, "SceneCollection"); + RNA_def_struct_ui_text(srna, "Collection Objects", "Objects of a collection"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_SceneCollection_objects_active_index_get", + "rna_SceneCollection_objects_active_index_set", + "rna_SceneCollection_objects_active_index_range"); + RNA_def_property_ui_text(prop, "Active Object Index", "Active index in collection objects array"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + func = RNA_def_function(srna, "link", "rna_SceneCollection_object_link"); + RNA_def_function_ui_description(func, "Link an object to collection"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "object", "Object", "", "Object to add to collection"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + + func = RNA_def_function(srna, "unlink", "rna_SceneCollection_object_unlink"); + RNA_def_function_ui_description(func, "Unlink object from collection"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove from collection"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); +} + +static void rna_def_scene_collection(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "SceneCollection", NULL); + RNA_def_struct_ui_text(srna, "Scene Collection", "Collection"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_name_set"); + RNA_def_property_ui_text(prop, "Name", "Collection name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + prop = RNA_def_property(srna, "filter", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_filter_set"); + RNA_def_property_ui_text(prop, "Filter", "Filter to dynamically include objects based on their names (e.g., CHAR_*)"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "scene_collections", NULL); + RNA_def_property_struct_type(prop, "SceneCollection"); + RNA_def_property_ui_text(prop, "SceneCollections", ""); + rna_def_scene_collections(brna, prop); + + prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "objects", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Objects", "All the objects directly added to this collection (not including sub-collection objects)"); + rna_def_collection_objects(brna, prop); + + prop = RNA_def_property(srna, "filters_objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "filter_objects", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Filter Objects", "All the objects dynamically added to this collection via the filter"); +} + +static void rna_def_layer_collection_override(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "LayerCollectionOverride", NULL); + RNA_def_struct_sdna(srna, "CollectionOverride"); + RNA_def_struct_ui_text(srna, "Collection Override", "Collection Override"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Collection name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); +} + +#define RNA_LAYER_ENGINE_USE(_NAME_) \ + prop = RNA_def_property(srna, #_NAME_"_use", PROP_BOOLEAN, PROP_NONE); \ + RNA_def_property_boolean_funcs(prop, \ + "rna_LayerEngineSettings_"#_NAME_"_use_get", \ + "rna_LayerEngineSettings_"#_NAME_"_use_set"); \ + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); \ + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + +static void rna_def_layer_collection_engine_settings_clay(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem clay_matcap_items[] = { + {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""}, + {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""}, + {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""}, + {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""}, + {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""}, + {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""}, + {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""}, + {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""}, + {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""}, + {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""}, + {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""}, + {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""}, + {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""}, + {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""}, + {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""}, + {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""}, + {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""}, + {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""}, + {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""}, + {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""}, + {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""}, + {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""}, + {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""}, + {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem clay_matcap_type[] = { + {CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"}, + {CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"}, + {CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "CollectionEngineSettingsClay", NULL); + RNA_def_struct_sdna(srna, "CollectionEngineSettings"); + RNA_def_struct_ui_text(srna, "Collections Clay Engine Settings", "Engine specific settings for this collection"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Engine name"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_name_property(srna, prop); + + /* see RNA_LAYER_ENGINE_GET_SET macro */ + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_type_get", "rna_LayerEngineSettings_type_set", NULL); + RNA_def_property_enum_items(prop, clay_matcap_type); + RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(type) + + prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_matcap_icon_get", "rna_LayerEngineSettings_matcap_icon_set", NULL); + RNA_def_property_enum_items(prop, clay_matcap_items); + RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(matcap_icon) + + prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_rotation_get", "rna_LayerEngineSettings_matcap_rotation_set", NULL); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(matcap_rotation) + + prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_hue_get", "rna_LayerEngineSettings_matcap_hue_set", NULL); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(matcap_hue) + + prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_saturation_get", "rna_LayerEngineSettings_matcap_saturation_set", NULL); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(matcap_saturation) + + prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_value_get", "rna_LayerEngineSettings_matcap_value_set", NULL); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(matcap_value) + + prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_cavity_get", "rna_LayerEngineSettings_ssao_factor_cavity_set", NULL); + RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect"); + RNA_def_property_range(prop, 0.0f, 250.0f); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(ssao_factor_cavity) + + prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_edge_get", "rna_LayerEngineSettings_ssao_factor_edge_set", NULL); + RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect"); + RNA_def_property_range(prop, 0.0f, 250.0f); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(ssao_factor_edge) + + prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_distance_get", "rna_LayerEngineSettings_ssao_distance_set", NULL); + RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect"); + RNA_def_property_range(prop, 0.0f, 100000.0f); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(ssao_distance) + + prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_attenuation_get", "rna_LayerEngineSettings_ssao_attenuation_set", NULL); + RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant"); + RNA_def_property_range(prop, 1.0f, 100000.0f); + RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update"); + RNA_LAYER_ENGINE_USE(ssao_attenuation) +} + +static void rna_def_layer_collection_engine_settings(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "CollectionEngineSettings", NULL); + RNA_def_struct_ui_text(srna, "Collections Engine Settings", "Engine specific settings for this collection"); + RNA_def_struct_refine_func(srna, "rna_CollectionEngineSettings_refine"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Engine name"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_name_property(srna, prop); + + /* the engine specific structs */ + rna_def_layer_collection_engine_settings_clay(brna); +} + +#undef RNA_LAYER_ENGINE_USE + +static void rna_def_layer_collection(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + FunctionRNA *func; + PropertyRNA *parm; + + srna = RNA_def_struct(brna, "LayerCollection", NULL); + RNA_def_struct_ui_text(srna, "Layer Collection", "Layer collection"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_LayerCollection_name_get", "rna_LayerCollection_name_length", "rna_LayerCollection_name_set"); + RNA_def_property_ui_text(prop, "Name", "Collection name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + prop = RNA_def_property(srna, "collection", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "scene_collection"); + RNA_def_property_struct_type(prop, "SceneCollection"); + RNA_def_property_ui_text(prop, "Collection", "Collection this layer collection is wrapping"); + + prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "layer_collections", NULL); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_ui_text(prop, "Layer Collections", ""); + + prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_LayerCollection_objects_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Objects", "All the objects directly or indirectly added to this collection (not including sub-collection objects)"); + + prop = RNA_def_property(srna, "overrides", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "overrides", NULL); + RNA_def_property_struct_type(prop, "LayerCollectionOverride"); + RNA_def_property_ui_text(prop, "Collection Overrides", ""); + + func = RNA_def_function(srna, "get_engine_settings", "rna_LayerCollection_engine_settings_get"); + RNA_def_function_ui_description(func, "Return the engine settings for this collection"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT); + parm = RNA_def_string(func, "engine", NO_ENGINE, MAX_NAME, "Engine", "use context one by default"); + RNA_def_parameter_clear_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "CollectionEngineSettings", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_RNAPTR); + RNA_def_function_return(func, parm); + + /* Flags */ + prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_VISIBLE); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1); + RNA_def_property_ui_text(prop, "Hide", "Restrict visiblity"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_update"); + + prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_SELECTABLE); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 1); + RNA_def_property_ui_text(prop, "Hide Selectable", "Restrict selection"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_select_update"); + + prop = RNA_def_property(srna, "is_unfolded", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_FOLDED); + RNA_def_property_ui_icon(prop, ICON_RIGHTARROW, 1); + RNA_def_property_ui_text(prop, "Folded", "Folded collection"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + /* TODO_LAYER_OVERRIDE */ +} + +static void rna_def_layer_collections(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *prop; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "LayerCollections"); + srna = RNA_def_struct(brna, "LayerCollections", NULL); + RNA_def_struct_sdna(srna, "SceneLayer"); + RNA_def_struct_ui_text(srna, "Layer Collections", "Collections of render layer"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "active_collection"); + RNA_def_property_int_funcs(prop, "rna_LayerCollections_active_collection_index_get", + "rna_LayerCollections_active_collection_index_set", + "rna_LayerCollections_active_collection_index_range"); + RNA_def_property_ui_text(prop, "Active Collection Index", "Active index in layer collection array"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_pointer_funcs(prop, "rna_LayerCollections_active_collection_get", + "rna_LayerCollections_active_collection_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL); + RNA_def_property_ui_text(prop, "Active Layer Collection", "Active Layer Collection"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + func = RNA_def_function(srna, "link", "rna_SceneLayer_collection_link"); + RNA_def_function_ui_description(func, "Link a collection to render layer"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); + parm = RNA_def_pointer(func, "scene_collection", "SceneCollection", "", "Collection to add to render layer"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "LayerCollection", "", "Newly created layer collection"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "unlink", "rna_SceneLayer_collection_unlink"); + RNA_def_function_ui_description(func, "Unlink a collection from render layer"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "layer_collection", "LayerCollection", "", "Layer collection to remove from render layer"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); +} + +static void rna_def_layer_objects(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + RNA_def_property_srna(cprop, "LayerObjects"); + srna = RNA_def_struct(brna, "LayerObjects", NULL); + RNA_def_struct_sdna(srna, "SceneLayer"); + RNA_def_struct_ui_text(srna, "Layer Objects", "Collections of objects"); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_pointer_funcs(prop, "rna_LayerObjects_active_object_get", "rna_LayerObjects_active_object_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Object", "Active object for this layer"); + /* Could call: ED_base_object_activate(C, rl->basact); + * but would be a bad level call and it seems the notifier is enough */ + RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL); + + prop = RNA_def_property(srna, "selected", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, "rna_LayerObjects_selected_begin", "rna_iterator_listbase_next", + "rna_iterator_listbase_end", "rna_SceneLayer_objects_get", + NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Selected Objects", "All the selected objects of this layer"); +} + +static void rna_def_scene_layer(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem engine_items[] = { + {0, "BLENDER_RENDER", 0, "Blender Render", "Use the Blender internal rendering engine for rendering"}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "SceneLayer", NULL); + RNA_def_struct_ui_text(srna, "Render Layer", "Render layer"); + RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneLayer_name_set"); + RNA_def_property_ui_text(prop, "Name", "Render layer name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "layer_collections", NULL); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_ui_text(prop, "Layer Collections", ""); + rna_def_layer_collections(brna, prop); + + prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneLayer_objects_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Objects", "All the objects in this layer"); + rna_def_layer_objects(brna, prop); + + /* layer options */ + prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SCENE_LAYER_RENDER); + RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render layer"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + /* engine */ + prop = RNA_def_property(srna, "engine", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, engine_items); + RNA_def_property_enum_funcs(prop, "rna_SceneLayer_engine_get", "rna_SceneLayer_engine_set", + "rna_SceneLayer_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_SceneLayer_engine_update"); + + prop = RNA_def_property(srna, "has_multiple_engines", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_SceneLayer_multiple_engines_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Multiple Engines", "More than one rendering engine is available"); +} + +static void rna_def_scene_layers(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + PropertyRNA *prop; + + RNA_def_property_srna(cprop, "SceneLayers"); + srna = RNA_def_struct(brna, "SceneLayers", NULL); + RNA_def_struct_sdna(srna, "Scene"); + RNA_def_struct_ui_text(srna, "Render Layers", "Collection of render layers"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "active_layer"); + RNA_def_property_int_funcs(prop, "rna_SceneLayer_active_layer_index_get", + "rna_SceneLayer_active_layer_index_set", + "rna_SceneLayer_active_layer_index_range"); + RNA_def_property_ui_text(prop, "Active Layer Index", "Active index in render layer array"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "SceneLayer"); + RNA_def_property_pointer_funcs(prop, "rna_SceneLayer_active_layer_get", + "rna_SceneLayer_active_layer_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL); + RNA_def_property_ui_text(prop, "Active Render Layer", "Active Render Layer"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + func = RNA_def_function(srna, "new", "rna_SceneLayer_new"); + RNA_def_function_ui_description(func, "Add a render layer to scene"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_string(func, "name", "SceneLayer", 0, "", "New name for the render layer (not unique)"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "SceneLayer", "", "Newly created render layer"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_SceneLayer_remove"); + RNA_def_function_ui_description(func, "Remove a render layer"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS | FUNC_USE_SELF_ID); + parm = RNA_def_pointer(func, "layer", "SceneLayer", "", "Render layer to remove"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); +} + +static void rna_def_object_base(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ObjectBase", NULL); + RNA_def_struct_sdna(srna, "Base"); + RNA_def_struct_ui_text(srna, "Object Base", "An object instance in a render layer"); + RNA_def_struct_ui_icon(srna, ICON_OBJECT_DATA); + + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "object"); + RNA_def_property_ui_text(prop, "Object", "Object this base links to"); + + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_SELECTED); + RNA_def_property_ui_text(prop, "Select", "Object base selection state"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ObjectBase_select_update"); +} + +/* TODO LAYERS: legacy SceneRenderLayers, to be removed */ static void rna_def_scene_render_layer(BlenderRNA *brna) { @@ -5774,6 +6893,115 @@ static void rna_def_scene_quicktime_settings(BlenderRNA *brna) } #endif +#ifdef WITH_CLAY_ENGINE +static void rna_def_render_engine_settings_clay(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + static EnumPropertyItem clay_matcap_items[] = { + {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""}, + {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""}, + {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""}, + {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""}, + {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""}, + {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""}, + {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""}, + {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""}, + {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""}, + {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""}, + {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""}, + {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""}, + {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""}, + {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""}, + {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""}, + {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""}, + {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""}, + {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""}, + {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""}, + {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""}, + {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""}, + {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""}, + {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""}, + {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "RenderEngineSettingsClay", "RenderEngineSettings"); + RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block"); + RNA_def_struct_sdna_from(srna, "RenderEngineSettingsClay", "data"); + + prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, clay_matcap_items); + RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material"); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "matcap_rot"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model"); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap"); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "matcap_sat"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap"); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "matcap_val"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap"); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect"); + RNA_def_property_range(prop, 0.0f, 250.0f); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect"); + RNA_def_property_range(prop, 0.0f, 250.0f); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect"); + RNA_def_property_range(prop, 0.0f, 100000.0f); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant"); + RNA_def_property_range(prop, 1.0f, 100000.0f); + RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3); + RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update"); + + /* Clay settings */ + prop = RNA_def_property(srna, "ssao_samples", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, "Samples", "Number of samples"); + RNA_def_property_range(prop, 1, 500); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); +} +#endif + +static void rna_def_scene_render_engine(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "RenderEngineSettings", NULL); + RNA_def_struct_ui_text(srna, "Render Engine Settings", "Engine specific render settings"); + RNA_def_struct_sdna(srna, "RenderEngineSettings"); + RNA_def_struct_refine_func(srna, "rna_RenderEngineSettings_refine"); + +#ifdef WITH_CLAY_ENGINE + rna_def_render_engine_settings_clay(brna); +#endif +} + static void rna_def_scene_render_data(BlenderRNA *brna) { StructRNA *srna; @@ -6760,7 +7988,7 @@ static void rna_def_scene_objects(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "object", "Object", "", "Object to add to scene"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); - parm = RNA_def_pointer(func, "base", "ObjectBase", "", "The newly created base"); + parm = RNA_def_pointer(func, "base", "ObjectBaseLegacy", "", "The newly created base"); RNA_def_function_return(func, parm); func = RNA_def_function(srna, "unlink", "rna_Scene_object_unlink"); @@ -6795,7 +8023,7 @@ static void rna_def_scene_bases(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_struct_ui_text(srna, "Scene Bases", "Collection of scene bases"); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "ObjectBase"); + RNA_def_property_struct_type(prop, "ObjectBaseLegacy"); RNA_def_property_pointer_sdna(prop, NULL, "basact"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Base", "Active object base in the scene"); @@ -7039,7 +8267,7 @@ void RNA_def_scene(BlenderRNA *brna) /* Bases/Objects */ prop = RNA_def_property(srna, "object_bases", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "base", NULL); - RNA_def_property_struct_type(prop, "ObjectBase"); + RNA_def_property_struct_type(prop, "ObjectBaseLegacy"); RNA_def_property_ui_text(prop, "Bases", ""); RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, "rna_Scene_object_bases_lookup_string", NULL); @@ -7269,7 +8497,17 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "r"); RNA_def_property_struct_type(prop, "RenderSettings"); RNA_def_property_ui_text(prop, "Render Data", ""); - + + /* Render Engine Data */ + prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "RenderEngineSettings"); + RNA_def_property_ui_text(prop, "Render Engine Settings", "Engine specific render settings"); + + prop = RNA_def_property(srna, "active_engine_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "RenderEngineSettings"); + RNA_def_property_pointer_funcs(prop, "rna_RenderEngineSettings_active_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Active Render Engine Settings", "Active Engine specific render settings for this scene"); + /* Safe Areas */ prop = RNA_def_property(srna, "safe_areas", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "safe_areas"); @@ -7385,6 +8623,19 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Depsgraph"); RNA_def_property_ui_text(prop, "Dependency Graph", "Dependencies in the scene data"); + /* Layer and Collections */ + prop = RNA_def_property(srna, "render_layers", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "render_layers", NULL); + RNA_def_property_struct_type(prop, "SceneLayer"); + RNA_def_property_ui_text(prop, "Render Layers", ""); + rna_def_scene_layers(brna, prop); + + prop = RNA_def_property(srna, "master_collection", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "collection"); + RNA_def_property_struct_type(prop, "SceneCollection"); + RNA_def_property_ui_text(prop, "Master Collection", "Collection that contains all other collections"); + /* Nestled Data */ /* *** Non-Animated *** */ RNA_define_animate_sdna(false); @@ -7400,9 +8651,16 @@ void RNA_def_scene(BlenderRNA *brna) rna_def_transform_orientation(brna); rna_def_selected_uv_element(brna); rna_def_display_safe_areas(brna); + rna_def_scene_collection(brna); + rna_def_layer_collection(brna); + rna_def_layer_collection_override(brna); + rna_def_layer_collection_engine_settings(brna); + rna_def_scene_layer(brna); + rna_def_object_base(brna); RNA_define_animate_sdna(true); /* *** Animated *** */ rna_def_scene_render_data(brna); + rna_def_scene_render_engine(brna); rna_def_scene_render_layer(brna); rna_def_gpu_fx(brna); rna_def_scene_render_view(brna); @@ -7412,3 +8670,5 @@ void RNA_def_scene(BlenderRNA *brna) } #endif + +#undef NO_ENGINE diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 92e7d9a7939..aa3346ec653 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -79,6 +79,7 @@ EnumPropertyItem rna_enum_space_type_items[] = { {0, "", ICON_NONE, NULL, NULL}, {SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related data-blocks"}, {SPACE_OUTLINER, "OUTLINER", ICON_OOPS, "Outliner", "Overview of scene graph and all available data-blocks"}, + {SPACE_COLLECTIONS, "COLLECTION_MANAGER", ICON_COLLAPSEMENU, "Collections", "Edit collections of active render layer"}, {SPACE_USERPREF, "USER_PREFERENCES", ICON_PREFERENCES, "User Preferences", "Edit persistent configuration settings"}, {SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages (drag down to expand and display)"}, {0, "", ICON_NONE, NULL, NULL}, @@ -210,6 +211,7 @@ static EnumPropertyItem buttons_context_items[] = { {BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"}, {BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"}, {BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"}, + {BCONTEXT_COLLECTION, "COLLECTION", ICON_COLLAPSEMENU, "Collection", "Collection"}, {0, NULL, 0, NULL, NULL} }; @@ -317,6 +319,8 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr) return &RNA_SpaceUserPreferences; case SPACE_CLIP: return &RNA_SpaceClipEditor; + case SPACE_COLLECTIONS: + return &RNA_SpaceCollectionManager; default: return &RNA_Space; } @@ -1080,6 +1084,10 @@ static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSED(C), RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_SCENE); } + if (sbuts->pathflag & (1 << BCONTEXT_COLLECTION)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_COLLECTION); + } + if (sbuts->pathflag & (1 << BCONTEXT_WORLD)) { RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_WORLD); } @@ -2104,6 +2112,7 @@ static void rna_def_space_outliner(BlenderRNA *brna) {SO_USERDEF, "USER_PREFERENCES", 0, "User Preferences", "Display user preference data"}, {SO_ID_ORPHANS, "ORPHAN_DATA", 0, "Orphan Data", "Display data-blocks which are unused and/or will be lost when the file is reloaded"}, + {SO_COLLECTIONS, "COLLECTIONS", 0, "Collections", "Display the collections of the active render layer"}, {0, NULL, 0, NULL, NULL} }; @@ -4815,6 +4824,15 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL); } +static void rna_def_space_collections(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "SpaceCollectionManager", "Space"); + RNA_def_struct_sdna(srna, "SpaceCollections"); + RNA_def_struct_ui_text(srna, "Space Collection Manager", "Layer Collection space data"); +} + void RNA_def_space(BlenderRNA *brna) { @@ -4841,6 +4859,7 @@ void RNA_def_space(BlenderRNA *brna) rna_def_space_node(brna); rna_def_space_logic(brna); rna_def_space_clip(brna); + rna_def_space_collections(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 57db23563f5..06b8e6e0737 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2956,6 +2956,26 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna) rna_def_userdef_theme_spaces_curves(srna, false, false, false, true); } +static void rna_def_userdef_theme_space_collections(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ThemeCollectionManager", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Theme Collection Manager", "Theme settings for the Collection Manager"); + + rna_def_userdef_theme_spaces_main(srna); + rna_def_userdef_theme_spaces_list_main(srna); + + prop = RNA_def_property(srna, "selected_collection", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "hilite"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Selected Collection", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); +} + static void rna_def_userdef_themes(BlenderRNA *brna) { StructRNA *srna; @@ -2982,6 +3002,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna) {16, "FILE_BROWSER", ICON_FILESEL, "File Browser", ""}, {17, "CONSOLE", ICON_CONSOLE, "Python Console", ""}, {20, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", ""}, + {21, "COLLECTION_MANAGER", ICON_COLLAPSEMENU, "Collection Manager", ""}, {0, NULL, 0, NULL, NULL} }; @@ -3115,6 +3136,12 @@ static void rna_def_userdef_themes(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "tclip"); RNA_def_property_struct_type(prop, "ThemeClipEditor"); RNA_def_property_ui_text(prop, "Clip Editor", ""); + + prop = RNA_def_property(srna, "collection_manager", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "tcollections"); + RNA_def_property_struct_type(prop, "ThemeCollectionManager"); + RNA_def_property_ui_text(prop, "Collection Manager", ""); } static void rna_def_userdef_addon(BlenderRNA *brna) @@ -3205,6 +3232,7 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna) rna_def_userdef_theme_space_console(brna); rna_def_userdef_theme_space_logic(brna); rna_def_userdef_theme_space_clip(brna); + rna_def_userdef_theme_space_collections(brna); rna_def_userdef_theme_colorset(brna); rna_def_userdef_themes(brna); } @@ -3937,7 +3965,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dpi"); - RNA_def_property_range(prop, 16, 256); + RNA_def_property_range(prop, 48, 144); RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 8efa4d63675..8aee7b66916 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -96,7 +96,7 @@ static void foreachObjectLink( { ArmatureModifierData *amd = (ArmatureModifierData *) md; - walk(userData, ob, &amd->object, IDWALK_NOP); + walk(userData, ob, &amd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 6017f964c26..61ac4d5692f 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -95,10 +95,10 @@ static void foreachObjectLink( { ArrayModifierData *amd = (ArrayModifierData *) md; - walk(userData, ob, &amd->start_cap, IDWALK_NOP); - walk(userData, ob, &amd->end_cap, IDWALK_NOP); - walk(userData, ob, &amd->curve_ob, IDWALK_NOP); - walk(userData, ob, &amd->offset_ob, IDWALK_NOP); + walk(userData, ob, &amd->start_cap, IDWALK_CB_NOP); + walk(userData, ob, &amd->end_cap, IDWALK_CB_NOP); + walk(userData, ob, &amd->curve_ob, IDWALK_CB_NOP); + walk(userData, ob, &amd->offset_ob, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index d2f19b78b50..51020566de6 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -101,7 +101,7 @@ static void foreachObjectLink( { BooleanModifierData *bmd = (BooleanModifierData *) md; - walk(userData, ob, &bmd->object, IDWALK_NOP); + walk(userData, ob, &bmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 16c5de45c49..9e718eab639 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -102,7 +102,7 @@ static void foreachObjectLink( { CastModifierData *cmd = (CastModifierData *) md; - walk(userData, ob, &cmd->object, IDWALK_NOP); + walk(userData, ob, &cmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index b6a7b5b57ec..59eb00207df 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -214,11 +214,11 @@ static void foreachIDLink(ModifierData *md, Object *ob, ClothModifierData *clmd = (ClothModifierData *) md; if (clmd->coll_parms) { - walk(userData, ob, (ID **)&clmd->coll_parms->group, IDWALK_NOP); + walk(userData, ob, (ID **)&clmd->coll_parms->group, IDWALK_CB_NOP); } if (clmd->sim_parms && clmd->sim_parms->effector_weights) { - walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_NOP); + walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_CB_NOP); } } diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 3e9b46ad8ea..6f3dbe841aa 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -89,7 +89,7 @@ static void foreachObjectLink( { CurveModifierData *cmd = (CurveModifierData *) md; - walk(userData, ob, &cmd->object, IDWALK_NOP); + walk(userData, ob, &cmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 26952e1e0d5..3bddbc7ee2b 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -124,7 +124,7 @@ static void foreachObjectLink( ObjectWalkFunc walk, void *userData) { DataTransferModifierData *dtmd = (DataTransferModifierData *) md; - walk(userData, ob, &dtmd->ob_source, IDWALK_NOP); + walk(userData, ob, &dtmd->ob_source, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, @@ -163,7 +163,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der /* Only used to check wehther we are operating on org data or not... */ Mesh *me = ob->data; - MVert *mvert; const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0; @@ -176,8 +175,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der BLI_SPACE_TRANSFORM_SETUP(space_transform, ob, dtmd->ob_source); } - mvert = dm->getVertArray(dm); - if ((me->mvert == mvert) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) { + MVert *mvert = dm->getVertArray(dm); + MEdge *medge = dm->getEdgeArray(dm); + if (((me->mvert == mvert) || (me->medge == medge)) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) { /* We need to duplicate data here, otherwise setting custom normals, edges' shaprness, etc., could * modify org mesh, see T43671. */ dm = CDDM_copy(dm); @@ -195,6 +195,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der if (BKE_reports_contain(&reports, RPT_ERROR)) { modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR)); } + else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) { + modifier_setError((ModifierData *)dtmd, "Enable 'Auto Smooth' option in mesh settings"); + } else if (dm->getNumVerts(dm) > HIGH_POLY_WARNING || ((Mesh *)(dtmd->ob_source->data))->totvert > HIGH_POLY_WARNING) { modifier_setError(md, "You are using a rather high poly as source or destination, computation might be slow"); } diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 4b5181e9c61..43e7ac238d1 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -38,10 +38,12 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BLI_task.h" #include "BKE_cdderivedmesh.h" #include "BKE_library.h" #include "BKE_library_query.h" +#include "BKE_image.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_texture.h" @@ -132,7 +134,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob, { DisplaceModifierData *dmd = (DisplaceModifierData *) md; - walk(userData, ob, &dmd->map_object, IDWALK_NOP); + walk(userData, ob, &dmd->map_object, IDWALK_CB_NOP); } static void foreachIDLink(ModifierData *md, Object *ob, @@ -140,7 +142,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, { DisplaceModifierData *dmd = (DisplaceModifierData *) md; - walk(userData, ob, (ID **)&dmd->texture, IDWALK_USER); + walk(userData, ob, (ID **)&dmd->texture, IDWALK_CB_USER); foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } @@ -175,21 +177,130 @@ static void updateDepsgraph(ModifierData *md, } } +typedef struct DisplaceUserdata { + /*const*/ DisplaceModifierData *dmd; + struct ImagePool *pool; + MDeformVert *dvert; + float weight; + int defgrp_index; + int direction; + bool use_global_direction; + float (*tex_co)[3]; + float (*vertexCos)[3]; + float local_mat[4][4]; + MVert *mvert; + float (*vert_clnors)[3]; +} DisplaceUserdata; + +static void displaceModifier_do_task(void *userdata, const int iter) +{ + DisplaceUserdata *data = (DisplaceUserdata *)userdata; + DisplaceModifierData *dmd = data->dmd; + MDeformVert *dvert = data->dvert; + float weight = data->weight; + int defgrp_index = data->defgrp_index; + int direction = data->direction; + bool use_global_direction = data->use_global_direction; + float (*tex_co)[3] = data->tex_co; + float (*vertexCos)[3] = data->vertexCos; + MVert *mvert = data->mvert; + float (*vert_clnors)[3] = data->vert_clnors; + + const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */ + + TexResult texres; + float strength = dmd->strength; + float delta; + float local_vec[3]; + + if (dvert) { + weight = defvert_find_weight(dvert + iter, defgrp_index); + if (weight == 0.0f) { + return; + } + } + + if (dmd->texture) { + texres.nor = NULL; + BKE_texture_get_value_ex(dmd->modifier.scene, dmd->texture, tex_co[iter], &texres, data->pool, false); + delta = texres.tin - dmd->midlevel; + } + else { + delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */ + } + + if (dvert) { + strength *= weight; + } + + delta *= strength; + CLAMP(delta, -10000, 10000); + + switch (direction) { + case MOD_DISP_DIR_X: + if (use_global_direction) { + vertexCos[iter][0] += delta * data->local_mat[0][0]; + vertexCos[iter][1] += delta * data->local_mat[1][0]; + vertexCos[iter][2] += delta * data->local_mat[2][0]; + } + else { + vertexCos[iter][0] += delta; + } + break; + case MOD_DISP_DIR_Y: + if (use_global_direction) { + vertexCos[iter][0] += delta * data->local_mat[0][1]; + vertexCos[iter][1] += delta * data->local_mat[1][1]; + vertexCos[iter][2] += delta * data->local_mat[2][1]; + } + else { + vertexCos[iter][1] += delta; + } + break; + case MOD_DISP_DIR_Z: + if (use_global_direction) { + vertexCos[iter][0] += delta * data->local_mat[0][2]; + vertexCos[iter][1] += delta * data->local_mat[1][2]; + vertexCos[iter][2] += delta * data->local_mat[2][2]; + } + else { + vertexCos[iter][2] += delta; + } + break; + case MOD_DISP_DIR_RGB_XYZ: + local_vec[0] = texres.tr - dmd->midlevel; + local_vec[1] = texres.tg - dmd->midlevel; + local_vec[2] = texres.tb - dmd->midlevel; + if (use_global_direction) { + mul_transposed_mat3_m4_v3(data->local_mat, local_vec); + } + mul_v3_fl(local_vec, strength); + add_v3_v3(vertexCos[iter], local_vec); + break; + case MOD_DISP_DIR_NOR: + vertexCos[iter][0] += delta * (mvert[iter].no[0] / 32767.0f); + vertexCos[iter][1] += delta * (mvert[iter].no[1] / 32767.0f); + vertexCos[iter][2] += delta * (mvert[iter].no[2] / 32767.0f); + break; + case MOD_DISP_DIR_CLNOR: + madd_v3_v3fl(vertexCos[iter], vert_clnors[iter], delta); + break; + } +} + /* dm must be a CDDerivedMesh */ static void displaceModifier_do( DisplaceModifierData *dmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { - int i; MVert *mvert; MDeformVert *dvert; int direction = dmd->direction; int defgrp_index; float (*tex_co)[3]; float weight = 1.0f; /* init value unused but some compilers may complain */ - const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */ float (*vert_clnors)[3] = NULL; - float local_mat[4][4]; + float local_mat[4][4] = {0}; const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL; if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return; @@ -234,81 +345,25 @@ static void displaceModifier_do( copy_m4_m4(local_mat, ob->obmat); } - for (i = 0; i < numVerts; i++) { - TexResult texres; - float strength = dmd->strength; - float delta; - float local_vec[3]; - - if (dvert) { - weight = defvert_find_weight(dvert + i, defgrp_index); - if (weight == 0.0f) continue; - } - - if (dmd->texture) { - texres.nor = NULL; - BKE_texture_get_value(dmd->modifier.scene, dmd->texture, tex_co[i], &texres, false); - delta = texres.tin - dmd->midlevel; - } - else { - delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */ - } + DisplaceUserdata data = {NULL}; + data.dmd = dmd; + data.dvert = dvert; + data.weight = weight; + data.defgrp_index = defgrp_index; + data.direction = direction; + data.use_global_direction = use_global_direction; + data.tex_co = tex_co; + data.vertexCos = vertexCos; + copy_m4_m4(data.local_mat, local_mat); + data.mvert = mvert; + data.vert_clnors = vert_clnors; + if (dmd->texture != NULL) { + data.pool = BKE_image_pool_new(); + } + BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512); - if (dvert) strength *= weight; - - delta *= strength; - CLAMP(delta, -10000, 10000); - - switch (direction) { - case MOD_DISP_DIR_X: - if (use_global_direction) { - vertexCos[i][0] += delta * local_mat[0][0]; - vertexCos[i][1] += delta * local_mat[1][0]; - vertexCos[i][2] += delta * local_mat[2][0]; - } - else { - vertexCos[i][0] += delta; - } - break; - case MOD_DISP_DIR_Y: - if (use_global_direction) { - vertexCos[i][0] += delta * local_mat[0][1]; - vertexCos[i][1] += delta * local_mat[1][1]; - vertexCos[i][2] += delta * local_mat[2][1]; - } - else { - vertexCos[i][1] += delta; - } - break; - case MOD_DISP_DIR_Z: - if (use_global_direction) { - vertexCos[i][0] += delta * local_mat[0][2]; - vertexCos[i][1] += delta * local_mat[1][2]; - vertexCos[i][2] += delta * local_mat[2][2]; - } - else { - vertexCos[i][2] += delta; - } - break; - case MOD_DISP_DIR_RGB_XYZ: - local_vec[0] = texres.tr - dmd->midlevel; - local_vec[1] = texres.tg - dmd->midlevel; - local_vec[2] = texres.tb - dmd->midlevel; - if (use_global_direction) { - mul_transposed_mat3_m4_v3(local_mat, local_vec); - } - mul_v3_fl(local_vec, strength); - add_v3_v3(vertexCos[i], local_vec); - break; - case MOD_DISP_DIR_NOR: - vertexCos[i][0] += delta * (mvert[i].no[0] / 32767.0f); - vertexCos[i][1] += delta * (mvert[i].no[1] / 32767.0f); - vertexCos[i][2] += delta * (mvert[i].no[2] / 32767.0f); - break; - case MOD_DISP_DIR_CLNOR: - madd_v3_v3fl(vertexCos[i], vert_clnors[i], delta); - break; - } + if (data.pool != NULL) { + BKE_image_pool_free(data.pool); } if (tex_co) { diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index ee6df153905..794d8bf6951 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -153,15 +153,15 @@ static void foreachIDLink(ModifierData *md, Object *ob, DynamicPaintSurface *surface = pmd->canvas->surfaces.first; for (; surface; surface = surface->next) { - walk(userData, ob, (ID **)&surface->brush_group, IDWALK_NOP); - walk(userData, ob, (ID **)&surface->init_texture, IDWALK_USER); + walk(userData, ob, (ID **)&surface->brush_group, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&surface->init_texture, IDWALK_CB_USER); if (surface->effector_weights) { - walk(userData, ob, (ID **)&surface->effector_weights->group, IDWALK_NOP); + walk(userData, ob, (ID **)&surface->effector_weights->group, IDWALK_CB_NOP); } } } if (pmd->brush) { - walk(userData, ob, (ID **)&pmd->brush->mat, IDWALK_USER); + walk(userData, ob, (ID **)&pmd->brush->mat, IDWALK_CB_USER); } } diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index dea1f9d8d4c..24ce2e3cc8e 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -1001,8 +1001,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, ExplodeModifierData *emd = (ExplodeModifierData *) md; ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ob, md); - DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ - if (psmd) { ParticleSystem *psys = psmd->psys; @@ -1010,6 +1008,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (psys->part == NULL || psys->particles == NULL) return derivedData; if (psmd->dm_final == NULL) return derivedData; + DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ + /* 1. find faces to be exploded if needed */ if (emd->facepa == NULL || psmd->flag & eParticleSystemFlag_Pars || diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c index bed25fa82db..35e9afe722b 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim.c +++ b/source/blender/modifiers/intern/MOD_fluidsim.c @@ -109,7 +109,7 @@ static void updateDepsgraph(ModifierData *md, FluidsimModifierData *fluidmd = (FluidsimModifierData *) md; if (fluidmd && fluidmd->fss) { if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) { - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { Object *ob1 = base->object; if (ob1 != ob) { diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 13d94abc92d..210e91d159a 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -115,7 +115,7 @@ static void foreachObjectLink( { HookModifierData *hmd = (HookModifierData *) md; - walk(userData, ob, &hmd->object, IDWALK_NOP); + walk(userData, ob, &hmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 292c2db61f8..2e02ab29d5f 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -88,7 +88,7 @@ static void foreachObjectLink( { LatticeModifierData *lmd = (LatticeModifierData *) md; - walk(userData, ob, &lmd->object, IDWALK_NOP); + walk(userData, ob, &lmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c index 7cb2f2c25d5..1c4406e1a4f 100644 --- a/source/blender/modifiers/intern/MOD_mask.c +++ b/source/blender/modifiers/intern/MOD_mask.c @@ -74,7 +74,7 @@ static void foreachObjectLink( ObjectWalkFunc walk, void *userData) { MaskModifierData *mmd = (MaskModifierData *)md; - walk(userData, ob, &mmd->ob_arm, IDWALK_NOP); + walk(userData, ob, &mmd->ob_arm, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 27782b05cd2..ed1f5e8938b 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -119,7 +119,7 @@ static void foreachObjectLink( { MeshDeformModifierData *mmd = (MeshDeformModifierData *) md; - walk(userData, ob, &mmd->object, IDWALK_NOP); + walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 985c365bb69..0b9298a26a6 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -151,7 +151,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, { MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; - walk(userData, ob, (ID **)&mcmd->cache_file, IDWALK_USER); + walk(userData, ob, (ID **)&mcmd->cache_file, IDWALK_CB_USER); } diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 9fdd75aeb68..8c01c560e75 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -72,7 +72,7 @@ static void foreachObjectLink( { MirrorModifierData *mmd = (MirrorModifierData *) md; - walk(userData, ob, &mmd->mirror_ob, IDWALK_NOP); + walk(userData, ob, &mmd->mirror_ob, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index eefca658305..b73f1074bc1 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -501,7 +501,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, { NormalEditModifierData *enmd = (NormalEditModifierData *) md; - walk(userData, ob, &enmd->target, IDWALK_NOP); + walk(userData, ob, &enmd->target, IDWALK_CB_NOP); } static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index a468cc6600d..9d8e1e181a4 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -127,7 +127,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob, { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md; - walk(userData, ob, &pimd->ob, IDWALK_NOP); + walk(userData, ob, &pimd->ob, IDWALK_CB_NOP); } static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p) diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index a834d1b5cae..1273a3a6e09 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -1075,7 +1075,7 @@ static void foreachObjectLink( { ScrewModifierData *ltmd = (ScrewModifierData *) md; - walk(userData, ob, <md->ob_axis, IDWALK_NOP); + walk(userData, ob, <md->ob_axis, IDWALK_CB_NOP); } ModifierTypeInfo modifierType_Screw = { diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index 29bce2ef3a4..d6d8c931c35 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -101,8 +101,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *) md; - walk(userData, ob, &smd->target, IDWALK_NOP); - walk(userData, ob, &smd->auxTarget, IDWALK_NOP); + walk(userData, ob, &smd->target, IDWALK_CB_NOP); + walk(userData, ob, &smd->auxTarget, IDWALK_CB_NOP); } static void deformVerts(ModifierData *md, Object *ob, diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 118d0117361..7c12de9059e 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -290,7 +290,7 @@ static void foreachObjectLink( ObjectWalkFunc walk, void *userData) { SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md; - walk(userData, ob, &smd->origin, IDWALK_NOP); + walk(userData, ob, &smd->origin, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index 637ed3ee390..8ba39819b5e 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -152,17 +152,17 @@ static void foreachIDLink(ModifierData *md, Object *ob, SmokeModifierData *smd = (SmokeModifierData *) md; if (smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain) { - walk(userData, ob, (ID **)&smd->domain->coll_group, IDWALK_NOP); - walk(userData, ob, (ID **)&smd->domain->fluid_group, IDWALK_NOP); - walk(userData, ob, (ID **)&smd->domain->eff_group, IDWALK_NOP); + walk(userData, ob, (ID **)&smd->domain->coll_group, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&smd->domain->fluid_group, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&smd->domain->eff_group, IDWALK_CB_NOP); if (smd->domain->effector_weights) { - walk(userData, ob, (ID **)&smd->domain->effector_weights->group, IDWALK_NOP); + walk(userData, ob, (ID **)&smd->domain->effector_weights->group, IDWALK_CB_NOP); } } if (smd->type == MOD_SMOKE_TYPE_FLOW && smd->flow) { - walk(userData, ob, (ID **)&smd->flow->noise_texture, IDWALK_USER); + walk(userData, ob, (ID **)&smd->flow->noise_texture, IDWALK_CB_USER); } } diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 54c25b687e1..fdbf4f47ce8 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -92,7 +92,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob, int i; for (i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i) - walk(userData, ob, &umd->projectors[i], IDWALK_NOP); + walk(userData, ob, &umd->projectors[i], IDWALK_CB_NOP); } static void foreachIDLink(ModifierData *md, Object *ob, @@ -100,7 +100,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, { UVProjectModifierData *umd = (UVProjectModifierData *) md; - walk(userData, ob, (ID **)&umd->image, IDWALK_USER); + walk(userData, ob, (ID **)&umd->image, IDWALK_CB_USER); foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 2ac6892b7b8..072267fc505 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -221,8 +221,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, { UVWarpModifierData *umd = (UVWarpModifierData *) md; - walk(userData, ob, &umd->object_dst, IDWALK_NOP); - walk(userData, ob, &umd->object_src, IDWALK_NOP); + walk(userData, ob, &umd->object_dst, IDWALK_CB_NOP); + walk(userData, ob, &umd->object_src, IDWALK_CB_NOP); } static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode, diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 13ce72ee2f5..8c6b94e5c79 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -116,16 +116,16 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, { WarpModifierData *wmd = (WarpModifierData *) md; - walk(userData, ob, &wmd->object_from, IDWALK_NOP); - walk(userData, ob, &wmd->object_to, IDWALK_NOP); - walk(userData, ob, &wmd->map_object, IDWALK_NOP); + walk(userData, ob, &wmd->object_from, IDWALK_CB_NOP); + walk(userData, ob, &wmd->object_to, IDWALK_CB_NOP); + walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP); } static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WarpModifierData *wmd = (WarpModifierData *) md; - walk(userData, ob, (ID **)&wmd->texture, IDWALK_USER); + walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER); foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 291913675c3..a60607cf372 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -111,8 +111,8 @@ static void foreachObjectLink( { WaveModifierData *wmd = (WaveModifierData *) md; - walk(userData, ob, &wmd->objectcenter, IDWALK_NOP); - walk(userData, ob, &wmd->map_object, IDWALK_NOP); + walk(userData, ob, &wmd->objectcenter, IDWALK_CB_NOP); + walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP); } static void foreachIDLink(ModifierData *md, Object *ob, @@ -120,7 +120,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, { WaveModifierData *wmd = (WaveModifierData *) md; - walk(userData, ob, (ID **)&wmd->texture, IDWALK_USER); + walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER); foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 585b223d436..57a10a24411 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -126,14 +126,14 @@ static bool dependsOnTime(ModifierData *md) static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md; - walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP); + walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP); } static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md; - walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER); + walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER); foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index a6adf72e4eb..9ab8fb4e0ff 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -175,14 +175,14 @@ static bool dependsOnTime(ModifierData *md) static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; - walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP); + walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP); } static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; - walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER); + walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER); foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index b26cbc3a7d3..126a1f951ca 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -325,15 +325,15 @@ static bool dependsOnTime(ModifierData *md) static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md; - walk(userData, ob, &wmd->proximity_ob_target, IDWALK_NOP); - walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP); + walk(userData, ob, &wmd->proximity_ob_target, IDWALK_CB_NOP); + walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP); } static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md; - walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER); + walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER); foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index df1c4155a6d..b8c9b3ff9e9 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -174,6 +174,7 @@ static eSpace_Type rna_Space_refine_reverse(StructRNA *srna) if (srna == &RNA_SpaceConsole) return SPACE_CONSOLE; if (srna == &RNA_SpaceUserPreferences) return SPACE_USERPREF; if (srna == &RNA_SpaceClipEditor) return SPACE_CLIP; + if (srna == &RNA_SpaceCollectionManager) return SPACE_COLLECTIONS; return SPACE_EMPTY; } diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c index 1037c83815c..72705ffb3fb 100644 --- a/source/blender/python/intern/bpy_rna_id_collection.c +++ b/source/blender/python/intern/bpy_rna_id_collection.c @@ -263,7 +263,7 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject * } data_cb.id_curr = id; - BKE_library_foreach_ID_link(id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_NOP); + BKE_library_foreach_ID_link(NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP); if (data_cb.py_id_curr) { Py_DECREF(data_cb.py_id_curr); diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index 50dd4618166..48230a723d2 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -138,6 +138,7 @@ static PyObject *PyInit_gpu(void) PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_MIR); /* -------------------------------------------------------------------- */ diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 9e40ab02ee4..27fa119bc88 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -35,6 +35,7 @@ set(INC ../makesdna ../makesrna ../physics + ../draw ../../../intern/guardedalloc ../../../intern/mikktspace ../../../intern/smoke/extern diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index f83a210275f..f1b3534b40a 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -39,6 +39,8 @@ struct bNode; struct bNodeTree; +struct CollectionEngineSettings; +struct Main; struct Object; struct Render; struct RenderData; @@ -63,6 +65,7 @@ struct BakePixel; #define RE_USE_TEXTURE_PREVIEW 128 #define RE_USE_SHADING_NODES_CUSTOM 256 #define RE_USE_SPHERICAL_STEREO 512 +#define RE_USE_OGL_PIPELINE 1024 /* RenderEngine.flag */ #define RE_ENGINE_ANIMATION 1 @@ -97,6 +100,8 @@ typedef struct RenderEngineType { void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node); + void (*collection_settings_create)(struct RenderEngine *engine, struct CollectionEngineSettings *ces); + /* RNA integration */ ExtensionRNA ext; } RenderEngineType; @@ -164,6 +169,7 @@ void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe) void RE_engines_init(void); void RE_engines_exit(void); +void RE_engines_register(struct Main *bmain, RenderEngineType *render_type); RenderEngineType *RE_engines_find(const char *idname); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 263ea3d4ef2..094e62e6ceb 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4977,7 +4977,7 @@ static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, in static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset) { - Base *base; + BaseLegacy *base; Object *ob; Group *group; ObjectInstanceRen *obi; diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index d97e18d6511..7de20ab2056 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -247,7 +247,7 @@ static void envmap_transmatrix(float mat[4][4], int part) static void env_set_imats(Render *re) { - Base *base; + BaseLegacy *base; float mat[4][4]; base = re->scene->base.first; diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index fd9d95c63b6..1744d88a14f 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -45,6 +45,7 @@ #include "BKE_camera.h" #include "BKE_global.h" #include "BKE_colortools.h" +#include "BKE_layer.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -58,6 +59,8 @@ #include "RE_pipeline.h" #include "RE_bake.h" +#include "DRW_engine.h" + #include "initrender.h" #include "renderpipeline.h" #include "render_types.h" @@ -68,7 +71,7 @@ static RenderEngineType internal_render_type = { NULL, NULL, "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, {NULL, NULL, NULL} }; @@ -77,7 +80,7 @@ static RenderEngineType internal_render_type = { static RenderEngineType internal_game_type = { NULL, NULL, "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME, - NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, {NULL, NULL, NULL} }; @@ -87,16 +90,21 @@ ListBase R_engines = {NULL, NULL}; void RE_engines_init(void) { - BLI_addtail(&R_engines, &internal_render_type); + RE_engines_register(NULL, &internal_render_type); #ifdef WITH_GAMEENGINE - BLI_addtail(&R_engines, &internal_game_type); + RE_engines_register(NULL, &internal_game_type); #endif + DRW_engines_init(); } void RE_engines_exit(void) { RenderEngineType *type, *next; + DRW_engines_free(); + + BKE_layer_collection_engine_settings_callback_free(); + for (type = R_engines.first; type; type = next) { next = type->next; @@ -111,6 +119,14 @@ void RE_engines_exit(void) } } +void RE_engines_register(Main *bmain, RenderEngineType *render_type) +{ + if (render_type->collection_settings_create) { + BKE_layer_collection_engine_settings_callback_register(bmain, render_type->idname, render_type->collection_settings_create); + } + BLI_addtail(&R_engines, render_type); +} + RenderEngineType *RE_engines_find(const char *idname) { RenderEngineType *type; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 52eca5f7005..34966e1b111 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2015,7 +2015,7 @@ bool RE_allow_render_generic_object(Object *ob) static void tag_dependend_objects_for_render(Scene *scene, int renderlay) { Scene *sce_iter; - Base *base; + BaseLegacy *base; for (SETLOOPER(scene, sce_iter, base)) { Object *object = base->object; diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index 6dbcf474e77..1022aeeec66 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -361,6 +361,7 @@ static void init_frame_smoke(VoxelData *vd, int cfra) #else // WITH_SMOKE (void)vd; + (void)cfra; vd->dataset = NULL; #endif diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 3bed4dac2cf..49e70b4f200 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -364,6 +364,7 @@ typedef struct wmNotifier { #define ND_SPACE_CHANGED (18<<16) /*sent to a new editor type after it's replaced an old one*/ #define ND_SPACE_CLIP (19<<16) #define ND_SPACE_FILE_PREVIEW (20<<16) +#define ND_SPACE_COLLECTIONS (21<<16) /* subtype, 256 entries too */ #define NOTE_SUBTYPE 0x0000FF00 diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 85a313b3f81..2d1dcd7f3c9 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -361,8 +361,8 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) drag_rect_minmax(rect, x, y, x + w, y + iconsize); } else { - glColor4ub(255, 255, 255, 255); - UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag)); + const unsigned char col[] = {255, 255, 255, 255}; + UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag), col); } /* operator name with roundbox */ diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index e201fa433d4..4179ac7f993 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -1861,6 +1861,10 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) else if (STRPREFIX(opname, "OUTLINER_OT")) { km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0); } + /* Layer Manager */ + else if (STRPREFIX(opname, "COLLECTIONS_OT")) { + km = WM_keymap_find_all(C, "Collection Manager", sl->spacetype, 0); + } /* Transform */ else if (STRPREFIX(opname, "TRANSFORM_OT")) { /* check for relevant editor */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index a8abc3bb54f..6591005b5f3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3950,8 +3950,12 @@ static void previews_id_ensure(bContext *C, Scene *scene, ID *id) } } -static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int UNUSED(cd_flag)) +static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int cb_flag) { + if (cb_flag & IDWALK_CB_PRIVATE) { + return IDWALK_RET_NOP; + } + PreviewsIDEnsureData *data = userdata; ID *id = *idptr; @@ -3984,7 +3988,7 @@ static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op)) preview_id_data.scene = scene; id = (ID *)scene; - BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE); + BKE_library_foreach_ID_link(NULL, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE); } /* Check a last time for ID not used (fake users only, in theory), and diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 6b615f5a121..0acc66ad9b0 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -45,6 +45,7 @@ struct ARegion; struct ARegionType; struct BMEditMesh; struct Base; +struct BaseLegacy; struct bContext; struct BoundBox; struct Brush; @@ -185,6 +186,7 @@ struct wmWindowManager; #include "../blender/render/extern/include/RE_pipeline.h" #include "../blender/render/extern/include/RE_render_ext.h" #include "../blender/render/extern/include/RE_shader_ext.h" +#include "../blender/draw/DRW_engine.h" #include "../blender/windowmanager/WM_api.h" @@ -237,13 +239,13 @@ struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) void RE_texture_rng_init() RET_NONE void RE_texture_rng_exit() RET_NONE -bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;} +bool RE_layers_have_name(struct RenderResult *result) RET_ZERO const char *RE_engine_active_view_get(struct RenderEngine *engine) RET_NULL -void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);} -void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo, float *r_modelmat) {STUB_ASSERT(0);} +void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) RET_NONE +void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo, float *r_modelmat) RET_NONE float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo) RET_ZERO int RE_engine_get_spherical_stereo(struct RenderEngine *engine, struct Object *camera) RET_ZERO -void RE_SetActiveRenderView(struct Render *re, const char *viewname) {STUB_ASSERT(0);} +void RE_SetActiveRenderView(struct Render *re, const char *viewname) RET_NONE struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL bool RE_HasFakeLayer(RenderResult *res) RET_ZERO @@ -462,17 +464,17 @@ void ED_node_texture_default(const struct bContext *C, struct Tex *tex) RET_NONE void ED_node_tag_update_id(struct ID *id) RET_NONE void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node) RET_NONE void ED_node_tree_update(const struct bContext *C) RET_NONE -void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo){} -void ED_init_custom_node_type(struct bNodeType *ntype){} -void ED_init_custom_node_socket_type(struct bNodeSocketType *stype){} +void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo) RET_NONE +void ED_init_custom_node_type(struct bNodeType *ntype) RET_NONE +void ED_init_custom_node_socket_type(struct bNodeSocketType *stype) RET_NONE void ED_init_standard_node_socket_type(struct bNodeSocketType *stype) RET_NONE void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype) RET_NONE -int ED_node_tree_path_length(struct SpaceNode *snode){return 0;} -void ED_node_tree_path_get(struct SpaceNode *snode, char *value){} -void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length){} -void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from){} -void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode){} -void ED_node_tree_pop(struct SpaceNode *snode){} +int ED_node_tree_path_length(struct SpaceNode *snode) RET_ZERO +void ED_node_tree_path_get(struct SpaceNode *snode, char *value) RET_NONE +void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length) RET_NONE +void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from) RET_NONE +void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode) RET_NONE +void ED_node_tree_pop(struct SpaceNode *snode) RET_NONE int ED_view3d_scene_layer_set(int lay, const int *values, int *active) RET_ZERO void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip) RET_NONE void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) RET_NONE @@ -485,7 +487,8 @@ void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh) RET_NONE struct bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm) RET_NULL -void ED_base_object_select(struct Base *base, short mode) RET_NONE +void ED_base_object_select(struct BaseLegacy *base, short mode) RET_NONE +void ED_object_base_select(struct Base *base, short mode) RET_NONE bool ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain, struct Object *ob, struct ModifierData *md) RET_ZERO struct ModifierData *ED_object_modifier_add(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name, int type) RET_ZERO void ED_object_modifier_clear(struct Main *bmain, struct Object *ob) RET_NONE @@ -506,7 +509,7 @@ void uiLayoutSetAlignment(uiLayout *layout, char alignment) RET_NONE void uiLayoutSetScaleX(struct uiLayout *layout, float scale) RET_NONE void uiLayoutSetScaleY(struct uiLayout *layout, float scale) RET_NONE void uiTemplateIconView(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale) RET_NONE -void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base) RET_NONE +void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *base) RET_NONE void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface) RET_NONE void ED_mesh_vertices_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE @@ -661,6 +664,7 @@ void RE_ReleaseResultImage(struct Render *re) RET_NONE int RE_engine_test_break(struct RenderEngine *engine) RET_ZERO void RE_engines_init() RET_NONE void RE_engines_exit() RET_NONE +void RE_engines_register(struct Main *bmain, RenderEngineType *render_type) RET_NONE void RE_engine_report(struct RenderEngine *engine, int type, const char *msg) RET_NONE ListBase R_engines = {NULL, NULL}; void RE_engine_free(struct RenderEngine *engine) RET_NONE @@ -670,13 +674,16 @@ struct RenderEngine *RE_engine_create(struct RenderEngineType *type) RET_NULL void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe) RET_NONE void RE_FreePersistentData(void) RET_NONE void RE_point_density_cache(struct Scene *scene, struct PointDensity *pd, const bool use_render_params) RET_NONE -void RE_point_density_minmax(struct Scene *scene, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE; -void RE_point_density_sample(struct Scene *scene, struct PointDensity *pd, int resolution, const bool use_render_params, float *values) RET_NONE; -void RE_point_density_free(struct PointDensity *pd) RET_NONE; +void RE_point_density_minmax(struct Scene *scene, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE +void RE_point_density_sample(struct Scene *scene, struct PointDensity *pd, int resolution, const bool use_render_params, float *values) RET_NONE +void RE_point_density_free(struct PointDensity *pd) RET_NONE void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE void RE_FreeAllPersistentData(void) RET_NONE float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO +/* Draw */ +void *DRW_render_settings_get(struct Scene *scene, const char *engine_name) RET_NULL + /* python */ struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL void WM_operatortype_iter(struct GHashIterator *ghi) RET_NONE @@ -754,7 +761,7 @@ void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb * void macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) RET_ZERO struct PyObject *pyrna_id_CreatePyObject(struct ID *id) RET_NULL -void BPY_context_update(struct bContext *C) RET_NONE; +void BPY_context_update(struct bContext *C) RET_NONE const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) RET_ARG(msgid) /* intern/dualcon */ diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 4751e60996d..2aa0145d1f3 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -394,7 +394,7 @@ static void SetDefaultLightMode(Scene* scene) { default_light_mode = false; Scene *sce_iter; - Base *base; + BaseLegacy *base; for (SETLOOPER(scene, sce_iter, base)) { @@ -1736,11 +1736,11 @@ static void UNUSED_FUNCTION(print_active_constraints2)(Object *ob) //not used, u static void blenderSceneSetBackground(Scene *blenderscene) { Scene *it; - Base *base; + BaseLegacy *base; for (SETLOOPER(blenderscene, it, base)) { base->object->lay = base->lay; - base->object->flag = base->flag; + BKE_scene_base_flag_sync_from_base(base); } } @@ -1911,7 +1911,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, Scene *blenderscene = kxscene->GetBlenderScene(); // for SETLOOPER Scene *sce_iter; - Base *base; + BaseLegacy *base; // Get the frame settings of the canvas. // Get the aspect ratio of the canvas as designed by the user. diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 5f490747c2b..b2a480e99ca 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -34,6 +34,7 @@ #endif #include <stdio.h> +#include "DNA_scene_types.h" #include "KX_Light.h" #include "KX_Camera.h" @@ -44,7 +45,6 @@ #include "KX_PyMath.h" #include "DNA_object_types.h" -#include "DNA_scene_types.h" #include "DNA_lamp_types.h" #include "BKE_scene.h" diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index b446acd6e63..469f2d62b76 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -38,7 +38,7 @@ struct GPULamp; struct Scene; -struct Base; +struct BaseLegacy; class KX_Camera; class RAS_IRasterizer; class RAS_ILightObject; @@ -51,7 +51,7 @@ protected: RAS_ILightObject* m_lightobj; class RAS_IRasterizer* m_rasterizer; //needed for registering and replication of lightobj Scene* m_blenderscene; - Base* m_base; + BaseLegacy* m_base; public: KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,RAS_IRasterizer* rasterizer,RAS_ILightObject* lightobj, bool glsl); diff --git a/source/tools b/source/tools -Subproject 6bbb68073bfa11e94bb0b3623db38f847037add +Subproject b11375e89061303401376f7aeae42ac2fd64692 diff --git a/tests/gtests/blenlib/BLI_array_store_test.cc b/tests/gtests/blenlib/BLI_array_store_test.cc index b71dc4575f1..5af6e639e64 100644 --- a/tests/gtests/blenlib/BLI_array_store_test.cc +++ b/tests/gtests/blenlib/BLI_array_store_test.cc @@ -280,8 +280,8 @@ static void testbuffer_run_tests_single( BArrayStore *bs, ListBase *lb) { testbuffer_list_store_populate(bs, lb); - EXPECT_EQ(true, testbuffer_list_validate(lb)); - EXPECT_EQ(true, BLI_array_store_is_valid(bs)); + EXPECT_TRUE(testbuffer_list_validate(lb)); + EXPECT_TRUE(BLI_array_store_is_valid(bs)); #ifdef DEBUG_PRINT print_mem_saved("data", bs); #endif @@ -326,7 +326,7 @@ TEST(array_store, NopState) BArrayStore *bs = BLI_array_store_create(1, 32); const unsigned char data[] = "test"; BArrayState *state = BLI_array_store_state_add(bs, data, sizeof(data) - 1, NULL); - EXPECT_EQ(sizeof(data) - 1, BLI_array_store_state_size_get(state)); + EXPECT_EQ(BLI_array_store_state_size_get(state), sizeof(data) - 1); BLI_array_store_state_remove(bs, state); BLI_array_store_destroy(bs); } @@ -340,7 +340,7 @@ TEST(array_store, Single) size_t data_dst_len; data_dst = (char *)BLI_array_store_state_data_get_alloc(state, &data_dst_len); EXPECT_STREQ(data_src, data_dst); - EXPECT_EQ(sizeof(data_src), data_dst_len); + EXPECT_EQ(data_dst_len, sizeof(data_src)); BLI_array_store_destroy(bs); MEM_freeN((void *)data_dst); } @@ -354,8 +354,8 @@ TEST(array_store, DoubleNop) BArrayState *state_a = BLI_array_store_state_add(bs, data_src, sizeof(data_src), NULL); BArrayState *state_b = BLI_array_store_state_add(bs, data_src, sizeof(data_src), state_a); - EXPECT_EQ(sizeof(data_src), BLI_array_store_calc_size_compacted_get(bs)); - EXPECT_EQ(sizeof(data_src) * 2, BLI_array_store_calc_size_expanded_get(bs)); + EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), sizeof(data_src)); + EXPECT_EQ(BLI_array_store_calc_size_expanded_get(bs), sizeof(data_src) * 2); size_t data_dst_len; @@ -367,7 +367,7 @@ TEST(array_store, DoubleNop) EXPECT_STREQ(data_src, data_dst); MEM_freeN((void *)data_dst); - EXPECT_EQ(sizeof(data_src), data_dst_len); + EXPECT_EQ(data_dst_len, sizeof(data_src)); BLI_array_store_destroy(bs); } @@ -382,8 +382,8 @@ TEST(array_store, DoubleDiff) BArrayState *state_b = BLI_array_store_state_add(bs, data_src_b, sizeof(data_src_b), state_a); size_t data_dst_len; - EXPECT_EQ(sizeof(data_src_a) * 2, BLI_array_store_calc_size_compacted_get(bs)); - EXPECT_EQ(sizeof(data_src_a) * 2, BLI_array_store_calc_size_expanded_get(bs)); + EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), sizeof(data_src_a) * 2); + EXPECT_EQ(BLI_array_store_calc_size_expanded_get(bs), sizeof(data_src_a) * 2); data_dst = (char *)BLI_array_store_state_data_get_alloc(state_a, &data_dst_len); EXPECT_STREQ(data_src_a, data_dst); @@ -423,19 +423,19 @@ TEST(array_store, TextDupeIncreaseDecrease) /* forward */ testbuffer_list_store_populate(bs, &lb); - EXPECT_EQ(true, testbuffer_list_validate(&lb)); - EXPECT_EQ(true, BLI_array_store_is_valid(bs)); - EXPECT_EQ(strlen(D), BLI_array_store_calc_size_compacted_get(bs)); + EXPECT_TRUE(testbuffer_list_validate(&lb)); + EXPECT_TRUE(BLI_array_store_is_valid(bs)); + EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), strlen(D)); testbuffer_list_store_clear(bs, &lb); BLI_listbase_reverse(&lb); /* backwards */ testbuffer_list_store_populate(bs, &lb); - EXPECT_EQ(true, testbuffer_list_validate(&lb)); - EXPECT_EQ(true, BLI_array_store_is_valid(bs)); + EXPECT_TRUE(testbuffer_list_validate(&lb)); + EXPECT_TRUE(BLI_array_store_is_valid(bs)); /* larger since first block doesn't de-duplicate */ - EXPECT_EQ(strlen(D) * 4, BLI_array_store_calc_size_compacted_get(bs)); + EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), strlen(D) * 4); #undef D testbuffer_list_free(&lb); \ @@ -708,7 +708,7 @@ static void random_chunk_mutate_helper( testbuffer_run_tests_single(bs, &lb); size_t expected_size = chunks_per_buffer * chunk_count * stride; - EXPECT_EQ(expected_size, BLI_array_store_calc_size_compacted_get(bs)); + EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), expected_size); BLI_array_store_destroy(bs); @@ -782,8 +782,8 @@ TEST(array_store, PlainTextFiles) /* forwards */ testbuffer_list_store_populate(bs, &lb); - EXPECT_EQ(true, testbuffer_list_validate(&lb)); - EXPECT_EQ(true, BLI_array_store_is_valid(bs)); + EXPECT_TRUE(testbuffer_list_validate(&lb)); + EXPECT_TRUE(BLI_array_store_is_valid(bs)); #ifdef DEBUG_PRINT print_mem_saved("source code forward", bs); #endif @@ -793,8 +793,8 @@ TEST(array_store, PlainTextFiles) /* backwards */ testbuffer_list_store_populate(bs, &lb); - EXPECT_EQ(true, testbuffer_list_validate(&lb)); - EXPECT_EQ(true, BLI_array_store_is_valid(bs)); + EXPECT_TRUE(testbuffer_list_validate(&lb)); + EXPECT_TRUE(BLI_array_store_is_valid(bs)); #ifdef DEBUG_PRINT print_mem_saved("source code backwards", bs); #endif diff --git a/tests/gtests/blenlib/BLI_array_utils_test.cc b/tests/gtests/blenlib/BLI_array_utils_test.cc index eabf5bc72cf..518cd097326 100644 --- a/tests/gtests/blenlib/BLI_array_utils_test.cc +++ b/tests/gtests/blenlib/BLI_array_utils_test.cc @@ -45,50 +45,50 @@ TEST(array_utils, ReverseInt4) TEST(array_utils, FindIndexStringEmpty) { char data[] = "", find = '0'; - EXPECT_EQ(-1, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find)); - EXPECT_EQ(-1, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find)); + EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), -1); + EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), -1); } TEST(array_utils, FindIndexStringSingle) { char data[] = "0", find = '0'; - EXPECT_EQ(0, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find)); - EXPECT_EQ(0, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find)); + EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), 0); + EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), 0); } TEST(array_utils, FindIndexStringSingleMissing) { char data[] = "1", find = '0'; - EXPECT_EQ(-1, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find)); - EXPECT_EQ(-1, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find)); + EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), -1); + EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), -1); } TEST(array_utils, FindIndexString4) { char data[] = "0123", find = '3'; - EXPECT_EQ(3, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find)); - EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find)); + EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), 3); + EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), 3); } TEST(array_utils, FindIndexInt4) { int data[] = {0, 1, 2, 3}, find = 3; - EXPECT_EQ(3, BLI_array_findindex(data, ARRAY_SIZE(data), &find)); - EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find)); + EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 3); + EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 3); } TEST(array_utils, FindIndexInt4_DupeEnd) { int data[] = {0, 1, 2, 0}, find = 0; - EXPECT_EQ(0, BLI_array_findindex(data, ARRAY_SIZE(data), &find)); - EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find)); + EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 0); + EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 3); } TEST(array_utils, FindIndexInt4_DupeMid) { int data[] = {1, 0, 0, 3}, find = 0; - EXPECT_EQ(1, BLI_array_findindex(data, ARRAY_SIZE(data), &find)); - EXPECT_EQ(2, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find)); + EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 1); + EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 2); } TEST(array_utils, FindIndexPointer) @@ -102,18 +102,18 @@ TEST(array_utils, FindIndexPointer) #define STACK_PUSH_AND_CHECK_FORWARD(v, i) { \ STACK_PUSH(data, v); \ - EXPECT_EQ(i, BLI_array_findindex(data, STACK_SIZE(data), &(v))); \ + EXPECT_EQ(BLI_array_findindex(data, STACK_SIZE(data), &(v)), i); \ } ((void)0) #define STACK_PUSH_AND_CHECK_BACKWARD(v, i) { \ STACK_PUSH(data, v); \ - EXPECT_EQ(i, BLI_array_rfindindex(data, STACK_SIZE(data), &(v))); \ + EXPECT_EQ(BLI_array_rfindindex(data, STACK_SIZE(data), &(v)), i); \ } ((void)0) #define STACK_PUSH_AND_CHECK_BOTH(v, i) { \ STACK_PUSH(data, v); \ - EXPECT_EQ(i, BLI_array_findindex(data, STACK_SIZE(data), &(v))); \ - EXPECT_EQ(i, BLI_array_rfindindex(data, STACK_SIZE(data), &(v))); \ + EXPECT_EQ(BLI_array_findindex(data, STACK_SIZE(data), &(v)), i); \ + EXPECT_EQ(BLI_array_rfindindex(data, STACK_SIZE(data), &(v)), i); \ } ((void)0) STACK_PUSH_AND_CHECK_BOTH(a, 0); diff --git a/tests/gtests/blenlib/BLI_ghash_performance_test.cc b/tests/gtests/blenlib/BLI_ghash_performance_test.cc index fb32cb3f0a5..924c84d72d0 100644 --- a/tests/gtests/blenlib/BLI_ghash_performance_test.cc +++ b/tests/gtests/blenlib/BLI_ghash_performance_test.cc @@ -118,21 +118,21 @@ static void str_ghash_tests(GHash *ghash, const char *id) TIMEIT_START(string_lookup); v = BLI_ghash_lookup(ghash, data_bis); - EXPECT_EQ(data_bis[0], GET_INT_FROM_POINTER(v)); + EXPECT_EQ(GET_INT_FROM_POINTER(v), data_bis[0]); for (p = w = c = data_bis; *c; c++) { if (*c == '.') { *c = '\0'; v = BLI_ghash_lookup(ghash, w); - EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v)); + EXPECT_EQ(GET_INT_FROM_POINTER(v), w[0]); v = BLI_ghash_lookup(ghash, p); - EXPECT_EQ(p[0], GET_INT_FROM_POINTER(v)); + EXPECT_EQ(GET_INT_FROM_POINTER(v), p[0]); p = w = c + 1; } else if (*c == ' ') { *c = '\0'; v = BLI_ghash_lookup(ghash, w); - EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v)); + EXPECT_EQ(GET_INT_FROM_POINTER(v), w[0]); w = c + 1; } } @@ -195,7 +195,7 @@ static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr while (i--) { void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(i)); - EXPECT_EQ(i, GET_UINT_FROM_POINTER(v)); + EXPECT_EQ(GET_UINT_FROM_POINTER(v), i); } TIMEIT_END(int_lookup); @@ -214,7 +214,7 @@ static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr TIMEIT_END(int_pop); } - EXPECT_EQ(0, BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), 0); BLI_ghash_free(ghash, NULL, NULL); @@ -292,7 +292,7 @@ static void randint_ghash_tests(GHash *ghash, const char *id, const unsigned int for (i = nbr, dt = data; i--; dt++) { void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*dt)); - EXPECT_EQ(*dt, GET_UINT_FROM_POINTER(v)); + EXPECT_EQ(GET_UINT_FROM_POINTER(v), *dt); } TIMEIT_END(int_lookup); @@ -403,7 +403,7 @@ static void int4_ghash_tests(GHash *ghash, const char *id, const unsigned int nb for (i = nbr, dt = data; i--; dt++) { void *v = BLI_ghash_lookup(ghash, (void *)(*dt)); - EXPECT_EQ(i, GET_UINT_FROM_POINTER(v)); + EXPECT_EQ(GET_UINT_FROM_POINTER(v), i); } TIMEIT_END(int_v4_lookup); @@ -469,7 +469,7 @@ static void multi_small_ghash_tests_one(GHash *ghash, RNG *rng, const unsigned i for (i = nbr, dt = data; i--; dt++) { void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*dt)); - EXPECT_EQ(*dt, GET_UINT_FROM_POINTER(v)); + EXPECT_EQ(GET_UINT_FROM_POINTER(v), *dt); } BLI_ghash_clear(ghash, NULL, NULL); diff --git a/tests/gtests/blenlib/BLI_ghash_test.cc b/tests/gtests/blenlib/BLI_ghash_test.cc index ffbe5f5547f..6d075e29114 100644 --- a/tests/gtests/blenlib/BLI_ghash_test.cc +++ b/tests/gtests/blenlib/BLI_ghash_test.cc @@ -62,11 +62,11 @@ TEST(ghash, InsertLookup) BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); } - EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE); for (i = TESTCASE_SIZE, k = keys; i--; k++) { void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*k)); - EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v)); + EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k); } BLI_ghash_free(ghash, NULL, NULL); @@ -85,16 +85,16 @@ TEST(ghash, InsertRemove) BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); } - EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE); bkt_size = BLI_ghash_buckets_size(ghash); for (i = TESTCASE_SIZE, k = keys; i--; k++) { void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL); - EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v)); + EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k); } - EXPECT_EQ(0, BLI_ghash_size(ghash)); - EXPECT_EQ(bkt_size, BLI_ghash_buckets_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), 0); + EXPECT_EQ(BLI_ghash_buckets_size(ghash), bkt_size); BLI_ghash_free(ghash, NULL, NULL); } @@ -113,15 +113,15 @@ TEST(ghash, InsertRemoveShrink) BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); } - EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE); bkt_size = BLI_ghash_buckets_size(ghash); for (i = TESTCASE_SIZE, k = keys; i--; k++) { void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL); - EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v)); + EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k); } - EXPECT_EQ(0, BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), 0); EXPECT_LT(BLI_ghash_buckets_size(ghash), bkt_size); BLI_ghash_free(ghash, NULL, NULL); @@ -141,16 +141,16 @@ TEST(ghash, Copy) BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); } - EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE); ghash_copy = BLI_ghash_copy(ghash, NULL, NULL); - EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash_copy)); - EXPECT_EQ(BLI_ghash_buckets_size(ghash), BLI_ghash_buckets_size(ghash_copy)); + EXPECT_EQ(BLI_ghash_size(ghash_copy), TESTCASE_SIZE); + EXPECT_EQ(BLI_ghash_buckets_size(ghash_copy), BLI_ghash_buckets_size(ghash)); for (i = TESTCASE_SIZE, k = keys; i--; k++) { void *v = BLI_ghash_lookup(ghash_copy, SET_UINT_IN_POINTER(*k)); - EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v)); + EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k); } BLI_ghash_free(ghash, NULL, NULL); @@ -171,7 +171,7 @@ TEST(ghash, Pop) BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); } - EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE); GHashIterState pop_state = {0}; @@ -179,14 +179,14 @@ TEST(ghash, Pop) void *k, *v; bool success = BLI_ghash_pop(ghash, &pop_state, &k, &v); EXPECT_EQ(k, v); - EXPECT_EQ(success, true); + EXPECT_TRUE(success); if (i % 2) { BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(i * 4), SET_UINT_IN_POINTER(i * 4)); } } - EXPECT_EQ((TESTCASE_SIZE - TESTCASE_SIZE / 2 + TESTCASE_SIZE / 4), BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), (TESTCASE_SIZE - TESTCASE_SIZE / 2 + TESTCASE_SIZE / 4)); { void *k, *v; @@ -194,7 +194,7 @@ TEST(ghash, Pop) EXPECT_EQ(k, v); } } - EXPECT_EQ(0, BLI_ghash_size(ghash)); + EXPECT_EQ(BLI_ghash_size(ghash), 0); BLI_ghash_free(ghash, NULL, NULL); } diff --git a/tests/gtests/blenlib/BLI_hash_mm2a_test.cc b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc index b35a1a809d6..109c925af4c 100644 --- a/tests/gtests/blenlib/BLI_hash_mm2a_test.cc +++ b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc @@ -19,9 +19,9 @@ TEST(hash_mm2a, MM2ABasic) BLI_hash_mm2a_init(&mm2, 0); BLI_hash_mm2a_add(&mm2, (const unsigned char *)data, strlen(data)); #ifdef __LITTLE_ENDIAN__ - EXPECT_EQ(1633988145, BLI_hash_mm2a_end(&mm2)); + EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 1633988145); #else - EXPECT_EQ(959283772, BLI_hash_mm2a_end(&mm2)); + EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 959283772); #endif } @@ -43,11 +43,11 @@ TEST(hash_mm2a, MM2AConcatenateStrings) BLI_hash_mm2a_init(&mm2, 0); BLI_hash_mm2a_add(&mm2, (const unsigned char *)data123, strlen(data123)); #ifdef __LITTLE_ENDIAN__ - EXPECT_EQ(1545105348, hash); + EXPECT_EQ(hash, 1545105348); #else - EXPECT_EQ(2604964730, hash); + EXPECT_EQ(hash, 2604964730); #endif - EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2)); + EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash); } TEST(hash_mm2a, MM2AIntegers) @@ -67,9 +67,9 @@ TEST(hash_mm2a, MM2AIntegers) BLI_hash_mm2a_add(&mm2, (const unsigned char *)ints, sizeof(ints)); /* Yes, same hash here on little and big endian. */ #ifdef __LITTLE_ENDIAN__ - EXPECT_EQ(405493096, hash); + EXPECT_EQ(hash, 405493096); #else - EXPECT_EQ(405493096, hash); + EXPECT_EQ(hash, 405493096); #endif - EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2)); + EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash); } diff --git a/tests/gtests/blenlib/BLI_listbase_test.cc b/tests/gtests/blenlib/BLI_listbase_test.cc index 994b8f74541..4dac2d05bd8 100644 --- a/tests/gtests/blenlib/BLI_listbase_test.cc +++ b/tests/gtests/blenlib/BLI_listbase_test.cc @@ -74,25 +74,25 @@ TEST(listbase, FindLinkOrIndex) /* Empty list */ BLI_listbase_clear(&lb); - EXPECT_EQ(NULL, BLI_findlink(&lb, -1)); - EXPECT_EQ(NULL, BLI_findlink(&lb, 0)); - EXPECT_EQ(NULL, BLI_findlink(&lb, 1)); - EXPECT_EQ(NULL, BLI_rfindlink(&lb, -1)); - EXPECT_EQ(NULL, BLI_rfindlink(&lb, 0)); - EXPECT_EQ(NULL, BLI_rfindlink(&lb, 1)); - EXPECT_EQ(-1, BLI_findindex(&lb, link1)); + EXPECT_EQ(BLI_findlink(&lb, -1), (void*)NULL); + EXPECT_EQ(BLI_findlink(&lb, 0), (void*)NULL); + EXPECT_EQ(BLI_findlink(&lb, 1), (void*)NULL); + EXPECT_EQ(BLI_rfindlink(&lb, -1), (void*)NULL); + EXPECT_EQ(BLI_rfindlink(&lb, 0), (void*)NULL); + EXPECT_EQ(BLI_rfindlink(&lb, 1), (void*)NULL); + EXPECT_EQ(BLI_findindex(&lb, link1), -1); /* One link */ BLI_addtail(&lb, link1); - EXPECT_EQ(link1, BLI_findlink(&lb, 0)); - EXPECT_EQ(link1, BLI_rfindlink(&lb, 0)); - EXPECT_EQ(0, BLI_findindex(&lb, link1)); + EXPECT_EQ(BLI_findlink(&lb, 0), link1); + EXPECT_EQ(BLI_rfindlink(&lb, 0), link1); + EXPECT_EQ(BLI_findindex(&lb, link1), 0); /* Two links */ BLI_addtail(&lb, link2); - EXPECT_EQ(link2, BLI_findlink(&lb, 1)); - EXPECT_EQ(link2, BLI_rfindlink(&lb, 0)); - EXPECT_EQ(1, BLI_findindex(&lb, link2)); + EXPECT_EQ(BLI_findlink(&lb, 1), link2); + EXPECT_EQ(BLI_rfindlink(&lb, 0), link2); + EXPECT_EQ(BLI_findindex(&lb, link2), 1); BLI_freelistN(&lb); } diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc index c80987c3586..d017ab18b4d 100644 --- a/tests/gtests/blenlib/BLI_path_util_test.cc +++ b/tests/gtests/blenlib/BLI_path_util_test.cc @@ -121,42 +121,42 @@ TEST(path_util, PathUtilFrame) { char path[FILE_MAX] = ""; ret = BLI_path_frame(path, 123, 1); - EXPECT_EQ(1, ret); + EXPECT_EQ(ret, 1); EXPECT_STREQ("123", path); } { char path[FILE_MAX] = ""; ret = BLI_path_frame(path, 123, 12); - EXPECT_EQ(1, ret); + EXPECT_EQ(ret, 1); EXPECT_STREQ("000000000123", path); } { char path[FILE_MAX] = "test_"; ret = BLI_path_frame(path, 123, 1); - EXPECT_EQ(1, ret); + EXPECT_EQ(ret, 1); EXPECT_STREQ("test_123", path); } { char path[FILE_MAX] = "test_"; ret = BLI_path_frame(path, 1, 12); - EXPECT_EQ(1, ret); + EXPECT_EQ(ret, 1); EXPECT_STREQ("test_000000000001", path); } { char path[FILE_MAX] = "test_############"; ret = BLI_path_frame(path, 1, 0); - EXPECT_EQ(1, ret); + EXPECT_EQ(ret, 1); EXPECT_STREQ("test_000000000001", path); } { char path[FILE_MAX] = "test_#_#_middle"; ret = BLI_path_frame(path, 123, 0); - EXPECT_EQ(1, ret); + EXPECT_EQ(ret, 1); EXPECT_STREQ("test_#_123_middle", path); } @@ -164,14 +164,14 @@ TEST(path_util, PathUtilFrame) { char path[FILE_MAX] = ""; ret = BLI_path_frame(path, 123, 0); - EXPECT_EQ(0, ret); + EXPECT_EQ(ret, 0); EXPECT_STREQ("", path); } { char path[FILE_MAX] = "test_middle"; ret = BLI_path_frame(path, 123, 0); - EXPECT_EQ(0, ret); + EXPECT_EQ(ret, 0); EXPECT_STREQ("test_middle", path); } } diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc index a4ed70fbec9..5d112751fa0 100644 --- a/tests/gtests/blenlib/BLI_polyfill2d_test.cc +++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc @@ -98,14 +98,14 @@ static void test_polyfill_topology( } } } - EXPECT_EQ(poly_tot + (poly_tot - 3), BLI_edgehash_size(edgehash)); + EXPECT_EQ(BLI_edgehash_size(edgehash), poly_tot + (poly_tot - 3)); for (i = 0; i < poly_tot; i++) { const unsigned int v1 = i; const unsigned int v2 = (i + 1) % poly_tot; void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); - EXPECT_EQ(1, (void *)p != NULL); - EXPECT_EQ(1, (intptr_t)*p); + EXPECT_EQ((void *)p != NULL, 1); + EXPECT_EQ((intptr_t)*p, 1); } for (ehi = BLI_edgehashIterator_new(edgehash), i = 0; @@ -113,7 +113,7 @@ static void test_polyfill_topology( BLI_edgehashIterator_step(ehi), i++) { void **p = BLI_edgehashIterator_getValue_p(ehi); - EXPECT_EQ(true, ELEM((intptr_t)*p, 1, 2)); + EXPECT_TRUE(ELEM((intptr_t)*p, 1, 2)); } BLI_edgehashIterator_free(ehi); @@ -135,7 +135,7 @@ static void test_polyfill_winding( count[winding_test < 0.0f] += 1; } } - EXPECT_EQ(true, ELEM(0, count[0], count[1])); + EXPECT_TRUE(ELEM(0, count[0], count[1])); } /** diff --git a/tests/gtests/blenlib/BLI_stack_test.cc b/tests/gtests/blenlib/BLI_stack_test.cc index 4c0b95f4b6b..18188937355 100644 --- a/tests/gtests/blenlib/BLI_stack_test.cc +++ b/tests/gtests/blenlib/BLI_stack_test.cc @@ -24,7 +24,7 @@ TEST(stack, Empty) BLI_Stack *stack; stack = BLI_stack_new(sizeof(int), __func__); - EXPECT_EQ(BLI_stack_is_empty(stack), true); + EXPECT_TRUE(BLI_stack_is_empty(stack)); EXPECT_EQ(BLI_stack_count(stack), 0); BLI_stack_free(stack); } @@ -37,11 +37,11 @@ TEST(stack, One) stack = BLI_stack_new(sizeof(in), __func__); BLI_stack_push(stack, (void *)&in); - EXPECT_EQ(BLI_stack_is_empty(stack), false); + EXPECT_FALSE(BLI_stack_is_empty(stack)); EXPECT_EQ(BLI_stack_count(stack), 1); BLI_stack_pop(stack, (void *)&out); - EXPECT_EQ(in, out); - EXPECT_EQ(BLI_stack_is_empty(stack), true); + EXPECT_EQ(out, in); + EXPECT_TRUE(BLI_stack_is_empty(stack)); EXPECT_EQ(BLI_stack_count(stack), 0); BLI_stack_free(stack); } @@ -59,12 +59,12 @@ TEST(stack, Range) } for (in = tot - 1; in >= 0; in--) { - EXPECT_EQ(BLI_stack_is_empty(stack), false); + EXPECT_FALSE(BLI_stack_is_empty(stack)); BLI_stack_pop(stack, (void *)&out); - EXPECT_EQ(in, out); + EXPECT_EQ(out, in); } - EXPECT_EQ(BLI_stack_is_empty(stack), true); + EXPECT_TRUE(BLI_stack_is_empty(stack)); BLI_stack_free(stack); } @@ -86,12 +86,12 @@ TEST(stack, String) } for (i = tot - 1; i >= 0; i--) { - EXPECT_EQ(BLI_stack_is_empty(stack), false); + EXPECT_FALSE(BLI_stack_is_empty(stack)); *((int *)in) = i; BLI_stack_pop(stack, (void *)&out); EXPECT_STREQ(in, out); } - EXPECT_EQ(BLI_stack_is_empty(stack), true); + EXPECT_TRUE(BLI_stack_is_empty(stack)); BLI_stack_free(stack); } @@ -115,7 +115,7 @@ TEST(stack, Peek) EXPECT_EQ(*ret, in[i % ARRAY_SIZE(in)]); } - EXPECT_EQ(BLI_stack_is_empty(stack), true); + EXPECT_TRUE(BLI_stack_is_empty(stack)); BLI_stack_free(stack); } @@ -140,7 +140,7 @@ TEST(stack, Clear) } BLI_stack_clear(stack); - EXPECT_EQ(BLI_stack_is_empty(stack), true); + EXPECT_TRUE(BLI_stack_is_empty(stack)); /* and again, this time check its valid */ for (in = 0; in < tot; in++) { @@ -148,12 +148,12 @@ TEST(stack, Clear) } for (in = tot - 1; in >= 0; in--) { - EXPECT_EQ(BLI_stack_is_empty(stack), false); + EXPECT_FALSE(BLI_stack_is_empty(stack)); BLI_stack_pop(stack, (void *)&out); - EXPECT_EQ(in, out); + EXPECT_EQ(out, in); } - EXPECT_EQ(BLI_stack_is_empty(stack), true); + EXPECT_TRUE(BLI_stack_is_empty(stack)); /* without this, we wont test case when mixed free/used */ tot /= 2; @@ -204,10 +204,10 @@ TEST(stack, Reuse) while (!BLI_stack_is_empty(stack)) { i--; BLI_stack_pop(stack, (void *)&sizes_test[i]); - EXPECT_EQ(sizes[i], sizes_test[i]); + EXPECT_EQ(sizes_test[i], sizes[i]); EXPECT_GT(i, -1); } - EXPECT_EQ(i, 0); + EXPECT_EQ(0, i); EXPECT_EQ(memcmp(sizes, sizes_test, sizeof(sizes) - sizeof(int)), 0); diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc index 08f2a745bdb..f6f7e17c8ca 100644 --- a/tests/gtests/blenlib/BLI_string_test.cc +++ b/tests/gtests/blenlib/BLI_string_test.cc @@ -44,7 +44,7 @@ TEST(string, StrPartition) /* "mat.e-r_ial" -> "mat", '.', "e-r_ial", 3 */ pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(3, pre_ln); + EXPECT_EQ(pre_ln, 3); EXPECT_EQ(&str[3], sep); EXPECT_STREQ("e-r_ial", suf); } @@ -55,7 +55,7 @@ TEST(string, StrPartition) /* ".mate-rial--" -> "", '.', "mate-rial--", 0 */ pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(0, pre_ln); + EXPECT_EQ(pre_ln, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("mate-rial--", suf); } @@ -65,7 +65,7 @@ TEST(string, StrPartition) /* ".__.--_" -> "", '.', "__.--_", 0 */ pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(0, pre_ln); + EXPECT_EQ(pre_ln, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("__.--_", suf); } @@ -75,9 +75,9 @@ TEST(string, StrPartition) /* "" -> "", NULL, NULL, 0 */ pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(0, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 0); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } { @@ -85,9 +85,9 @@ TEST(string, StrPartition) /* "material" -> "material", NULL, NULL, 8 */ pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(8, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 8); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } } @@ -103,7 +103,7 @@ TEST(string, StrRPartition) /* "mat.e-r_ial" -> "mat.e-r", '_', "ial", 7 */ pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(7, pre_ln); + EXPECT_EQ(pre_ln, 7); EXPECT_EQ(&str[7], sep); EXPECT_STREQ("ial", suf); } @@ -114,7 +114,7 @@ TEST(string, StrRPartition) /* ".mate-rial--" -> ".mate-rial-", '-', "", 11 */ pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(11, pre_ln); + EXPECT_EQ(pre_ln, 11); EXPECT_EQ(&str[11], sep); EXPECT_STREQ("", suf); } @@ -124,7 +124,7 @@ TEST(string, StrRPartition) /* ".__.--_" -> ".__.--", '_', "", 6 */ pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(6, pre_ln); + EXPECT_EQ(pre_ln, 6); EXPECT_EQ(&str[6], sep); EXPECT_STREQ("", suf); } @@ -134,9 +134,9 @@ TEST(string, StrRPartition) /* "" -> "", NULL, NULL, 0 */ pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(0, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 0); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } { @@ -144,9 +144,9 @@ TEST(string, StrRPartition) /* "material" -> "material", NULL, NULL, 8 */ pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(8, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 8); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } } @@ -164,7 +164,7 @@ TEST(string, StrPartitionEx) /* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */ pre_ln = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true); - EXPECT_EQ(5, pre_ln); + EXPECT_EQ(pre_ln, 5); EXPECT_EQ(&str[5], sep); EXPECT_STREQ("r_ia.l", suf); } @@ -175,9 +175,9 @@ TEST(string, StrPartitionEx) /* "mate.rial" over "mate" -> "mate.rial", NULL, NULL, 4 */ pre_ln = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true); - EXPECT_EQ(4, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 4); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } } @@ -193,7 +193,7 @@ TEST(string, StrPartitionUtf8) /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */ pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(2, pre_ln); + EXPECT_EQ(pre_ln, 2); EXPECT_EQ(&str[2], sep); EXPECT_STREQ("te-r\xe2\x98\xafial", suf); } @@ -204,7 +204,7 @@ TEST(string, StrPartitionUtf8) /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "", '\xe2\x98\xaf', "mate-rial-\xc3\xb1", 0 */ pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(0, pre_ln); + EXPECT_EQ(pre_ln, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("mate-rial-\xc3\xb1", suf); } @@ -214,7 +214,7 @@ TEST(string, StrPartitionUtf8) /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "", '\xe2\x98\xaf', ".\xc3\xb1_.--\xc3\xb1", 0 */ pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(0, pre_ln); + EXPECT_EQ(pre_ln, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ(".\xc3\xb1_.--\xc3\xb1", suf); } @@ -224,9 +224,9 @@ TEST(string, StrPartitionUtf8) /* "" -> "", NULL, NULL, 0 */ pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(0, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 0); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } { @@ -234,9 +234,9 @@ TEST(string, StrPartitionUtf8) /* "material" -> "material", NULL, NULL, 8 */ pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(8, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 8); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } } @@ -252,7 +252,7 @@ TEST(string, StrRPartitionUtf8) /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "mat\xc3\xb1te-r", '\xe2\x98\xaf', "ial", 8 */ pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(8, pre_ln); + EXPECT_EQ(pre_ln, 8); EXPECT_EQ(&str[8], sep); EXPECT_STREQ("ial", suf); } @@ -263,7 +263,7 @@ TEST(string, StrRPartitionUtf8) /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "\xe2\x98\xafmate-rial-", '\xc3\xb1', "", 13 */ pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(13, pre_ln); + EXPECT_EQ(pre_ln, 13); EXPECT_EQ(&str[13], sep); EXPECT_STREQ("", suf); } @@ -273,7 +273,7 @@ TEST(string, StrRPartitionUtf8) /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "\xe2\x98\xaf.\xc3\xb1_.--", '\xc3\xb1', "", 10 */ pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(10, pre_ln); + EXPECT_EQ(pre_ln, 10); EXPECT_EQ(&str[10], sep); EXPECT_STREQ("", suf); } @@ -283,9 +283,9 @@ TEST(string, StrRPartitionUtf8) /* "" -> "", NULL, NULL, 0 */ pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(0, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 0); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } { @@ -293,9 +293,9 @@ TEST(string, StrRPartitionUtf8) /* "material" -> "material", NULL, NULL, 8 */ pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(8, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 8); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } } @@ -313,7 +313,7 @@ TEST(string, StrPartitionExUtf8) /* "ma\xc3\xb1te-r\xe2\x98\xafial" over "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */ pre_ln = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true); - EXPECT_EQ(2, pre_ln); + EXPECT_EQ(pre_ln, 2); EXPECT_EQ(&str[2], sep); EXPECT_STREQ("te-r\xe2\x98\xafial", suf); } @@ -324,9 +324,9 @@ TEST(string, StrPartitionExUtf8) /* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", NULL, NULL, 4 */ pre_ln = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true); - EXPECT_EQ(4, pre_ln); - EXPECT_EQ(NULL, sep); - EXPECT_EQ(NULL, suf); + EXPECT_EQ(pre_ln, 4); + EXPECT_EQ(sep, (void*)NULL); + EXPECT_EQ(suf, (void*)NULL); } } @@ -373,7 +373,7 @@ TEST(string, StrFormatIntGrouped) const int word_cmp_size = ARRAY_SIZE(word_cmp); \ const int word_num = BLI_string_find_split_words( \ word_str_src, word_str_src_len, ' ', word_info, word_cmp_size_input); \ - EXPECT_EQ(word_num, word_cmp_size - 1); \ + EXPECT_EQ(word_cmp_size - 1, word_num); \ EXPECT_EQ_ARRAY_ND<const int[2]>(word_cmp, word_info, word_cmp_size, 2); \ } ((void)0) @@ -449,20 +449,20 @@ TEST(string, StringStrncasestr) const char *res; res = BLI_strncasestr(str_test0, "", 0); - EXPECT_EQ(str_test0, res); + EXPECT_EQ(res, str_test0); res = BLI_strncasestr(str_test0, " ", 1); - EXPECT_EQ(str_test0 + 6, res); + EXPECT_EQ(res, str_test0 + 6); res = BLI_strncasestr(str_test0, "her", 3); - EXPECT_EQ(str_test0 + 7, res); + EXPECT_EQ(res, str_test0 + 7); res = BLI_strncasestr(str_test0, "ARCh", 4); - EXPECT_EQ(str_test0 + 2, res); + EXPECT_EQ(res, str_test0 + 2); res = BLI_strncasestr(str_test0, "earcq", 4); - EXPECT_EQ(str_test0 + 1, res); + EXPECT_EQ(res, str_test0 + 1); res = BLI_strncasestr(str_test0, "not there", 9); - EXPECT_EQ(NULL, res); + EXPECT_EQ(res, (void*)NULL); } diff --git a/tests/gtests/blenlib/BLI_string_utf8_test.cc b/tests/gtests/blenlib/BLI_string_utf8_test.cc index c0beb92eeec..95d73b4242f 100644 --- a/tests/gtests/blenlib/BLI_string_utf8_test.cc +++ b/tests/gtests/blenlib/BLI_string_utf8_test.cc @@ -298,7 +298,7 @@ TEST(string, Utf8InvalidBytes) const int num_errors_found = BLI_utf8_invalid_strip(buff, sizeof(buff) - 1); printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", num_errors, num_errors_found, tst, buff); - EXPECT_EQ(num_errors, num_errors_found); + EXPECT_EQ(num_errors_found, num_errors); EXPECT_STREQ(buff, tst_stripped); } } diff --git a/tests/gtests/bmesh/bmesh_core_test.cc b/tests/gtests/bmesh/bmesh_core_test.cc index f386abc0b2b..b2cb1a4e8a3 100644 --- a/tests/gtests/bmesh/bmesh_core_test.cc +++ b/tests/gtests/bmesh/bmesh_core_test.cc @@ -12,18 +12,18 @@ TEST(bmesh_core, BMVertCreate) { BMeshCreateParams bm_params; bm_params.use_toolflags = true; bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_params); - EXPECT_EQ(0, bm->totvert); + EXPECT_EQ(bm->totvert, 0); /* make a custom layer so we can see if it is copied properly */ BM_data_layer_add(bm, &bm->vdata, CD_PROP_FLT); bv1 = BM_vert_create(bm, co1, NULL, BM_CREATE_NOP); ASSERT_TRUE(bv1 != NULL); - EXPECT_EQ(1.0f, bv1->co[0]); - EXPECT_EQ(2.0f, bv1->co[1]); - EXPECT_EQ(0.0f, bv1->co[2]); + EXPECT_EQ(bv1->co[0], 1.0f); + EXPECT_EQ(bv1->co[1], 2.0f); + EXPECT_EQ(bv1->co[2], 0.0f); EXPECT_TRUE(is_zero_v3(bv1->no)); - EXPECT_EQ((char)BM_VERT, bv1->head.htype); - EXPECT_EQ(0, bv1->head.hflag); - EXPECT_EQ(0, bv1->head.api_flag); + EXPECT_EQ(bv1->head.htype, (char)BM_VERT); + EXPECT_EQ(bv1->head.hflag, 0); + EXPECT_EQ(bv1->head.api_flag, 0); bv2 = BM_vert_create(bm, NULL, NULL, BM_CREATE_NOP); ASSERT_TRUE(bv2 != NULL); EXPECT_TRUE(is_zero_v3(bv2->co)); @@ -33,7 +33,7 @@ TEST(bmesh_core, BMVertCreate) { bv3 = BM_vert_create(bm, co1, bv2, BM_CREATE_NOP); ASSERT_TRUE(bv3 != NULL); EXPECT_FALSE(BM_elem_flag_test((BMElem *)bv3, BM_ELEM_SELECT)); - EXPECT_EQ(1.5f, BM_elem_float_data_get(&bm->vdata, bv3, CD_PROP_FLT)); - EXPECT_EQ(3, BM_mesh_elem_count(bm, BM_VERT)); + EXPECT_EQ(BM_elem_float_data_get(&bm->vdata, bv3, CD_PROP_FLT), 1.5f); + EXPECT_EQ(BM_mesh_elem_count(bm, BM_VERT), 3); BM_mesh_free(bm); } diff --git a/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc b/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc index 345c3824b63..01ff38f0528 100644 --- a/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc +++ b/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc @@ -8,7 +8,7 @@ extern "C" { #include "MEM_guardedalloc.h" -#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ(0, (size_t)ptr % align) +#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ((size_t)ptr % align, 0) namespace { diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 4b5666e9b5a..4e0283adf88 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -425,3 +425,10 @@ if(WITH_CYCLES) MESSAGE(STATUS "Disabling Cycles tests because tests folder does not exist") endif() endif() + +# ------------------------------------------------------------------------------ +# LAYER SYSTEM TESTS +add_test(render_layer ${TEST_BLENDER_EXE} + --python ${CMAKE_CURRENT_LIST_DIR}/bl_render_layer.py -- + --testdir="${TEST_SRC_DIR}/layers" +) diff --git a/tests/python/bl_render_layer.py b/tests/python/bl_render_layer.py new file mode 100644 index 00000000000..e0b1711c9dc --- /dev/null +++ b/tests/python/bl_render_layer.py @@ -0,0 +1,1040 @@ +# Apache License, Version 2.0 + +# ./blender.bin --background -noaudio --python tests/python/bl_render_layer.py -- --testdir="/data/lib/tests/" +import unittest + + +# ############################################################ +# Layer Collection Crawler +# ############################################################ + +def listbase_iter(data, struct, listbase): + element = data.get_pointer((struct, listbase, b'first')) + while element is not None: + yield element + element = element.get_pointer(b'next') + + +def linkdata_iter(collection, data): + element = collection.get_pointer((data, b'first')) + while element is not None: + yield element + element = element.get_pointer(b'next') + + +def get_layer_collection(layer_collection): + data = {} + flag = layer_collection.get(b'flag') + + data['is_visible'] = (flag & (1 << 0)) != 0; + data['is_selectable'] = (flag & (1 << 1)) != 0; + data['is_folded'] = (flag & (1 << 2)) != 0; + + scene_collection = layer_collection.get_pointer(b'scene_collection') + if scene_collection is None: + name = 'Fail!' + else: + name = scene_collection.get(b'name') + data['name'] = name + + objects = [] + for link in linkdata_iter(layer_collection, b'object_bases'): + ob_base = link.get_pointer(b'data') + ob = ob_base.get_pointer(b'object') + objects.append(ob.get((b'id', b'name'))[2:]) + data['objects'] = objects + + collections = {} + for nested_layer_collection in linkdata_iter(layer_collection, b'layer_collections'): + subname, subdata = get_layer_collection(nested_layer_collection) + collections[subname] = subdata + data['collections'] = collections + + return name, data + + +def get_layer(layer): + data = {} + name = layer.get(b'name') + + data['name'] = name + data['active_object'] = layer.get((b'basact', b'object', b'id', b'name'))[2:] + data['engine'] = layer.get(b'engine') + + objects = [] + for link in linkdata_iter(layer, b'object_bases'): + ob = link.get_pointer(b'object') + objects.append(ob.get((b'id', b'name'))[2:]) + data['objects'] = objects + + collections = {} + for layer_collection in linkdata_iter(layer, b'layer_collections'): + subname, subdata = get_layer_collection(layer_collection) + collections[subname] = subdata + data['collections'] = collections + + return name, data + + +def get_layers(scene): + """Return all the render layers and their data""" + layers = {} + for layer in linkdata_iter(scene, b'render_layers'): + name, data = get_layer(layer) + layers[name] = data + return layers + + +def get_scene_collection_objects(collection, listbase): + objects = [] + for link in linkdata_iter(collection, listbase): + ob = link.get_pointer(b'data') + if ob is None: + name = 'Fail!' + else: + name = ob.get((b'id', b'name'))[2:] + objects.append(name) + return objects + + +def get_scene_collection(collection): + """""" + data = {} + name = collection.get(b'name') + + data['name'] = name + data['filter'] = collection.get(b'filter') + + data['objects'] = get_scene_collection_objects(collection, b'objects') + data['filter_objects'] = get_scene_collection_objects(collection, b'filter_objects') + + collections = {} + for nested_collection in linkdata_iter(collection, b'scene_collections'): + subname, subdata = get_scene_collection(nested_collection) + collections[subname] = subdata + data['collections'] = collections + + return name, data + + +def get_scene_collections(scene): + """Return all the scene collections ahd their data""" + master_collection = scene.get_pointer(b'collection') + return get_scene_collection(master_collection) + + +def query_scene(filepath, name, callbacks): + """Return the equivalent to bpy.context.scene""" + import blendfile + with blendfile.open_blend(filepath) as blend: + scenes = [block for block in blend.blocks if block.code == b'SC'] + for scene in scenes: + if scene.get((b'id', b'name'))[2:] == name: + output = [] + for callback in callbacks: + output.append(callback(scene)) + return output + + +# ############################################################ +# Utils +# ############################################################ + +def import_blendfile(): + import bpy + import os, sys + path = os.path.join( + bpy.utils.resource_path('LOCAL'), + 'scripts', + 'addons', + 'io_blend_utils', + 'blend', + ) + + if path not in sys.path: + sys.path.append(path) + + +def dump(data): + import json + return json.dumps( + data, + sort_keys=True, + indent=4, + separators=(',', ': '), + ) + + +# ############################################################ +# Tests +# ############################################################ + +PDB = False +DUMP_DIFF = True + +def compare_files(file_a, file_b): + import filecmp + + if not filecmp.cmp( + file_a, + file_b): + + if DUMP_DIFF: + import subprocess + subprocess.call(["diff", "-u", file_a, file_b]) + + if PDB: + import pdb + print("Files differ:", file_a, file_b) + pdb.set_trace() + + return False + + return True + + +class UnitsTesting(unittest.TestCase): + _test_simple = False + + @classmethod + def setUpClass(cls): + """Runs once""" + cls.pretest_import_blendfile() + cls.pretest_parsing() + + @classmethod + def setUp(cls): + """Runs once per test""" + import bpy + bpy.ops.wm.read_factory_settings() + + def path_exists(self, filepath): + import os + self.assertTrue( + os.path.exists(filepath), + "Test file \"{0}\" not found".format(filepath)) + + @classmethod + def get_root(cls): + """ + return the folder with the test files + """ + arguments = {} + for argument in extra_arguments: + name, value = argument.split('=') + cls.assertTrue(name and name.startswith("--"), "Invalid argument \"{0}\"".format(argument)) + cls.assertTrue(value, "Invalid argument \"{0}\"".format(argument)) + arguments[name[2:]] = value.strip('"') + + return arguments.get('testdir') + + @classmethod + def pretest_parsing(cls): + """ + Test if the arguments are properly set, and store ROOT + name has extra _ because we need this test to run first + """ + root = cls.get_root() + cls.assertTrue(root, "Testdir not set") + + @staticmethod + def pretest_import_blendfile(): + """ + Make sure blendfile imports with no problems + name has extra _ because we need this test to run first + """ + import_blendfile() + import blendfile + + def do_scene_write_read(self, filepath_layers, filepath_layers_json, data_callbacks, do_read): + """ + See if write/read is working for scene collections and layers + """ + import bpy + import os + import tempfile + import filecmp + + with tempfile.TemporaryDirectory() as dirpath: + (self.path_exists(f) for f in (filepath_layers, filepath_layers_json)) + + filepath_doversion = os.path.join(dirpath, 'doversion.blend') + filepath_saved = os.path.join(dirpath, 'doversion_saved.blend') + filepath_read_json = os.path.join(dirpath, "read.json") + + # doversion + write test + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_doversion) + + datas = query_scene(filepath_doversion, 'Main', data_callbacks) + self.assertTrue(datas, "Data is not valid") + + filepath_doversion_json = os.path.join(dirpath, "doversion.json") + with open(filepath_doversion_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_doversion_json, + filepath_layers_json, + ), + "Run: test_scene_write_layers") + + if do_read: + # read test, simply open and save the file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_doversion) + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved) + + datas = query_scene(filepath_saved, 'Main', data_callbacks) + self.assertTrue(datas, "Data is not valid") + + with open(filepath_read_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_read_json, + filepath_layers_json, + ), + "Scene dump files differ") + + def test_scene_write_collections(self): + """ + See if the doversion and writing are working for scene collections + """ + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_layers_json = os.path.join(ROOT, 'layers_simple.json') + + self.do_scene_write_read( + filepath_layers, + filepath_layers_json, + (get_scene_collections,), + False) + + def test_scene_write_layers(self): + """ + See if the doversion and writing are working for collections and layers + """ + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_layers_json = os.path.join(ROOT, 'layers.json') + + self.do_scene_write_read( + filepath_layers, + filepath_layers_json, + (get_scene_collections, get_layers), + False) + + def test_scene_read_collections(self): + """ + See if read is working for scene collections + (run `test_scene_write_colections` first) + """ + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_layers_json = os.path.join(ROOT, 'layers_simple.json') + + self.do_scene_write_read( + filepath_layers, + filepath_layers_json, + (get_scene_collections,), + True) + + def test_scene_read_layers(self): + """ + See if read is working for scene layers + (run `test_scene_write_layers` first) + """ + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_layers_json = os.path.join(ROOT, 'layers.json') + + self.do_scene_write_read( + filepath_layers, + filepath_layers_json, + (get_scene_collections, get_layers), + True) + + def do_scene_copy(self, filepath_json_reference, copy_mode, data_callbacks): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + + (self.path_exists(f) for f in ( + filepath_layers, + filepath_json_reference, + )) + + filepath_saved = os.path.join(dirpath, '{0}.blend'.format(copy_mode)) + filepath_json = os.path.join(dirpath, "{0}.json".format(copy_mode)) + + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + bpy.ops.scene.new(type=copy_mode) + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved) + + datas = query_scene(filepath_saved, 'Main.001', data_callbacks) + self.assertTrue(datas, "Data is not valid") + + with open(filepath_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_json, + filepath_json_reference, + ), + "Scene copy \"{0}\" test failed".format(copy_mode.title())) + + def test_scene_collections_copy_full(self): + """ + See if scene copying 'FULL_COPY' is working for scene collections + """ + import os + ROOT = self.get_root() + + filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full_simple.json') + self.do_scene_copy( + filepath_layers_json_copy, + 'FULL_COPY', + (get_scene_collections,)) + + def test_scene_collections_link(self): + """ + See if scene copying 'LINK_OBJECTS' is working for scene collections + """ + import os + ROOT = self.get_root() + + # note: nothing should change, so using `layers_simple.json` + filepath_layers_json_copy = os.path.join(ROOT, 'layers_simple.json') + self.do_scene_copy( + filepath_layers_json_copy, + 'LINK_OBJECTS', + (get_scene_collections,)) + + def test_scene_layers_copy(self): + """ + See if scene copying 'FULL_COPY' is working for scene layers + """ + import os + ROOT = self.get_root() + + filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full.json') + self.do_scene_copy( + filepath_layers_json_copy, + 'FULL_COPY', + (get_scene_collections, get_layers)) + + def test_scene_layers_link(self): + """ + See if scene copying 'FULL_COPY' is working for scene layers + """ + import os + ROOT = self.get_root() + + filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_link.json') + self.do_scene_copy( + filepath_layers_json_copy, + 'LINK_OBJECTS', + (get_scene_collections, get_layers)) + + def do_syncing(self, filepath_json, unlink_mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + three_d = bpy.data.objects.get('T.3d') + + scene = bpy.context.scene + + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = scene.master_collection.collections['1'].collections.new('scorpion') + + # test linking sync + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + + # test unlinking sync + if unlink_mode in {'OBJECT', 'COLLECTION'}: + scorpion.objects.link(three_d) + scorpion.objects.unlink(three_d) + + if unlink_mode == 'COLLECTION': + scorpion.objects.link(three_d) + scene.master_collection.collections['1'].collections.remove(subzero) + scene.master_collection.collections['1'].collections.remove(scorpion) + + # save file + filepath_nested = os.path.join(dirpath, 'nested.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested) + + # get the generated json + datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_nested_json = os.path.join(dirpath, "nested.json") + with open(filepath_nested_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_nested_json, + filepath_json, + ), + "Scene dump files differ") + + def test_syncing_link(self): + """ + See if scene collections and layer collections are in sync + when we create new subcollections and link new objects + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_nested.json') + self.do_syncing(filepath_json, 'NONE') + + def test_syncing_unlink_object(self): + """ + See if scene collections and layer collections are in sync + when we create new subcollections, link new objects and unlink + some. + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_nested.json') + self.do_syncing(filepath_json, 'OBJECT') + + def test_syncing_unlink_collection(self): + """ + See if scene collections and layer collections are in sync + when we create new subcollections, link new objects and unlink full collections + some. + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers.json') + self.do_syncing(filepath_json, 'COLLECTION') + + def do_layer_linking(self, filepath_json, link_mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + + scene = bpy.context.scene + + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + + # test linking sync + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + + # test unlinking sync + layer = scene.render_layers.new('Fresh new Layer') + + if link_mode in {'COLLECTION_LINK', 'COLLECTION_UNLINK'}: + layer.collections.link(subzero) + + if link_mode == 'COLLECTION_UNLINK': + initial_collection = layer.collections['Master Collection'] + layer.collections.unlink(initial_collection) + + # save file + filepath_nested = os.path.join(dirpath, 'nested.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested) + + # get the generated json + datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_nested_json = os.path.join(dirpath, "nested.json") + with open(filepath_nested_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_nested_json, + filepath_json, + ), + "Scene dump files differ") + + def test_syncing_layer_new(self): + """ + See if the creation of new layers is going well + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_new_layer.json') + self.do_layer_linking(filepath_json, 'LAYER_NEW') + + def test_syncing_layer_collection_link(self): + """ + See if the creation of new layers is going well + And linking a new scene collection in the layer works + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_layer_collection_link.json') + self.do_layer_linking(filepath_json, 'COLLECTION_LINK') + + def test_syncing_layer_collection_unlink(self): + """ + See if the creation of new layers is going well + And unlinking the origin scene collection works + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_layer_collection_unlink.json') + self.do_layer_linking(filepath_json, 'COLLECTION_UNLINK') + + def test_active_collection(self): + """ + See if active collection index is working + layer.collections.active_index works recursively + """ + import bpy + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + + scene = bpy.context.scene + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + layer = scene.render_layers.new('Fresh new Layer') + layer.collections.link(subzero) + + lookup = [ + 'Master Collection', + '1', + 'sub-zero', + 'scorpion', + '2', + '3', + '4', + '5', + 'sub-zero', + 'scorpion'] + + for i, name in enumerate(lookup): + layer.collections.active_index = i + self.assertEqual(name, layer.collections.active.name, + "Collection index mismatch: [{0}] : {1} != {2}".format( + i, name, layer.collections.active.name)) + + def do_object_delete(self, del_mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_reference_json = os.path.join(ROOT, 'layers_object_delete.json') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_d = bpy.data.objects.get('T.3d') + + scene = bpy.context.scene + + # mangle the file a bit with some objects linked across collections + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_d) + scorpion.objects.link(three_b) + scorpion.objects.link(three_d) + + # object to delete + ob = three_d + + # delete object + if del_mode == 'DATA': + bpy.data.objects.remove(ob, do_unlink=True) + + elif del_mode == 'OPERATOR': + bpy.ops.object.select_all(action='DESELECT') + ob.select_set(action='SELECT') + bpy.ops.object.delete() + + # save file + filepath_generated = os.path.join(dirpath, 'generated.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_generated) + + # get the generated json + datas = query_scene(filepath_generated, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_generated_json = os.path.join(dirpath, "generated.json") + with open(filepath_generated_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_generated_json, + filepath_reference_json, + ), + "Scene dump files differ") + + def test_object_delete_data(self): + """ + See if objects are removed correctly from all related collections + bpy.data.objects.remove() + """ + self.do_object_delete('DATA') + + def test_object_delete_operator(self): + """ + See if new objects are added to the correct collection + bpy.ops.object.del() + """ + self.do_object_delete('OPERATOR') + + def do_link(self, master_collection): + import bpy + self.assertEqual(master_collection.name, "Master Collection") + self.assertEqual(master_collection, bpy.context.scene.master_collection) + master_collection.objects.link(bpy.data.objects.new('object', None)) + + def test_link_scene(self): + """ + See if we can link objects + """ + import bpy + master_collection = bpy.context.scene.master_collection + self.do_link(master_collection) + + def test_link_context(self): + """ + See if we can link objects via bpy.context.scene_collection + """ + import bpy + bpy.context.scene.render_layers.active_index = len(bpy.context.scene.render_layers) - 1 + master_collection = bpy.context.scene_collection + self.do_link(master_collection) + + def test_operator_context(self): + """ + See if render layer context is properly set/get with operators overrides + when we set render_layer in context, the collection should change as well + """ + import bpy + import os + + class SampleOperator(bpy.types.Operator): + bl_idname = "testing.sample" + bl_label = "Sample Operator" + + render_layer = bpy.props.StringProperty( + default="Not Set", + options={'SKIP_SAVE'}, + ) + + scene_collection = bpy.props.StringProperty( + default="", + options={'SKIP_SAVE'}, + ) + + use_verbose = bpy.props.BoolProperty( + default=False, + options={'SKIP_SAVE'}, + ) + + def execute(self, context): + render_layer = context.render_layer + ret = {'FINISHED'} + + # this is simply playing safe + if render_layer.name != self.render_layer: + if self.use_verbose: + print('ERROR: Render Layer mismatch: "{0}" != "{1}"'.format( + render_layer.name, self.render_layer)) + ret = {'CANCELLED'} + + scene_collection_name = None + if self.scene_collection: + scene_collection_name = self.scene_collection + else: + scene_collection_name = render_layer.collections.active.name + + # while this is the real test + if context.scene_collection.name != scene_collection_name: + if self.use_verbose: + print('ERROR: Scene Collection mismatch: "{0}" != "{1}"'.format( + context.scene_collection.name, scene_collection_name)) + ret = {'CANCELLED'} + return ret + + bpy.utils.register_class(SampleOperator) + + # open sample file + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # change the file + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + scene = bpy.context.scene + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + layer = scene.render_layers.new('Fresh new Layer') + layer.collections.unlink(layer.collections.active) + layer.collections.link(subzero) + layer.collections.active_index = 3 + self.assertEqual(layer.collections.active.name, 'scorpion') + + scene = bpy.context.scene + scene.render_layers.active_index = len(scene.render_layers) - 2 + self.assertEqual(scene.render_layers.active.name, "Render Layer") + + # old layer + self.assertEqual(bpy.ops.testing.sample(render_layer='Render Layer', use_verbose=True), {'FINISHED'}) + + # expected to fail + self.assertTrue(bpy.ops.testing.sample(render_layer=layer.name), {'CANCELLED'}) + + # set render layer and scene collection + override = bpy.context.copy() + override["render_layer"] = layer + override["scene_collection"] = subzero + self.assertEqual(bpy.ops.testing.sample(override, + render_layer=layer.name, + scene_collection=subzero.name, # 'sub-zero' + use_verbose=True), {'FINISHED'}) + + # set only render layer + override = bpy.context.copy() + override["render_layer"] = layer + + self.assertEqual(bpy.ops.testing.sample(override, + render_layer=layer.name, + scene_collection=layer.collections.active.name, # 'scorpion' + use_verbose=True), {'FINISHED'}) + + def do_object_add(self, filepath_json, add_mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + + scene = bpy.context.scene + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + layer = scene.render_layers.new('Fresh new Layer') + layer.collections.link(subzero) + + # change active collection + layer.collections.active_index = 3 + self.assertEqual(layer.collections.active.name, 'scorpion', "Run: test_syncing_object_add") + + # change active layer + override = bpy.context.copy() + override["render_layer"] = layer + override["scene_collection"] = layer.collections.active.collection + + # add new objects + if add_mode == 'EMPTY': + bpy.ops.object.add(override) # 'Empty' + + elif add_mode == 'CYLINDER': + bpy.ops.mesh.primitive_cylinder_add(override) # 'Cylinder' + + elif add_mode == 'TORUS': + bpy.ops.mesh.primitive_torus_add(override) # 'Torus' + + # save file + filepath_objects = os.path.join(dirpath, 'objects.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects) + + # get the generated json + datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_objects_json = os.path.join(dirpath, "objects.json") + with open(filepath_objects_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_objects_json, + filepath_json, + ), + "Scene dump files differ") + + def test_syncing_object_add_empty(self): + """ + See if new objects are added to the correct collection + bpy.ops.object.add() + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_object_add_empty.json') + self.do_object_add(filepath_json, 'EMPTY') + + def test_syncing_object_add_cylinder(self): + """ + See if new objects are added to the correct collection + bpy.ops.mesh.primitive_cylinder_add() + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_object_add_cylinder.json') + self.do_object_add(filepath_json, 'CYLINDER') + + def test_syncing_object_add_torus(self): + """ + See if new objects are added to the correct collection + bpy.ops.mesh.primitive_torus_add() + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_object_add_torus.json') + self.do_object_add(filepath_json, 'TORUS') + + def do_copy_object(self, mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_json = os.path.join(ROOT, 'layers_object_copy_duplicate.json') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + + scene = bpy.context.scene + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + layer = scene.render_layers.new('Fresh new Layer') + layer.collections.link(subzero) + + scene.render_layers.active_index = len(scene.render_layers) - 1 + + if mode == 'DUPLICATE': + # assuming the latest layer is the active layer + bpy.ops.object.select_all(action='DESELECT') + three_c.select_set(action='SELECT') + bpy.ops.object.duplicate() + + elif mode == 'NAMED': + bpy.ops.object.add_named(name=three_c.name) + + # save file + filepath_objects = os.path.join(dirpath, 'objects.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects) + + # get the generated json + datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_objects_json = os.path.join(dirpath, "objects.json") + with open(filepath_objects_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_objects_json, + filepath_json, + ), + "Scene dump files differ") + + def test_copy_object(self): + """ + OBJECT_OT_duplicate + """ + self.do_copy_object('DUPLICATE') + + def test_copy_object_named(self): + """ + OBJECT_OT_add_named + """ + self.do_copy_object('NAMED') + + +# ############################################################ +# Main +# ############################################################ + +if __name__ == '__main__': + import sys + + global extra_arguments + extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [] + + sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else []) + unittest.main() diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py index ae8848570f0..64a71da301a 100755 --- a/tests/python/cycles_render_tests.py +++ b/tests/python/cycles_render_tests.py @@ -52,6 +52,7 @@ def render_file(filepath): "--background", "-noaudio", "--factory-startup", + "--enable-autoexec", filepath, "-E", "CYCLES", # Run with OSL enabled |