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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt20
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp2
-rw-r--r--intern/cycles/blender/addon/properties.py7
-rw-r--r--intern/cycles/blender/addon/ui.py1
-rw-r--r--intern/cycles/blender/blender_shader.cpp4
-rw-r--r--intern/cycles/blender/blender_sync.cpp13
-rw-r--r--intern/cycles/device/device_memory.h8
-rw-r--r--intern/cycles/kernel/CMakeLists.txt2
-rw-r--r--intern/cycles/kernel/closure/bsdf.h1
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h154
-rw-r--r--intern/cycles/kernel/kernel_bvh.h328
-rw-r--r--intern/cycles/kernel/kernel_camera.h11
-rw-r--r--intern/cycles/kernel/kernel_compat_cpu.h15
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h1
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h14
-rw-r--r--intern/cycles/kernel/kernel_displace.h2
-rw-r--r--intern/cycles/kernel/kernel_emission.h3
-rw-r--r--intern/cycles/kernel/kernel_globals.h34
-rw-r--r--intern/cycles/kernel/kernel_path.h457
-rw-r--r--intern/cycles/kernel/kernel_random.h14
-rw-r--r--intern/cycles/kernel/kernel_shader.h113
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h241
-rw-r--r--intern/cycles/kernel/kernel_textures.h4
-rw-r--r--intern/cycles/kernel/kernel_types.h50
-rw-r--r--intern/cycles/kernel/osl/CMakeLists.txt2
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp90
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.h65
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp2
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h2
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp41
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/shaders/node_subsurface_scattering.osl33
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h1
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h78
-rw-r--r--intern/cycles/kernel/svm/svm_types.h4
-rw-r--r--intern/cycles/render/CMakeLists.txt6
-rw-r--r--intern/cycles/render/bssrdf.cpp141
-rw-r--r--intern/cycles/render/bssrdf.h31
-rw-r--r--intern/cycles/render/film.cpp94
-rw-r--r--intern/cycles/render/film.h14
-rw-r--r--intern/cycles/render/filter.cpp142
-rw-r--r--intern/cycles/render/graph.h1
-rw-r--r--intern/cycles/render/integrator.cpp3
-rw-r--r--intern/cycles/render/integrator.h1
-rw-r--r--intern/cycles/render/nodes.cpp37
-rw-r--r--intern/cycles/render/nodes.h10
-rw-r--r--intern/cycles/render/osl.cpp12
-rw-r--r--intern/cycles/render/osl.h6
-rw-r--r--intern/cycles/render/scene.cpp34
-rw-r--r--intern/cycles/render/scene.h8
-rw-r--r--intern/cycles/render/shader.cpp34
-rw-r--r--intern/cycles/render/shader.h7
-rw-r--r--intern/cycles/render/svm.cpp11
-rw-r--r--intern/cycles/render/svm.h2
-rw-r--r--intern/cycles/render/tables.cpp110
-rw-r--r--intern/cycles/render/tables.h (renamed from intern/cycles/render/filter.h)33
-rw-r--r--intern/cycles/util/util_math.h9
-rw-r--r--intern/ffmpeg/ffmpeg_compat.h14
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp2
-rw-r--r--intern/opencolorio/CMakeLists.txt1
-rw-r--r--intern/opencolorio/SConscript2
-rw-r--r--intern/opencolorio/fallback_impl.cc3
-rw-r--r--intern/opencolorio/ocio_capi.cc4
-rw-r--r--intern/opencolorio/ocio_capi.h2
-rw-r--r--intern/opencolorio/ocio_impl.cc225
-rw-r--r--intern/opencolorio/ocio_impl.h6
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc62
-rw-r--r--release/datafiles/colormanagement/config.ocio2
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py34
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py2
-rw-r--r--release/scripts/startup/bl_ui/space_node.py7
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h1
-rw-r--r--source/blender/blenkernel/BKE_group.h23
-rw-r--r--source/blender/blenkernel/BKE_library.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h3
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h1
-rw-r--r--source/blender/blenkernel/BKE_node.h7
-rw-r--r--source/blender/blenkernel/BKE_particle.h3
-rw-r--r--source/blender/blenkernel/BKE_smoke.h1
-rw-r--r--source/blender/blenkernel/BKE_texture.h3
-rw-r--r--source/blender/blenkernel/depsgraph_private.h4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c1
-rw-r--r--source/blender/blenkernel/intern/anim.c48
-rw-r--r--source/blender/blenkernel/intern/colortools.c25
-rw-r--r--source/blender/blenkernel/intern/constraint.c4
-rw-r--r--source/blender/blenkernel/intern/group.c51
-rw-r--r--source/blender/blenkernel/intern/library.c3
-rw-r--r--source/blender/blenkernel/intern/mball.c9
-rw-r--r--source/blender/blenkernel/intern/movieclip.c6
-rw-r--r--source/blender/blenkernel/intern/node.c28
-rw-r--r--source/blender/blenkernel/intern/object.c12
-rw-r--r--source/blender/blenkernel/intern/particle.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c4
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c125
-rw-r--r--source/blender/blenlib/BLI_math_vector.h2
-rw-r--r--source/blender/blenlib/intern/math_rotation.c10
-rw-r--r--source/blender/blenlib/intern/math_vector.c22
-rw-r--r--source/blender/blenloader/intern/readfile.c8
-rw-r--r--source/blender/blenloader/intern/versioning_250.c58
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c26
-rw-r--r--source/blender/compositor/nodes/COM_BoxMaskNode.cpp39
-rw-r--r--source/blender/compositor/nodes/COM_EllipseMaskNode.cpp40
-rw-r--r--source/blender/editors/animation/anim_filter.c2
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c22
-rw-r--r--source/blender/editors/include/BIF_glutil.h45
-rw-r--r--source/blender/editors/include/ED_mesh.h1
-rw-r--r--source/blender/editors/include/ED_space_api.h4
-rw-r--r--source/blender/editors/include/ED_transform.h33
-rw-r--r--source/blender/editors/include/ED_util.h1
-rw-r--r--source/blender/editors/include/UI_interface.h29
-rw-r--r--source/blender/editors/include/UI_interface_icons.h2
-rw-r--r--source/blender/editors/interface/interface.c126
-rw-r--r--source/blender/editors/interface/interface_draw.c61
-rw-r--r--source/blender/editors/interface/interface_handlers.c26
-rw-r--r--source/blender/editors/interface/interface_icons.c6
-rw-r--r--source/blender/editors/interface/interface_intern.h22
-rw-r--r--source/blender/editors/interface/interface_layout.c54
-rw-r--r--source/blender/editors/interface/interface_ops.c2
-rw-r--r--source/blender/editors/interface/interface_regions.c32
-rw-r--r--source/blender/editors/interface/interface_templates.c18
-rw-r--r--source/blender/editors/interface/interface_widgets.c4
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c29
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c44
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c4
-rw-r--r--source/blender/editors/object/object_add.c4
-rw-r--r--source/blender/editors/object/object_group.c24
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/object/object_select.c6
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c6
-rw-r--r--source/blender/editors/physics/rigidbody_object.c6
-rw-r--r--source/blender/editors/render/render_internal.c32
-rw-r--r--source/blender/editors/render/render_opengl.c15
-rw-r--r--source/blender/editors/screen/CMakeLists.txt1
-rw-r--r--source/blender/editors/screen/glutil.c239
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c22
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h2
-rw-r--r--source/blender/editors/space_action/action_select.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c12
-rw-r--r--source/blender/editors/space_clip/clip_draw.c73
-rw-r--r--source/blender/editors/space_clip/clip_editor.c79
-rw-r--r--source/blender/editors/space_clip/clip_intern.h2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c41
-rw-r--r--source/blender/editors/space_clip/space_clip.c29
-rw-r--r--source/blender/editors/space_file/file_draw.c4
-rw-r--r--source/blender/editors/space_image/image_draw.c10
-rw-r--r--source/blender/editors/space_image/space_image.c12
-rw-r--r--source/blender/editors/space_node/drawnode.c4
-rw-r--r--source/blender/editors/space_node/node_draw.c2
-rw-r--r--source/blender/editors/space_node/node_edit.c13
-rw-r--r--source/blender/editors/space_node/node_intern.h7
-rw-r--r--source/blender/editors/space_node/node_ops.c6
-rw-r--r--source/blender/editors/space_node/node_relationships.c30
-rw-r--r--source/blender/editors/space_node/node_select.c106
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c153
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h4
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c78
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c6
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h6
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c37
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c1
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c12
-rw-r--r--source/blender/editors/space_view3d/drawobject.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c19
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c90
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c2
-rw-r--r--source/blender/editors/transform/transform.c5
-rw-r--r--source/blender/editors/transform/transform.h24
-rw-r--r--source/blender/editors/transform/transform_constraints.c55
-rw-r--r--source/blender/editors/transform/transform_conversions.c137
-rw-r--r--source/blender/editors/transform/transform_manipulator.c50
-rw-r--r--source/blender/editors/transform/transform_orientations.c14
-rw-r--r--source/blender/editors/transform/transform_snap.c213
-rw-r--r--source/blender/editors/util/CMakeLists.txt4
-rw-r--r--source/blender/editors/util/SConscript2
-rw-r--r--source/blender/editors/util/ed_util.c37
-rw-r--r--source/blender/gpu/GPU_material.h4
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c6
-rw-r--r--source/blender/gpu/intern/gpu_draw.c4
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c18
-rw-r--r--source/blender/gpu/intern/gpu_material.c72
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl5
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h31
-rw-r--r--source/blender/imbuf/intern/colormanagement.c115
-rw-r--r--source/blender/imbuf/intern/divers.c18
-rw-r--r--source/blender/makesdna/DNA_movieclip_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_access.c3
-rw-r--r--source/blender/makesrna/intern/rna_group.c4
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c42
-rw-r--r--source/blender/makesrna/intern/rna_object.c4
-rw-r--r--source/blender/makesrna/intern/rna_space.c19
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c2
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_composite.h1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_common.c1
-rw-r--r--source/blender/nodes/intern/node_common.c12
-rw-r--r--source/blender/nodes/intern/node_socket.c3
-rw-r--r--source/blender/nodes/shader/node_shader_util.h1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_common.c1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c69
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_common.c1
-rw-r--r--source/blender/python/intern/bpy_rna.c8
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h3
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h16
-rw-r--r--source/blender/render/intern/source/shadeoutput.c22
-rw-r--r--source/blender/windowmanager/WM_api.h24
-rw-r--r--source/blender/windowmanager/intern/wm.c4
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c2
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c2
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c4
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c14
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c7
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c12
-rw-r--r--source/blender/windowmanager/intern/wm_window.c6
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c12
-rw-r--r--source/creator/creator.c2
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp23
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.h2
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp2
228 files changed, 4273 insertions, 2175 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f33bb73e607..80008e24d95 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1292,18 +1292,14 @@ elseif(WIN32)
if(WITH_OPENCOLLADA)
set(OPENCOLLADA ${LIBDIR}/opencollada)
set(OPENCOLLADA_INCLUDE_DIRS
- ${OPENCOLLADA}/include/COLLADAStreamWriter
- ${OPENCOLLADA}/include/COLLADABaseUtils
- ${OPENCOLLADA}/include/COLLADAFramework
- ${OPENCOLLADA}/include/COLLADASaxFrameworkLoader
- ${OPENCOLLADA}/include/GeneratedSaxParser
+ ${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter
+ ${OPENCOLLADA}/include/opencollada/COLLADABaseUtils
+ ${OPENCOLLADA}/include/opencollada/COLLADAFramework
+ ${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader
+ ${OPENCOLLADA}/include/opencollada/GeneratedSaxParser
)
set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib/opencollada)
- if(WITH_MINGW64)
- set(OPENCOLLADA_LIBRARIES OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver pcre buffer ftoa xml)
- else()
- set(OPENCOLLADA_LIBRARIES OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver expat pcre buffer ftoa)
- endif()
+ set(OPENCOLLADA_LIBRARIES OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver buffer ftoa xml)
set(PCRE_LIBRARIES pcre)
endif()
@@ -1416,8 +1412,8 @@ elseif(WIN32)
LLVMX86Disassembler LLVMX86Info
LLVMX86Utils LLVMipa
LLVMipo LLVMCore)
- #imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc
- set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -limagehlp")
+ #imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc
+ set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -limagehlp")
set(LLVM_STATIC YES)
endif()
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
index c359c5ec3e2..408a4e56f1c 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
@@ -88,7 +88,7 @@ int AUD_FFMPEGReader::decode(AVPacket& packet, AUD_Buffer& buffer)
}
}
else
- memcpy(((data_t*)buffer.getBuffer()) + buf_pos, frame->data[1], data_size);
+ memcpy(((data_t*)buffer.getBuffer()) + buf_pos, frame->data[0], data_size);
buf_pos += data_size;
}
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 039fd39fc7d..ac0a1d7bdb7 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -205,6 +205,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=1,
)
+ cls.subsurface_samples = IntProperty(
+ name="Subsurface Samples",
+ description="Number of subsurface scattering samples to render for each AA sample",
+ min=1, max=10000,
+ default=1,
+ )
+
cls.no_caustics = BoolProperty(
name="No Caustics",
description="Leave out caustics, resulting in a darker image with less noise",
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index ee33bf6572a..d1d007079bb 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -83,6 +83,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
sub.prop(cscene, "transmission_samples", text="Transmission")
sub.prop(cscene, "ao_samples", text="AO")
sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
+ sub.prop(cscene, "subsurface_samples", text="Subsurface")
class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index b451764c347..7749f164b90 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -252,7 +252,6 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
else if (b_node.is_a(&RNA_ShaderNodeNormal)) {
BL::Node::outputs_iterator out_it;
b_node.outputs.begin(out_it);
- BL::NodeSocket vec_sock(*out_it);
NormalNode *norm = new NormalNode();
norm->direction = get_node_output_vector(b_node, "Normal");
@@ -302,6 +301,9 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
node = new DiffuseBsdfNode();
}
+ else if (b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
+ node = new SubsurfaceScatteringNode();
+ }
else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
GlossyBsdfNode *glossy = new GlossyBsdfNode();
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index f6ff78ab2ac..721eaeefc08 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -19,7 +19,6 @@
#include "background.h"
#include "camera.h"
#include "film.h"
-#include "../render/filter.h"
#include "graph.h"
#include "integrator.h"
#include "light.h"
@@ -197,6 +196,7 @@ void BlenderSync::sync_integrator()
integrator->transmission_samples = get_int(cscene, "transmission_samples");
integrator->ao_samples = get_int(cscene, "ao_samples");
integrator->mesh_light_samples = get_int(cscene, "mesh_light_samples");
+ integrator->subsurface_samples = get_int(cscene, "subsurface_samples");
integrator->progressive = get_boolean(cscene, "progressive");
if(integrator->modified(previntegrator))
@@ -213,18 +213,11 @@ void BlenderSync::sync_film()
Film prevfilm = *film;
film->exposure = get_float(cscene, "film_exposure");
+ film->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type");
+ film->filter_width = (film->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
if(film->modified(prevfilm))
film->tag_update(scene);
-
- Filter *filter = scene->filter;
- Filter prevfilter = *filter;
-
- filter->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type");
- filter->filter_width = (filter->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
-
- if(filter->modified(prevfilter))
- filter->tag_update(scene);
}
/* Render Layer */
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 3223ca91b9e..fd0bed33396 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -216,6 +216,14 @@ public:
return mem;
}
+ void copy_at(T *ptr, size_t offset, size_t size)
+ {
+ if(size > 0) {
+ size_t mem_size = size*data_elements*datatype_size(data_type);
+ memcpy(&data[0] + offset, ptr, mem_size);
+ }
+ }
+
void reference(T *ptr, size_t width, size_t height = 0)
{
data.clear();
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index e83756b7c8a..fbaba1da094 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -42,6 +42,7 @@ set(SRC_HEADERS
kernel_projection.h
kernel_random.h
kernel_shader.h
+ kernel_subsurface.h
kernel_textures.h
kernel_triangle.h
kernel_types.h
@@ -62,6 +63,7 @@ set(SRC_CLOSURE_HEADERS
closure/bsdf_util.h
closure/bsdf_ward.h
closure/bsdf_westin.h
+ closure/bssrdf.h
closure/emissive.h
closure/volume.h
)
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index f26aefe7fd3..6403606c2df 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -29,6 +29,7 @@
#include "../closure/bsdf_ward.h"
#endif
#include "../closure/bsdf_westin.h"
+#include "../closure/bssrdf.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
new file mode 100644
index 00000000000..1327fbd011e
--- /dev/null
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2013, 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.
+ */
+
+#ifndef __KERNEL_BSSRDF_H__
+#define __KERNEL_BSSRDF_H__
+
+CCL_NAMESPACE_BEGIN
+
+__device int bssrdf_setup(ShaderClosure *sc)
+{
+ if(sc->data0 < BSSRDF_MIN_RADIUS) {
+ /* revert to diffuse BSDF if radius too small */
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
+ return bsdf_diffuse_setup(sc);
+ }
+ else {
+ /* radius + IOR params */
+ sc->data0 = max(sc->data0, 0.0f);
+ sc->data1 = max(sc->data1, 1.0f);
+ sc->type = CLOSURE_BSSRDF_ID;
+
+ return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF;
+ }
+}
+
+/* Simple Cubic BSSRDF falloff */
+
+__device float bssrdf_cubic(float ld, float r)
+{
+ if(ld == 0.0f)
+ return (r == 0.0f)? 1.0f: 0.0f;
+
+ return powf(ld - min(r, ld), 3.0f) * 4.0f/powf(ld, 4.0f);
+}
+
+/* Original BSSRDF fallof function */
+
+typedef struct BSSRDFParams {
+ float eta; /* index of refraction */
+ float sigma_t_; /* reduced extinction coefficient */
+ float sigma_tr; /* effective extinction coefficient */
+ float Fdr; /* diffuse fresnel reflectance */
+ float D; /* diffusion constant */
+ float A;
+ float alpha_; /* reduced albedo */
+ float zr; /* distance of virtual lightsource above surface */
+ float zv; /* distance of virtual lightsource below surface */
+ float ld; /* mean free path */
+ float ro; /* diffuse reflectance */
+} BSSRDFParams;
+
+__device float bssrdf_reduced_albedo_Rd(float alpha_, float A, float ro)
+{
+ float sq;
+
+ sq = sqrt(3.0f*(1.0f - alpha_));
+ return (alpha_/2.0f)*(1.0f + expf((-4.0f/3.0f)*A*sq))*expf(-sq) - ro;
+}
+
+__device float bssrdf_compute_reduced_albedo(float A, float ro)
+{
+ const float tolerance = 1e-8;
+ const int max_iteration_count = 20;
+ float d, fsub, xn_1 = 0.0f, xn = 1.0f, fxn, fxn_1;
+ int i;
+
+ /* use secant method to compute reduced albedo using Rd function inverse
+ * with a given reflectance */
+ fxn = bssrdf_reduced_albedo_Rd(xn, A, ro);
+ fxn_1 = bssrdf_reduced_albedo_Rd(xn_1, A, ro);
+
+ for (i= 0; i < max_iteration_count; i++) {
+ fsub = (fxn - fxn_1);
+ if (fabsf(fsub) < tolerance)
+ break;
+ d = ((xn - xn_1)/fsub)*fxn;
+ if (fabsf(d) < tolerance)
+ break;
+
+ xn_1 = xn;
+ fxn_1 = fxn;
+ xn = xn - d;
+
+ if (xn > 1.0f) xn = 1.0f;
+ if (xn_1 > 1.0f) xn_1 = 1.0f;
+
+ fxn = bssrdf_reduced_albedo_Rd(xn, A, ro);
+ }
+
+ /* avoid division by zero later */
+ if (xn <= 0.0f)
+ xn = 0.00001f;
+
+ return xn;
+}
+
+__device void bssrdf_setup_params(BSSRDFParams *ss, float refl, float radius, float ior)
+{
+ ss->eta = ior;
+ ss->Fdr = -1.440f/ior*ior + 0.710f/ior + 0.668f + 0.0636f*ior;
+ ss->A = (1.0f + ss->Fdr)/(1.0f - ss->Fdr);
+ ss->ld = radius;
+ ss->ro = min(refl, 0.999f);
+
+ ss->alpha_ = bssrdf_compute_reduced_albedo(ss->A, ss->ro);
+
+ ss->sigma_tr = 1.0f/ss->ld;
+ ss->sigma_t_ = ss->sigma_tr/sqrtf(3.0f*(1.0f - ss->alpha_));
+
+ ss->D = 1.0f/(3.0f*ss->sigma_t_);
+
+ ss->zr = 1.0f/ss->sigma_t_;
+ ss->zv = ss->zr + 4.0f*ss->A*ss->D;
+}
+
+/* exponential falloff function */
+
+__device float bssrdf_original(const BSSRDFParams *ss, float r)
+{
+ if(ss->ld == 0.0f)
+ return (r == 0.0f)? 1.0f: 0.0f;
+
+ float rr = r*r;
+ float sr, sv, Rdr, Rdv;
+
+ sr = sqrt(rr + ss->zr*ss->zr);
+ sv = sqrt(rr + ss->zv*ss->zv);
+
+ Rdr = ss->zr*(1.0f + ss->sigma_tr*sr)*expf(-ss->sigma_tr*sr)/(sr*sr*sr);
+ Rdv = ss->zv*(1.0f + ss->sigma_tr*sv)*expf(-ss->sigma_tr*sv)/(sv*sv*sv);
+
+ return ss->alpha_*(1.0f/(4.0f*(float)M_PI))*(Rdr + Rdv);
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __KERNEL_BSSRDF_H__ */
+
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index 2b9ebf35d0c..b44e1194672 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -923,6 +923,330 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const ui
#endif
}
+/* Special ray intersection routines for subsurface scattering. In that case we
+ * only want to intersect with primitives in the same object, and if case of
+ * multiple hits we pick a single random primitive as the intersection point. */
+
+__device_inline void bvh_triangle_intersect_subsurface(KernelGlobals *kg, Intersection *isect,
+ float3 P, float3 idir, int object, int triAddr, float tmax, int *num_hits, float subsurface_random)
+{
+ /* compute and check intersection t-value */
+ float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
+ float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
+ float3 dir = 1.0f/idir;
+
+ float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
+ float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z);
+ float t = Oz * invDz;
+
+ if(t > 0.0f && t < tmax) {
+ /* compute and check barycentric u */
+ float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z;
+ float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z;
+ float u = Ox + t*Dx;
+
+ if(u >= 0.0f) {
+ /* compute and check barycentric v */
+ float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z;
+ float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z;
+ float v = Oy + t*Dy;
+
+ if(v >= 0.0f && u + v <= 1.0f) {
+ (*num_hits)++;
+
+ if(subsurface_random * (*num_hits) <= 1.0f) {
+ /* record intersection */
+ isect->prim = triAddr;
+ isect->object = object;
+ isect->u = u;
+ isect->v = v;
+ isect->t = t;
+ }
+ }
+ }
+ }
+}
+
+__device_inline int bvh_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, float subsurface_random)
+{
+ /* traversal stack in CUDA thread-local memory */
+ int traversalStack[BVH_STACK_SIZE];
+ traversalStack[0] = ENTRYPOINT_SENTINEL;
+
+ /* traversal variables in registers */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* ray parameters in registers */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 idir = bvh_inverse_direction(ray->D);
+ int object = ~0;
+
+ int num_hits = 0;
+
+ isect->t = tmax;
+ isect->object = ~0;
+ isect->prim = ~0;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+
+ /* traversal loop */
+ do {
+ do
+ {
+ /* traverse internal nodes */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL)
+ {
+ bool traverseChild0, traverseChild1, closestChild1;
+ int nodeAddrChild1;
+
+ bvh_node_intersect(kg, &traverseChild0, &traverseChild1,
+ &closestChild1, &nodeAddr, &nodeAddrChild1,
+ P, idir, isect->t, ~0, nodeAddr);
+
+ if(traverseChild0 != traverseChild1) {
+ /* one child was intersected */
+ if(traverseChild1) {
+ nodeAddr = nodeAddrChild1;
+ }
+ }
+ else {
+ if(!traverseChild0) {
+ /* neither child was intersected */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ else {
+ /* both children were intersected, push the farther one */
+ if(closestChild1) {
+ int tmp = nodeAddr;
+ nodeAddr = nodeAddrChild1;
+ nodeAddrChild1 = tmp;
+ }
+
+ ++stackPtr;
+ traversalStack[stackPtr] = nodeAddrChild1;
+ }
+ }
+ }
+
+ /* if node is leaf, fetch triangle list */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ int primAddr = __float_as_int(leaf.x);
+
+#ifdef __INSTANCING__
+ if(primAddr >= 0) {
+#endif
+ int primAddr2 = __float_as_int(leaf.y);
+
+ /* pop */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+
+ /* primitive intersection */
+ while(primAddr < primAddr2) {
+ /* only primitives from the same object */
+ uint tri_object = (object == ~0)? kernel_tex_fetch(__prim_object, primAddr): object;
+
+ if(tri_object == subsurface_object) {
+ /* intersect ray against primitive */
+#ifdef __HAIR__
+ uint segment = kernel_tex_fetch(__prim_segment, primAddr);
+ if(segment == ~0) /* ignore hair for sss */
+#endif
+ bvh_triangle_intersect_subsurface(kg, isect, P, idir, object, primAddr, tmax, &num_hits, subsurface_random);
+ }
+
+ primAddr++;
+ }
+#ifdef __INSTANCING__
+ }
+ else {
+ /* instance push */
+ if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) {
+ object = subsurface_object;
+ bvh_instance_push(kg, object, ray, &P, &idir, &isect->t, tmax);
+
+ ++stackPtr;
+ traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* pop */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ }
+#endif
+ }
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+#ifdef __INSTANCING__
+ if(stackPtr >= 0) {
+ kernel_assert(object != ~0);
+
+ /* instance pop */
+ bvh_instance_pop(kg, object, ray, &P, &idir, &isect->t, tmax);
+ object = ~0;
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+#endif
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return num_hits;
+}
+
+#ifdef __OBJECT_MOTION__
+__device bool bvh_intersect_motion_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, float subsurface_random)
+{
+ /* traversal stack in CUDA thread-local memory */
+ int traversalStack[BVH_STACK_SIZE];
+ traversalStack[0] = ENTRYPOINT_SENTINEL;
+
+ /* traversal variables in registers */
+ int stackPtr = 0;
+ int nodeAddr = kernel_data.bvh.root;
+
+ /* ray parameters in registers */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 idir = bvh_inverse_direction(ray->D);
+ int object = ~0;
+
+ int num_hits = 0;
+
+ Transform ob_tfm;
+
+ isect->t = tmax;
+ isect->object = ~0;
+ isect->prim = ~0;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+
+ /* traversal loop */
+ do {
+ do
+ {
+ /* traverse internal nodes */
+ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL)
+ {
+ bool traverseChild0, traverseChild1, closestChild1;
+ int nodeAddrChild1;
+
+ bvh_node_intersect(kg, &traverseChild0, &traverseChild1,
+ &closestChild1, &nodeAddr, &nodeAddrChild1,
+ P, idir, isect->t, ~0, nodeAddr);
+
+ if(traverseChild0 != traverseChild1) {
+ /* one child was intersected */
+ if(traverseChild1) {
+ nodeAddr = nodeAddrChild1;
+ }
+ }
+ else {
+ if(!traverseChild0) {
+ /* neither child was intersected */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ else {
+ /* both children were intersected, push the farther one */
+ if(closestChild1) {
+ int tmp = nodeAddr;
+ nodeAddr = nodeAddrChild1;
+ nodeAddrChild1 = tmp;
+ }
+
+ ++stackPtr;
+ traversalStack[stackPtr] = nodeAddrChild1;
+ }
+ }
+ }
+
+ /* if node is leaf, fetch triangle list */
+ if(nodeAddr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1));
+ int primAddr = __float_as_int(leaf.x);
+
+ if(primAddr >= 0) {
+ int primAddr2 = __float_as_int(leaf.y);
+
+ /* pop */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+
+ /* primitive intersection */
+ while(primAddr < primAddr2) {
+ /* only primitives from the same object */
+ uint tri_object = (object == ~0)? kernel_tex_fetch(__prim_object, primAddr): object;
+
+ if(tri_object == subsurface_object) {
+ /* intersect ray against primitive */
+#ifdef __HAIR__
+ uint segment = kernel_tex_fetch(__prim_segment, primAddr);
+ if(segment == ~0) /* ignore hair for sss */
+#endif
+ bvh_triangle_intersect_subsurface(kg, isect, P, idir, object, primAddr, tmax, &num_hits, subsurface_random);
+ }
+
+ primAddr++;
+ }
+ }
+ else {
+ /* instance push */
+ if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) {
+ object = subsurface_object;
+ object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ bvh_instance_motion_push(kg, object, ray, &P, &idir, &isect->t, &ob_tfm, tmax);
+
+ ++stackPtr;
+ traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
+
+ nodeAddr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* pop */
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ }
+ }
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ if(stackPtr >= 0) {
+ kernel_assert(object != ~0);
+
+ /* instance pop */
+ bvh_instance_motion_pop(kg, object, ray, &P, &idir, &isect->t, &ob_tfm, tmax);
+ object = ~0;
+ nodeAddr = traversalStack[stackPtr];
+ --stackPtr;
+ }
+ } while(nodeAddr != ENTRYPOINT_SENTINEL);
+
+ return num_hits;
+}
+#endif
+
+__device_inline int scene_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, float subsurface_random)
+{
+#ifdef __OBJECT_MOTION__
+ if(kernel_data.bvh.have_motion)
+ return bvh_intersect_motion_subsurface(kg, ray, isect, subsurface_object, subsurface_random);
+ else
+ return bvh_intersect_subsurface(kg, ray, isect, subsurface_object, subsurface_random);
+#else
+ return bvh_intersect_subsurface(kg, ray, isect, subsurface_object, subsurface_random);
+#endif
+}
+
+/* Ray offset to avoid self intersection */
+
__device_inline float3 ray_offset(float3 P, float3 Ng)
{
#ifdef __INTERSECTION_REFINE__
@@ -971,6 +1295,10 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
#endif
}
+/* Refine triangle intersection to more precise hit point. For rays that travel
+ * far the precision is often not so good, this reintersects the primitive from
+ * a closer distance. */
+
__device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
{
float3 P = ray->P;
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 02f64cd649a..694ef8bd01d 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -53,7 +53,7 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float
/* compute point on plane of focus */
float ft = kernel_data.cam.focaldistance/ray->D.z;
- float3 Pfocus = ray->P + ray->D*ft;
+ float3 Pfocus = ray->D*ft;
/* update ray for effect of lens */
ray->P = make_float3(lensuv.x, lensuv.y, 0.0f);
@@ -112,11 +112,13 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa
/* compute point on plane of focus */
float ft = kernel_data.cam.focaldistance/ray->D.z;
- float3 Pfocus = ray->P + ray->D*ft;
+ float3 Pfocus = ray->D*ft;
/* update ray for effect of lens */
ray->P = make_float3(lensuv.x, lensuv.y, 0.0f);
ray->D = normalize(Pfocus - ray->P);
+
+ ray->P += Pcamera;
}
/* transform ray from camera to world */
@@ -224,8 +226,9 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo
float lens_u, float lens_v, float time, Ray *ray)
{
/* pixel filter */
- float raster_x = x + kernel_tex_interp(__filter_table, filter_u, FILTER_TABLE_SIZE);
- float raster_y = y + kernel_tex_interp(__filter_table, filter_v, FILTER_TABLE_SIZE);
+ int filter_table_offset = kernel_data.film.filter_table_offset;
+ float raster_x = x + lookup_table_read(kg, filter_u, filter_table_offset, FILTER_TABLE_SIZE);
+ float raster_y = y + lookup_table_read(kg, filter_v, filter_table_offset, FILTER_TABLE_SIZE);
#ifdef __CAMERA_MOTION__
/* motion blur */
diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h
index 01bb78e8e1c..9972a63bfbb 100644
--- a/intern/cycles/kernel/kernel_compat_cpu.h
+++ b/intern/cycles/kernel/kernel_compat_cpu.h
@@ -57,19 +57,6 @@ template<typename T> struct texture {
}
#endif
- float interp(float x, int size)
- {
- kernel_assert(size == width);
-
- x = clamp(x, 0.0f, 1.0f)*width;
-
- int index = min((int)x, width-1);
- int nindex = min(index+1, width-1);
- float t = x - index;
-
- return (1.0f - t)*data[index] + t*data[nindex];
- }
-
T *data;
int width;
};
@@ -157,7 +144,7 @@ typedef texture_image<uchar4> texture_image_uchar4;
#define kernel_tex_fetch(tex, index) (kg->tex.fetch(index))
#define kernel_tex_fetch_m128(tex, index) (kg->tex.fetch_m128(index))
#define kernel_tex_fetch_m128i(tex, index) (kg->tex.fetch_m128i(index))
-#define kernel_tex_interp(tex, t, size) (kg->tex.interp(t, size))
+#define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size))
#define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y))
#define kernel_data (kg->__data)
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index 9fd065c3cda..a11f8f403cd 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -58,7 +58,6 @@ typedef texture<uchar4, 2, cudaReadModeNormalizedFloat> texture_image_uchar4;
/* Macros to handle different memory storage on different devices */
#define kernel_tex_fetch(t, index) tex1Dfetch(t, index)
-#define kernel_tex_interp(t, x, size) tex1D(t, x)
#define kernel_tex_image_interp(t, x, y) tex2D(t, x, y)
#define kernel_data __data
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index abb2f094f5c..999820891b2 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -45,18 +45,6 @@
/* no assert in opencl */
#define kernel_assert(cond)
-/* manual implementation of interpolated 1D lookup */
-__device float kernel_tex_interp_(__global float *data, int width, float x)
-{
- x = clamp(x, 0.0f, 1.0f)*width;
-
- int index = min((int)x, width-1);
- int nindex = min(index+1, width-1);
- float t = x - index;
-
- return (1.0f - t)*data[index] + t*data[nindex];
-}
-
/* make_type definitions with opencl style element initializers */
#ifdef make_float2
#undef make_float2
@@ -114,7 +102,7 @@ __device float kernel_tex_interp_(__global float *data, int width, float x)
/* data lookup defines */
#define kernel_data (*kg->data)
-#define kernel_tex_interp(t, x, size) kernel_tex_interp_(kg->t, size, x)
+#define kernel_tex_lookup(t, x, offset, size) kernel_tex_lookup_(kg->t, offset, size, x)
#define kernel_tex_fetch(t, index) kg->t[index]
/* define NULL */
diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h
index fc2be342e02..5f95e0c2e3b 100644
--- a/intern/cycles/kernel/kernel_displace.h
+++ b/intern/cycles/kernel/kernel_displace.h
@@ -66,8 +66,6 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou
out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN);
}
- shader_release(kg, &sd);
-
/* write output */
output[i] = make_float4(out.x, out.y, out.z, 0.0f);
}
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 9787af535bb..7d7494657e2 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -69,8 +69,6 @@ __device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando,
eval *= ls->eval_fac;
- shader_release(kg, &sd);
-
return eval;
}
@@ -207,7 +205,6 @@ __device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int pa
ShaderData sd;
shader_setup_from_background(kg, &sd, ray);
float3 L = shader_eval_background(kg, &sd, path_flag, SHADER_CONTEXT_EMISSION);
- shader_release(kg, &sd);
#ifdef __BACKGROUND_MIS__
/* check if background light exists or if we should skip pdf */
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index 529b7b8768f..abf1f5b4cb0 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -88,5 +88,39 @@ typedef struct KernelGlobals {
#endif
+/* Interpolated lookup table access */
+
+__device float lookup_table_read(KernelGlobals *kg, float x, int offset, int size)
+{
+ x = clamp(x, 0.0f, 1.0f)*(size-1);
+
+ int index = min((int)x, size-1);
+ int nindex = min(index+1, size-1);
+ float t = x - index;
+
+ float data0 = kernel_tex_fetch(__lookup_table, index + offset);
+ if(t == 0.0f)
+ return data0;
+
+ float data1 = kernel_tex_fetch(__lookup_table, nindex + offset);
+ return (1.0f - t)*data0 + t*data1;
+}
+
+__device float lookup_table_read_2D(KernelGlobals *kg, float x, float y, int offset, int xsize, int ysize)
+{
+ y = clamp(y, 0.0f, 1.0f)*(ysize-1);
+
+ int index = min((int)y, ysize-1);
+ int nindex = min(index+1, ysize-1);
+ float t = y - index;
+
+ float data0 = lookup_table_read(kg, x, offset + xsize*index, xsize);
+ if(t == 0.0f)
+ return data0;
+
+ float data1 = lookup_table_read(kg, x, offset + xsize*nindex, xsize);
+ return (1.0f - t)*data0 + t*data1;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 865ba7ca676..7aa1ec365b7 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -37,6 +37,10 @@
#include "kernel_random.h"
#include "kernel_passes.h"
+#ifdef __SUBSURFACE__
+#include "kernel_subsurface.h"
+#endif
+
CCL_NAMESPACE_BEGIN
typedef struct PathState {
@@ -149,7 +153,7 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
}
/* probalistic termination */
- return average(throughput);
+ return average(throughput); /* todo: try using max here */
}
__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow)
@@ -212,8 +216,6 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
if(ray->t != FLT_MAX)
ray->D = normalize_len(Pend - ray->P, &ray->t);
- shader_release(kg, &sd);
-
bounce++;
}
}
@@ -323,10 +325,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
L_transparent += average(holdout_weight*throughput);
}
- if(sd.flag & SD_HOLDOUT_MASK) {
- shader_release(kg, &sd);
+ if(sd.flag & SD_HOLDOUT_MASK)
break;
- }
}
#endif
@@ -345,13 +345,29 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
float probability = path_state_terminate_probability(kg, &state, throughput);
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
- if(terminate >= probability) {
- shader_release(kg, &sd);
+ if(terminate >= probability)
break;
- }
throughput /= probability;
+#ifdef __SUBSURFACE__
+ /* bssrdf scatter to a different location on the same object, replacing
+ * the closures with a diffuse BSDF */
+ if(sd.flag & SD_BSSRDF) {
+ float bssrdf_probability;
+ ShaderClosure *sc = subsurface_scatter_pick_closure(kg, &sd, &bssrdf_probability);
+
+ /* modify throughput for picking bssrdf or bsdf */
+ throughput *= bssrdf_probability;
+
+ /* do bssrdf scatter step if we picked a bssrdf closure */
+ if(sc) {
+ uint lcg_state = lcg_init(rbsdf);
+ subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false);
+ }
+ }
+#endif
+
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
@@ -415,10 +431,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
#endif
/* no BSDF? we can stop here */
- if(!(sd.flag & SD_BSDF)) {
- shader_release(kg, &sd);
+ if(!(sd.flag & SD_BSDF))
break;
- }
/* sample BSDF */
float bsdf_pdf;
@@ -432,8 +446,6 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
&bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
- shader_release(kg, &sd);
-
if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
break;
@@ -481,7 +493,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __NON_PROGRESSIVE__
__device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer,
- float3 throughput, float throughput_normalize,
+ float3 throughput, float num_samples_adjust,
float min_ray_pdf, float ray_pdf, PathState state, int rng_offset, PathRadiance *L)
{
#ifdef __LAMP_MIS__
@@ -554,16 +566,32 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
/* path termination. this is a strange place to put the termination, it's
* mainly due to the mixed in MIS that we use. gives too many unneeded
* shader evaluations, only need emission if we are going to terminate */
- float probability = path_state_terminate_probability(kg, &state, throughput*throughput_normalize);
+ float probability = path_state_terminate_probability(kg, &state, throughput*num_samples_adjust);
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
- if(terminate >= probability) {
- shader_release(kg, &sd);
+ if(terminate >= probability)
break;
- }
throughput /= probability;
+#ifdef __SUBSURFACE__
+ /* bssrdf scatter to a different location on the same object, replacing
+ * the closures with a diffuse BSDF */
+ if(sd.flag & SD_BSSRDF) {
+ float bssrdf_probability;
+ ShaderClosure *sc = subsurface_scatter_pick_closure(kg, &sd, &bssrdf_probability);
+
+ /* modify throughput for picking bssrdf or bsdf */
+ throughput *= bssrdf_probability;
+
+ /* do bssrdf scatter step if we picked a bssrdf closure */
+ if(sc) {
+ uint lcg_state = lcg_init(rbsdf);
+ subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false);
+ }
+ }
+#endif
+
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
@@ -628,10 +656,8 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
#endif
/* no BSDF? we can stop here */
- if(!(sd.flag & SD_BSDF)) {
- shader_release(kg, &sd);
+ if(!(sd.flag & SD_BSDF))
break;
- }
/* sample BSDF */
float bsdf_pdf;
@@ -645,8 +671,6 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
&bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
- shader_release(kg, &sd);
-
if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
break;
@@ -676,6 +700,193 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
}
}
+__device_noinline void kernel_path_non_progressive_lighting(KernelGlobals *kg, RNG *rng, int sample,
+ ShaderData *sd, float3 throughput, float num_samples_adjust,
+ float min_ray_pdf, float ray_pdf, PathState state,
+ int rng_offset, PathRadiance *L, __global float *buffer)
+{
+#ifdef __AO__
+ /* ambient occlusion */
+ if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
+ int num_samples = ceil(kernel_data.integrator.ao_samples*num_samples_adjust);
+ float num_samples_inv = num_samples_adjust/num_samples;
+ float ao_factor = kernel_data.background.ao_factor;
+ float3 ao_N;
+ float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
+
+ for(int j = 0; j < num_samples; j++) {
+ /* todo: solve correlation */
+ float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U);
+ float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V);
+
+ float3 ao_D;
+ float ao_pdf;
+
+ sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
+
+ if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
+ Ray light_ray;
+ float3 ao_shadow;
+
+ light_ray.P = ray_offset(sd->P, sd->Ng);
+ light_ray.D = ao_D;
+ light_ray.t = kernel_data.background.ao_distance;
+#ifdef __OBJECT_MOTION__
+ light_ray.time = sd->time;
+#endif
+
+ if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow))
+ path_radiance_accum_ao(L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce);
+ }
+ }
+ }
+#endif
+
+
+#ifdef __EMISSION__
+ /* sample illumination from lights to find path contribution */
+ if(sd->flag & SD_BSDF_HAS_EVAL) {
+ Ray light_ray;
+ BsdfEval L_light;
+ bool is_lamp;
+
+#ifdef __OBJECT_MOTION__
+ light_ray.time = sd->time;
+#endif
+
+ /* lamp sampling */
+ for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
+ int num_samples = ceil(num_samples_adjust*light_select_num_samples(kg, i));
+ float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
+
+ if(kernel_data.integrator.pdf_triangles != 0.0f)
+ num_samples_inv *= 0.5f;
+
+ for(int j = 0; j < num_samples; j++) {
+ float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U);
+ float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V);
+
+ if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp);
+ }
+ }
+ }
+ }
+
+ /* mesh light sampling */
+ if(kernel_data.integrator.pdf_triangles != 0.0f) {
+ int num_samples = ceil(num_samples_adjust*kernel_data.integrator.mesh_light_samples);
+ float num_samples_inv = num_samples_adjust/num_samples;
+
+ if(kernel_data.integrator.num_all_lights)
+ num_samples_inv *= 0.5f;
+
+ for(int j = 0; j < num_samples; j++) {
+ float light_t = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT);
+ float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U);
+ float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V);
+
+ /* only sample triangle lights */
+ if(kernel_data.integrator.num_all_lights)
+ light_t = 0.5f*light_t;
+
+ if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ for(int i = 0; i< sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(!CLOSURE_IS_BSDF(sc->type))
+ continue;
+ /* transparency is not handled here, but in outer loop */
+ if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID)
+ continue;
+
+ int num_samples;
+
+ if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
+ num_samples = kernel_data.integrator.diffuse_samples;
+ else if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
+ num_samples = kernel_data.integrator.glossy_samples;
+ else
+ num_samples = kernel_data.integrator.transmission_samples;
+
+ num_samples = ceil(num_samples_adjust*num_samples);
+
+ float num_samples_inv = num_samples_adjust/num_samples;
+
+ for(int j = 0; j < num_samples; j++) {
+ /* sample BSDF */
+ float bsdf_pdf;
+ BsdfEval bsdf_eval;
+ float3 bsdf_omega_in;
+ differential3 bsdf_domega_in;
+ float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U);
+ float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V);
+ int label;
+
+ label = shader_bsdf_sample_closure(kg, sd, sc, bsdf_u, bsdf_v, &bsdf_eval,
+ &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
+
+ if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
+ continue;
+
+ /* modify throughput */
+ float3 tp = throughput;
+ path_radiance_bsdf_bounce(L, &tp, &bsdf_eval, bsdf_pdf, state.bounce, label);
+
+ /* set labels */
+ float min_ray_pdf = FLT_MAX;
+
+ if(!(label & LABEL_TRANSPARENT))
+ min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
+
+ /* modify path state */
+ PathState ps = state;
+ path_state_next(kg, &ps, label);
+
+ /* setup ray */
+ Ray bsdf_ray;
+
+ bsdf_ray.P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng);
+ bsdf_ray.D = bsdf_omega_in;
+ bsdf_ray.t = FLT_MAX;
+#ifdef __RAY_DIFFERENTIALS__
+ bsdf_ray.dP = sd->dP;
+ bsdf_ray.dD = bsdf_domega_in;
+#endif
+#ifdef __OBJECT_MOTION__
+ bsdf_ray.time = sd->time;
+#endif
+
+ kernel_path_indirect(kg, rng, sample*num_samples + j, bsdf_ray, buffer,
+ tp*num_samples_inv, num_samples,
+ min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, L);
+
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(L);
+ path_radiance_reset_indirect(L);
+ }
+ }
+}
+
__device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer)
{
/* initialize */
@@ -740,10 +951,8 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
L_transparent += average(holdout_weight*throughput);
}
- if(sd.flag & SD_HOLDOUT_MASK) {
- shader_release(kg, &sd);
+ if(sd.flag & SD_HOLDOUT_MASK)
break;
- }
}
#endif
@@ -763,195 +972,47 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
float probability = path_state_terminate_probability(kg, &state, throughput);
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
- if(terminate >= probability) {
- shader_release(kg, &sd);
+ if(terminate >= probability)
break;
- }
throughput /= probability;
}
-#ifdef __AO__
- /* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
- int num_samples = kernel_data.integrator.ao_samples;
- float num_samples_inv = 1.0f/num_samples;
- float ao_factor = kernel_data.background.ao_factor;
- float3 ao_N;
- float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N);
-
- for(int j = 0; j < num_samples; j++) {
- /* todo: solve correlation */
- float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U);
- float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V);
-
- float3 ao_D;
- float ao_pdf;
-
- sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
-
- if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
- Ray light_ray;
- float3 ao_shadow;
-
- light_ray.P = ray_offset(sd.P, sd.Ng);
- light_ray.D = ao_D;
- light_ray.t = kernel_data.background.ao_distance;
-#ifdef __OBJECT_MOTION__
- light_ray.time = sd.time;
-#endif
-
- if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow))
- path_radiance_accum_ao(&L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce);
- }
- }
- }
-#endif
-
-#ifdef __EMISSION__
- /* sample illumination from lights to find path contribution */
- if(sd.flag & SD_BSDF_HAS_EVAL) {
- Ray light_ray;
- BsdfEval L_light;
- bool is_lamp;
-
-#ifdef __OBJECT_MOTION__
- light_ray.time = sd.time;
-#endif
-
- /* lamp sampling */
- for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
- int num_samples = light_select_num_samples(kg, i);
- float num_samples_inv = 1.0f/(num_samples*kernel_data.integrator.num_all_lights);
-
- if(kernel_data.integrator.pdf_triangles != 0.0f)
- num_samples_inv *= 0.5f;
-
- for(int j = 0; j < num_samples; j++) {
- float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U);
- float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V);
-
- if(direct_emission(kg, &sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
- /* trace shadow ray */
- float3 shadow;
+#ifdef __SUBSURFACE__
+ /* bssrdf scatter to a different location on the same object */
+ if(sd.flag & SD_BSSRDF) {
+ for(int i = 0; i< sd.num_closure; i++) {
+ ShaderClosure *sc = &sd.closure[i];
- if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp);
- }
- }
- }
- }
+ if(!CLOSURE_IS_BSSRDF(sc->type))
+ continue;
- /* mesh light sampling */
- if(kernel_data.integrator.pdf_triangles != 0.0f) {
- int num_samples = kernel_data.integrator.mesh_light_samples;
+ /* set up random number generator */
+ uint lcg_state = lcg_init(rbsdf);
+ int num_samples = kernel_data.integrator.subsurface_samples;
float num_samples_inv = 1.0f/num_samples;
- if(kernel_data.integrator.num_all_lights)
- num_samples_inv *= 0.5f;
-
+ /* do subsurface scatter step with copy of shader data, this will
+ * replace the BSSRDF with a diffuse BSDF closure */
for(int j = 0; j < num_samples; j++) {
- float light_t = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT);
- float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U);
- float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V);
-
- /* only sample triangle lights */
- if(kernel_data.integrator.num_all_lights)
- light_t = 0.5f*light_t;
-
- if(direct_emission(kg, &sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp);
- }
- }
+ ShaderData bssrdf_sd = sd;
+ subsurface_scatter_step(kg, &bssrdf_sd, state.flag, sc, &lcg_state, true);
+
+ /* compute lighting with the BSDF closure */
+ kernel_path_non_progressive_lighting(kg, rng, sample*num_samples + j,
+ &bssrdf_sd, throughput, num_samples_inv,
+ ray_pdf, ray_pdf, state, rng_offset, &L, buffer);
}
}
}
#endif
- for(int i = 0; i< sd.num_closure; i++) {
- const ShaderClosure *sc = &sd.closure[i];
-
- if(!CLOSURE_IS_BSDF(sc->type))
- continue;
- /* transparency is not handled here, but in outer loop */
- if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID)
- continue;
-
- int num_samples;
-
- if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
- num_samples = kernel_data.integrator.diffuse_samples;
- else if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
- num_samples = kernel_data.integrator.glossy_samples;
- else
- num_samples = kernel_data.integrator.transmission_samples;
-
- float num_samples_inv = 1.0f/num_samples;
-
- for(int j = 0; j < num_samples; j++) {
- /* sample BSDF */
- float bsdf_pdf;
- BsdfEval bsdf_eval;
- float3 bsdf_omega_in;
- differential3 bsdf_domega_in;
- float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U);
- float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V);
- int label;
-
- label = shader_bsdf_sample_closure(kg, &sd, sc, bsdf_u, bsdf_v, &bsdf_eval,
- &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
-
- if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
- continue;
-
- /* modify throughput */
- float3 tp = throughput;
- path_radiance_bsdf_bounce(&L, &tp, &bsdf_eval, bsdf_pdf, state.bounce, label);
-
- /* set labels */
- float min_ray_pdf = FLT_MAX;
-
- if(!(label & LABEL_TRANSPARENT))
- min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
-
- /* modify path state */
- PathState ps = state;
- path_state_next(kg, &ps, label);
-
- /* setup ray */
- Ray bsdf_ray;
-
- bsdf_ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
- bsdf_ray.D = bsdf_omega_in;
- bsdf_ray.t = FLT_MAX;
-#ifdef __RAY_DIFFERENTIALS__
- bsdf_ray.dP = sd.dP;
- bsdf_ray.dD = bsdf_domega_in;
-#endif
-#ifdef __OBJECT_MOTION__
- bsdf_ray.time = sd.time;
-#endif
-
- kernel_path_indirect(kg, rng, sample*num_samples + j, bsdf_ray, buffer,
- tp*num_samples_inv, num_samples,
- min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L);
-
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(&L);
- path_radiance_reset_indirect(&L);
- }
- }
+ /* lighting */
+ kernel_path_non_progressive_lighting(kg, rng, sample, &sd, throughput,
+ 1.0f, ray_pdf, ray_pdf, state, rng_offset, &L, buffer);
/* continue in case of transparency */
throughput *= shader_bsdf_transparency(kg, &sd);
- shader_release(kg, &sd);
if(is_zero(throughput))
break;
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index 9083b7cbfd7..e2eb8d5db83 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -200,5 +200,19 @@ __device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng)
#endif
+__device float lcg_step(uint *rng)
+{
+ /* implicit mod 2^32 */
+ *rng = (1103515245*(*rng) + 12345);
+ return (float)*rng * (1.0f/(float)0xFFFFFFFF);
+}
+
+__device uint lcg_init(float seed)
+{
+ uint rng = __float_as_int(seed);
+ lcg_step(&rng);
+ return rng;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index df86b352697..444543bf709 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -158,6 +158,103 @@ __device_noinline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#endif
}
+/* ShaderData setup from BSSRDF scatter */
+
+#ifdef __SUBSURFACE__
+__device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderData *sd,
+ const Intersection *isect, const Ray *ray)
+{
+ bool backfacing = sd->flag & SD_BACKFACING;
+
+ /* object, matrices, time, ray_length stay the same */
+ sd->flag = kernel_tex_fetch(__object_flag, sd->object);
+ sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
+
+#ifdef __HAIR__
+ if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) {
+ /* Strand Shader setting*/
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+
+ sd->shader = __float_as_int(curvedata.z);
+ sd->segment = isect->segment;
+
+ float tcorr = isect->t;
+ if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_POSTINTERSECTCORRECTION)
+ tcorr = (isect->u < 0)? tcorr + sqrtf(isect->v) : tcorr - sqrtf(isect->v);
+
+ sd->P = bvh_curve_refine(kg, sd, isect, ray, tcorr);
+ }
+ else {
+#endif
+ /* fetch triangle data */
+ float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
+ float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
+ sd->shader = __float_as_int(Ns.w);
+
+#ifdef __HAIR__
+ sd->segment = ~0;
+#endif
+
+#ifdef __UV__
+ sd->u = isect->u;
+ sd->v = isect->v;
+#endif
+
+ /* vectors */
+ sd->P = bvh_triangle_refine(kg, sd, isect, ray);
+ sd->Ng = Ng;
+ sd->N = Ng;
+
+ /* smooth normal */
+ if(sd->shader & SHADER_SMOOTH_NORMAL)
+ sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+
+#ifdef __DPDU__
+ /* dPdu/dPdv */
+ triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
+#endif
+
+#ifdef __HAIR__
+ }
+#endif
+
+ sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
+
+#ifdef __INSTANCING__
+ if(isect->object != ~0) {
+ /* instance transform */
+ object_normal_transform(kg, sd, &sd->N);
+ object_normal_transform(kg, sd, &sd->Ng);
+#ifdef __DPDU__
+ object_dir_transform(kg, sd, &sd->dPdu);
+ object_dir_transform(kg, sd, &sd->dPdv);
+#endif
+ }
+#endif
+
+ /* backfacing test */
+ if(backfacing) {
+ sd->flag |= SD_BACKFACING;
+ sd->Ng = -sd->Ng;
+ sd->N = -sd->N;
+#ifdef __DPDU__
+ sd->dPdu = -sd->dPdu;
+ sd->dPdv = -sd->dPdv;
+#endif
+ }
+
+ /* should not get used in principle as the shading will only use a diffuse
+ * BSDF, but the shader might still access it */
+ sd->I = sd->N;
+
+#ifdef __RAY_DIFFERENTIALS__
+ /* differentials */
+ differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
+ /* don't modify dP and dI */
+#endif
+}
+#endif
+
/* ShaderData setup from position sampled on mesh */
__device_noinline void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
@@ -283,11 +380,9 @@ __device_noinline void shader_setup_from_sample(KernelGlobals *kg, ShaderData *s
/* ShaderData setup for displacement */
-__device_noinline void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
+__device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
int object, int prim, float u, float v)
{
- /* Note: no OSLShader::init call here, this is done in shader_setup_from_sample! */
-
float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f);
int shader;
@@ -418,7 +513,7 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
const ShaderClosure *sc = &sd->closure[sampled];
if(CLOSURE_IS_BSDF(sc->type)) {
- sum += sd->closure[sampled].sample_weight;
+ sum += sc->sample_weight;
if(r <= sum)
break;
@@ -811,7 +906,7 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd)
ShaderClosure *scj = &sd->closure[j];
#ifdef __OSL__
- if(!sci->prim && sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) {
+ if(!sci->prim && !scj->prim && sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) {
#else
if(sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) {
#endif
@@ -823,18 +918,12 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd)
memmove(scj, scj+1, size*sizeof(ShaderClosure));
sd->num_closure--;
+ j--;
}
}
}
}
#endif
-/* Free ShaderData */
-
-__device void shader_release(KernelGlobals *kg, ShaderData *sd)
-{
- /* nothing to do currently */
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
new file mode 100644
index 00000000000..5fef9965c7f
--- /dev/null
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2013, 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+#define BSSRDF_MULTI_EVAL
+#define BSSRDF_SKIP_NO_HIT
+
+__device float bssrdf_sample_distance(KernelGlobals *kg, float radius, float refl, float u)
+{
+ int table_offset = kernel_data.bssrdf.table_offset;
+ float r = lookup_table_read_2D(kg, u, refl, table_offset, BSSRDF_RADIUS_TABLE_SIZE, BSSRDF_REFL_TABLE_SIZE);
+
+ return r*radius;
+}
+
+#ifdef BSSRDF_MULTI_EVAL
+__device float bssrdf_pdf(KernelGlobals *kg, float radius, float refl, float r)
+{
+ if(r >= radius)
+ return 0.0f;
+
+ /* todo: when we use the real BSSRDF this will need to be divided by the maximum
+ * radius instead of the average radius */
+ float t = r/radius;
+
+ int table_offset = kernel_data.bssrdf.table_offset + BSSRDF_PDF_TABLE_OFFSET;
+ float pdf = lookup_table_read_2D(kg, t, refl, table_offset, BSSRDF_RADIUS_TABLE_SIZE, BSSRDF_REFL_TABLE_SIZE);
+
+ pdf /= radius;
+
+ return pdf;
+}
+#endif
+
+__device ShaderClosure *subsurface_scatter_pick_closure(KernelGlobals *kg, ShaderData *sd, float *probability)
+{
+ /* sum sample weights of bssrdf and bsdf */
+ float bsdf_sum = 0.0f;
+ float bssrdf_sum = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSDF(sc->type))
+ bsdf_sum += sc->sample_weight;
+ else if(CLOSURE_IS_BSSRDF(sc->type))
+ bssrdf_sum += sc->sample_weight;
+ }
+
+ /* use bsdf or bssrdf? */
+ float r = sd->randb_closure*(bsdf_sum + bssrdf_sum);
+
+ if(r < bsdf_sum) {
+ /* use bsdf, and adjust randb so we can reuse it for picking a bsdf */
+ sd->randb_closure = r/bsdf_sum;
+ *probability = (bsdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bsdf_sum: 1.0f;
+ return NULL;
+ }
+
+ /* use bssrdf */
+ r -= bsdf_sum;
+ sd->randb_closure = 0.0f; /* not needed anymore */
+
+ float sum = 0.0f;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSSRDF(sc->type)) {
+ sum += sc->sample_weight;
+
+ if(r <= sum) {
+#ifdef BSSRDF_MULTI_EVAL
+ *probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bssrdf_sum: 1.0f;
+#else
+ *probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/sc->sample_weight: 1.0f;
+#endif
+ return sc;
+ }
+ }
+ }
+
+ /* should never happen */
+ *probability = 1.0f;
+ return NULL;
+}
+
+#ifdef BSSRDF_MULTI_EVAL
+__device float3 subsurface_scatter_multi_eval(KernelGlobals *kg, ShaderData *sd, bool hit, float refl, float *r, int num_r, bool all)
+{
+ /* compute pdf */
+ float3 eval_sum = make_float3(0.0f, 0.0f, 0.0f);
+ float pdf_sum = 0.0f;
+ float sample_weight_sum = 0.0f;
+ int num_bssrdf = 0;
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSSRDF(sc->type)) {
+ float sample_weight = (all)? 1.0f: sc->sample_weight;
+
+ /* compute pdf */
+ float pdf = 1.0f;
+ for(int i = 0; i < num_r; i++)
+ pdf *= bssrdf_pdf(kg, sc->data0, refl, r[i]);
+
+ eval_sum += sc->weight*pdf;
+ pdf_sum += sample_weight*pdf;
+
+ sample_weight_sum += sample_weight;
+ num_bssrdf++;
+ }
+ }
+
+ float inv_pdf_sum;
+
+ if(pdf_sum > 0.0f) {
+ /* in case of non-progressive integrate we sample all bssrdf's once,
+ * for progressive we pick one, so adjust pdf for that */
+ if(all)
+ inv_pdf_sum = 1.0f/pdf_sum;
+ else
+ inv_pdf_sum = sample_weight_sum/pdf_sum;
+ }
+ else
+ inv_pdf_sum = 0.0f;
+
+ float3 weight = eval_sum * inv_pdf_sum;
+
+ return weight;
+}
+#endif
+
+/* replace closures with a single diffuse bsdf closure after scatter step */
+__device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 weight)
+{
+ ShaderClosure *sc = &sd->closure[0];
+ sd->num_closure = 1;
+
+ sc->weight = weight;
+ sc->sample_weight = 1.0f;
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
+ sc->N = sd->N;
+ sd->flag &= ~SD_CLOSURE_FLAGS;
+ sd->flag |= bsdf_diffuse_setup(sc);
+ sd->randb_closure = 0.0f;
+
+ /* todo: evaluate shading to get blurred textures and bump mapping */
+ /* shader_eval_surface(kg, sd, 0.0f, state_flag, SHADER_CONTEXT_SSS); */
+}
+
+/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
+__device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, int state_flag, ShaderClosure *sc, uint *lcg_state, bool all)
+{
+ float radius = sc->data0;
+ float refl = max(average(sc->weight)*3.0f, 0.0f);
+ float r = 0.0f;
+ bool hit = false;
+ float3 weight = make_float3(1.0f, 1.0f, 1.0f);
+#ifdef BSSRDF_MULTI_EVAL
+ float r_attempts[BSSRDF_MAX_ATTEMPTS];
+#endif
+ int num_attempts;
+
+ /* attempt to find a hit a given number of times before giving up */
+ for(num_attempts = 0; num_attempts < kernel_data.bssrdf.num_attempts; num_attempts++) {
+ /* random numbers for sampling */
+ float u1 = lcg_step(lcg_state);
+ float u2 = lcg_step(lcg_state);
+ float u3 = lcg_step(lcg_state);
+ float u4 = lcg_step(lcg_state);
+ float u5 = lcg_step(lcg_state);
+ float u6 = lcg_step(lcg_state);
+
+ r = bssrdf_sample_distance(kg, radius, refl, u5);
+#ifdef BSSRDF_MULTI_EVAL
+ r_attempts[num_attempts] = r;
+#endif
+
+ float3 p1 = sd->P + sample_uniform_sphere(u1, u2)*r;
+ float3 p2 = sd->P + sample_uniform_sphere(u3, u4)*r;
+
+ /* create ray */
+ Ray ray;
+ ray.P = p1;
+ ray.D = normalize_len(p2 - p1, &ray.t);
+ ray.dP = sd->dP;
+ ray.dD.dx = make_float3(0.0f, 0.0f, 0.0f);
+ ray.dD.dy = make_float3(0.0f, 0.0f, 0.0f);
+ ray.time = sd->time;
+
+ /* intersect with the same object. if multiple intersections are
+ * found it will randomly pick one of them */
+ Intersection isect;
+ if(scene_intersect_subsurface(kg, &ray, &isect, sd->object, u6) == 0)
+ continue;
+
+ /* setup new shading point */
+ shader_setup_from_subsurface(kg, sd, &isect, &ray);
+
+ hit = true;
+ num_attempts++;
+ break;
+ }
+
+ /* evaluate subsurface scattering closures */
+#ifdef BSSRDF_MULTI_EVAL
+ weight *= subsurface_scatter_multi_eval(kg, sd, hit, refl, r_attempts, num_attempts, all);
+#else
+ weight *= sc->weight;
+#endif
+
+#ifdef BSSRDF_SKIP_NO_HIT
+ if(!hit)
+ weight = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+ /* replace closures with a single diffuse BSDF */
+ subsurface_scatter_setup_diffuse_bsdf(sd, weight);
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index e27de95e7ab..55c6e15ad04 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -66,8 +66,8 @@ KERNEL_TEX(uint4, texture_uint4, __svm_nodes)
KERNEL_TEX(uint, texture_uint, __shader_flag)
KERNEL_TEX(uint, texture_uint, __object_flag)
-/* camera/film */
-KERNEL_TEX(float, texture_float, __filter_table)
+/* lookup tables */
+KERNEL_TEX(float, texture_float, __lookup_table)
/* sobol */
KERNEL_TEX(uint, texture_uint, __sobol_directions)
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index ddbda9240fb..526609d0506 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -37,6 +37,13 @@ CCL_NAMESPACE_BEGIN
#define PARTICLE_SIZE 5
#define TIME_INVALID FLT_MAX
+#define BSSRDF_RADIUS_TABLE_SIZE 1024
+#define BSSRDF_REFL_TABLE_SIZE 256
+#define BSSRDF_PDF_TABLE_OFFSET (BSSRDF_RADIUS_TABLE_SIZE*BSSRDF_REFL_TABLE_SIZE)
+#define BSSRDF_LOOKUP_TABLE_SIZE (BSSRDF_RADIUS_TABLE_SIZE*BSSRDF_REFL_TABLE_SIZE*2)
+#define BSSRDF_MIN_RADIUS 1e-8f
+#define BSSRDF_MAX_ATTEMPTS 8
+
#define TEX_NUM_FLOAT_IMAGES 5
/* device capabilities */
@@ -48,6 +55,7 @@ CCL_NAMESPACE_BEGIN
#ifdef WITH_OSL
#define __OSL__
#endif
+#define __SUBSURFACE__
#endif
#ifdef __KERNEL_CUDA__
@@ -423,7 +431,8 @@ typedef enum ShaderContext {
SHADER_CONTEXT_INDIRECT = 1,
SHADER_CONTEXT_EMISSION = 2,
SHADER_CONTEXT_SHADOW = 3,
- SHADER_CONTEXT_NUM = 4
+ SHADER_CONTEXT_SSS = 4,
+ SHADER_CONTEXT_NUM = 5
} ShaderContext;
/* Shader Data
@@ -438,20 +447,23 @@ enum ShaderDataFlag {
SD_BSDF = 4, /* have bsdf closure? */
SD_BSDF_HAS_EVAL = 8, /* have non-singular bsdf closure? */
SD_BSDF_GLOSSY = 16, /* have glossy bsdf */
- SD_HOLDOUT = 32, /* have holdout closure? */
- SD_VOLUME = 64, /* have volume closure? */
- SD_AO = 128, /* have ao closure? */
+ SD_BSSRDF = 32, /* have bssrdf */
+ SD_HOLDOUT = 64, /* have holdout closure? */
+ SD_VOLUME = 128, /* have volume closure? */
+ SD_AO = 256, /* have ao closure? */
+
+ SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|SD_BSSRDF|SD_HOLDOUT|SD_VOLUME|SD_AO),
/* shader flags */
- SD_SAMPLE_AS_LIGHT = 256, /* direct light sample */
- SD_HAS_SURFACE_TRANSPARENT = 512, /* has surface transparency */
- SD_HAS_VOLUME = 1024, /* has volume shader */
- SD_HOMOGENEOUS_VOLUME = 2048, /* has homogeneous volume */
+ SD_SAMPLE_AS_LIGHT = 512, /* direct light sample */
+ SD_HAS_SURFACE_TRANSPARENT = 1024, /* has surface transparency */
+ SD_HAS_VOLUME = 2048, /* has volume shader */
+ SD_HOMOGENEOUS_VOLUME = 4096, /* has homogeneous volume */
/* object flags */
- SD_HOLDOUT_MASK = 4096, /* holdout for camera rays */
- SD_OBJECT_MOTION = 8192, /* has object motion blur */
- SD_TRANSFORM_APPLIED = 16384 /* vertices have transform applied */
+ SD_HOLDOUT_MASK = 8192, /* holdout for camera rays */
+ SD_OBJECT_MOTION = 16384, /* has object motion blur */
+ SD_TRANSFORM_APPLIED = 32768 /* vertices have transform applied */
};
typedef struct ShaderData {
@@ -611,8 +623,9 @@ typedef struct KernelFilm {
int pass_shadow;
float pass_shadow_scale;
- int pass_pad1;
- int pass_pad2;
+
+ int filter_table_offset;
+ int filter_pad;
} KernelFilm;
typedef struct KernelBackground {
@@ -680,6 +693,9 @@ typedef struct KernelIntegrator {
int ao_samples;
int mesh_light_samples;
int use_lamp_mis;
+ int subsurface_samples;
+
+ int pad1, pad2, pad3;
} KernelIntegrator;
typedef struct KernelBVH {
@@ -711,9 +727,14 @@ typedef struct KernelCurves {
float encasing_ratio;
int curveflags;
int subdivisions;
-
} KernelCurves;
+typedef struct KernelBSSRDF {
+ int table_offset;
+ int num_attempts;
+ int pad1, pad2;
+} KernelBSSRDF;
+
typedef struct KernelData {
KernelCamera cam;
KernelFilm film;
@@ -722,6 +743,7 @@ typedef struct KernelData {
KernelIntegrator integrator;
KernelBVH bvh;
KernelCurves curve_kernel_data;
+ KernelBSSRDF bssrdf;
} KernelData;
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt
index 5a27f7823e4..0ce40eda4df 100644
--- a/intern/cycles/kernel/osl/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/CMakeLists.txt
@@ -18,12 +18,14 @@ set(SRC
bsdf_phong_ramp.cpp
bsdf_toon.cpp
emissive.cpp
+ osl_bssrdf.cpp
osl_closures.cpp
osl_services.cpp
osl_shader.cpp
)
set(HEADER_SRC
+ osl_bssrdf.h
osl_closures.h
osl_globals.h
osl_services.h
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
new file mode 100644
index 00000000000..ba9b13126ac
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -0,0 +1,90 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_bssrdf.h"
+#include "osl_closures.h"
+
+#include "kernel_types.h"
+#include "kernel_montecarlo.h"
+
+#include "closure/bsdf_diffuse.h"
+#include "closure/bssrdf.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+class BSSRDFClosure : public CBSSRDFClosure {
+public:
+ size_t memsize() const { return sizeof(*this); }
+ const char *name() const { return "bssrdf_cubic"; }
+
+ void setup()
+ {
+ sc.prim = NULL;
+ sc.data0 = fabsf(average(radius));
+ sc.data1 = 1.3f;
+
+ m_shaderdata_flag = bssrdf_setup(&sc);
+ }
+
+ bool mergeable(const ClosurePrimitive *other) const
+ {
+ return false;
+ }
+
+ void print_on(std::ostream &out) const
+ {
+ out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
+ }
+};
+
+ClosureParam *closure_bssrdf_params()
+{
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(BSSRDFClosure, sc.N),
+ CLOSURE_FLOAT3_PARAM(BSSRDFClosure, radius),
+ //CLOSURE_FLOAT_PARAM(BSSRDFClosure, sc.data1),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(BSSRDFClosure)
+ };
+ return params;
+}
+
+CLOSURE_PREPARE(closure_bssrdf_prepare, BSSRDFClosure)
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.h b/intern/cycles/kernel/osl/osl_bssrdf.h
new file mode 100644
index 00000000000..54df055405e
--- /dev/null
+++ b/intern/cycles/kernel/osl/osl_bssrdf.h
@@ -0,0 +1,65 @@
+/*
+ * Adapted from Open Shading Language with this license:
+ *
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sony Pictures Imageworks nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OSL_BSSRDF_H__
+#define __OSL_BSSRDF_H__
+
+#include <OSL/oslclosure.h>
+#include <OSL/oslexec.h>
+#include <OSL/genclosure.h>
+
+#include "kernel_types.h"
+
+#include "util_types.h"
+
+CCL_NAMESPACE_BEGIN
+
+class CBSSRDFClosure : public OSL::ClosurePrimitive {
+public:
+ ShaderClosure sc;
+ float3 radius;
+
+ CBSSRDFClosure() : OSL::ClosurePrimitive(BSSRDF),
+ m_shaderdata_flag(0) { }
+ ~CBSSRDFClosure() { }
+
+ int scattering() const { return LABEL_DIFFUSE; }
+ int shaderdata_flag() const { return m_shaderdata_flag; }
+
+protected:
+ int m_shaderdata_flag;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __OSL_BSSRDF_H__ */
+
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 9e65cda1e8f..9ce11ca1207 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -201,6 +201,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
closure_bsdf_diffuse_toon_params(), closure_bsdf_diffuse_toon_prepare);
register_closure(ss, "specular_toon", id++,
closure_bsdf_specular_toon_params(), closure_bsdf_specular_toon_prepare);
+ register_closure(ss, "bssrdf_cubic", id++,
+ closure_bssrdf_params(), closure_bssrdf_prepare);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index daccc03ede2..d0e25bb2b0c 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -51,6 +51,7 @@ OSL::ClosureParam *closure_bsdf_diffuse_ramp_params();
OSL::ClosureParam *closure_bsdf_phong_ramp_params();
OSL::ClosureParam *closure_bsdf_diffuse_toon_params();
OSL::ClosureParam *closure_bsdf_specular_toon_params();
+OSL::ClosureParam *closure_bssrdf_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
@@ -60,6 +61,7 @@ void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *da
void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_diffuse_toon_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_specular_toon_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bssrdf_prepare(OSL::RendererServices *, int id, void *data);
enum {
AmbientOcclusion = 100
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index a32c526a2be..555edf598f1 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -21,6 +21,7 @@
#include "kernel_globals.h"
#include "kernel_object.h"
+#include "osl_bssrdf.h"
#include "osl_closures.h"
#include "osl_globals.h"
#include "osl_services.h"
@@ -201,7 +202,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
}
break;
}
- case OSL::ClosurePrimitive::Holdout:
+ case OSL::ClosurePrimitive::Holdout: {
sc.sample_weight = 0.0f;
sc.type = CLOSURE_HOLDOUT_ID;
sc.prim = NULL;
@@ -211,7 +212,43 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
sd->flag |= SD_HOLDOUT;
}
break;
- case OSL::ClosurePrimitive::BSSRDF:
+ }
+ case OSL::ClosurePrimitive::BSSRDF: {
+ CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
+ float sample_weight = fabsf(average(weight));
+
+ if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) {
+ sc.sample_weight = sample_weight;
+
+ sc.type = bssrdf->sc.type;
+ sc.N = bssrdf->sc.N;
+ sc.data1 = bssrdf->sc.data1;
+ sc.prim = NULL;
+
+ /* create one closure for each color channel */
+ if(fabsf(weight.x) > 0.0f) {
+ sc.weight = make_float3(weight.x, 0.0f, 0.0f);
+ sc.data0 = bssrdf->radius.x;
+ sd->closure[sd->num_closure++] = sc;
+ sd->flag |= bssrdf->shaderdata_flag();
+ }
+
+ if(fabsf(weight.y) > 0.0f) {
+ sc.weight = make_float3(0.0f, weight.y, 0.0f);
+ sc.data0 = bssrdf->radius.y;
+ sd->closure[sd->num_closure++] = sc;
+ sd->flag |= bssrdf->shaderdata_flag();
+ }
+
+ if(fabsf(weight.z) > 0.0f) {
+ sc.weight = make_float3(0.0f, 0.0f, weight.z);
+ sc.data0 = bssrdf->radius.z;
+ sd->closure[sd->num_closure++] = sc;
+ sd->flag |= bssrdf->shaderdata_flag();
+ }
+ }
+ break;
+ }
case OSL::ClosurePrimitive::Debug:
break; /* not implemented */
case OSL::ClosurePrimitive::Background:
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index acae46f1615..0cff264d8e1 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -55,6 +55,7 @@ set(SRC_OSL
node_separate_rgb.osl
node_set_normal.osl
node_sky_texture.osl
+ node_subsurface_scattering.osl
node_tangent.osl
node_texture_coordinate.osl
node_translucent_bsdf.osl
diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
new file mode 100644
index 00000000000..5c25c44ec8f
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "stdosl.h"
+
+shader node_subsurface_scattering(
+ color Color = 0.8,
+ float Scale = 1.0,
+ vector Radius = vector(0.1, 0.1, 0.1),
+ float IOR = 1.3,
+ normal Normal = N,
+ output closure color BSSRDF = 0)
+{
+ float eta = max(IOR, 1.0 + 1e-5);
+
+ BSSRDF = Color * bssrdf_cubic(N, Scale * Radius);
+}
+
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index f340eaff95f..010d6ddd200 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -461,6 +461,7 @@ closure color emission() BUILTIN;
closure color background() BUILTIN;
closure color holdout() BUILTIN;
closure color ambient_occlusion() BUILTIN;
+closure color bssrdf_cubic(normal N, vector radius) BUILTIN;
// Renderer state
int raytype (string typename) BUILTIN;
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index b5bd2b42cb4..72e6a047158 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -25,6 +25,7 @@ __device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type,
if(type == CLOSURE_BSDF_SHARP_GLASS_ID) {
if(refract) {
sc->data0 = eta;
+ sc->data1 = 0.0f;
sd->flag |= bsdf_refraction_setup(sc);
}
else
@@ -58,6 +59,9 @@ __device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, Clo
if(sd->num_closure < MAX_CLOSURE) {
sc->weight *= mix_weight;
sc->type = type;
+#ifdef __OSL__
+ sc->prim = NULL;
+#endif
sd->num_closure++;
return sc;
}
@@ -79,6 +83,9 @@ __device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float m
sc->weight = weight;
sc->sample_weight = sample_weight;
sd->num_closure++;
+#ifdef __OSL__
+ sc->prim = NULL;
+#endif
return sc;
}
@@ -125,10 +132,13 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
float roughness = param1;
if(roughness == 0.0f) {
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
sd->flag |= bsdf_diffuse_setup(sc);
}
else {
sc->data0 = roughness;
+ sc->data1 = 0.0f;
sd->flag |= bsdf_oren_nayar_setup(sc);
}
}
@@ -138,6 +148,8 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
if(sc) {
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
sc->N = N;
sd->flag |= bsdf_translucent_setup(sc);
}
@@ -147,6 +159,8 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
if(sc) {
+ sc->data0 = 0.0f;
+ sc->data1 = 0.0f;
sc->N = N;
sd->flag |= bsdf_transparent_setup(sc);
}
@@ -164,6 +178,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
if(sc) {
sc->N = N;
sc->data0 = param1;
+ sc->data1 = 0.0f;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID)
@@ -302,10 +317,73 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
/* sigma */
sc->data0 = clamp(param1, 0.0f, 1.0f);
+ sc->data1 = 0.0f;
sd->flag |= bsdf_ashikhmin_velvet_setup(sc);
}
break;
}
+#ifdef __SUBSURFACE__
+ case CLOSURE_BSSRDF_ID: {
+ ShaderClosure *sc = &sd->closure[sd->num_closure];
+ float3 weight = sc->weight * mix_weight;
+ float sample_weight = fabsf(average(weight));
+
+ if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) {
+ /* radius * scale */
+ float3 radius = stack_load_float3(stack, data_node.w)*param1;
+ /* index of refraction */
+ float eta = fmaxf(param2, 1.0f + 1e-5f);
+
+ /* create one closure per color channel */
+ if(fabsf(weight.x) > 0.0f) {
+ sc->weight = make_float3(weight.x, 0.0f, 0.0f);
+ sc->sample_weight = sample_weight;
+ sc->data0 = radius.x;
+ sc->data1 = eta;
+#ifdef __OSL__
+ sc->prim = NULL;
+#endif
+ sc->N = N;
+ sd->flag |= bssrdf_setup(sc);
+
+ sd->num_closure++;
+ sc++;
+ }
+
+ if(fabsf(weight.y) > 0.0f) {
+ sc->weight = make_float3(0.0f, weight.y, 0.0f);
+ sc->sample_weight = sample_weight;
+ sc->data0 = radius.y;
+ sc->data1 = eta;
+#ifdef __OSL__
+ sc->prim = NULL;
+#endif
+ sc->N = N;
+ sd->flag |= bssrdf_setup(sc);
+
+ sd->num_closure++;
+ sc++;
+ }
+
+ if(fabsf(weight.z) > 0.0f) {
+ sc->weight = make_float3(0.0f, 0.0f, weight.z);
+ sc->sample_weight = sample_weight;
+ sc->data0 = radius.z;
+ sc->data1 = eta;
+#ifdef __OSL__
+ sc->prim = NULL;
+#endif
+ sc->N = N;
+ sd->flag |= bssrdf_setup(sc);
+
+ sd->num_closure++;
+ sc++;
+ }
+ }
+
+ break;
+ }
+#endif
default:
break;
}
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 57177eec48f..70d73f98498 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -346,12 +346,11 @@ typedef enum ClosureType {
CLOSURE_BSDF_TRANSPARENT_ID,
- CLOSURE_BSSRDF_CUBIC_ID,
+ CLOSURE_BSSRDF_ID,
CLOSURE_EMISSION_ID,
CLOSURE_DEBUG_ID,
CLOSURE_BACKGROUND_ID,
CLOSURE_HOLDOUT_ID,
- CLOSURE_SUBSURFACE_ID,
CLOSURE_AMBIENT_OCCLUSION_ID,
CLOSURE_VOLUME_ID,
@@ -366,6 +365,7 @@ typedef enum ClosureType {
#define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_OREN_NAYAR_ID)
#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_PHONG_RAMP_ID)
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
+#define CLOSURE_IS_BSSRDF(type) (type == CLOSURE_BSSRDF_ID)
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID)
#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index d67a686d1e8..e06364c6715 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -17,10 +17,10 @@ set(SRC
attribute.cpp
background.cpp
buffers.cpp
+ bssrdf.cpp
camera.cpp
film.cpp
# film_response.cpp (code unused)
- filter.cpp
graph.cpp
image.cpp
integrator.cpp
@@ -37,6 +37,7 @@ set(SRC
shader.cpp
sobol.cpp
svm.cpp
+ tables.cpp
tile.cpp
)
@@ -44,10 +45,10 @@ set(SRC_HEADERS
attribute.h
background.h
buffers.h
+ bssrdf.h
camera.h
film.h
# film_response.h (code unused)
- filter.h
graph.h
image.h
integrator.h
@@ -63,6 +64,7 @@ set(SRC_HEADERS
shader.h
sobol.h
svm.h
+ tables.h
tile.h
)
diff --git a/intern/cycles/render/bssrdf.cpp b/intern/cycles/render/bssrdf.cpp
new file mode 100644
index 00000000000..f3f889f071a
--- /dev/null
+++ b/intern/cycles/render/bssrdf.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "bssrdf.h"
+
+#include "util_algorithm.h"
+#include "util_math.h"
+#include "util_types.h"
+
+#include "kernel_types.h"
+#include "kernel_montecarlo.h"
+
+#include "closure/bsdf_diffuse.h"
+#include "closure/bssrdf.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Cumulative density function utilities */
+
+static float cdf_lookup_inverse(const vector<float>& table, float2 range, float x)
+{
+ int index = upper_bound(table.begin(), table.end(), x) - table.begin();
+
+ if(index == 0)
+ return range[0];
+ else if(index == table.size())
+ return range[1];
+ else
+ index--;
+
+ float t = (x - table[index])/(table[index+1] - table[index]);
+ float y = ((index + t)/(table.size() - 1));
+
+ return y*(range[1] - range[0]) + range[0];
+}
+
+static void cdf_invert(vector<float>& to, float2 to_range, const vector<float>& from, float2 from_range)
+{
+ float step = 1.0f/(float)(to.size() - 1);
+
+ for(int i = 0; i < to.size(); i++) {
+ float x = (i*step)*(from_range[1] - from_range[0]) + from_range[0];
+ to[i] = cdf_lookup_inverse(from, to_range, x);
+ }
+}
+
+/* BSSRDF */
+
+static float bssrdf_lookup_table_max_radius(const BSSRDFParams *ss)
+{
+ /* todo: adjust when we use the real BSSRDF */
+ return ss->ld;
+}
+
+static void bssrdf_lookup_table_create(const BSSRDFParams *ss, vector<float>& sample_table, vector<float>& pdf_table)
+{
+ const int size = BSSRDF_RADIUS_TABLE_SIZE;
+ vector<float> cdf(size);
+ vector<float> pdf(size);
+ float step = 1.0f/(float)(size - 1);
+ float max_radius = bssrdf_lookup_table_max_radius(ss);
+ float pdf_sum = 0.0f;
+
+ /* compute the probability density function */
+ for(int i = 0; i < pdf.size(); i++) {
+ float x = (i*step)*max_radius;
+ pdf[i] = bssrdf_cubic(ss->ld, x);
+ pdf_sum += pdf[i];
+ }
+
+ /* adjust for area covered by each distance */
+ for(int i = 0; i < pdf.size(); i++) {
+ float x = (i*step)*max_radius;
+ pdf[i] *= 2*M_PI_F*x;
+ }
+
+ /* normalize pdf, we multiply in reflectance later */
+ if(pdf_sum > 0.0f)
+ for(int i = 0; i < pdf.size(); i++)
+ pdf[i] /= pdf_sum;
+
+ /* sum to account for sampling which uses overlapping sphere */
+ for(int i = pdf.size() - 2; i >= 0; i--)
+ pdf[i] = pdf[i] + pdf[i+1];
+
+ /* compute the cumulative density function */
+ cdf[0] = 0.0f;
+
+ for(int i = 1; i < size; i++)
+ cdf[i] = cdf[i-1] + 0.5f*(pdf[i-1] + pdf[i])*step*max_radius;
+
+ /* invert cumulative density function for importance sampling */
+ float2 cdf_range = make_float2(0.0f, cdf[size - 1]);
+ float2 table_range = make_float2(0.0f, max_radius);
+
+ cdf_invert(sample_table, table_range, cdf, cdf_range);
+
+ /* copy pdf table */
+ for(int i = 0; i < pdf.size(); i++)
+ pdf_table[i] = pdf[i];
+}
+
+void bssrdf_table_build(vector<float>& table)
+{
+ vector<float> sample_table(BSSRDF_RADIUS_TABLE_SIZE);
+ vector<float> pdf_table(BSSRDF_RADIUS_TABLE_SIZE);
+
+ table.resize(BSSRDF_LOOKUP_TABLE_SIZE);
+
+ /* create a 2D lookup table, for reflection x sample radius */
+ for(int i = 0; i < BSSRDF_REFL_TABLE_SIZE; i++) {
+ float refl = (float)i/(float)(BSSRDF_REFL_TABLE_SIZE-1);
+ float ior = 1.3f;
+ float radius = 1.0f;
+
+ BSSRDFParams ss;
+ bssrdf_setup_params(&ss, refl, radius, ior);
+ bssrdf_lookup_table_create(&ss, sample_table, pdf_table);
+
+ memcpy(&table[i*BSSRDF_RADIUS_TABLE_SIZE], &sample_table[0], BSSRDF_RADIUS_TABLE_SIZE*sizeof(float));
+ memcpy(&table[BSSRDF_PDF_TABLE_OFFSET + i*BSSRDF_RADIUS_TABLE_SIZE], &pdf_table[0], BSSRDF_RADIUS_TABLE_SIZE*sizeof(float));
+ }
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/render/bssrdf.h b/intern/cycles/render/bssrdf.h
new file mode 100644
index 00000000000..975ac0b46ec
--- /dev/null
+++ b/intern/cycles/render/bssrdf.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __BSSRDF_H__
+#define __BSSRDF_H__
+
+#include "util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+void bssrdf_table_build(vector<float>& table);
+
+CCL_NAMESPACE_END
+
+#endif /* __BSSRDF_H__ */
+
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index fdf25ca7908..9fc6e867166 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -22,9 +22,12 @@
#include "integrator.h"
#include "mesh.h"
#include "scene.h"
+#include "tables.h"
#include "util_algorithm.h"
+#include "util_debug.h"
#include "util_foreach.h"
+#include "util_math.h"
CCL_NAMESPACE_BEGIN
@@ -171,12 +174,84 @@ bool Pass::contains(const vector<Pass>& passes, PassType type)
return false;
}
+/* Pixel Filter */
+
+static float filter_func_box(float v, float width)
+{
+ return (float)1;
+}
+
+static float filter_func_gaussian(float v, float width)
+{
+ v *= (float)2/width;
+ return (float)expf((float)-2*v*v);
+}
+
+static vector<float> filter_table(FilterType type, float width)
+{
+ const int filter_table_size = FILTER_TABLE_SIZE-1;
+ vector<float> filter_table_cdf(filter_table_size+1);
+ vector<float> filter_table(filter_table_size+1);
+ float (*filter_func)(float, float) = NULL;
+ int i, half_size = filter_table_size/2;
+
+ switch(type) {
+ case FILTER_BOX:
+ filter_func = filter_func_box;
+ break;
+ case FILTER_GAUSSIAN:
+ filter_func = filter_func_gaussian;
+ break;
+ default:
+ assert(0);
+ }
+
+ /* compute cumulative distribution function */
+ filter_table_cdf[0] = 0.0f;
+
+ for(i = 0; i < filter_table_size; i++) {
+ float x = i*width*0.5f/(filter_table_size-1);
+ float y = filter_func(x, width);
+ filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y);
+ }
+
+ for(i = 0; i <= filter_table_size; i++)
+ filter_table_cdf[i] /= filter_table_cdf[filter_table_size];
+
+ /* create importance sampling table */
+ for(i = 0; i <= half_size; i++) {
+ float x = i/(float)half_size;
+ int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin();
+ float t;
+
+ if(index < filter_table_size+1) {
+ t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]);
+ }
+ else {
+ t = 0.0f;
+ index = filter_table_size;
+ }
+
+ float y = ((index + t)/(filter_table_size))*width;
+
+ filter_table[half_size+i] = 0.5f*(1.0f + y);
+ filter_table[half_size-i] = 0.5f*(1.0f - y);
+ }
+
+ return filter_table;
+}
+
/* Film */
Film::Film()
{
exposure = 0.8f;
Pass::add(PASS_COMBINED, passes);
+
+ filter_type = FILTER_BOX;
+ filter_width = 1.0f;
+ filter_table_offset = TABLE_OFFSET_INVALID;
+
need_update = true;
}
@@ -184,10 +259,12 @@ Film::~Film()
{
}
-void Film::device_update(Device *device, DeviceScene *dscene)
+void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
if(!need_update)
return;
+
+ device_free(device, dscene, scene);
KernelFilm *kfilm = &dscene->data.film;
@@ -284,17 +361,28 @@ void Film::device_update(Device *device, DeviceScene *dscene)
kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
+ /* update filter table */
+ vector<float> table = filter_table(filter_type, filter_width);
+ filter_table_offset = scene->lookup_tables->add_table(dscene, table);
+ kfilm->filter_table_offset = (int)filter_table_offset;
+
need_update = false;
}
-void Film::device_free(Device *device, DeviceScene *dscene)
+void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene)
{
+ if(filter_table_offset != TABLE_OFFSET_INVALID) {
+ scene->lookup_tables->remove_table(filter_table_offset);
+ filter_table_offset = TABLE_OFFSET_INVALID;
+ }
}
bool Film::modified(const Film& film)
{
return !(exposure == film.exposure
- && Pass::equals(passes, film.passes));
+ && Pass::equals(passes, film.passes)
+ && filter_type == film.filter_type
+ && filter_width == film.filter_width);
}
void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index 52d1a8428f8..bc1619c3f2d 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -30,6 +30,11 @@ class Device;
class DeviceScene;
class Scene;
+typedef enum FilterType {
+ FILTER_BOX,
+ FILTER_GAUSSIAN
+} FilterType;
+
class Pass {
public:
PassType type;
@@ -47,13 +52,18 @@ class Film {
public:
float exposure;
vector<Pass> passes;
+
+ FilterType filter_type;
+ float filter_width;
+ size_t filter_table_offset;
+
bool need_update;
Film();
~Film();
- void device_update(Device *device, DeviceScene *dscene);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
bool modified(const Film& film);
void tag_passes_update(Scene *scene, const vector<Pass>& passes_);
diff --git a/intern/cycles/render/filter.cpp b/intern/cycles/render/filter.cpp
deleted file mode 100644
index 0bd4fb4d579..00000000000
--- a/intern/cycles/render/filter.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "camera.h"
-#include "device.h"
-#include "filter.h"
-#include "scene.h"
-
-#include "kernel_types.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_math.h"
-
-CCL_NAMESPACE_BEGIN
-
-Filter::Filter()
-{
- filter_type = FILTER_BOX;
- filter_width = 1.0f;
- need_update = true;
-}
-
-Filter::~Filter()
-{
-}
-
-static float filter_func_box(float v, float width)
-{
- return (float)1;
-}
-
-static float filter_func_gaussian(float v, float width)
-{
- v *= (float)2/width;
- return (float)expf((float)-2*v*v);
-}
-
-static vector<float> filter_table(FilterType type, float width)
-{
- const int filter_table_size = FILTER_TABLE_SIZE-1;
- vector<float> filter_table_cdf(filter_table_size+1);
- vector<float> filter_table(filter_table_size+1);
- float (*filter_func)(float, float) = NULL;
- int i, half_size = filter_table_size/2;
-
- switch(type) {
- case FILTER_BOX:
- filter_func = filter_func_box;
- break;
- case FILTER_GAUSSIAN:
- filter_func = filter_func_gaussian;
- break;
- default:
- assert(0);
- }
-
- /* compute cumulative distribution function */
- filter_table_cdf[0] = 0.0f;
-
- for(i = 0; i < filter_table_size; i++) {
- float x = i*width*0.5f/(filter_table_size-1);
- float y = filter_func(x, width);
- filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y);
- }
-
- for(i = 0; i <= filter_table_size; i++)
- filter_table_cdf[i] /= filter_table_cdf[filter_table_size];
-
- /* create importance sampling table */
- for(i = 0; i <= half_size; i++) {
- float x = i/(float)half_size;
- int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin();
- float t;
-
- if(index < filter_table_size+1) {
- t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]);
- }
- else {
- t = 0.0f;
- index = filter_table_size;
- }
-
- float y = ((index + t)/(filter_table_size))*width;
-
- filter_table[half_size+i] = 0.5f*(1.0f + y);
- filter_table[half_size-i] = 0.5f*(1.0f - y);
- }
-
- return filter_table;
-}
-
-void Filter::device_update(Device *device, DeviceScene *dscene)
-{
- if(!need_update)
- return;
-
- device_free(device, dscene);
-
- /* update __filter_table */
- vector<float> table = filter_table(filter_type, filter_width);
-
- dscene->filter_table.copy(&table[0], table.size());
- device->tex_alloc("__filter_table", dscene->filter_table, true);
-
- need_update = false;
-}
-
-void Filter::device_free(Device *device, DeviceScene *dscene)
-{
- device->tex_free(dscene->filter_table);
- dscene->filter_table.clear();
-}
-
-bool Filter::modified(const Filter& filter)
-{
- return !(filter_type == filter.filter_type &&
- filter_width == filter.filter_width);
-}
-
-void Filter::tag_update(Scene *scene)
-{
- need_update = true;
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index c6b9ae08508..46043cf85d2 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -187,6 +187,7 @@ public:
virtual bool has_surface_emission() { return false; }
virtual bool has_surface_transparent() { return false; }
+ virtual bool has_surface_bssrdf() { return false; }
vector<ShaderInput*> inputs;
vector<ShaderOutput*> outputs;
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 699e6979990..00039170733 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -54,6 +54,7 @@ Integrator::Integrator()
transmission_samples = 1;
ao_samples = 1;
mesh_light_samples = 1;
+ subsurface_samples = 1;
progressive = true;
need_update = true;
@@ -108,6 +109,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->transmission_samples = transmission_samples;
kintegrator->ao_samples = ao_samples;
kintegrator->mesh_light_samples = mesh_light_samples;
+ kintegrator->subsurface_samples = subsurface_samples;
/* sobol directions table */
int max_samples = 1;
@@ -163,6 +165,7 @@ bool Integrator::modified(const Integrator& integrator)
transmission_samples == integrator.transmission_samples &&
ao_samples == integrator.ao_samples &&
mesh_light_samples == integrator.mesh_light_samples &&
+ subsurface_samples == integrator.subsurface_samples &&
motion_blur == integrator.motion_blur);
}
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index 8fb341182b7..9867e310d4d 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -54,6 +54,7 @@ public:
int transmission_samples;
int ao_samples;
int mesh_light_samples;
+ int subsurface_samples;
bool progressive;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index a4ffc2518fb..b4ff6e3152b 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1262,16 +1262,19 @@ void ProxyNode::compile(OSLCompiler& compiler)
/* BSDF Closure */
-BsdfNode::BsdfNode()
-: ShaderNode("bsdf")
+BsdfNode::BsdfNode(bool scattering_)
+: ShaderNode("subsurface_scattering"), scattering(scattering_)
{
- closure = ccl::CLOSURE_BSDF_DIFFUSE_ID;
+ closure = ccl::CLOSURE_BSSRDF_ID;
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
- add_output("BSDF", SHADER_SOCKET_CLOSURE);
+ if(scattering)
+ add_output("BSSRDF", SHADER_SOCKET_CLOSURE);
+ else
+ add_output("BSDF", SHADER_SOCKET_CLOSURE);
}
void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3)
@@ -1313,7 +1316,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
(param3)? param3->stack_offset: SVM_STACK_INVALID);
}
else {
- compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset);
+ compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, SVM_STACK_INVALID,
+ (param3)? param3->stack_offset: SVM_STACK_INVALID);
}
}
@@ -1548,6 +1552,29 @@ void TransparentBsdfNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_transparent_bsdf");
}
+/* Subsurface Scattering Closure */
+
+SubsurfaceScatteringNode::SubsurfaceScatteringNode()
+: BsdfNode(true)
+{
+ name = "subsurface_scattering";
+ closure = CLOSURE_BSSRDF_ID;
+
+ add_input("Scale", SHADER_SOCKET_FLOAT, 0.01f);
+ add_input("Radius", SHADER_SOCKET_VECTOR, make_float3(0.1f, 0.1f, 0.1f));
+ add_input("IOR", SHADER_SOCKET_FLOAT, 1.3f);
+}
+
+void SubsurfaceScatteringNode::compile(SVMCompiler& compiler)
+{
+ BsdfNode::compile(compiler, input("Scale"), input("IOR"), input("Radius"));
+}
+
+void SubsurfaceScatteringNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "node_subsurface_scattering");
+}
+
/* Emissive Closure */
EmissionNode::EmissionNode()
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 1efe4ae076d..0d9f84327d0 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -198,11 +198,13 @@ public:
class BsdfNode : public ShaderNode {
public:
- SHADER_NODE_CLASS(BsdfNode)
+ BsdfNode(bool scattering = false);
+ SHADER_NODE_BASE_CLASS(BsdfNode);
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL);
ClosureType closure;
+ bool scattering;
};
class WardBsdfNode : public BsdfNode {
@@ -257,6 +259,12 @@ public:
static ShaderEnum distribution_enum;
};
+class SubsurfaceScatteringNode : public BsdfNode {
+public:
+ SHADER_NODE_CLASS(SubsurfaceScatteringNode)
+ bool has_surface_bssrdf() { return true; }
+};
+
class EmissionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(EmissionNode)
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index f5585babf5c..cefb6315725 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -73,7 +73,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
if(!need_update)
return;
- device_free(device, dscene);
+ device_free(device, dscene, scene);
/* determine which shaders are in use */
device_update_shaders_used(scene);
@@ -114,11 +114,11 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
device_update_common(device, dscene, scene, progress);
}
-void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
+void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
{
OSLGlobals *og = (OSLGlobals*)device->osl_memory();
- device_free_common(device, dscene);
+ device_free_common(device, dscene, scene);
/* clear shader engine */
og->use = false;
@@ -328,6 +328,7 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str
OSLShaderInfo info;
info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
+ info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos);
loaded_shaders[hash] = info;
return loaded_shaders.find(hash)->first.c_str();
@@ -511,6 +512,8 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
current_shader->has_surface_emission = true;
if(info->has_surface_transparent)
current_shader->has_surface_transparent = true;
+ if(info->has_surface_bssrdf)
+ current_shader->has_surface_bssrdf = true;
}
}
@@ -671,6 +674,8 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes)
current_shader->has_surface_emission = true;
if(node->has_surface_transparent())
current_shader->has_surface_transparent = true;
+ if(node->has_surface_bssrdf())
+ current_shader->has_surface_bssrdf = true;
}
else
nodes_done = false;
@@ -736,6 +741,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
shader->has_surface = false;
shader->has_surface_emission = false;
shader->has_surface_transparent = false;
+ shader->has_surface_bssrdf = false;
shader->has_volume = false;
shader->has_displacement = false;
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 4b4ed6cba00..2d3996df0eb 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -50,11 +50,13 @@ class ShaderOutput;
struct OSLShaderInfo {
OSLShaderInfo()
- : has_surface_emission(false), has_surface_transparent(false)
+ : has_surface_emission(false), has_surface_transparent(false),
+ has_surface_bssrdf(false)
{}
bool has_surface_emission;
bool has_surface_transparent;
+ bool has_surface_bssrdf;
};
/* Shader Manage */
@@ -69,7 +71,7 @@ public:
bool use_osl() { return true; }
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
/* osl compile and query */
static bool osl_compile(const string& inputfile, const string& outputfile);
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 7b82a91cae8..a6dca62ffd0 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -20,19 +20,19 @@
#include "background.h"
#include "camera.h"
+#include "curves.h"
#include "device.h"
#include "film.h"
-#include "filter.h"
#include "integrator.h"
#include "light.h"
-#include "shader.h"
#include "mesh.h"
#include "object.h"
+#include "osl.h"
#include "particles.h"
-#include "curves.h"
#include "scene.h"
+#include "shader.h"
#include "svm.h"
-#include "osl.h"
+#include "tables.h"
#include "util_foreach.h"
#include "util_progress.h"
@@ -46,7 +46,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
memset(&dscene.data, 0, sizeof(dscene.data));
camera = new Camera();
- filter = new Filter();
+ lookup_tables = new LookupTables();
film = new Film();
background = new Background();
light_manager = new LightManager();
@@ -93,14 +93,13 @@ void Scene::free_memory(bool final)
if(device) {
camera->device_free(device, &dscene);
- filter->device_free(device, &dscene);
- film->device_free(device, &dscene);
+ film->device_free(device, &dscene, this);
background->device_free(device, &dscene);
integrator->device_free(device, &dscene);
object_manager->device_free(device, &dscene);
mesh_manager->device_free(device, &dscene);
- shader_manager->device_free(device, &dscene);
+ shader_manager->device_free(device, &dscene, this);
light_manager->device_free(device, &dscene);
particle_system_manager->device_free(device, &dscene);
@@ -108,10 +107,12 @@ void Scene::free_memory(bool final)
if(!params.persistent_data || final)
image_manager->device_free(device, &dscene);
+
+ lookup_tables->device_free(device, &dscene);
}
if(final) {
- delete filter;
+ delete lookup_tables;
delete camera;
delete film;
delete background;
@@ -188,13 +189,8 @@ void Scene::device_update(Device *device_, Progress& progress)
if(progress.get_cancel()) return;
- progress.set_status("Updating Filter");
- filter->device_update(device, &dscene);
-
- if(progress.get_cancel()) return;
-
progress.set_status("Updating Film");
- film->device_update(device, &dscene);
+ film->device_update(device, &dscene, this);
if(progress.get_cancel()) return;
@@ -203,6 +199,11 @@ void Scene::device_update(Device *device_, Progress& progress)
if(progress.get_cancel()) return;
+ progress.set_status("Updating Lookup Tables");
+ lookup_tables->device_update(device, &dscene);
+
+ if(progress.get_cancel()) return;
+
progress.set_status("Updating Device", "Writing constant memory");
device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
}
@@ -247,7 +248,7 @@ bool Scene::need_reset()
|| object_manager->need_update
|| mesh_manager->need_update
|| light_manager->need_update
- || filter->need_update
+ || lookup_tables->need_update
|| integrator->need_update
|| shader_manager->need_update
|| particle_system_manager->need_update
@@ -261,7 +262,6 @@ void Scene::reset()
/* ensure all objects are updated */
camera->tag_update();
- filter->tag_update(this);
film->tag_update(this);
background->tag_update(this);
integrator->tag_update(this);
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index fc6b538af03..545a765cc22 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -39,10 +39,10 @@ class Camera;
class Device;
class DeviceInfo;
class Film;
-class Filter;
class Integrator;
class Light;
class LightManager;
+class LookupTables;
class Mesh;
class MeshManager;
class Object;
@@ -99,8 +99,8 @@ public:
device_vector<uint> shader_flag;
device_vector<uint> object_flag;
- /* filter */
- device_vector<float> filter_table;
+ /* lookup tables */
+ device_vector<float> lookup_table;
/* integrator */
device_vector<uint> sobol_directions;
@@ -155,7 +155,7 @@ class Scene {
public:
/* data */
Camera *camera;
- Filter *filter;
+ LookupTables *lookup_tables;
Film *film;
Background *background;
Integrator *integrator;
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index b9b49bf2989..c7f39b4151a 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -16,6 +16,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "bssrdf.h"
#include "device.h"
#include "graph.h"
#include "light.h"
@@ -25,6 +26,7 @@
#include "scene.h"
#include "shader.h"
#include "svm.h"
+#include "tables.h"
#include "util_foreach.h"
@@ -46,6 +48,7 @@ Shader::Shader()
has_surface = false;
has_surface_transparent = false;
has_surface_emission = false;
+ has_surface_bssrdf = false;
has_volume = false;
has_displacement = false;
@@ -115,6 +118,7 @@ void Shader::tag_used(Scene *scene)
ShaderManager::ShaderManager()
{
need_update = true;
+ bssrdf_table_offset = TABLE_OFFSET_INVALID;
}
ShaderManager::~ShaderManager()
@@ -196,7 +200,8 @@ void ShaderManager::device_update_shaders_used(Scene *scene)
void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
- device_free_common(device, dscene);
+ device->tex_free(dscene->shader_flag);
+ dscene->shader_flag.clear();
if(scene->shaders.size() == 0)
return;
@@ -204,6 +209,7 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
uint shader_flag_size = scene->shaders.size()*4;
uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
uint i = 0;
+ bool has_surface_bssrdf = false;
foreach(Shader *shader, scene->shaders) {
uint flag = 0;
@@ -216,6 +222,8 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
flag |= SD_HAS_VOLUME;
if(shader->homogeneous_volume)
flag |= SD_HOMOGENEOUS_VOLUME;
+ if(shader->has_surface_bssrdf)
+ has_surface_bssrdf = true;
shader_flag[i++] = flag;
shader_flag[i++] = shader->pass_id;
@@ -224,10 +232,32 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
}
device->tex_alloc("__shader_flag", dscene->shader_flag);
+
+ /* bssrdf lookup table */
+ KernelBSSRDF *kbssrdf = &dscene->data.bssrdf;
+
+ if(has_surface_bssrdf && bssrdf_table_offset == TABLE_OFFSET_INVALID) {
+ vector<float> table;
+
+ bssrdf_table_build(table);
+ bssrdf_table_offset = scene->lookup_tables->add_table(dscene, table);
+
+ kbssrdf->table_offset = (int)bssrdf_table_offset;
+ kbssrdf->num_attempts = BSSRDF_MAX_ATTEMPTS;
+ }
+ else if(!has_surface_bssrdf && bssrdf_table_offset != TABLE_OFFSET_INVALID) {
+ scene->lookup_tables->remove_table(bssrdf_table_offset);
+ bssrdf_table_offset = TABLE_OFFSET_INVALID;
+ }
}
-void ShaderManager::device_free_common(Device *device, DeviceScene *dscene)
+void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
{
+ if(bssrdf_table_offset != TABLE_OFFSET_INVALID) {
+ scene->lookup_tables->remove_table(bssrdf_table_offset);
+ bssrdf_table_offset = TABLE_OFFSET_INVALID;
+ }
+
device->tex_free(dscene->shader_flag);
dscene->shader_flag.clear();
}
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index b38e098e3cb..2a9f1198467 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -75,6 +75,7 @@ public:
bool has_surface_transparent;
bool has_volume;
bool has_displacement;
+ bool has_surface_bssrdf;
/* requested mesh attributes */
AttributeRequestSet attributes;
@@ -116,11 +117,11 @@ public:
/* device update */
virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0;
- virtual void device_free(Device *device, DeviceScene *dscene) = 0;
+ virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0;
void device_update_shaders_used(Scene *scene);
void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free_common(Device *device, DeviceScene *dscene);
+ void device_free_common(Device *device, DeviceScene *dscene, Scene *scene);
/* get globally unique id for a type of attribute */
uint get_attribute_id(ustring name);
@@ -138,6 +139,8 @@ protected:
typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
AttributeIDMap unique_attribute_id;
+
+ size_t bssrdf_table_offset;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 5cb11a4ec1a..ea2fe4991db 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -50,7 +50,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
return;
/* test if we need to update */
- device_free(device, dscene);
+ device_free(device, dscene, scene);
/* determine which shaders are in use */
device_update_shaders_used(scene);
@@ -99,9 +99,9 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
need_update = false;
}
-void SVMShaderManager::device_free(Device *device, DeviceScene *dscene)
+void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
{
- device_free_common(device, dscene);
+ device_free_common(device, dscene, scene);
device->tex_free(dscene->svm_nodes);
dscene->svm_nodes.clear();
@@ -486,6 +486,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
current_shader->has_surface_emission = true;
if(node->has_surface_transparent())
current_shader->has_surface_transparent = true;
+ if(node->has_surface_bssrdf())
+ current_shader->has_surface_bssrdf = true;
/* end node is added outside of this */
}
@@ -546,6 +548,8 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
current_shader->has_surface_emission = true;
if(node->has_surface_transparent())
current_shader->has_surface_transparent = true;
+ if(node->has_surface_bssrdf())
+ current_shader->has_surface_bssrdf = true;
}
done.insert(node);
@@ -654,6 +658,7 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in
shader->has_surface = false;
shader->has_surface_emission = false;
shader->has_surface_transparent = false;
+ shader->has_surface_bssrdf = false;
shader->has_volume = false;
shader->has_displacement = false;
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index c1ce619e12a..e09144a4e76 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -48,7 +48,7 @@ public:
void reset(Scene *scene);
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
};
/* Graph Compiler */
diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp
new file mode 100644
index 00000000000..c7c86f68960
--- /dev/null
+++ b/intern/cycles/render/tables.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "device.h"
+#include "scene.h"
+#include "tables.h"
+
+#include "util_debug.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Lookup Tables */
+
+LookupTables::LookupTables()
+{
+ need_update = true;
+}
+
+LookupTables::~LookupTables()
+{
+ assert(lookup_tables.size() == 0);
+}
+
+void LookupTables::device_update(Device *device, DeviceScene *dscene)
+{
+ if(!need_update)
+ return;
+
+ device->tex_alloc("__lookup_table", dscene->lookup_table);
+
+ need_update = false;
+}
+
+void LookupTables::device_free(Device *device, DeviceScene *dscene)
+{
+ device->tex_free(dscene->lookup_table);
+ dscene->lookup_table.clear();
+}
+
+static size_t round_up_to_multiple(size_t size, size_t chunk)
+{
+ return ((size + chunk - 1)/chunk) * chunk;
+}
+
+size_t LookupTables::add_table(DeviceScene *dscene, vector<float>& data)
+{
+ assert(data.size() > 0);
+
+ need_update = true;
+
+ Table new_table;
+ new_table.offset = 0;
+ new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE);
+
+ /* find space to put lookup table */
+ list<Table>::iterator table;
+
+ for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
+ if(new_table.offset + new_table.size <= table->offset) {
+ lookup_tables.insert(table, new_table);
+ break;
+ }
+ else
+ new_table.offset = table->offset + table->size;
+ }
+
+ if(table == lookup_tables.end()) {
+ /* add at the end */
+ lookup_tables.push_back(new_table);
+ dscene->lookup_table.resize(new_table.offset + new_table.size);
+ }
+
+ /* copy table data and return offset */
+ dscene->lookup_table.copy_at(&data[0], new_table.offset, data.size());
+ return new_table.offset;
+}
+
+void LookupTables::remove_table(size_t offset)
+{
+ need_update = true;
+
+ list<Table>::iterator table;
+
+ for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
+ if(table->offset == offset) {
+ lookup_tables.erase(table);
+ break;
+ }
+ }
+
+ assert(table != lookup_tables.end());
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/render/filter.h b/intern/cycles/render/tables.h
index 5df7bb8fd14..605efd3747f 100644
--- a/intern/cycles/render/filter.h
+++ b/intern/cycles/render/tables.h
@@ -16,8 +16,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __FILTER_H__
-#define __FILTER_H__
+#ifndef __TABLES_H__
+#define __TABLES_H__
+
+#include <util_list.h>
CCL_NAMESPACE_BEGIN
@@ -25,29 +27,30 @@ class Device;
class DeviceScene;
class Scene;
-typedef enum FilterType {
- FILTER_BOX,
- FILTER_GAUSSIAN
-} FilterType;
+enum { TABLE_CHUNK_SIZE = 256 };
+enum { TABLE_OFFSET_INVALID = -1 };
-class Filter {
+class LookupTables {
public:
- /* pixel filter */
- FilterType filter_type;
- float filter_width;
+ struct Table {
+ size_t offset;
+ size_t size;
+ };
+
bool need_update;
+ list<Table> lookup_tables;
- Filter();
- ~Filter();
+ LookupTables();
+ ~LookupTables();
void device_update(Device *device, DeviceScene *dscene);
void device_free(Device *device, DeviceScene *dscene);
- bool modified(const Filter& filter);
- void tag_update(Scene *scene);
+ size_t add_table(DeviceScene *dscene, vector<float>& data);
+ void remove_table(size_t offset);
};
CCL_NAMESPACE_END
-#endif /* __FILTER_H__ */
+#endif /* __TABLES_H__ */
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index c37fa1a4dc6..f2e814527fd 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -1151,14 +1151,7 @@ __device float safe_logf(float a, float b)
__device float safe_divide(float a, float b)
{
- float result;
-
- if(b == 0.0f)
- result = 0.0f;
- else
- result = a/b;
-
- return result;
+ return (b != 0.0f)? a/b: 0.0f;
}
/* Ray Intersection */
diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h
index 69e2e014761..aaedbe2dccd 100644
--- a/intern/ffmpeg/ffmpeg_compat.h
+++ b/intern/ffmpeg/ffmpeg_compat.h
@@ -171,6 +171,20 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
}
#endif
+#if ((LIBAVCODEC_VERSION_MAJOR < 54) || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR < 28))
+static inline
+void avcodec_free_frame(AVFrame **frame)
+{
+ /* don't need to do anything with old AVFrame
+ * since it does not have malloced members */
+ (void)frame;
+}
+#endif
+
+#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 13))
+#define FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
+#endif
+
#ifndef FFMPEG_HAVE_AVIO
#define AVIO_FLAG_WRITE URL_WRONLY
#define avio_open url_fopen
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 795b5200ae2..61b853d79b0 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -454,7 +454,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
GHOST_TDrawingContextType type,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples
) :
- GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples),
+ GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, false, numOfAASamples),
m_customCursor(0)
{
NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40];
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index e3d092101b0..f595fa7d794 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -53,7 +53,7 @@ public:
const bool stereoVisual,
const GHOST_TUns16 numOfAASamples
) :
- GHOST_Window(width, height, state, type, stereoVisual, numOfAASamples),
+ GHOST_Window(width, height, state, type, stereoVisual, false, numOfAASamples),
m_system(system)
{
setTitle(title);
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index b1a9ca52605..2b1bdfa78f0 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -130,7 +130,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
int msPixelFormat)
:
GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone,
- stereoVisual, numOfAASamples),
+ stereoVisual, false, numOfAASamples),
m_system(system),
m_hDC(0),
m_hGlRc(0),
diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt
index 5680ce79762..30a74baa646 100644
--- a/intern/opencolorio/CMakeLists.txt
+++ b/intern/opencolorio/CMakeLists.txt
@@ -44,6 +44,7 @@ set(SRC
if(WITH_OPENCOLORIO)
add_definitions(
-DWITH_OCIO
+ -DGLEW_STATIC
)
list(APPEND INC_SYS
diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript
index 73a8fd7a2e0..7f050f25cae 100644
--- a/intern/opencolorio/SConscript
+++ b/intern/opencolorio/SConscript
@@ -30,7 +30,7 @@ Import('env')
sources = env.Glob('*.cc')
incs = '. ../guardedalloc ../../source/blender/blenlib'
-defs = []
+defs = [ 'GLEW_STATIC' ]
if env['WITH_BF_OCIO']:
defs.append('WITH_OCIO')
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index 47c648e9cba..37f624e1f8b 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -381,8 +381,9 @@ void FallbackImpl::matrixTransformScale(float * , float * , const float *)
{
}
-void FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor)
+bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide)
{
+ return false;
}
void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState *state)
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index 73d8af295f2..c8db2c2b531 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -283,9 +283,9 @@ void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4
impl->matrixTransformScale(m44, offset4, scale4f);
}
-void OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor)
+int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide)
{
- impl->setupGLSLDraw(state_r, processor);
+ return (int) impl->setupGLSLDraw(state_r, processor, (bool) predivide);
}
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state)
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index 3c42e0a1a1e..3632a0da1c6 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -121,7 +121,7 @@ void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale4);
-void OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor);
+int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide);
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc
index 8803814ce3f..05c29fd5854 100644
--- a/intern/opencolorio/ocio_impl.cc
+++ b/intern/opencolorio/ocio_impl.cc
@@ -551,228 +551,3 @@ void OCIOImpl::matrixTransformScale(float * m44, float * offset4, const float *s
{
MatrixTransform::Scale(m44, offset4, scale4f);
}
-
-/* **** OpenGL drawing routines using GLSL for color space transform ***** */
-
-/* Some of the GLSL transform related functions below are adopted from
- * ociodisplay utility of OpenColorIO project which are originally
- *
- * Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
- */
-
-typedef struct OCIO_GLSLDrawState {
- bool lut3d_texture_allocated; /* boolean flag indicating whether
- * lut texture is allocated
- */
-
- GLuint lut3d_texture; /* OGL texture ID for 3D LUT */
-
- float *lut3d; /* 3D LUT table */
-
- /* Cache */
- std::string lut3dcacheid;
- std::string shadercacheid;
-
- /* GLSL stuff */
- GLuint fragShader;
- GLuint program;
-
- /* Previous OpenGL state. */
- GLint last_texture, last_texture_unit;
-} OCIO_GLSLDrawState;
-
-static const char * g_fragShaderText = ""
-"\n"
-"uniform sampler2D tex1;\n"
-"uniform sampler3D tex2;\n"
-"\n"
-"void main()\n"
-"{\n"
-" vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
-" gl_FragColor = OCIODisplay(col, tex2);\n"
-"}\n";
-
-static GLuint compileShaderText(GLenum shaderType, const char *text)
-{
- GLuint shader;
- GLint stat;
-
- shader = glCreateShader(shaderType);
- glShaderSource(shader, 1, (const GLchar **) &text, NULL);
- glCompileShader(shader);
- glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
-
- if (!stat) {
- GLchar log[1000];
- GLsizei len;
- glGetShaderInfoLog(shader, 1000, &len, log);
- return 0;
- }
-
- return shader;
-}
-
-static GLuint linkShaders(GLuint fragShader)
-{
- if (!fragShader)
- return 0;
-
- GLuint program = glCreateProgram();
-
- if (fragShader)
- glAttachShader(program, fragShader);
-
- glLinkProgram(program);
-
- /* check link */
- {
- GLint stat;
- glGetProgramiv(program, GL_LINK_STATUS, &stat);
- if (!stat) {
- GLchar log[1000];
- GLsizei len;
- glGetProgramInfoLog(program, 1000, &len, log);
- fprintf(stderr, "Shader link error:\n%s\n", log);
- return 0;
- }
- }
-
- return program;
-}
-
-static OCIO_GLSLDrawState *allocateOpenGLState(void)
-{
- OCIO_GLSLDrawState *state;
-
- /* Allocate memory for state. */
- state = (OCIO_GLSLDrawState *) MEM_callocN(sizeof(OCIO_GLSLDrawState),
- "OCIO OpenGL State struct");
-
- /* Call constructors on new memory. */
- new (&state->lut3dcacheid) std::string("");
- new (&state->shadercacheid) std::string("");
-
- return state;
-}
-
-/* Ensure LUT texture and array are allocated */
-static void ensureLUT3DAllocated(OCIO_GLSLDrawState *state)
-{
- int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE;
-
- if (state->lut3d_texture_allocated)
- return;
-
- glGenTextures(1, &state->lut3d_texture);
-
- state->lut3d = (float *) MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT");
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
- 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);
- glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
- LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
- 0, GL_RGB,GL_FLOAT, &state->lut3d);
-
- state->lut3d_texture_allocated = true;
-}
-
-/**
- * Setup OpenGL contexts for a transform defined by processor using GLSL
- * All LUT allocating baking and shader compilation happens here.
- *
- * Once this function is called, callee could start drawing images
- * using regular 2D texture.
- *
- * When all drawing is finished, finishGLSLDraw shall be called to
- * restore OpenGL context to it's pre-GLSL draw state.
- */
-void OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor)
-{
- ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
-
- /* Create state if needed. */
- OCIO_GLSLDrawState *state;
- if (!*state_r)
- *state_r = allocateOpenGLState();
- state = *state_r;
-
- glGetIntegerv(GL_TEXTURE_2D, &state->last_texture);
- glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit);
-
- ensureLUT3DAllocated(state);
-
- /* Step 1: Create a GPU Shader Description */
- GpuShaderDesc shaderDesc;
- shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_0);
- shaderDesc.setFunctionName("OCIODisplay");
- shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
-
- /* Step 2: Compute the 3D LUT */
- std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
- if (lut3dCacheID != state->lut3dcacheid) {
- state->lut3dcacheid = lut3dCacheID;
- ocio_processor->getGpuLut3D(state->lut3d, shaderDesc);
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
- glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
- LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
- GL_RGB, GL_FLOAT, state->lut3d);
- }
-
- /* Step 3: Compute the Shader */
- std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
- if (state->program == 0 || shaderCacheID != state->shadercacheid) {
- state->shadercacheid = shaderCacheID;
-
- std::ostringstream os;
- os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
- os << g_fragShaderText;
-
- if (state->fragShader)
- glDeleteShader(state->fragShader);
- state->fragShader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
-
- if (state->program)
- glDeleteProgram(state->program);
-
- state->program = linkShaders(state->fragShader);
- }
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
-
- glActiveTexture(GL_TEXTURE0);
-
- glUseProgram(state->program);
- glUniform1i(glGetUniformLocation(state->program, "tex1"), 0);
- glUniform1i(glGetUniformLocation(state->program, "tex2"), 1);
-}
-
-void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState *state)
-{
- glActiveTexture(state->last_texture_unit);
- glBindTexture(GL_TEXTURE_2D, state->last_texture);
- glUseProgram(0);
-}
-
-void OCIOImpl::freeGLState(struct OCIO_GLSLDrawState *state)
-{
- using std::string;
-
- if (state->lut3d_texture_allocated)
- glDeleteTextures(1, &state->lut3d_texture);
-
- if (state->lut3d)
- MEM_freeN(state->lut3d);
-
- state->lut3dcacheid.~string();
- state->shadercacheid.~string();
-
- MEM_freeN(state);
-}
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 2a1f88be5f4..a328470ccb5 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -96,7 +96,7 @@ public:
virtual void matrixTransformScale(float * m44, float * offset4, const float * scale4) = 0;
- virtual void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) = 0;
+ virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) = 0;
virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0;
virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0;
};
@@ -169,7 +169,7 @@ public:
void matrixTransformScale(float * m44, float * offset4, const float * scale4);
- void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor);
+ bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
};
@@ -243,7 +243,7 @@ public:
void matrixTransformScale(float * m44, float * offset4, const float * scale4);
- void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor);
+ bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
};
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index c79593779cf..9343a13e888 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -77,15 +77,33 @@ typedef struct OCIO_GLSLDrawState {
GLint last_texture, last_texture_unit;
} OCIO_GLSLDrawState;
-static const char * g_fragShaderText = ""
+/* Hardcoded to do alpha predivide before color space conversion */
+static const char *g_fragShaderText = ""
"\n"
"uniform sampler2D tex1;\n"
"uniform sampler3D tex2;\n"
+"uniform bool predivide;\n"
"\n"
"void main()\n"
"{\n"
" vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
-" gl_FragColor = OCIODisplay(col, tex2);\n"
+" if (predivide == false || col[3] == 1.0f || col[3] == 0.0f) {\n"
+" gl_FragColor = OCIODisplay(col, tex2);\n"
+" } else {\n"
+" float alpha = col[3];\n"
+" float inv_alpha = 1.0f / alpha;\n"
+"\n"
+" col[0] *= inv_alpha;\n"
+" col[1] *= inv_alpha;\n"
+" col[2] *= inv_alpha;\n"
+"\n"
+" gl_FragColor = OCIODisplay(col, tex2);\n"
+"\n"
+" col[0] *= alpha;\n"
+" col[1] *= alpha;\n"
+" col[2] *= alpha;\n"
+" }\n"
+"\n"
"}\n";
static GLuint compileShaderText(GLenum shaderType, const char *text)
@@ -187,7 +205,7 @@ static void ensureLUT3DAllocated(OCIO_GLSLDrawState *state)
* When all drawing is finished, finishGLSLDraw shall be called to
* restore OpenGL context to it's pre-GLSL draw state.
*/
-void OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor)
+bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide)
{
ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
@@ -232,22 +250,36 @@ void OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
if (state->fragShader)
glDeleteShader(state->fragShader);
+
state->fragShader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
- if (state->program)
- glDeleteProgram(state->program);
+ if (state->fragShader) {
+ if (state->program)
+ glDeleteProgram(state->program);
- state->program = linkShaders(state->fragShader);
+ state->program = linkShaders(state->fragShader);
+ }
}
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+ if (state->program) {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glUseProgram(state->program);
+ glUniform1i(glGetUniformLocation(state->program, "tex1"), 0);
+ glUniform1i(glGetUniformLocation(state->program, "tex2"), 1);
+ glUniform1i(glGetUniformLocation(state->program, "predivide"), predivide);
- glActiveTexture(GL_TEXTURE0);
+ return true;
+ }
+ else {
+ glActiveTexture(state->last_texture_unit);
+ glBindTexture(GL_TEXTURE_2D, state->last_texture);
- glUseProgram(state->program);
- glUniform1i(glGetUniformLocation(state->program, "tex1"), 0);
- glUniform1i(glGetUniformLocation(state->program, "tex2"), 1);
+ return false;
+ }
}
void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState *state)
@@ -267,6 +299,12 @@ void OCIOImpl::freeGLState(struct OCIO_GLSLDrawState *state)
if (state->lut3d)
MEM_freeN(state->lut3d);
+ if (state->program)
+ glDeleteProgram(state->program);
+
+ if (state->fragShader)
+ glDeleteShader(state->fragShader);
+
state->lut3dcacheid.~string();
state->shadercacheid.~string();
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio
index d73561338ba..2d5f68f0a45 100644
--- a/release/datafiles/colormanagement/config.ocio
+++ b/release/datafiles/colormanagement/config.ocio
@@ -66,7 +66,7 @@ colorspaces:
Rec. 709 (Full Range), Blender native linear space
isdata: false
allocation: lg2
- allocationvars: [-8.5, 5]
+ allocationvars: [-15, 6]
- !<ColorSpace>
name: Raw
diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
index 3dbddc30f0d..9daddfe5dc4 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -296,6 +296,7 @@ class SpellChecker():
"spacebar",
"tooltip", "tooltips",
"trackpad",
+ "tuple",
"unicode",
"viewport", "viewports",
"viscoelastic",
@@ -437,6 +438,7 @@ class SpellChecker():
"ascii",
"atrac",
"bsdf",
+ "bssrdf",
"bw",
"ccd",
"cmd",
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index c5dbe946012..7c32e72b3e3 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -204,36 +204,40 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- ob = context.object
+ obj = context.object
split = layout.split()
col = split.column()
- col.prop(ob, "draw_type", text="Type")
+ col.prop(obj, "draw_type", text="Type")
col = split.column()
row = col.row()
- row.prop(ob, "show_bounds", text="Bounds")
+ row.prop(obj, "show_bounds", text="Bounds")
sub = row.row()
- sub.active = ob.show_bounds
- sub.prop(ob, "draw_bounds_type", text="")
+ sub.active = obj.show_bounds
+ sub.prop(obj, "draw_bounds_type", text="")
split = layout.split()
col = split.column()
- col.prop(ob, "show_name", text="Name")
- col.prop(ob, "show_axis", text="Axis")
- if ob.type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}:
+ col.prop(obj, "show_name", text="Name")
+ col.prop(obj, "show_axis", text="Axis")
+
+ obj_type = obj.type
+
+ if obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}:
# Makes no sense for cameras, armtures, etc.!
- col.prop(ob, "show_wire", text="Wire")
+ col.prop(obj, "show_wire", text="Wire")
# Only useful with object having faces/materials...
- col.prop(ob, "color", text="Object Color")
+ col.prop(obj, "color", text="Object Color")
col = split.column()
- col.prop(ob, "show_texture_space", text="Texture Space")
- col.prop(ob, "show_x_ray", text="X-Ray")
- if ob.type == 'MESH':
- col.prop(ob, "show_transparent", text="Transparency")
- col.prop(ob, "show_all_edges")
+ col.prop(obj, "show_texture_space", text="Texture Space")
+ col.prop(obj, "show_x_ray", text="X-Ray")
+ if obj_type == 'MESH' or (obj_type == 'EMPTY' and obj.empty_draw_type == 'IMAGE'):
+ col.prop(obj, "show_transparent", text="Transparency")
+ if obj_type == 'MESH':
+ col.prop(obj, "show_all_edges")
class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 43761dd439e..d81356b3113 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -886,6 +886,7 @@ class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel):
layout.operator("clip.set_viewport_background")
layout.operator("clip.setup_tracking_scene")
+ layout.operator("clip.prefetch")
class CLIP_MT_view(Menu):
@@ -945,6 +946,7 @@ class CLIP_MT_clip(Menu):
layout.operator("clip.open")
if clip:
+ layout.operator("clip.prefetch")
layout.operator("clip.reload")
layout.menu("CLIP_MT_proxy")
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 26c76bd6655..ac76b988e05 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -151,10 +151,17 @@ class NODE_MT_select(Menu):
layout.operator("node.select_all", text="Inverse").action = 'INVERT'
layout.operator("node.select_linked_from")
layout.operator("node.select_linked_to")
+
+ layout.separator()
+
layout.operator("node.select_same_type")
layout.operator("node.select_same_type_step").prev = True
layout.operator("node.select_same_type_step").prev = False
+ layout.separator()
+
+ layout.operator("node.find_node")
+
class NODE_MT_node(Menu):
bl_label = "Node"
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 0c988ac45fc..2cb9d42b479 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -247,6 +247,7 @@ struct DerivedMesh {
void *(*getVertDataArray)(DerivedMesh *dm, int type);
void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
void *(*getTessFaceDataArray)(DerivedMesh *dm, int type);
+ void *(*getLoopDataArray)(DerivedMesh *dm, int type);
void *(*getPolyDataArray)(DerivedMesh *dm, int type);
/** Retrieves the base CustomData structures for
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 8c36a73a088..0f36b7a8cfc 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -41,18 +41,17 @@ struct Object;
struct bAction;
struct Scene;
-void BKE_group_free(struct Group *group);
-void BKE_group_unlink(struct Group *group);
-struct Group *add_group(struct Main *bmain, const char *name);
+void BKE_group_free(struct Group *group);
+void BKE_group_unlink(struct Group *group);
+struct Group *BKE_group_add(struct Main *bmain, const char *name);
struct Group *BKE_group_copy(struct Group *group);
-int add_to_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
-int rem_from_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
-struct Group *find_group(struct Object *ob, struct Group *group);
-int object_in_group(struct Object *ob, struct Group *group);
-int group_is_animated(struct Object *parent, struct Group *group);
+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);
+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_is_animated(struct Group *group, struct Object *parent);
-void group_tag_recalc(struct Group *group);
-void group_handle_recalc_and_update(struct Scene *scene, struct Object *parent, struct Group *group);
-
-#endif
+void BKE_group_tag_recalc(struct Group *group);
+void BKE_group_handle_recalc_and_update(struct Scene *scene, struct Object *parent, struct Group *group);
+#endif /* __BKE_GROUP_H__ */
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 944b6e9b8c0..99247414cff 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -107,10 +107,12 @@ __attribute__((nonnull))
;
void clear_id_newpoins(void);
+#if 0
void IDnames_to_pupstring(const char **str, const char *title, const char *extraops,
struct ListBase *lb, struct ID *link, short *nr);
void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops,
struct ListBase *lb, struct ID *link, short *nr);
+#endif
void flag_listbase_ids(ListBase *lb, short flag, short value);
void flag_all_listbases_ids(short flag, short value);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 350eaf23f6f..0bcbbb8576a 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -59,7 +59,8 @@ struct Material *give_node_material(struct Material *ma); /* returns node materi
void BKE_material_make_local(struct Material *ma);
void extern_local_matarar(struct Material **matar, short totcol);
-void automatname(struct Material *);
+/* UNUSED */
+// void automatname(struct Material *);
/* material slots */
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index f97b5b1f3a1..4828df2fbec 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -45,6 +45,7 @@ void BKE_movieclip_unlink(struct Main *bmain, struct MovieClip *clip);
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
void BKE_movieclip_reload(struct MovieClip *clip);
+void BKE_movieclip_clear_cache(struct MovieClip *clip);
struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user);
struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip, struct MovieClipUser *user, int postprocess_flag);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index fc1cd6e45d5..3c4c3fc6f5c 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -444,9 +444,6 @@ const char * nodeStaticSocketInterfaceType(int type, int subtype);
BLI_ghashIterator_free(__node_socket_type_iter__); \
}
-void nodeMakeDynamicType(struct bNode *node);
-int nodeDynamicUnlinkText(struct ID *txtid);
-
struct bNodeSocket *nodeFindSocket(struct bNode *node, int in_out, const char *identifier);
struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
const char *identifier, const char *name);
@@ -575,9 +572,6 @@ void BKE_node_preview_set_pixel(struct bNodePreview *preview, const f
/* ************** NODE TYPE ACCESS *************** */
const char *nodeLabel(struct bNode *node);
-struct bNodeTree *nodeGroupEditGet(struct bNode *node);
-struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit);
-void nodeGroupEditClear(struct bNode *node);
int nodeGroupPoll(struct bNodeTree *nodetree, struct bNodeTree *grouptree);
@@ -752,6 +746,7 @@ struct ShadeResult;
#define SH_NODE_TANGENT 174
#define SH_NODE_NORMAL_MAP 175
#define SH_NODE_HAIR_INFO 176
+#define SH_NODE_SUBSURFACE_SCATTERING 177
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 1009472cf40..2b753cba098 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -255,7 +255,8 @@ struct ParticleSystem *psys_get_current(struct Object *ob);
/* for rna */
short psys_get_current_num(struct Object *ob);
void psys_set_current_num(Object *ob, int index);
-struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);
+/* UNUSED */
+// struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);
struct Object *psys_get_lattice(struct ParticleSimulationData *sim);
diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h
index 3a9d2b86b41..20366f00df6 100644
--- a/source/blender/blenkernel/BKE_smoke.h
+++ b/source/blender/blenkernel/BKE_smoke.h
@@ -45,7 +45,6 @@ void smokeModifier_reset_turbulence(struct SmokeModifierData *smd);
void smokeModifier_createType(struct SmokeModifierData *smd);
void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData *tsmd);
-long long smoke_get_mem_req(int xres, int yres, int zres, int amplify);
float smoke_get_velocity_at(struct Object *ob, float position[3], float velocity[3]);
int smoke_get_data_flags(struct SmokeDomainSettings *sds);
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 621fc13af67..23a6a96c75c 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -78,7 +78,8 @@ struct MTex *add_mtex_id(struct ID *id, int slot);
struct Tex *BKE_texture_copy(struct Tex *tex);
struct Tex *localize_texture(struct Tex *tex);
void BKE_texture_make_local(struct Tex *tex);
-void autotexname(struct Tex *tex);
+/* UNUSED */
+// void autotexname(struct Tex *tex);
struct Tex *give_current_object_texture(struct Object *ob);
struct Tex *give_current_material_texture(struct Material *ma);
diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h
index 14e7d220449..c8ce2bb2a77 100644
--- a/source/blender/blenkernel/depsgraph_private.h
+++ b/source/blender/blenkernel/depsgraph_private.h
@@ -124,7 +124,6 @@ void push_queue(DagNodeQueue *queue, DagNode *node);
void push_stack(DagNodeQueue *queue, DagNode *node);
DagNode *pop_queue(DagNodeQueue *queue);
DagNode *get_top_node_queue(DagNodeQueue *queue);
-int queue_count(DagNodeQueue *queue);
void queue_delete(DagNodeQueue *queue);
// Dag management
@@ -137,9 +136,6 @@ DagNode *dag_get_node(DagForest *forest, void *fob);
DagNode *dag_get_sub_node(DagForest *forest, void *fob);
void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name);
-DagNodeQueue *graph_dfs(void);
-
-void set_node_xy(DagNode *node, float x, float y);
void graph_print_queue(DagNodeQueue *nqueue);
void graph_print_queue_dist(DagNodeQueue *nqueue);
void graph_print_adj_list(DagForest *dag);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index f53743ea06e..bf29fd571c4 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -270,6 +270,7 @@ void DM_init_funcs(DerivedMesh *dm)
dm->getEdgeDataArray = DM_get_edge_data_layer;
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
dm->getPolyDataArray = DM_get_poly_data_layer;
+ dm->getLoopDataArray = DM_get_loop_data_layer;
bvhcache_init(&dm->bvhCache);
}
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index ad791852253..8c49ce22dea 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -766,10 +766,10 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persiste
if (flag & DUPLILIST_DO_UPDATE) {
/* note: update is optional because we don't always need object
* transformations to be correct. Also fixes bug [#29616]. */
- group_handle_recalc_and_update(scene, ob, group);
+ BKE_group_handle_recalc_and_update(scene, ob, group);
}
- if (group_is_animated(ob, group))
+ if (BKE_group_is_animated(group, ob))
flag |= DUPLILIST_ANIMATED;
for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
@@ -953,6 +953,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
float vec[3], no[3], pmat[4][4];
int totvert, a, oblay;
unsigned int lay;
+ CustomDataMask dm_mask;
copy_m4_m4(pmat, par->obmat);
@@ -961,16 +962,18 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
em = BMEdit_FromObject(par);
- if (em) {
- dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
- }
+ /* get derived mesh */
+ dm_mask = CD_MASK_BAREMESH;
+ if (flag & DUPLILIST_FOR_RENDER)
+ dm_mask |= CD_MASK_ORCO;
+
+ if (em)
+ dm = editbmesh_get_derived_cage(scene, par, em, dm_mask);
else
- dm = mesh_get_derived_final(scene, par, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(scene, par, dm_mask);
- if (flag & DUPLILIST_FOR_RENDER) {
- vdd.orco = (float(*)[3])BKE_mesh_orco_verts_get(par);
- BKE_mesh_orco_verts_transform(me, vdd.orco, me->totvert, 0);
- }
+ if (flag & DUPLILIST_FOR_RENDER)
+ vdd.orco = dm->getVertDataArray(dm, CD_ORCO);
else
vdd.orco = NULL;
@@ -1057,8 +1060,6 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
else go = go->next; /* group loop */
}
- if (vdd.orco)
- MEM_freeN(vdd.orco);
dm->release(dm);
}
@@ -1069,7 +1070,6 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
Base *base = NULL;
DupliObject *dob;
DerivedMesh *dm;
- Mesh *me = par->data;
MLoopUV *mloopuv;
MPoly *mpoly, *mp;
MLoop *mloop;
@@ -1081,6 +1081,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
GroupObject *go = NULL;
BMEditMesh *em;
float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
+ CustomDataMask dm_mask;
/* simple preventing of too deep nested groups */
if (level > MAX_DUPLI_RECUR) return;
@@ -1088,11 +1089,16 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
copy_m4_m4(pmat, par->obmat);
em = BMEdit_FromObject(par);
+ /* get derived mesh */
+ dm_mask = CD_MASK_BAREMESH;
+ if (flag & DUPLILIST_FOR_RENDER)
+ dm_mask |= CD_MASK_ORCO | CD_MASK_MLOOPUV;
+
if (em) {
- dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
+ dm = editbmesh_get_derived_cage(scene, par, em, dm_mask);
}
else {
- dm = mesh_get_derived_final(scene, par, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(scene, par, dm_mask);
}
totface = dm->getNumPolys(dm);
@@ -1101,9 +1107,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
mvert = dm->getVertArray(dm);
if (flag & DUPLILIST_FOR_RENDER) {
- orco = (float(*)[3])BKE_mesh_orco_verts_get(par);
- BKE_mesh_orco_verts_transform(me, orco, me->totvert, 0);
- mloopuv = me->mloopuv;
+ orco = dm->getVertDataArray(dm, CD_ORCO);
+ mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
}
else {
orco = NULL;
@@ -1215,7 +1220,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
if (mloopuv) {
int j;
for (j = 0; j < mpoly->totloop; j++) {
- madd_v2_v2fl(dob->orco, mloopuv[loopstart[j].v].uv, w);
+ madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w);
}
}
}
@@ -1238,9 +1243,6 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
else go = go->next; /* group loop */
}
- if (orco)
- MEM_freeN(orco);
-
dm->release(dm);
}
@@ -1331,7 +1333,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
/* gather list of objects or single object */
if (part->ren_as == PART_DRAW_GR) {
if (flag & DUPLILIST_DO_UPDATE) {
- group_handle_recalc_and_update(scene, par, part->dup_group);
+ BKE_group_handle_recalc_and_update(scene, par, part->dup_group);
}
if (part->draw & PART_DRAW_COUNT_GR) {
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 5176f93f4f3..04cc3cc6a09 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -1008,6 +1008,7 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
IMB_colormanagement_processor_free(cm_processor);
}
+/* if view_settings, it also applies this to byte buffers */
void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings)
{
@@ -1021,7 +1022,7 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
float rgba[4], ycc[3], luma;
int ycc_mode = -1;
const short is_float = (ibuf->rect_float != NULL);
-
+ void *cache_handle = NULL;
struct ColormanageProcessor *cm_processor = NULL;
if (ibuf->rect == NULL && ibuf->rect_float == NULL) return;
@@ -1090,9 +1091,10 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
if (is_float)
rf = ibuf->rect_float;
- else
- rc = (unsigned char *)ibuf->rect;
-
+ else {
+ rc = (unsigned char *)IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
+ }
+
if (ibuf->rect_float)
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
@@ -1173,11 +1175,12 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
if (bin_b[x] > nb) nb = bin_b[x];
if (bin_a[x] > na) na = bin_a[x];
}
- divl = 1.0 / (double)nl;
- diva = 1.0 / (double)na;
- divr = 1.0 / (double)nr;
- divg = 1.0 / (double)ng;
- divb = 1.0 / (double)nb;
+ divl = nl ? 1.0 / (double)nl : 1.0;
+ diva = na ? 1.0 / (double)na : 1.0;
+ divr = nr ? 1.0 / (double)nr : 1.0;
+ divg = ng ? 1.0 / (double)ng : 1.0;
+ divb = nb ? 1.0 / (double)nb : 1.0;
+
for (x = 0; x < 256; x++) {
scopes->hist.data_luma[x] = bin_lum[x] * divl;
scopes->hist.data_r[x] = bin_r[x] * divr;
@@ -1193,7 +1196,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
if (cm_processor)
IMB_colormanagement_processor_free(cm_processor);
-
+ if (cache_handle)
+ IMB_display_buffer_release(cache_handle);
+
scopes->ok = 1;
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 4d9f0fc769c..12fa16e3273 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1204,8 +1204,8 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
vec_to_quat(quat, dir, (short)data->trackflag, (short)data->upflag);
normalize_v3(dir);
- q[0] = (float)cos(0.5 * vec[3]);
- x1 = (float)sin(0.5 * vec[3]);
+ q[0] = cosf(0.5 * vec[3]);
+ x1 = sinf(0.5 * vec[3]);
q[1] = -x1 * dir[0];
q[2] = -x1 * dir[1];
q[3] = -x1 * dir[2];
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 98d1d301f65..d0a9a6efe6b 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -95,7 +95,9 @@ void BKE_group_unlink(Group *group)
/* ensure objects are not in this group */
for (; base; base = base->next) {
- if (rem_from_group(group, base->object, sce, base) && find_group(base->object, NULL) == NULL) {
+ if (BKE_group_object_unlink(group, base->object, sce, base) &&
+ BKE_group_object_find(NULL, base->object) == NULL)
+ {
base->object->flag &= ~OB_FROMGROUP;
base->flag &= ~OB_FROMGROUP;
}
@@ -132,7 +134,7 @@ void BKE_group_unlink(Group *group)
group->id.us = 0;
}
-Group *add_group(Main *bmain, const char *name)
+Group *BKE_group_add(Main *bmain, const char *name)
{
Group *group;
@@ -152,7 +154,7 @@ Group *BKE_group_copy(Group *group)
}
/* external */
-static int add_to_group_internal(Group *group, Object *ob)
+static int group_object_add_internal(Group *group, Object *ob)
{
GroupObject *go;
@@ -173,9 +175,9 @@ static int add_to_group_internal(Group *group, Object *ob)
return TRUE;
}
-int add_to_group(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base)
{
- if (add_to_group_internal(group, object)) {
+ if (group_object_add_internal(group, object)) {
if ((object->flag & OB_FROMGROUP) == 0) {
if (scene && base == NULL)
@@ -186,15 +188,15 @@ int add_to_group(Group *group, Object *object, Scene *scene, Base *base)
if (base)
base->flag |= OB_FROMGROUP;
}
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
/* also used for (ob == NULL) */
-static int rem_from_group_internal(Group *group, Object *ob)
+static int group_object_unlink_internal(Group *group, Object *ob)
{
GroupObject *go, *gon;
int removed = 0;
@@ -214,11 +216,11 @@ static int rem_from_group_internal(Group *group, Object *ob)
return removed;
}
-int rem_from_group(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base)
{
- if (rem_from_group_internal(group, object)) {
+ if (group_object_unlink_internal(group, object)) {
/* object can be NULL */
- if (object && find_group(object, NULL) == NULL) {
+ if (object && BKE_group_object_find(NULL, object) == NULL) {
if (scene && base == NULL)
base = BKE_scene_base_find(scene, object);
@@ -227,23 +229,24 @@ int rem_from_group(Group *group, Object *object, Scene *scene, Base *base)
if (base)
base->flag &= ~OB_FROMGROUP;
}
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
-int object_in_group(Object *ob, Group *group)
+bool BKE_group_object_exists(Group *group, Object *ob)
{
if (group == NULL || ob == NULL) {
- return FALSE;
+ return false;
+ }
+ else {
+ return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL);
}
-
- return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL);
}
-Group *find_group(Object *ob, Group *group)
+Group *BKE_group_object_find(Group *group, Object *ob)
{
if (group)
group = group->id.next;
@@ -251,14 +254,14 @@ Group *find_group(Object *ob, Group *group)
group = G.main->group.first;
while (group) {
- if (object_in_group(ob, group))
+ if (BKE_group_object_exists(group, ob))
return group;
group = group->id.next;
}
return NULL;
}
-void group_tag_recalc(Group *group)
+void BKE_group_tag_recalc(Group *group)
{
GroupObject *go;
@@ -270,7 +273,7 @@ void group_tag_recalc(Group *group)
}
}
-int group_is_animated(Object *UNUSED(parent), Group *group)
+bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
{
GroupObject *go;
@@ -281,9 +284,9 @@ int group_is_animated(Object *UNUSED(parent), Group *group)
for (go = group->gobject.first; go; go = go->next)
if (go->ob && go->ob->proxy)
- return 1;
+ return true;
- return 0;
+ return false;
}
#if 0 // add back when timeoffset & animsys work again
@@ -332,7 +335,7 @@ static void group_replaces_nla(Object *parent, Object *target, char mode)
* you can draw everything, leaves tags in objects to signal it needs further updating */
/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
-void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group *group)
+void BKE_group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group *group)
{
GroupObject *go;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 56480434b70..3a59f578446 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1065,6 +1065,7 @@ ID *BKE_libblock_find_name(const short type, const char *name) /* type: "OB
return BLI_findstring(lb, name, offsetof(ID, name) + 2);
}
+#if 0 /* UNUSED */
static void get_flags_for_id(ID *id, char *buf)
{
int isfake = id->flag & LIB_FAKEUSER;
@@ -1145,7 +1146,6 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor
}
}
-
/* used by headerbuttons.c buttons.c editobject.c editseq.c */
/* if (nr == NULL) no MAX_IDPUP, this for non-header browsing */
void IDnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
@@ -1170,7 +1170,6 @@ void IDnames_to_pupstring(const char **str, const char *title, const char *extra
}
/* skips viewer images */
-#if 0 /* unused */
void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
{
DynStr *pupds = BLI_dynstr_new();
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 72284130869..b93d924ddf9 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -1426,7 +1426,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2,
while (1) {
if (i++ == RES) return;
p[0] = 0.5f * (pos[0] + neg[0]);
- if ((function(p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; else neg[0] = p[0];
+ if ((function(p[0], p[1], p[2])) > 0.0f) pos[0] = p[0];
+ else neg[0] = p[0];
}
}
@@ -1436,7 +1437,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2,
while (1) {
if (i++ == RES) return;
p[1] = 0.5f * (pos[1] + neg[1]);
- if ((function(p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; else neg[1] = p[1];
+ if ((function(p[0], p[1], p[2])) > 0.0f) pos[1] = p[1];
+ else neg[1] = p[1];
}
}
@@ -1446,7 +1448,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2,
while (1) {
if (i++ == RES) return;
p[2] = 0.5f * (pos[2] + neg[2]);
- if ((function(p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; else neg[2] = p[2];
+ if ((function(p[0], p[1], p[2])) > 0.0f) pos[2] = p[2];
+ else neg[2] = p[2];
}
}
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index d0eb1494451..c8f3399665c 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -1162,13 +1162,17 @@ static void free_buffers(MovieClip *clip)
BKE_free_animdata((ID *) clip);
}
+void BKE_movieclip_clear_cache(MovieClip *clip)
+{
+ free_buffers(clip);
+}
+
void BKE_movieclip_reload(MovieClip *clip)
{
/* clear cache */
free_buffers(clip);
clip->tracking.stabilization.ok = FALSE;
- clip->prefetch_ok = FALSE;
/* update clip source */
detect_clip_source(clip);
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 5cf8758aa1b..83e2ff6593b 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -190,7 +190,10 @@ static void node_socket_set_typeinfo(bNodeTree *ntree, bNodeSocket *sock, bNodeS
{
if (typeinfo) {
sock->typeinfo = typeinfo;
-
+
+ /* deprecated integer type */
+ sock->type = typeinfo->type;
+
if (sock->default_value == NULL) {
/* initialize the default_value pointer used by standard socket types */
node_socket_init_default_value(sock);
@@ -435,28 +438,6 @@ GHashIterator *nodeSocketTypeGetIterator(void)
return BLI_ghashIterator_new(nodesockettypes_hash);
}
-void nodeMakeDynamicType(bNode *UNUSED(node))
-{
- #if 0 /* XXX deprecated */
- /* find SH_DYNAMIC_NODE ntype */
- bNodeType *ntype = ntreeType_Shader->node_types.first;
- while (ntype) {
- if (ntype->type == NODE_DYNAMIC)
- break;
- ntype = ntype->next;
- }
-
- /* make own type struct to fill */
- if (ntype) {
- /*node->typeinfo= MEM_dupallocN(ntype);*/
- bNodeType *newtype = MEM_callocN(sizeof(bNodeType), "dynamic bNodeType");
- *newtype = *ntype;
- BLI_strncpy(newtype->name, ntype->name, sizeof(newtype->name));
- node->typeinfo = newtype;
- }
- #endif
-}
-
struct bNodeSocket *nodeFindSocket(bNode *node, int in_out, const char *identifier)
{
bNodeSocket *sock = (in_out == SOCK_IN ? node->inputs.first : node->outputs.first);
@@ -3438,6 +3419,7 @@ static void registerShaderNodes(void)
register_node_type_sh_holdout();
//register_node_type_sh_volume_transparent();
//register_node_type_sh_volume_isotropic();
+ register_node_type_sh_subsurface_scattering();
register_node_type_sh_mix_shader();
register_node_type_sh_add_shader();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 6f0f6a357bb..3750eadb6db 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -771,7 +771,7 @@ void BKE_object_unlink(Object *ob)
/* groups */
group = bmain->group.first;
while (group) {
- rem_from_group(group, ob, NULL, NULL);
+ BKE_group_object_unlink(group, ob, NULL, NULL);
group = group->id.next;
}
@@ -1848,8 +1848,8 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
/* the tilt */
normalize_v3(dir);
- q[0] = (float)cos(0.5 * vec[3]);
- si = (float)sin(0.5 * vec[3]);
+ q[0] = cosf(0.5 * vec[3]);
+ si = sinf(0.5 * vec[3]);
q[1] = -si * dir[0];
q[2] = -si * dir[1];
q[3] = -si * dir[2];
@@ -3403,7 +3403,7 @@ struct LinkNode *BKE_object_groups(Object *ob)
{
LinkNode *group_linknode = NULL;
Group *group = NULL;
- while ((group = find_group(ob, group))) {
+ while ((group = BKE_group_object_find(group, ob))) {
BLI_linklist_prepend(&group_linknode, group);
}
@@ -3420,7 +3420,7 @@ void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
base = BKE_scene_base_find(scene, object);
}
- while ((group = find_group(base->object, group))) {
- rem_from_group(group, object, scene, base);
+ while ((group = BKE_group_object_find(group, base->object))) {
+ BKE_group_object_unlink(group, object, scene, base);
}
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index d9dabf24ba0..4e78ab52499 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -314,7 +314,7 @@ void psys_check_group_weights(ParticleSettings *part)
/* first remove all weights that don't have an object in the group */
dw = part->dupliweights.first;
while (dw) {
- if (!object_in_group(dw->ob, part->dup_group)) {
+ if (!BKE_group_object_exists(part->dup_group, dw->ob)) {
tdw = dw->next;
BLI_freelinkN(&part->dupliweights, dw);
dw = tdw;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 83ee6759b4f..c2d25ce54db 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1093,7 +1093,7 @@ static void scene_depsgraph_hack(Scene *scene, Scene *scene_parent)
if (go->ob)
go->ob->recalc |= recalc;
}
- group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
+ BKE_group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
}
}
}
@@ -1136,7 +1136,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen
BKE_object_handle_update_ex(scene_parent, ob, scene->rigidbody_world);
if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP))
- group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
+ BKE_group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
/* always update layer, so that animating layers works (joshua july 2010) */
/* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index a88a9e4954b..3249de49fe6 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -88,10 +88,11 @@ static uint8_t *video_buffer = 0;
static int video_buffersize = 0;
static uint8_t *audio_input_buffer = 0;
+static uint8_t *audio_deinterleave_buffer = 0;
static int audio_input_samples = 0;
-static uint8_t *audio_output_buffer = 0;
-static int audio_outbuf_size = 0;
static double audio_time = 0.0f;
+static bool audio_deinterleave = false;
+static int audio_sample_size = 0;
#ifdef WITH_AUDASPACE
static AUD_Device *audio_mixdown_device = 0;
@@ -122,37 +123,69 @@ static int write_audio_frame(void)
{
AVCodecContext *c = NULL;
AVPacket pkt;
+ AVFrame *frame;
+ int got_output = 0;
c = audio_stream->codec;
av_init_packet(&pkt);
pkt.size = 0;
+ pkt.data = NULL;
+
+ frame = avcodec_alloc_frame();
+ frame->nb_samples = audio_input_samples;
+ frame->format = c->sample_fmt;
+#ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
+ frame->channel_layout = c->channel_layout;
+#endif
AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples);
audio_time += (double) audio_input_samples / (double) c->sample_rate;
- pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer);
+ if (audio_deinterleave) {
+ int channel, i;
+ uint8_t *temp;
+
+ for (channel = 0; channel < c->channels; channel++) {
+ for (i = 0; i < frame->nb_samples; i++) {
+ memcpy(audio_deinterleave_buffer + (i + channel * frame->nb_samples) * audio_sample_size,
+ audio_input_buffer + (c->channels * i + channel) * audio_sample_size, audio_sample_size);
+ }
+ }
+
+ temp = audio_deinterleave_buffer;
+ audio_deinterleave_buffer = audio_input_buffer;
+ audio_input_buffer = temp;
+ }
+
+ avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, audio_input_buffer,
+ audio_input_samples * c->channels * audio_sample_size, 0);
- if (pkt.size < 0) {
+ if (avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) {
// XXX error("Error writing audio packet");
return -1;
}
- pkt.data = audio_output_buffer;
+ if (got_output) {
+ if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) {
+ pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base);
+ PRINT("Audio Frame PTS: %d\n", (int) pkt.pts);
+ }
- if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) {
- pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base);
- PRINT("Audio Frame PTS: %d\n", (int) pkt.pts);
- }
+ pkt.stream_index = audio_stream->index;
- pkt.stream_index = audio_stream->index;
+ pkt.flags |= AV_PKT_FLAG_KEY;
- pkt.flags |= AV_PKT_FLAG_KEY;
+ if (av_interleaved_write_frame(outfile, &pkt) != 0) {
+ fprintf(stderr, "Error writing audio packet!\n");
+ return -1;
+ }
- if (av_interleaved_write_frame(outfile, &pkt) != 0) {
- fprintf(stderr, "Error writing audio packet!\n");
- return -1;
+ av_free_packet(&pkt);
}
+
+ avcodec_free_frame(&frame);
+
return 0;
}
#endif // #ifdef WITH_AUDASPACE
@@ -608,8 +641,6 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
return st;
}
-/* Prepare an audio stream for the output file */
-
static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size)
{
AVStream *st;
@@ -659,11 +690,6 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
}
}
- if (c->sample_fmt == AV_SAMPLE_FMT_FLTP) {
- BLI_strncpy(error, "Requested audio codec requires planar float sample format, which is not supported yet", error_size);
- return NULL;
- }
-
if (codec->supported_samplerates) {
const int *p = codec->supported_samplerates;
int best = 0;
@@ -692,24 +718,23 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
st->codec->time_base.num = 1;
st->codec->time_base.den = st->codec->sample_rate;
- audio_outbuf_size = FF_MIN_BUFFER_SIZE;
-
- if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
- audio_input_samples = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels;
+ if (c->frame_size == 0)
+ // used to be if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
+ // not sure if that is needed anymore, so let's try out if there are any
+ // complaints regarding some ffmpeg versions users might have
+ audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels;
else {
audio_input_samples = c->frame_size;
- if (c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size)
- audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
}
- audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size);
+ audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);
- if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
- audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float));
- }
- else {
- audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t));
- }
+ audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);
+
+ audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size);
+
+ if (audio_deinterleave)
+ audio_deinterleave_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size);
audio_time = 0.0f;
@@ -1010,12 +1035,27 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
AVCodecContext *c = audio_stream->codec;
AUD_DeviceSpecs specs;
specs.channels = c->channels;
- if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
- specs.format = AUD_FORMAT_FLOAT32;
- }
- else {
+
+ switch (av_get_packed_sample_fmt(c->sample_fmt)) {
+ case AV_SAMPLE_FMT_U8:
+ specs.format = AUD_FORMAT_U8;
+ break;
+ case AV_SAMPLE_FMT_S16:
specs.format = AUD_FORMAT_S16;
+ break;
+ case AV_SAMPLE_FMT_S32:
+ specs.format = AUD_FORMAT_S32;
+ break;
+ case AV_SAMPLE_FMT_FLT:
+ specs.format = AUD_FORMAT_FLOAT32;
+ break;
+ case AV_SAMPLE_FMT_DBL:
+ specs.format = AUD_FORMAT_FLOAT64;
+ break;
+ default:
+ return -31415;
}
+
specs.rate = rd->ffcodecdata.audio_mixrate;
audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
#ifdef FFMPEG_CODEC_TIME_BASE
@@ -1138,15 +1178,16 @@ static void end_ffmpeg_impl(int is_autosplit)
MEM_freeN(video_buffer);
video_buffer = 0;
}
- if (audio_output_buffer) {
- av_free(audio_output_buffer);
- audio_output_buffer = 0;
- }
if (audio_input_buffer) {
av_free(audio_input_buffer);
audio_input_buffer = 0;
}
+ if (audio_deinterleave_buffer) {
+ av_free(audio_deinterleave_buffer);
+ audio_deinterleave_buffer = 0;
+ }
+
if (img_convert_ctx) {
sws_freeContext(img_convert_ctx);
img_convert_ctx = 0;
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 9cf571aa98b..d4f16506551 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -244,6 +244,8 @@ void minmax_v2v2_v2(float min[2], float max[2], const float vec[2]);
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist);
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist);
+void axis_sort_v3(const float axis_values[3], int r_axis_order[3]);
+
/***************************** Array Functions *******************************/
/* attempted to follow fixed length vertex functions. names could be improved*/
double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size);
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 26576b2dcb2..cf9280d418f 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -539,9 +539,9 @@ void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t)
if ((1.0f - cosom) > 0.0001f) {
omega = (float)acos(cosom);
- sinom = (float)sin(omega);
- sc1 = (float)sin((1.0 - t) * omega) / sinom;
- sc2 = (float)sin(t * omega) / sinom;
+ sinom = sinf(omega);
+ sc1 = sinf((1.0 - t) * omega) / sinom;
+ sc2 = sinf(t * omega) / sinom;
}
else {
sc1 = 1.0f - t;
@@ -558,8 +558,8 @@ void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t)
result[2] = quat2[1];
result[3] = -quat2[0];
- sc1 = (float)sin((1.0 - t) * M_PI_2);
- sc2 = (float)sin(t * M_PI_2);
+ sc1 = sinf((1.0 - t) * M_PI_2);
+ sc2 = sinf(t * M_PI_2);
result[0] = sc1 * quat1[0] + sc2 * result[0];
result[1] = sc1 * quat1[1] + sc2 * result[1];
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 58d444f5794..572bc4526af 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -527,6 +527,28 @@ void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist)
}
}
+void axis_sort_v3(const float axis_values[3], int r_axis_order[3])
+{
+ float v[3];
+ copy_v3_v3(v, axis_values);
+
+#define SWAP_AXIS(a, b) { \
+ SWAP(float, v[a], v[b]); \
+ SWAP(int, r_axis_order[a], r_axis_order[b]); \
+} (void)0
+
+ if (v[0] < v[1]) {
+ if (v[2] < v[0]) { SWAP_AXIS(0, 2); }
+ }
+ else {
+ if (v[1] < v[2]) { SWAP_AXIS(0, 1); }
+ else { SWAP_AXIS(0, 2); }
+ }
+ if (v[2] < v[1]) { SWAP_AXIS(1, 2); }
+
+#undef SWAP_AXIS
+}
+
/***************************** Array Functions *******************************/
double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index ccbe3b9beaa..c4f56b345a1 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2374,7 +2374,7 @@ static void lib_node_do_versions_group_indices(bNode *gnode)
int old_index = sock->to_index;
for (link = ngroup->links.first; link; link = link->next) {
- if (link->tonode->type == NODE_GROUP_OUTPUT && link->fromsock->own_index == old_index) {
+ if (link->tonode == NULL && link->fromsock->own_index == old_index) {
strcpy(sock->identifier, link->fromsock->identifier);
/* deprecated */
sock->own_index = link->fromsock->own_index;
@@ -2387,7 +2387,7 @@ static void lib_node_do_versions_group_indices(bNode *gnode)
int old_index = sock->to_index;
for (link = ngroup->links.first; link; link = link->next) {
- if (link->fromnode->type == NODE_GROUP_INPUT && link->tosock->own_index == old_index) {
+ if (link->fromnode == NULL && link->tosock->own_index == old_index) {
strcpy(sock->identifier, link->tosock->identifier);
/* deprecated */
sock->own_index = link->tosock->own_index;
@@ -6553,7 +6553,7 @@ static void lib_link_group(FileData *fd, Main *main)
}
}
if (add_us) group->id.us++;
- rem_from_group(group, NULL, NULL, NULL); /* removes NULL entries */
+ BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */
}
}
}
@@ -6606,8 +6606,6 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
clip->tracking.dopesheet.channels.first = clip->tracking.dopesheet.channels.last = NULL;
clip->tracking.dopesheet.coverage_segments.first = clip->tracking.dopesheet.coverage_segments.last = NULL;
- clip->prefetch_ok = FALSE;
-
link_list(fd, &tracking->objects);
for (object = tracking->objects.first; object; object = object->next) {
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 2445775ad44..034857d7c54 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -742,22 +742,6 @@ static void do_versions_socket_default_value_259(bNodeSocket *sock)
}
}
-static void do_versions_nodetree_default_value_259(bNodeTree *ntree)
-{
- bNode *node;
- bNodeSocket *sock;
- for (node=ntree->nodes.first; node; node=node->next) {
- for (sock = node->inputs.first; sock; sock = sock->next)
- do_versions_socket_default_value_259(sock);
- for (sock = node->outputs.first; sock; sock = sock->next)
- do_versions_socket_default_value_259(sock);
- }
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- do_versions_socket_default_value_259(sock);
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- do_versions_socket_default_value_259(sock);
-}
-
void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
@@ -2736,33 +2720,25 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 2)) {
{
/* Convert default socket values from bNodeStack */
- Scene *sce;
- Material *mat;
- Tex *tex;
- bNodeTree *ntree;
-
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- do_versions_nodetree_default_value_259(ntree);
+ FOREACH_NODETREE(main, ntree, id) {
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ do_versions_socket_default_value_259(sock);
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ do_versions_socket_default_value_259(sock);
+ }
+
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ do_versions_socket_default_value_259(sock);
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ do_versions_socket_default_value_259(sock);
+
ntree->update |= NTREE_UPDATE;
}
-
- for (sce = main->scene.first; sce; sce = sce->id.next)
- if (sce->nodetree) {
- do_versions_nodetree_default_value_259(sce->nodetree);
- sce->nodetree->update |= NTREE_UPDATE;
- }
-
- for (mat = main->mat.first; mat; mat = mat->id.next)
- if (mat->nodetree) {
- do_versions_nodetree_default_value_259(mat->nodetree);
- mat->nodetree->update |= NTREE_UPDATE;
- }
-
- for (tex = main->tex.first; tex; tex = tex->id.next)
- if (tex->nodetree) {
- do_versions_nodetree_default_value_259(tex->nodetree);
- tex->nodetree->update |= NTREE_UPDATE;
- }
+ FOREACH_NODETREE_END
}
{
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 4e29756104a..2cc84671e41 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -619,7 +619,7 @@ void BM_editselection_center(BMEditSelection *ese, float r_center[3])
}
else if (ese->htype == BM_FACE) {
BMFace *efa = (BMFace *)ese->ele;
- BM_face_calc_center_bounds(efa, r_center);
+ BM_face_calc_center_mean(efa, r_center);
}
}
@@ -710,8 +710,28 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
cross_v3_v3v3(r_plane, efa->no, vec);
}
else {
- if (efa->len == 4) {
- BMVert *verts[4] = {NULL};
+ if (efa->len == 3) {
+ BMVert *verts[3];
+ float lens[3];
+ float difs[3];
+ int order[3] = {0, 1, 2};
+
+ BM_face_as_array_vert_tri(efa, verts);
+
+ lens[0] = len_v3v3(verts[0]->co, verts[1]->co);
+ lens[1] = len_v3v3(verts[1]->co, verts[2]->co);
+ lens[2] = len_v3v3(verts[2]->co, verts[0]->co);
+
+ /* find the shortest or the longest loop */
+ difs[0] = fabsf(lens[1] - lens[2]);
+ difs[1] = fabsf(lens[2] - lens[0]);
+ difs[2] = fabsf(lens[0] - lens[1]);
+
+ axis_sort_v3(difs, order);
+ sub_v3_v3v3(r_plane, verts[order[0]]->co, verts[(order[0] + 1) % 3]->co);
+ }
+ else if (efa->len == 4) {
+ BMVert *verts[4];
float vecA[3], vecB[3];
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
diff --git a/source/blender/compositor/nodes/COM_BoxMaskNode.cpp b/source/blender/compositor/nodes/COM_BoxMaskNode.cpp
index 0580a32ed8c..e3fb6ecc704 100644
--- a/source/blender/compositor/nodes/COM_BoxMaskNode.cpp
+++ b/source/blender/compositor/nodes/COM_BoxMaskNode.cpp
@@ -24,6 +24,9 @@
#include "COM_BoxMaskOperation.h"
#include "COM_ExecutionSystem.h"
+#include "COM_SetValueOperation.h"
+#include "COM_ScaleOperation.h"
+
BoxMaskNode::BoxMaskNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -34,9 +37,41 @@ void BoxMaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext
BoxMaskOperation *operation;
operation = new BoxMaskOperation();
operation->setData((NodeBoxMask *)this->getbNode()->storage);
- this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
+
+ InputSocket *inputSocket = this->getInputSocket(0);
+ OutputSocket *outputSocket = this->getOutputSocket(0);
+
+ if (inputSocket->isConnected()) {
+ inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
+ outputSocket->relinkConnections(operation->getOutputSocket());
+ }
+ else {
+ /* Value operation to produce original transparent image */
+ SetValueOperation *valueOperation = new SetValueOperation();
+ valueOperation->setValue(0.0f);
+ graph->addOperation(valueOperation);
+
+ /* Scale that image up to render resolution */
+ const RenderData *rd = context->getRenderData();
+ ScaleFixedSizeOperation *scaleOperation = new ScaleFixedSizeOperation();
+
+ scaleOperation->setIsAspect(false);
+ scaleOperation->setIsCrop(false);
+ scaleOperation->setOffset(0.0f, 0.0f);
+
+ scaleOperation->setNewWidth(rd->xsch * rd->size / 100.0f);
+ scaleOperation->setNewHeight(rd->ysch * rd->size / 100.0f);
+
+ addLink(graph, valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0));
+ addLink(graph, scaleOperation->getOutputSocket(0), operation->getInputSocket(0));
+ outputSocket->relinkConnections(operation->getOutputSocket(0));
+
+ scaleOperation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true);
+
+ graph->addOperation(scaleOperation);
+ }
+
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
- this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
operation->setMaskType(this->getbNode()->custom1);
graph->addOperation(operation);
diff --git a/source/blender/compositor/nodes/COM_EllipseMaskNode.cpp b/source/blender/compositor/nodes/COM_EllipseMaskNode.cpp
index dc4421abb25..fe0c85c173a 100644
--- a/source/blender/compositor/nodes/COM_EllipseMaskNode.cpp
+++ b/source/blender/compositor/nodes/COM_EllipseMaskNode.cpp
@@ -24,6 +24,9 @@
#include "COM_EllipseMaskOperation.h"
#include "COM_ExecutionSystem.h"
+#include "COM_SetValueOperation.h"
+#include "COM_ScaleOperation.h"
+
EllipseMaskNode::EllipseMaskNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -32,11 +35,44 @@ EllipseMaskNode::EllipseMaskNode(bNode *editorNode) : Node(editorNode)
void EllipseMaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
EllipseMaskOperation *operation;
+
operation = new EllipseMaskOperation();
operation->setData((NodeEllipseMask *)this->getbNode()->storage);
- this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
+
+ InputSocket *inputSocket = this->getInputSocket(0);
+ OutputSocket *outputSocket = this->getOutputSocket(0);
+
+ if (inputSocket->isConnected()) {
+ inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
+ outputSocket->relinkConnections(operation->getOutputSocket());
+ }
+ else {
+ /* Value operation to produce original transparent image */
+ SetValueOperation *valueOperation = new SetValueOperation();
+ valueOperation->setValue(0.0f);
+ graph->addOperation(valueOperation);
+
+ /* Scale that image up to render resolution */
+ const RenderData *rd = context->getRenderData();
+ ScaleFixedSizeOperation *scaleOperation = new ScaleFixedSizeOperation();
+
+ scaleOperation->setIsAspect(false);
+ scaleOperation->setIsCrop(false);
+ scaleOperation->setOffset(0.0f, 0.0f);
+
+ scaleOperation->setNewWidth(rd->xsch * rd->size / 100.0f);
+ scaleOperation->setNewHeight(rd->ysch * rd->size / 100.0f);
+
+ addLink(graph, valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0));
+ addLink(graph, scaleOperation->getOutputSocket(0), operation->getInputSocket(0));
+ outputSocket->relinkConnections(operation->getOutputSocket(0));
+
+ scaleOperation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true);
+
+ graph->addOperation(scaleOperation);
+ }
+
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
- this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
operation->setMaskType(this->getbNode()->custom1);
graph->addOperation(operation);
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 61e03806391..df840df05e7 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -2326,7 +2326,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
* - used to ease the process of doing multiple-character choreographies
*/
if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (object_in_group(ob, ads->filter_grp) == 0)
+ if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
continue;
}
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index a3515e0983d..7a20f0727c0 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -626,7 +626,7 @@ static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk)
}
}
-static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], int *dist, int *index, int all_pts)
+static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], float *r_dist_px, int *index, int all_pts)
{
ARegion *ar = CTX_wm_region(C);
SK_Point *pt = NULL;
@@ -641,8 +641,8 @@ static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], in
pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
- if (pdist < *dist) {
- *dist = pdist;
+ if (pdist < *r_dist_px) {
+ *r_dist_px = pdist;
pt = stk->points + i;
if (index != NULL) {
@@ -729,13 +729,13 @@ static void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK
if (sketch->over.target == NULL) {
SK_Stroke *target;
int closest_index = -1;
- int dist = SNAP_MIN_DISTANCE * 2;
+ float dist_px = SNAP_MIN_DISTANCE * 2;
for (target = sketch->strokes.first; target; target = target->next) {
if (target != stk) {
int index;
- SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist, &index, 1);
+ SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist_px, &index, 1);
if (spt != NULL) {
sketch->over.target = target;
@@ -764,10 +764,10 @@ static void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK
}
else if (sketch->over.target != NULL) {
SK_Point *closest_pt = NULL;
- int dist = SNAP_MIN_DISTANCE * 2;
+ float dist_px = SNAP_MIN_DISTANCE * 2;
int index;
- closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist, &index, 1);
+ closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist_px, &index, 1);
if (closest_pt != NULL) {
if (sk_lastStrokePoint(stk)->type == PT_EXACT) {
@@ -1064,17 +1064,17 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
float no[3];
float mval[2];
int found = 0;
- int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
+ float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
/* snap to strokes */
// if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next) {
SK_Point *spt = NULL;
if (snap_stk == stk) {
- spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0);
+ spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist_px, NULL, 0);
}
else {
- spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1);
+ spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist_px, NULL, 1);
}
if (spt != NULL) {
@@ -1087,7 +1087,7 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
mval[1] = dd->mval[1];
/* try to snap to closer object */
- found = snapObjectsContext(C, mval, &dist, vec, no, SNAP_NOT_SELECTED);
+ found = snapObjectsContext(C, mval, &dist_px, vec, no, SNAP_NOT_SELECTED);
if (found == 1) {
pt->type = dd->type;
pt->mode = PT_SNAP;
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 5774a057eb5..af2dc884508 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -33,6 +33,9 @@
struct rcti;
struct rctf;
+struct ImBuf;
+struct bContext;
+
void fdrawbezier(float vec[4][3]);
void fdrawline(float x1, float y1, float x2, float y2);
void fdrawbox(float x1, float y1, float x2, float y2);
@@ -141,17 +144,17 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
* 1-to-1 mapping to screen space.
*/
-void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect);
+void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect);
/**
* glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef.
* only RGBA
* needs glaDefine2DArea to be set.
*/
-void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect);
+void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect);
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY);
+void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY);
/* 2D Drawing Assistance */
@@ -170,35 +173,19 @@ void glaDefine2DArea(struct rcti *screen_rect);
typedef struct gla2DDrawInfo gla2DDrawInfo;
-/** Save the current OpenGL state and initialize OpenGL for 2D
- * rendering. glaEnd2DDraw should be called on the returned structure
- * to free it and to return OpenGL to its previous state. The
- * scissor rectangle is set to match the viewport.
- *
- * See glaDefine2DArea for an explanation of why this function uses integers.
- *
- * \param screen_rect The screen rectangle to be used for 2D drawing.
- * \param world_rect The world rectangle that the 2D area represented
- * by \a screen_rect is supposed to represent. If NULL it is assumed the
- * world has a 1 to 1 mapping to the screen.
- */
-gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect);
-
-/** Translate the (\a wo_x, \a wo_y) point from world coordinates into screen space. */
-void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r);
+/* UNUSED */
+#if 0
-/** Translate the \a world point from world coordiantes into screen space. */
+gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect);
+void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r);
void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]);
-/* Restores the previous OpenGL state and free's the auxilary
- * gla data.
- */
-void glaEnd2DDraw(gla2DDrawInfo *di);
+void glaEnd2DDraw(gla2DDrawInfo *di);
/** Adjust the transformation mapping of a 2d area */
void gla2DGetMap(gla2DDrawInfo *di, struct rctf *rect);
void gla2DSetMap(gla2DDrawInfo *di, struct rctf *rect);
-
+#endif
/* use this for platform hacks. glPointSize is solved here */
void bglBegin(int mode);
@@ -223,5 +210,13 @@ typedef struct bglMats {
} bglMats;
void bgl_get_mats(bglMats *mats);
+/* **** Color management helper functions for GLSL display/transform ***** */
+
+/* Draw imbuf on a screen, preferably using GLSL display transform */
+void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter);
+
+/* Transform buffer from role to scene linear space using GLSL OCIO conversion */
+int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role);
+
#endif /* __BIF_GLUTIL_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index ab112fde48d..a39476dad66 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -251,7 +251,6 @@ void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int
void ED_mesh_transform(struct Mesh *me, float *mat);
void ED_mesh_calc_normals(struct Mesh *me);
void ED_mesh_calc_tessface(struct Mesh *mesh);
-void ED_mesh_material_link(struct Mesh *me, struct Material *ma);
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface);
int ED_mesh_uv_texture_add(struct Mesh *me, const char *name, const bool active_set);
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index a40cf90f7ad..4fbe01a5fc7 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -74,6 +74,8 @@ void *ED_region_draw_cb_activate(struct ARegionType *,
void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int);
void ED_region_draw_cb_exit(struct ARegionType *, void *);
void *ED_region_draw_cb_customdata(void *handle);
+/* generic callbacks */
+/* ed_util.c */
+void ED_region_draw_mouse_line_cb(const struct bContext *C, struct ARegion *ar, void *arg_info);
#endif /* __ED_SPACE_API_H__ */
-
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index d43582fa8d1..5fe44aa17f7 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -34,17 +34,18 @@
/* ******************* Registration Function ********************** */
-struct wmWindowManager;
-struct wmOperatorType;
+struct ARegion;
+struct EnumPropertyItem;
struct ListBase;
-struct wmEvent;
-struct bContext;
struct Object;
+struct View3D;
+struct bContext;
struct uiLayout;
-struct EnumPropertyItem;
-struct wmOperatorType;
-struct wmKeyMap;
+struct wmEvent;
struct wmKeyConfig;
+struct wmKeyMap;
+struct wmOperatorType;
+struct wmWindowManager;
void transform_keymap_for_space(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, int spaceid);
void transform_operatortypes(void);
@@ -112,7 +113,8 @@ struct Base;
struct Scene;
struct Object;
-int BIF_snappingSupported(struct Object *obedit);
+/* UNUSED */
+// int BIF_snappingSupported(struct Object *obedit);
struct TransformOrientation;
struct bContext;
@@ -179,10 +181,17 @@ typedef enum SnapMode {
bool peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
bool peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
-bool snapObjectsTransform(struct TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode);
-bool snapObjectsContext(struct bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode);
-bool snapNodesTransform(struct TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode);
-bool snapNodesContext(struct bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode);
+bool snapObjectsTransform(struct TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode);
+bool snapObjectsContext(struct bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode);
+/* taks args for all settings */
+bool snapObjectsEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode,
+ const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode);
+bool snapObjectsRayEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode,
+ const float ray_start[3], const float ray_normal[3],
+ const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode);
+
+bool snapNodesTransform(struct TransInfo *t, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode);
+bool snapNodesContext(struct bContext *C, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode);
#endif
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index d0ca079b8c9..67f790f0b46 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -90,7 +90,6 @@ void ED_clipboard_posebuf_free(void);
/* ************** XXX OLD CRUFT WARNING ************* */
void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert);
-int GetButStringLength(const char *str);
/* where else to go ? */
void unpack_menu(struct bContext *C, const char *opname, const char *id_name, const char *abs_name, const char *folder, struct PackedFile *pf);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 2572d4b4d99..7e1bd2b9eb6 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -280,7 +280,6 @@ typedef enum {
* Functions to draw various shapes, taking theme settings into account.
* Used for code that draws its own UI style elements. */
-void uiEmboss(float x1, float y1, float x2, float y2, int sel);
void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad);
void uiSetRoundBox(int type);
int uiGetRoundBox(void);
@@ -398,7 +397,7 @@ void uiFreeActiveButtons(const struct bContext *C, struct bScreen *screen);
void uiBlockSetRegion(uiBlock *block, struct ARegion *region);
-void uiBlockSetButLock(uiBlock *block, int val, const char *lockstr);
+void uiBlockSetButLock(uiBlock *block, bool val, const char *lockstr);
void uiBlockClearButLock(uiBlock *block);
/* automatic aligning, horiz or verical */
@@ -448,7 +447,7 @@ void uiButSetDrawFlag(uiBut *but, int flag);
void uiButClearDrawFlag(uiBut *but, int flag);
/* special button case, only draw it when used actively, for outliner etc */
-int uiButActiveOnly(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
+bool uiButActiveOnly(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
void uiButExecute(const struct bContext *C, uiBut *but);
@@ -621,7 +620,7 @@ void uiComposeLinks(uiBlock *block);
uiBut *uiFindInlink(uiBlock *block, void *poin);
/* use inside searchfunc to add items */
-int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid);
+bool uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid);
/* bfunc gets search item *poin as arg2, or if NULL the old string */
void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc, void *active);
/* height in pixels, it's using hardcoded values still */
@@ -770,20 +769,20 @@ void uiLayoutOperatorButs(const struct bContext *C, struct uiLayout *layout, str
struct MenuType *uiButGetMenuType(uiBut *but);
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext);
-void uiLayoutSetActive(uiLayout *layout, int active);
-void uiLayoutSetEnabled(uiLayout *layout, int enabled);
-void uiLayoutSetRedAlert(uiLayout *layout, int redalert);
-void uiLayoutSetAlignment(uiLayout *layout, int alignment);
-void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect);
+void uiLayoutSetActive(uiLayout *layout, bool active);
+void uiLayoutSetEnabled(uiLayout *layout, bool enabled);
+void uiLayoutSetRedAlert(uiLayout *layout, bool redalert);
+void uiLayoutSetAlignment(uiLayout *layout, char alignment);
+void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect);
void uiLayoutSetScaleX(uiLayout *layout, float scale);
void uiLayoutSetScaleY(uiLayout *layout, float scale);
int uiLayoutGetOperatorContext(uiLayout *layout);
-int uiLayoutGetActive(uiLayout *layout);
-int uiLayoutGetEnabled(uiLayout *layout);
-int uiLayoutGetRedAlert(uiLayout *layout);
+bool uiLayoutGetActive(uiLayout *layout);
+bool uiLayoutGetEnabled(uiLayout *layout);
+bool uiLayoutGetRedAlert(uiLayout *layout);
int uiLayoutGetAlignment(uiLayout *layout);
-int uiLayoutGetKeepAspect(uiLayout *layout);
+bool uiLayoutGetKeepAspect(uiLayout *layout);
int uiLayoutGetWidth(uiLayout *layout);
float uiLayoutGetScaleX(uiLayout *layout);
float uiLayoutGetScaleY(uiLayout *layout);
@@ -803,7 +802,6 @@ uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout);
/* templates */
void uiTemplateHeader(uiLayout *layout, struct bContext *C, int menus);
-void uiTemplateDopeSheetFilter(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
const char *newop, const char *openop, const char *unlinkop);
void uiTemplateIDBrowse(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
@@ -836,7 +834,6 @@ void uiOperatorSearch_But(uiBut *but);
void uiTemplateOperatorSearch(uiLayout *layout);
void uiTemplateHeader3D(uiLayout *layout, struct bContext *C);
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
-void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
@@ -922,7 +919,7 @@ uiStyle *UI_GetStyleDraw(void); /* DPI scaled settings for drawing */
void UI_template_fix_linking(void);
/* UI_OT_editsource helpers */
-int UI_editsource_enable_check(void);
+bool UI_editsource_enable_check(void);
void UI_editsource_active_but_test(uiBut *but);
#endif /* __UI_INTERFACE_H__ */
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 10026bbd50f..6104505ef58 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -79,6 +79,6 @@ int UI_iconfile_get_index(const char *filename);
struct PreviewImage *UI_icon_to_preview(int icon_id);
-int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big);
+int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
#endif /* __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index be51651dee7..0c484a82778 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -549,22 +549,22 @@ static void ui_draw_links(uiBlock *block)
/* ************** BLOCK ENDING FUNCTION ************* */
/* NOTE: if but->poin is allocated memory for every defbut, things fail... */
-static int ui_but_equals_old(uiBut *but, uiBut *oldbut)
+static bool ui_but_equals_old(uiBut *but, uiBut *oldbut)
{
/* various properties are being compared here, hopefully sufficient
* to catch all cases, but it is simple to add more checks later */
- if (but->retval != oldbut->retval) return 0;
- if (but->rnapoin.data != oldbut->rnapoin.data) return 0;
+ if (but->retval != oldbut->retval) return false;
+ if (but->rnapoin.data != oldbut->rnapoin.data) return false;
if (but->rnaprop != oldbut->rnaprop)
- if (but->rnaindex != oldbut->rnaindex) return 0;
- if (but->func != oldbut->func) return 0;
- if (but->funcN != oldbut->funcN) return 0;
- if (oldbut->func_arg1 != oldbut && but->func_arg1 != oldbut->func_arg1) return 0;
- if (oldbut->func_arg2 != oldbut && but->func_arg2 != oldbut->func_arg2) return 0;
- if (!but->funcN && ((but->poin != oldbut->poin && (uiBut *)oldbut->poin != oldbut) || but->pointype != oldbut->pointype)) return 0;
- if (but->optype != oldbut->optype) return 0;
+ if (but->rnaindex != oldbut->rnaindex) return false;
+ if (but->func != oldbut->func) return false;
+ if (but->funcN != oldbut->funcN) return false;
+ if (oldbut->func_arg1 != oldbut && but->func_arg1 != oldbut->func_arg1) return false;
+ if (oldbut->func_arg2 != oldbut && but->func_arg2 != oldbut->func_arg2) return false;
+ if (!but->funcN && ((but->poin != oldbut->poin && (uiBut *)oldbut->poin != oldbut) || but->pointype != oldbut->pointype)) return false;
+ if (but->optype != oldbut->optype) return false;
- return 1;
+ return true;
}
/* oldbut is being inserted in new block, so we use the lines from new button, and replace button pointers */
@@ -682,37 +682,38 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
/* needed for temporarily rename buttons, such as in outliner or file-select,
* they should keep calling uiDefButs to keep them alive */
/* returns 0 when button removed */
-int uiButActiveOnly(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
+bool uiButActiveOnly(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
{
uiBlock *oldblock;
uiBut *oldbut;
- int activate = FALSE, found = FALSE, isactive = FALSE;
+ bool activate = false, found = false, isactive = false;
oldblock = block->oldblock;
- if (!oldblock)
- activate = TRUE;
+ if (!oldblock) {
+ activate = true;
+ }
else {
for (oldbut = oldblock->buttons.first; oldbut; oldbut = oldbut->next) {
if (ui_but_equals_old(oldbut, but)) {
- found = TRUE;
+ found = true;
if (oldbut->active)
- isactive = TRUE;
+ isactive = true;
break;
}
}
}
- if ((activate == TRUE) || (found == FALSE)) {
+ if ((activate == true) || (found == false)) {
ui_button_activate_do((bContext *)C, ar, but);
}
- else if ((found == TRUE) && (isactive == FALSE)) {
+ else if ((found == true) && (isactive == false)) {
BLI_remlink(&block->buttons, but);
ui_free_but(C, but);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* simulate button click */
@@ -1243,17 +1244,17 @@ void uiComposeLinks(uiBlock *block)
/* ************************************************ */
-void uiBlockSetButLock(uiBlock *block, int val, const char *lockstr)
+void uiBlockSetButLock(uiBlock *block, bool val, const char *lockstr)
{
if (val) {
- block->lock = val ? TRUE : FALSE;
+ block->lock = val;
block->lockstr = lockstr;
}
}
void uiBlockClearButLock(uiBlock *block)
{
- block->lock = FALSE;
+ block->lock = false;
block->lockstr = NULL;
}
@@ -1392,63 +1393,63 @@ void ui_set_but_vectorf(uiBut *but, const float vec[3])
}
}
-int ui_is_but_float(uiBut *but)
+bool ui_is_but_float(uiBut *but)
{
if (but->pointype == UI_BUT_POIN_FLOAT && but->poin)
- return 1;
+ return true;
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_FLOAT)
- return 1;
+ return true;
- return 0;
+ return false;
}
-int ui_is_but_bool(uiBut *but)
+bool ui_is_but_bool(uiBut *but)
{
if (ELEM5(but->type, TOG, TOGN, TOGR, ICONTOG, ICONTOGN))
- return 1;
+ return true;
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN)
- return 1;
+ return true;
- return 0;
+ return false;
}
-int ui_is_but_unit(uiBut *but)
+bool ui_is_but_unit(uiBut *but)
{
UnitSettings *unit = but->block->unit;
const int unit_type = uiButGetUnitType(but);
if (unit_type == PROP_UNIT_NONE)
- return 0;
+ return false;
#if 1 /* removed so angle buttons get correct snapping */
if (unit->system_rotation == USER_UNIT_ROT_RADIANS && unit_type == PROP_UNIT_ROTATION)
- return 0;
+ return false;
#endif
/* for now disable time unit conversion */
if (unit_type == PROP_UNIT_TIME)
- return 0;
+ return false;
if (unit->system == USER_UNIT_NONE) {
if (unit_type != PROP_UNIT_ROTATION) {
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
-int ui_is_but_rna_valid(uiBut *but)
+bool ui_is_but_rna_valid(uiBut *but)
{
if (but->rnaprop == NULL || RNA_struct_contains_property(&but->rnapoin, but->rnaprop)) {
- return TRUE;
+ return true;
}
else {
printf("property removed %s: %p\n", but->drawstr, but->rnaprop);
- return FALSE;
+ return false;
}
}
@@ -1789,7 +1790,7 @@ void ui_get_but_string(uiBut *but, char *str, const size_t maxlen)
#ifdef WITH_PYTHON
-static int ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value)
+static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value)
{
char str_unit_convert[256];
const int unit_type = uiButGetUnitType(but);
@@ -1807,9 +1808,9 @@ static int ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *
#endif /* WITH_PYTHON */
-int ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double *value)
+bool ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double *value)
{
- int ok = FALSE;
+ bool ok = false;
#ifdef WITH_PYTHON
@@ -1825,7 +1826,7 @@ int ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double
ok = ui_set_but_string_eval_num_unit(C, but, str_new, value);
}
else {
- ok = TRUE; /* parse normal string via py (no unit conversion needed) */
+ ok = true; /* parse normal string via py (no unit conversion needed) */
}
}
else if (is_unit_but) {
@@ -1848,7 +1849,7 @@ int ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double
}
-int ui_set_but_string(bContext *C, uiBut *but, const char *str)
+bool ui_set_but_string(bContext *C, uiBut *but, const char *str)
{
if (but->rnaprop && ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
@@ -1859,7 +1860,7 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
if (type == PROP_STRING) {
/* RNA string */
RNA_property_string_set(&but->rnapoin, but->rnaprop, str);
- return 1;
+ return true;
}
else if (type == PROP_POINTER) {
/* RNA pointer */
@@ -1868,7 +1869,7 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
if (str == NULL || str[0] == '\0') {
RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL);
- return 1;
+ return true;
}
else {
ptr = but->rnasearchpoin;
@@ -1877,18 +1878,18 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr))
RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
else if (type == PROP_ENUM) {
int value;
if (RNA_property_enum_value(but->block->evil_C, &but->rnapoin, but->rnaprop, str, &value)) {
RNA_property_enum_set(&but->rnapoin, but->rnaprop, value);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
else {
BLI_assert(0);
@@ -1898,23 +1899,23 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
else if (but->type == IDPOIN) {
/* ID pointer */
but->idpoin_func(C, str, but->idpoin_idpp);
- return 1;
+ return true;
}
else if (but->type == TEX) {
/* string */
if (ui_is_but_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax);
else BLI_strncpy(but->poin, str, but->hardmax);
- return 1;
+ return true;
}
else if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* string */
BLI_strncpy(but->poin, str, but->hardmax);
- return 1;
+ return true;
}
else if (ui_but_anim_expression_set(but, str)) {
/* driver expression */
- return 1;
+ return true;
}
else if (str[0] == '#') {
/* shortcut to create new driver expression (versus immediate Py-execution) */
@@ -1924,8 +1925,8 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
/* number editing */
double value;
- if (ui_set_but_string_eval_num(C, but, str, &value) == FALSE) {
- return 0;
+ if (ui_set_but_string_eval_num(C, but, str, &value) == false) {
+ return false;
}
if (!ui_is_but_float(but)) value = (int)floor(value + 0.5);
@@ -1936,10 +1937,10 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
if (value > (double)but->hardmax) value = but->hardmax;
ui_set_but_val(but, value);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
void ui_set_but_default(bContext *C, short all)
@@ -2464,15 +2465,14 @@ void uiBlockBeginAlign(uiBlock *block)
/* buttons declared after this call will get this align nr */ // XXX flag?
}
-static int buts_are_horiz(uiBut *but1, uiBut *but2)
+static bool buts_are_horiz(uiBut *but1, uiBut *but2)
{
float dx, dy;
dx = fabs(but1->rect.xmax - but2->rect.xmin);
dy = fabs(but1->rect.ymin - but2->rect.ymax);
- if (dx > dy) return 0;
- return 1;
+ return (dx <= dy);
}
void uiBlockEndAlign(uiBlock *block)
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index b9b877c1fb6..cd2a2161315 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -61,15 +61,6 @@
/* own include */
#include "interface_intern.h"
-/* only for bug workaround [#34346] */
-#if !defined(WIN32) && !defined(__APPLE__)
-# define GPU_OSS_BUG_WOKAROUND
-#endif
-
-#ifdef GPU_OSS_BUG_WOKAROUND
-# include "GPU_extensions.h"
-#endif
-
static int roundboxtype = UI_CNR_ALL;
void uiSetRoundBox(int type)
@@ -402,32 +393,6 @@ void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA);
}
-
-/* ************** generic embossed rect, for window sliders etc ************* */
-
-
-/* text_draw.c uses this */
-void uiEmboss(float x1, float y1, float x2, float y2, int sel)
-{
-
- /* below */
- if (sel) glColor3ub(200, 200, 200);
- else glColor3ub(50, 50, 50);
- fdrawline(x1, y1, x2, y1);
-
- /* right */
- fdrawline(x2, y1, x2, y2);
-
- /* top */
- if (sel) glColor3ub(50, 50, 50);
- else glColor3ub(200, 200, 200);
- fdrawline(x1, y2, x2, y2);
-
- /* left */
- fdrawline(x1, y1, x1, y2);
-
-}
-
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
@@ -463,7 +428,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
float facy = (float)h / (float)ibuf->y;
glPixelZoom(facx, facy);
}
- glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect);
+ glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect);
glPixelZoom(1.0f, 1.0f);
@@ -1245,7 +1210,6 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
{
- static int use_displist = -1;
static GLuint displist = 0;
int a, old[8];
GLfloat diff[4], diffn[4] = {1.0f, 1.0f, 1.0f, 1.0f};
@@ -1294,20 +1258,12 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
size = BLI_rcti_size_y(rect) / 200.f;
glScalef(size, size, size);
-
-#ifdef GPU_OSS_BUG_WOKAROUND
- if (use_displist == -1) {
- use_displist = !GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE);
- }
-#endif
- if (displist == 0 || use_displist == 0) {
+ if (displist == 0) {
GLUquadricObj *qobj;
- if (use_displist) {
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE_AND_EXECUTE);
- }
+ displist = glGenLists(1);
+ glNewList(displist, GL_COMPILE);
qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_FILL);
@@ -1316,14 +1272,11 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
glShadeModel(GL_FLAT);
gluDeleteQuadric(qobj);
- if (use_displist) {
- glEndList();
- }
- }
- else {
- glCallList(displist);
+ glEndList();
}
+ glCallList(displist);
+
/* restore */
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 6d30db9c4d6..a644feca080 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -215,8 +215,8 @@ typedef struct uiAfterFunc {
int autokey;
} uiAfterFunc;
-static int ui_but_contains_pt(uiBut *but, int mx, int my);
-static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y);
+static bool ui_but_contains_pt(uiBut *but, int mx, int my);
+static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y);
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata);
static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
@@ -333,7 +333,7 @@ static void ui_mouse_scale_warp(uiHandleButtonData *data,
}
/* file selectors are exempt from utf-8 checks */
-int ui_is_but_utf8(uiBut *but)
+bool ui_is_but_utf8(uiBut *but)
{
if (but->rnaprop) {
const int subtype = RNA_property_subtype(but->rnaprop);
@@ -5507,7 +5507,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* ************************ button utilities *********************** */
-static int ui_but_contains_pt(uiBut *but, int mx, int my)
+static bool ui_but_contains_pt(uiBut *but, int mx, int my)
{
return BLI_rctf_isect_pt(&but->rect, mx, my);
}
@@ -5525,7 +5525,7 @@ static uiBut *ui_but_find_activated(ARegion *ar)
return NULL;
}
-int ui_button_is_active(ARegion *ar)
+bool ui_button_is_active(ARegion *ar)
{
return (ui_but_find_activated(ar) != NULL);
}
@@ -5580,7 +5580,7 @@ static void ui_blocks_set_tooltips(ARegion *ar, int enable)
block->tooltipdisabled = !enable;
}
-static int ui_mouse_inside_region(ARegion *ar, int x, int y)
+static bool ui_mouse_inside_region(ARegion *ar, int x, int y)
{
uiBlock *block;
@@ -5589,7 +5589,7 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
for (block = ar->uiblocks.first; block; block = block->next)
block->auto_open = FALSE;
- return 0;
+ return false;
}
/* also, check that with view2d, that the mouse is not over the scrollbars
@@ -5608,23 +5608,23 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
/* check if in the rect */
if (!BLI_rcti_isect_pt(&v2d->mask, mx, my))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
+static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
{
if (!ui_mouse_inside_region(ar, x, y))
- return 0;
+ return false;
ui_window_to_block(ar, but->block, &x, &y);
if (!ui_but_contains_pt(but, x, y))
- return 0;
+ return false;
- return 1;
+ return true;
}
/**
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 09686d7b416..52710a62855 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1164,7 +1164,7 @@ static void ui_id_preview_image_render_size(bContext *C, ID *id, PreviewImage *p
}
}
-static void ui_id_icon_render(bContext *C, ID *id, int big)
+static void ui_id_icon_render(bContext *C, ID *id, const bool big)
{
PreviewImage *pi = BKE_previewimg_get(id);
@@ -1248,7 +1248,7 @@ static int ui_id_brush_get_icon(bContext *C, ID *id)
return id->icon_id;
}
-int ui_id_icon_get(bContext *C, ID *id, int big)
+int ui_id_icon_get(bContext *C, ID *id, const bool big)
{
int iconid = 0;
@@ -1273,7 +1273,7 @@ int ui_id_icon_get(bContext *C, ID *id, int big)
return iconid;
}
-int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, int big)
+int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big)
{
ID *id = NULL;
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index e7b659f99fc..41ceeb141c9 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -391,18 +391,18 @@ extern void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rc
extern void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision);
extern void ui_get_but_string(uiBut *but, char *str, const size_t maxlen);
extern void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen);
-extern int ui_set_but_string(struct bContext *C, uiBut *but, const char *str);
-extern int ui_get_but_string_max_length(uiBut *but);
-extern int ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value);
+extern bool ui_set_but_string(struct bContext *C, uiBut *but, const char *str);
+extern bool ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value);
+extern int ui_get_but_string_max_length(uiBut *but);
extern void ui_set_but_default(struct bContext *C, short all);
extern void ui_check_but(uiBut *but);
-extern int ui_is_but_float(uiBut *but);
-extern int ui_is_but_bool(uiBut *but);
-extern int ui_is_but_unit(uiBut *but);
-extern int ui_is_but_rna_valid(uiBut *but);
-extern int ui_is_but_utf8(uiBut *but);
+extern bool ui_is_but_float(uiBut *but);
+extern bool ui_is_but_bool(uiBut *but);
+extern bool ui_is_but_unit(uiBut *but);
+extern bool ui_is_but_rna_valid(uiBut *but);
+extern bool ui_is_but_utf8(uiBut *but);
extern bool ui_is_but_interactive(uiBut *but);
extern int ui_is_but_push_ex(uiBut *but, double *value);
@@ -464,7 +464,7 @@ void ui_popup_block_scrolltest(struct uiBlock *block);
/* searchbox for string button */
ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
-int ui_searchbox_inside(struct ARegion *ar, int x, int y);
+bool ui_searchbox_inside(struct ARegion *ar, int x, int y);
void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, int reset);
void ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str);
void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, const struct wmEvent *event);
@@ -511,7 +511,7 @@ extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_execute_do(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_active_free(const struct bContext *C, uiBut *but);
-extern int ui_button_is_active(struct ARegion *ar);
+extern bool ui_button_is_active(struct ARegion *ar);
extern int ui_button_open_menu_direction(uiBut *but);
extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, int restore);
@@ -544,7 +544,7 @@ extern unsigned char checker_stipple_sml[32 * 32 / 8];
void uiStyleInit(void);
/* interface_icons.c */
-int ui_id_icon_get(struct bContext *C, struct ID *id, int preview);
+int ui_id_icon_get(struct bContext *C, struct ID *id, const bool big);
/* resources.c */
void init_userdef_do_versions(void);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 53887163778..4b1b96f7975 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -140,11 +140,11 @@ struct uiLayout {
int x, y, w, h;
float scale[2];
short space;
- char align;
- char active;
- char enabled;
- char redalert;
- char keepaspect;
+ bool align;
+ bool active;
+ bool enabled;
+ bool redalert;
+ bool keepaspect;
char alignment;
};
@@ -1333,7 +1333,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s
BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui));
#endif
name = BLI_strdup(name_ui);
- iconid = ui_id_icon_get((bContext *)C, id, 0);
+ iconid = ui_id_icon_get((bContext *)C, id, false);
}
else {
name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
@@ -1359,7 +1359,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s
/* add search items from temporary list */
for (cis = items_list->first; cis; cis = cis->next) {
- if (!uiSearchItemAdd(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) {
+ if (false == uiSearchItemAdd(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) {
break;
}
}
@@ -2267,8 +2267,8 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align)
litem->item.type = ITEM_LAYOUT_ROW;
litem->root = layout->root;
litem->align = align;
- litem->active = 1;
- litem->enabled = 1;
+ litem->active = true;
+ litem->enabled = true;
litem->context = layout->context;
litem->space = (align) ? 0 : layout->root->style->buttonspacex;
litem->redalert = layout->redalert;
@@ -2288,8 +2288,8 @@ uiLayout *uiLayoutColumn(uiLayout *layout, int align)
litem->item.type = ITEM_LAYOUT_COLUMN;
litem->root = layout->root;
litem->align = align;
- litem->active = 1;
- litem->enabled = 1;
+ litem->active = true;
+ litem->enabled = true;
litem->context = layout->context;
litem->space = (litem->align) ? 0 : layout->root->style->buttonspacey;
litem->redalert = layout->redalert;
@@ -2309,8 +2309,8 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
flow->litem.item.type = ITEM_LAYOUT_COLUMN_FLOW;
flow->litem.root = layout->root;
flow->litem.align = align;
- flow->litem.active = 1;
- flow->litem.enabled = 1;
+ flow->litem.active = true;
+ flow->litem.enabled = true;
flow->litem.context = layout->context;
flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
flow->litem.redalert = layout->redalert;
@@ -2402,8 +2402,8 @@ uiLayout *uiLayoutOverlap(uiLayout *layout)
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
litem->item.type = ITEM_LAYOUT_OVERLAP;
litem->root = layout->root;
- litem->active = 1;
- litem->enabled = 1;
+ litem->active = true;
+ litem->enabled = true;
litem->context = layout->context;
litem->redalert = layout->redalert;
BLI_addtail(&layout->items, litem);
@@ -2421,8 +2421,8 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align)
split->litem.item.type = ITEM_LAYOUT_SPLIT;
split->litem.root = layout->root;
split->litem.align = align;
- split->litem.active = 1;
- split->litem.enabled = 1;
+ split->litem.active = true;
+ split->litem.enabled = true;
split->litem.context = layout->context;
split->litem.space = layout->root->style->columnspace;
split->litem.redalert = layout->redalert;
@@ -2435,27 +2435,27 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align)
return &split->litem;
}
-void uiLayoutSetActive(uiLayout *layout, int active)
+void uiLayoutSetActive(uiLayout *layout, bool active)
{
layout->active = active;
}
-void uiLayoutSetEnabled(uiLayout *layout, int enabled)
+void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
{
layout->enabled = enabled;
}
-void uiLayoutSetRedAlert(uiLayout *layout, int redalert)
+void uiLayoutSetRedAlert(uiLayout *layout, bool redalert)
{
layout->redalert = redalert;
}
-void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect)
+void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect)
{
layout->keepaspect = keepaspect;
}
-void uiLayoutSetAlignment(uiLayout *layout, int alignment)
+void uiLayoutSetAlignment(uiLayout *layout, char alignment)
{
layout->alignment = alignment;
}
@@ -2470,22 +2470,22 @@ void uiLayoutSetScaleY(uiLayout *layout, float scale)
layout->scale[1] = scale;
}
-int uiLayoutGetActive(uiLayout *layout)
+bool uiLayoutGetActive(uiLayout *layout)
{
return layout->active;
}
-int uiLayoutGetEnabled(uiLayout *layout)
+bool uiLayoutGetEnabled(uiLayout *layout)
{
return layout->enabled;
}
-int uiLayoutGetRedAlert(uiLayout *layout)
+bool uiLayoutGetRedAlert(uiLayout *layout)
{
return layout->redalert;
}
-int uiLayoutGetKeepAspect(uiLayout *layout)
+bool uiLayoutGetKeepAspect(uiLayout *layout)
{
return layout->keepaspect;
}
@@ -2937,7 +2937,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
/* poll() on this operator may still fail, at the moment there is no nice feedback when this happens
* just fails silently */
if (!WM_operator_repeat_check(C, op)) {
- uiBlockSetButLock(uiLayoutGetBlock(layout), TRUE, "Operator can't' redo");
+ uiBlockSetButLock(uiLayoutGetBlock(layout), true, "Operator can't' redo");
/* XXX, could give some nicer feedback or not show redo panel at all? */
uiItemL(layout, IFACE_("* Redo Unsupported *"), ICON_NONE);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 145deb35667..52a26f4f528 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -716,7 +716,7 @@ struct uiEditSourceButStore {
/* should only ever be set while the edit source operator is running */
static struct uiEditSourceStore *ui_editsource_info = NULL;
-int UI_editsource_enable_check(void)
+bool UI_editsource_enable_check(void)
{
return (ui_editsource_info != NULL);
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index febd1820e5c..2ccba2e35f0 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -514,7 +514,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
opptr = uiButGetOperatorPtrRNA(but); /* allocated when needed, the button owns it */
/* so the context is passed to itemf functions (some py itemf functions use it) */
- WM_operator_properties_sanitize(opptr, FALSE);
+ WM_operator_properties_sanitize(opptr, false);
str = WM_operator_pystring(C, but->optype, opptr, 0);
@@ -742,8 +742,8 @@ typedef struct uiSearchboxData {
uiFontStyle fstyle;
uiSearchItems items;
int active; /* index in items array */
- int noback; /* when menu opened with enough space for this */
- int preview; /* draw thumbnail previews, rather than list */
+ bool noback; /* when menu opened with enough space for this */
+ bool preview; /* draw thumbnail previews, rather than list */
int prv_rows, prv_cols;
} uiSearchboxData;
@@ -751,12 +751,12 @@ typedef struct uiSearchboxData {
/* exported for use by search callbacks */
/* returns zero if nothing to add */
-int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid)
+bool uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid)
{
/* hijack for autocomplete */
if (items->autocpl) {
autocomplete_do_name(items->autocpl, name);
- return 1;
+ return true;
}
/* hijack for finding active item */
@@ -764,18 +764,18 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon
if (poin == items->active)
items->offset_i = items->totitem;
items->totitem++;
- return 1;
+ return true;
}
if (items->totitem >= items->maxitem) {
items->more = 1;
- return 0;
+ return false;
}
/* skip first items in list */
if (items->offset_i > 0) {
items->offset_i--;
- return 1;
+ return true;
}
if (items->names)
@@ -787,7 +787,7 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon
items->totitem++;
- return 1;
+ return true;
}
int uiSearchBoxHeight(void)
@@ -867,11 +867,11 @@ static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr)
}
/* x and y in screencoords */
-int ui_searchbox_inside(ARegion *ar, int x, int y)
+bool ui_searchbox_inside(ARegion *ar, int x, int y)
{
uiSearchboxData *data = ar->regiondata;
- return(BLI_rcti_isect_pt(&data->bbox, x - ar->winrct.xmin, y - ar->winrct.ymin));
+ return BLI_rcti_isect_pt(&data->bbox, x - ar->winrct.xmin, y - ar->winrct.ymin);
}
/* string validated to be of correct length (but->hardmax) */
@@ -1023,7 +1023,7 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
/* pixel space */
wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
- if (!data->noback)
+ if (data->noback == false)
ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
/* draw text */
@@ -1136,10 +1136,10 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
/* special case, hardcoded feature, not draw backdrop when called from menus,
* assume for design that popup already added it */
if (but->block->flag & UI_BLOCK_SEARCH_MENU)
- data->noback = 1;
+ data->noback = true;
if (but->a1 > 0 && but->a2 > 0) {
- data->preview = 1;
+ data->preview = true;
data->prv_rows = but->a1;
data->prv_cols = but->a2;
}
@@ -2236,7 +2236,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_
{
uiBut *but = arg_but;
uiBlock *block;
- int show_picker = TRUE;
+ bool show_picker = true;
block = uiBeginBlock(C, handle->region, __func__, UI_EMBOSS);
@@ -2703,7 +2703,7 @@ void uiPupMenuInvoke(bContext *C, const char *idname)
uiPopupMenu *pup;
uiLayout *layout;
Menu menu;
- MenuType *mt = WM_menutype_find(idname, TRUE);
+ MenuType *mt = WM_menutype_find(idname, true);
if (mt == NULL) {
printf("%s: named menu \"%s\" not found\n", __func__, idname);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 4b70b6bd63b..dd575dbf522 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -106,7 +106,7 @@ typedef struct TemplateID {
ListBase *idlb;
int prv_rows, prv_cols;
- int preview;
+ bool preview;
} TemplateID;
/* Search browse menu, assign */
@@ -156,7 +156,7 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str,
iconid = ui_id_icon_get((bContext *)C, id, template->preview);
- if (!uiSearchItemAdd(items, name_ui, id, iconid))
+ if (false == uiSearchItemAdd(items, name_ui, id, iconid))
break;
}
}
@@ -413,13 +413,13 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
type = idptr.type;
if (flag & UI_ID_PREVIEWS) {
- template->preview = TRUE;
+ template->preview = true;
but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6,
TIP_(template_id_browse_tip(type)));
if (type) {
but->icon = RNA_struct_ui_icon(type);
- if (id) but->icon = ui_id_icon_get(C, id, 1);
+ if (id) but->icon = ui_id_icon_get(C, id, true);
uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW);
}
if ((idfrom && idfrom->lib) || !editable)
@@ -1217,7 +1217,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
/* Set but-locks for protected settings (magic numbers are used here!) */
if (proxy_protected)
- uiBlockSetButLock(block, 1, IFACE_("Cannot edit Proxy-Protected Constraint"));
+ uiBlockSetButLock(block, true, IFACE_("Cannot edit Proxy-Protected Constraint"));
/* Draw constraint data */
if ((con->flag & CONSTRAINT_EXPAND) == 0) {
@@ -2631,7 +2631,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
sub = uiLayoutRow(overlap, FALSE);
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
if (icon == ICON_DOT)
icon = ICON_NONE;
draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
@@ -2665,7 +2665,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
found = (activei == i);
if (found) {
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
if (icon == ICON_DOT)
icon = ICON_NONE;
draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
@@ -2712,7 +2712,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
sub = uiLayoutRow(overlap, FALSE);
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
i++;
@@ -2760,7 +2760,7 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char
}
}
- if (0 == uiSearchItemAdd(items, name, ot, 0))
+ if (false == uiSearchItemAdd(items, name, ot, 0))
break;
}
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index b5b10b623d2..e5f9e48c3b0 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1349,8 +1349,8 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* unlink icon for this button type */
if (but->type == SEARCH_MENU_UNLINK && but->drawstr[0]) {
rcti temp = *rect;
-
- temp.xmin = temp.xmax - BLI_rcti_size_y(rect);
+
+ temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
widget_draw_icon(but, ICON_X, alpha, &temp);
}
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index d79f12551dd..a34ca4dcb9e 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -34,6 +34,7 @@
#include "BLF_translation.h"
#include "BKE_context.h"
+#include "BKE_global.h"
#include "BKE_tessmesh.h"
#include "RNA_define.h"
@@ -45,6 +46,7 @@
#include "ED_mesh.h"
#include "ED_numinput.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_transform.h"
#include "ED_view3d.h"
@@ -55,13 +57,17 @@
typedef struct {
BMEditMesh *em;
- BMBackup mesh_backup;
- int mcenter[2];
float initial_length;
float pixel_size; /* use when mouse input is interpreted as spatial distance */
- int is_modal;
+ bool is_modal;
NumInput num_input;
float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */
+
+ /* modal only */
+ int mcenter[2];
+ BMBackup mesh_backup;
+ void *draw_handle_pixel;
+ short twtype;
} BevelData;
#define HEADER_LENGTH 180
@@ -85,7 +91,7 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C)
}
}
-static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
+static int edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
@@ -105,8 +111,16 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
opdata->num_input.flag = NUM_NO_NEGATIVE;
/* avoid the cost of allocating a bm copy */
- if (is_modal)
+ if (is_modal) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+
opdata->mesh_backup = EDBM_redo_state_store(em);
+ opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
+ G.moving = true;
+ opdata->twtype = v3d->twtype;
+ v3d->twtype = 0;
+ }
return 1;
}
@@ -163,7 +177,12 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
}
if (opdata->is_modal) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
+ ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
+ v3d->twtype = opdata->twtype;
+ G.moving = false;
}
MEM_freeN(opdata);
op->customdata = NULL;
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 10f384f5b7c..f7cf32a074f 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -34,6 +34,7 @@
#include "BLF_translation.h"
#include "BKE_context.h"
+#include "BKE_global.h"
#include "BKE_tessmesh.h"
#include "RNA_define.h"
@@ -45,6 +46,7 @@
#include "ED_mesh.h"
#include "ED_numinput.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_transform.h"
#include "ED_view3d.h"
@@ -56,16 +58,20 @@
typedef struct {
float old_thickness;
float old_depth;
- int mcenter[2];
- int modify_depth;
+ bool modify_depth;
float initial_length;
float pixel_size; /* use when mouse input is interpreted as spatial distance */
- int is_modal;
- int shift;
+ bool is_modal;
+ bool shift;
float shift_amount;
- BMBackup backup;
BMEditMesh *em;
NumInput num_input;
+
+ /* modal only */
+ int mcenter[2];
+ BMBackup mesh_backup;
+ void *draw_handle_pixel;
+ short twtype;
} InsetData;
@@ -100,7 +106,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
}
-static int edbm_inset_init(bContext *C, wmOperator *op, int is_modal)
+static int edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
{
InsetData *opdata;
Object *obedit = CTX_data_edit_object(C);
@@ -119,8 +125,16 @@ static int edbm_inset_init(bContext *C, wmOperator *op, int is_modal)
initNumInput(&opdata->num_input);
opdata->num_input.idx_max = 1; /* Two elements. */
- if (is_modal)
- opdata->backup = EDBM_redo_state_store(em);
+ if (is_modal) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ opdata->mesh_backup = EDBM_redo_state_store(em);
+ opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
+ G.moving = true;
+ opdata->twtype = v3d->twtype;
+ v3d->twtype = 0;
+ }
return 1;
}
@@ -132,8 +146,14 @@ static void edbm_inset_exit(bContext *C, wmOperator *op)
opdata = op->customdata;
- if (opdata->is_modal)
- EDBM_redo_state_free(&opdata->backup, NULL, false);
+ if (opdata->is_modal) {
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
+ ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
+ v3d->twtype = opdata->twtype;
+ G.moving = false;
+ }
if (sa) {
ED_area_headerprint(sa, NULL);
@@ -147,7 +167,7 @@ static int edbm_inset_cancel(bContext *C, wmOperator *op)
opdata = op->customdata;
if (opdata->is_modal) {
- EDBM_redo_state_free(&opdata->backup, opdata->em, true);
+ EDBM_redo_state_free(&opdata->mesh_backup, opdata->em, true);
EDBM_update_generic(opdata->em, false, true);
}
@@ -176,7 +196,7 @@ static int edbm_inset_calc(wmOperator *op)
em = opdata->em;
if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->backup, em, false);
+ EDBM_redo_state_restore(opdata->mesh_backup, em, false);
}
EDBM_op_init(em, &bmop, op,
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 5befcd7b5f2..0e4161d232d 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -199,9 +199,9 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
float mval[2], co_proj[3], no_dummy[3];
- int dist_dummy;
+ float dist_px_dummy;
if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- if (snapObjectsContext(C, mval, &dist_dummy, co_proj, no_dummy, SNAP_NOT_OBEDIT)) {
+ if (snapObjectsContext(C, mval, &dist_px_dummy, co_proj, no_dummy, SNAP_NOT_OBEDIT)) {
mul_v3_m4v3(eve->co, obedit->imat, co_proj);
}
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index b33c7212f0e..d63a964c26a 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1786,8 +1786,8 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) {
Group *group;
for (group = bmain->group.first; group; group = group->id.next) {
- if (object_in_group(ob, group))
- add_to_group(group, obn, scene, basen);
+ if (BKE_group_object_exists(group, ob))
+ BKE_group_object_add(group, obn, scene, basen);
}
}
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 3112bb21091..8afd3049b84 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -78,7 +78,7 @@ static EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA *UNUS
Group *group = NULL;
int i = 0;
- while ((group = find_group(ob, group))) {
+ while ((group = BKE_group_object_find(group, ob))) {
item_tmp.identifier = item_tmp.name = group->id.name + 2;
/* item_tmp.icon = ICON_ARMATURE_DATA; */
item_tmp.value = i;
@@ -98,7 +98,7 @@ static Group *group_object_active_find_index(Object *ob, const int group_object_
{
Group *group = NULL;
int i = 0;
- while ((group = find_group(ob, group))) {
+ while ((group = BKE_group_object_find(group, ob))) {
if (i == group_object_index) {
break;
}
@@ -125,7 +125,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
if (base->object->dup_group != group) {
- add_to_group(group, base->object, scene, base);
+ BKE_group_object_add(group, base->object, scene, base);
}
else {
is_cycle = TRUE;
@@ -184,11 +184,11 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
* looking up the active objects groups each time */
for (group = bmain->group.first; group; group = group->id.next) {
- if (object_in_group(ob, group)) {
+ if (BKE_group_object_exists(group, ob)) {
/* Assign groups to selected objects */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- rem_from_group(group, base->object, scene, base);
+ BKE_group_object_unlink(group, base->object, scene, base);
ok = 1;
}
CTX_DATA_END;
@@ -265,7 +265,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- rem_from_group(group, base->object, scene, base);
+ BKE_group_object_unlink(group, base->object, scene, base);
}
CTX_DATA_END;
@@ -311,11 +311,11 @@ static int group_create_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "name", name);
- group = add_group(bmain, name);
+ group = BKE_group_add(bmain, name);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- add_to_group(group, base->object, scene, base);
+ BKE_group_object_add(group, base->object, scene, base);
}
CTX_DATA_END;
@@ -354,8 +354,8 @@ static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
if (ob == NULL)
return OPERATOR_CANCELLED;
- group = add_group(bmain, "Group");
- add_to_group(group, ob, scene, NULL);
+ group = BKE_group_add(bmain, "Group");
+ BKE_group_object_add(group, ob, scene, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -386,7 +386,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
if (ELEM(NULL, ob, group))
return OPERATOR_CANCELLED;
- add_to_group(group, ob, scene, NULL);
+ BKE_group_object_add(group, ob, scene, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -425,7 +425,7 @@ static int group_remove_exec(bContext *C, wmOperator *UNUSED(op))
if (!ob || !group)
return OPERATOR_CANCELLED;
- rem_from_group(group, ob, scene, NULL); /* base will be used if found */
+ BKE_group_object_unlink(group, ob, scene, NULL); /* base will be used if found */
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 34a6d359f6b..cdc920ba3ec 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1486,7 +1486,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
/* 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) {
- add_to_group(group_node->link, ob_dst, scene, base_dst);
+ BKE_group_object_add(group_node->link, ob_dst, scene, base_dst);
}
else {
is_cycle = TRUE;
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index b7303b2af51..974dc3acef9 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -586,7 +586,7 @@ static short select_grouped_group(bContext *C, Object *ob) /* Select objects in
uiLayout *layout;
for (group = CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group = group->id.next) {
- if (object_in_group(ob, group)) {
+ if (BKE_group_object_exists(group, ob)) {
ob_groups[group_count] = group;
group_count++;
}
@@ -598,7 +598,7 @@ static short 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) && object_in_group(base->object, group)) {
+ if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
ED_base_object_select(base, BA_SELECT);
changed = 1;
}
@@ -1040,7 +1040,7 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (!(base->flag & SELECT) && object_in_group(base->object, group))
+ if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object))
ED_base_object_select(base, BA_SELECT);
}
CTX_DATA_END;
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index b3f92d3de46..d38ffa491e2 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -88,14 +88,14 @@ void ED_rigidbody_con_add(wmOperator *op, Scene *scene, Object *ob, int type)
}
/* create constraint group if it doesn't already exits */
if (rbw->constraints == NULL) {
- rbw->constraints = add_group(G.main, "RigidBodyConstraints");
+ rbw->constraints = BKE_group_add(G.main, "RigidBodyConstraints");
}
/* make rigidbody constraint settings */
ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE;
/* add constraint to rigid body constraint group */
- add_to_group(rbw->constraints, ob, scene, NULL);
+ BKE_group_object_add(rbw->constraints, ob, scene, NULL);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
@@ -106,7 +106,7 @@ void ED_rigidbody_con_remove(Scene *scene, Object *ob)
BKE_rigidbody_remove_constraint(scene, ob);
if (rbw)
- rem_from_group(rbw->constraints, ob, scene, NULL);
+ BKE_group_object_unlink(rbw->constraints, ob, scene, NULL);
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 9c03c6173a5..9f981256a31 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -111,7 +111,7 @@ void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type)
scene->rigidbody_world = rbw;
}
if (rbw->group == NULL) {
- rbw->group = add_group(G.main, "RigidBodyWorld");
+ rbw->group = BKE_group_add(G.main, "RigidBodyWorld");
}
/* make rigidbody object settings */
@@ -122,7 +122,7 @@ void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type)
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* add object to rigid body group */
- add_to_group(rbw->group, ob, scene, NULL);
+ BKE_group_object_add(rbw->group, ob, scene, NULL);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
@@ -133,7 +133,7 @@ void ED_rigidbody_ob_remove(Scene *scene, Object *ob)
BKE_rigidbody_remove_object(scene, ob);
if (rbw)
- rem_from_group(rbw->group, ob, scene, NULL);
+ BKE_group_object_unlink(rbw->group, ob, scene, NULL);
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 365ac02d15b..6832cd5baa0 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -143,7 +143,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
if (ibuf->rect == NULL)
imb_addrectImBuf(ibuf);
-
+
rectf += 4 * (rr->rectx * ymin + xmin);
IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin,
@@ -429,10 +429,38 @@ static void render_endjob(void *rjv)
nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
}
-
+
/* XXX render stability hack */
G.is_rendering = FALSE;
WM_main_add_notifier(NC_WINDOW, NULL);
+
+ /* Partial render result will always update display buffer
+ * for first render layer only. This is nice because you'll
+ * see render progress during rendering, but it ends up in
+ * wrong display buffer shown after rendering.
+ *
+ * The code below will mark display buffer as invalid after
+ * rendering in case multiple layers were rendered, which
+ * ensures display buffer matches render layer after
+ * rendering.
+ *
+ * Perhaps proper way would be to toggle active render
+ * layer in image editor and job, so we always display
+ * layer being currently rendered. But this is not so much
+ * trivial at this moment, especially because of external
+ * engine API, so lets use simple and robust way for now
+ * - sergey -
+ */
+ if (rj->scene->r.layers.first != rj->scene->r.layers.last) {
+ void *lock;
+ Image *ima = rj->image;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
+
+ if (ibuf)
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
}
/* called by render, check job 'stop' value or the global */
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index f47d737beca..9d443fab552 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -69,6 +69,8 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
#include "GPU_extensions.h"
@@ -261,11 +263,14 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
*/
if (!oglrender->is_sequencer) {
- /* sequencer has got tricker ocnversion happened above */
-
- IMB_buffer_float_from_float(rr->rectf, rr->rectf,
- 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, TRUE,
- oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
+ /* sequencer has got trickier conversion happened above
+ * also assume opengl's space matches byte buffer color space
+ */
+ if (!glaBufferTransformFromRole_glsl(rr->rectf, oglrender->sizex, oglrender->sizey, COLOR_ROLE_DEFAULT_BYTE)) {
+ IMB_buffer_float_from_float(rr->rectf, rr->rectf,
+ 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, TRUE,
+ oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
+ }
}
/* rr->rectf is now filled with image data */
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index 33373354aa4..c9c4c253e28 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../../blenlib
../../blenloader
../../bmesh
+ ../../gpu
../../imbuf
../../makesdna
../../makesrna
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 89315e041de..3469604b3dd 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -42,11 +42,18 @@
#include "BLI_threads.h"
#include "BKE_blender.h"
+#include "BKE_global.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_extensions.h"
+
+#include "IMB_colormanagement.h"
+#include "IMB_imbuf_types.h"
+
#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
#endif
@@ -482,7 +489,7 @@ static int get_cached_work_texture(int *w_r, int *h_r)
return texid;
}
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY)
+void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY)
{
unsigned char *uc_rect = (unsigned char *) rect;
float *f_rect = (float *)rect;
@@ -492,7 +499,8 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
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;
+
/* Specify the color outside this function, and tex will modulate it.
* This is useful for changing alpha without using glPixelTransferf()
*/
@@ -519,13 +527,24 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
- if (format == GL_FLOAT) {
+ if (format == GL_RGBA)
+ components = 4;
+ else if (format == GL_RGB)
+ components = 3;
+ else if (format == GL_LUMINANCE)
+ components = 1;
+ else {
+ BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
+ return;
+ }
+
+ if (type == GL_FLOAT) {
/* need to set internal format to higher range float */
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, tex_w, tex_h, 0, GL_RGBA, GL_FLOAT, NULL);
+ 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, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
}
for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
@@ -545,26 +564,26 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
if (subpart_w <= seamless || subpart_h <= seamless)
continue;
- if (format == GL_FLOAT) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * 4 + subpart_x * offset_x * 4]);
+ if (type == GL_FLOAT) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[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, GL_RGBA, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[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, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + subpart_x * offset_x * 4]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(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, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(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, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * 4 + subpart_x * offset_x * 4]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[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, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[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, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + subpart_x * offset_x * 4]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(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, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
}
glEnable(GL_TEXTURE_2D);
@@ -595,9 +614,9 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
#endif
}
-void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect)
+void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
{
- glaDrawPixelsTexScaled(x, y, img_w, img_h, format, zoomfilter, rect, 1.0f, 1.0f);
+ glaDrawPixelsTexScaled(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f);
}
void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
@@ -680,7 +699,7 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
}
/* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */
-void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect)
+void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
{
if (U.image_gpubuffer_limit) {
/* Megapixels, use float math to prevent overflow */
@@ -688,11 +707,11 @@ void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int z
if (U.image_gpubuffer_limit > (int)img_size) {
glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTex(x, y, img_w, img_h, format, zoomfilter, rect);
+ glaDrawPixelsTex(x, y, img_w, img_h, format, type, zoomfilter, rect);
return;
}
}
- glaDrawPixelsSafe(x, y, img_w, img_h, img_w, GL_RGBA, format, rect);
+ glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect);
}
/* 2D Drawing Assistance */
@@ -753,6 +772,18 @@ void gla2DSetMap(gla2DDrawInfo *di, rctf *rect)
di->wo_to_sc[1] = sc_h / wo_h;
}
+/** Save the current OpenGL state and initialize OpenGL for 2D
+ * rendering. glaEnd2DDraw should be called on the returned structure
+ * to free it and to return OpenGL to its previous state. The
+ * scissor rectangle is set to match the viewport.
+ *
+ * See glaDefine2DArea for an explanation of why this function uses integers.
+ *
+ * \param screen_rect The screen rectangle to be used for 2D drawing.
+ * \param world_rect The world rectangle that the 2D area represented
+ * by \a screen_rect is supposed to represent. If NULL it is assumed the
+ * world has a 1 to 1 mapping to the screen.
+ */
gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
{
gla2DDrawInfo *di = MEM_mallocN(sizeof(*di), "gla2DDrawInfo");
@@ -788,17 +819,27 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
return di;
}
+/**
+ * Translate the (\a wo_x, \a wo_y) point from world coordinates into screen space.
+ */
void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r)
{
*sc_x_r = (wo_x - di->world_rect.xmin) * di->wo_to_sc[0];
*sc_y_r = (wo_y - di->world_rect.ymin) * di->wo_to_sc[1];
}
+
+/**
+ * Translate the \a world point from world coordiantes into screen space.
+ */
void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2])
{
screen_r[0] = (world[0] - di->world_rect.xmin) * di->wo_to_sc[0];
screen_r[1] = (world[1] - di->world_rect.ymin) * di->wo_to_sc[1];
}
+/**
+ * Restores the previous OpenGL state and free's the auxilary gla data.
+ */
void glaEnd2DDraw(gla2DDrawInfo *di)
{
glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
@@ -983,3 +1024,163 @@ void bglFlush(void)
#endif
}
#endif
+
+/* **** Color management helper functions for GLSL display/transform ***** */
+
+/* Draw given image buffer on a screen using GLSL for display transform */
+void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter)
+{
+ bool force_fallback = false;
+ bool need_fallback = true;
+
+ /* Early out */
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL)
+ return;
+
+ /* Dithering is not supported on GLSL yet */
+ force_fallback = ibuf->dither != 0.0f;
+
+ /* Single channel images could not be transformed using GLSL yet */
+ force_fallback = ibuf->channels == 1;
+
+ /* This is actually lots of crap, but currently not sure about
+ * more clear way to bypass partial buffer update crappyness
+ * while rendering.
+ *
+ * The thing is -- render engines are only updating byte and
+ * display buffers for active render result opened in image
+ * editor. This works fine to show render progress without
+ * switching render layers in image editor user, but this is
+ * completely useless for GLSL display, where we need to have
+ * original buffer which we could color manage.
+ *
+ * For the time of rendering, we'll stick back to slower CPU
+ * display buffer update. GLSL could be used as soon as some
+ * fixes (?) are done in render itself, so we'll always have
+ * image buffer with relevant float buffer opened while
+ * rendering.
+ *
+ * On the other hand, when using Cycles, stressing GPU with
+ * GLSL could backfire on a performance.
+ * - sergey -
+ */
+ if (G.is_rendering) {
+ /* Try to detect whether we're drawing render result,
+ * other images could have both rect and rect_float
+ * but they'll be synchronized
+ */
+ if (ibuf->rect_float && ibuf->rect &&
+ ((ibuf->mall & IB_rectfloat) == 0))
+ {
+ force_fallback = true;
+ }
+ }
+
+ /* Try to draw buffer using GLSL display transform */
+ if (force_fallback == false) {
+ int ok;
+
+ if (ibuf->rect_float)
+ ok = IMB_colormanagement_setup_glsl_draw_ctx(C, TRUE);
+ else
+ ok = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, FALSE);
+
+ if (ok) {
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ if (ibuf->rect_float) {
+ int format = 0;
+
+ if (ibuf->channels == 3)
+ format = GL_RGB;
+ else if (ibuf->channels == 4)
+ format = GL_RGBA;
+ else
+ BLI_assert(!"Incompatible number of channels for GLSL display");
+
+ if (format != 0) {
+ glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
+ zoomfilter, ibuf->rect_float);
+ }
+ }
+ else if (ibuf->rect) {
+ /* ibuf->rect is always RGBA */
+ glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+ zoomfilter, ibuf->rect);
+ }
+
+ IMB_colormanagement_finish_glsl_draw();
+
+ need_fallback = false;
+ }
+ }
+
+ /* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */
+ if (need_fallback) {
+ unsigned char *display_buffer;
+ void *cache_handle;
+
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+
+ if (display_buffer)
+ glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+ zoomfilter, display_buffer);
+
+ IMB_display_buffer_release(cache_handle);
+ }
+}
+
+/* Transform buffer from role to scene linear space using GLSL OCIO conversion
+ *
+ * See IMB_colormanagement_setup_transform_from_role_glsl description for
+ * some more details
+ *
+ * NOTE: this only works for RGBA buffers!
+ */
+int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role)
+{
+ GPUOffScreen *ofs;
+ char err_out[256];
+ rcti display_rect;
+
+ ofs = GPU_offscreen_create(width, height, err_out);
+
+ if (!ofs)
+ return FALSE;
+
+ GPU_offscreen_bind(ofs);
+
+ if (!IMB_colormanagement_setup_transform_from_role_glsl(role, TRUE)) {
+ GPU_offscreen_unbind(ofs);
+ GPU_offscreen_free(ofs);
+ return FALSE;
+ }
+
+ BLI_rcti_init(&display_rect, 0, width, 0, height);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glaDefine2DArea(&display_rect);
+
+ glaDrawPixelsTex(0, 0, width, height, GL_RGBA, GL_FLOAT,
+ GL_NEAREST, buffer);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, buffer);
+
+ IMB_colormanagement_finish_glsl_transform();
+
+ /* unbind */
+ GPU_offscreen_unbind(ofs);
+ GPU_offscreen_free(ofs);
+
+ return TRUE;
+}
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index cd9523f8ff6..40a18734948 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -62,7 +62,7 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op))
{
/*int type = RNA_enum_get(op->ptr, "type");*/
Paint *paint = paint_get_active_from_context(C);
- struct Brush *br = paint_brush(paint);
+ Brush *br = paint_brush(paint);
Main *bmain = CTX_data_main(C);
if (br)
@@ -94,7 +94,7 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Paint *paint = paint_get_active_from_context(C);
- struct Brush *brush = paint_brush(paint);
+ Brush *brush = paint_brush(paint);
// Object *ob = CTX_data_active_object(C);
float scalar = RNA_float_get(op->ptr, "scalar");
@@ -176,10 +176,10 @@ static void PAINT_OT_vertex_color_set(wmOperatorType *ot)
static int brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
{
Paint *paint = paint_get_active_from_context(C);
- struct Brush *brush = paint_brush(paint);
+ Brush *brush = paint_brush(paint);
Object *ob = CTX_data_active_object(C);
- if (!ob) return OPERATOR_CANCELLED;
+ if (!ob || !brush) return OPERATOR_CANCELLED;
if (ob->mode & OB_MODE_SCULPT)
BKE_brush_sculpt_reset(brush);
@@ -215,7 +215,7 @@ static void brush_tool_set(const Brush *brush, size_t tool_offset, int tool)
/* generic functions for setting the active brush based on the tool */
static Brush *brush_tool_cycle(Main *bmain, Brush *brush_orig, const int tool, const size_t tool_offset, const int ob_mode)
{
- struct Brush *brush;
+ Brush *brush;
if (!brush_orig && !(brush_orig = bmain->brush.first)) {
return NULL;
@@ -266,7 +266,7 @@ static int brush_generic_tool_set(Main *bmain, Paint *paint, const int tool,
const char *tool_name, int create_missing,
int toggle)
{
- struct Brush *brush, *brush_orig = paint_brush(paint);
+ Brush *brush, *brush_orig = paint_brush(paint);
if (toggle)
brush = brush_tool_toggle(bmain, brush_orig, tool, tool_offset, ob_mode);
@@ -467,7 +467,7 @@ typedef struct {
static int stencil_control_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Paint *paint = paint_get_active_from_context(C);
- Brush *br = paint->brush;
+ Brush *br = paint_brush(paint);
int mdiff[2];
StencilControlData *scd = MEM_mallocN(sizeof(StencilControlData), "stencil_control");
@@ -520,7 +520,7 @@ static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *eve
float len, factor;
sub_v2_v2v2_int(mdiff, event->mval, scd->br->stencil_pos);
len = sqrtf(mdiff[0] * mdiff[0] + mdiff[1] * mdiff[1]);
- factor = len/scd->lenorig;
+ factor = len / scd->lenorig;
mdiff[0] = factor * scd->init_sdim[0];
mdiff[1] = factor * scd->init_sdim[1];
copy_v2_v2_int(scd->br->stencil_dimension, mdiff);
@@ -567,15 +567,15 @@ static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *eve
static int stencil_control_poll(bContext *C)
{
Paint *paint = paint_get_active_from_context(C);
- Brush *br = paint->brush;
+ Brush *br = paint_brush(paint);
- return br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL;
+ return (br && br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL);
}
static void BRUSH_OT_stencil_control(wmOperatorType *ot)
{
static EnumPropertyItem stencil_control_items[] = {
- {STENCIL_TRANSLATE, "TRANSLATION", 0, "Transation", ""},
+ {STENCIL_TRANSLATE, "TRANSLATION", 0, "Translation", ""},
{STENCIL_SCALE, "SCALE", 0, "Scale", ""},
{STENCIL_ROTATE, "ROTATION", 0, "Rotation", ""},
{0, NULL, 0, NULL, NULL}
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 47e20bcc5fb..315fdd2fb32 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -381,7 +381,9 @@ void paint_sample_color(const bContext *C, ARegion *ar, int x, int y) /* fron
static int brush_curve_preset_exec(bContext *C, wmOperator *op)
{
Brush *br = paint_brush(paint_get_active_from_context(C));
- BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
+
+ if (br)
+ BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 82a07c9e3be..1060999e13f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -54,8 +54,6 @@ struct SculptUndoNode;
/* Interface */
struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct Object *ob);
-void sculpt(struct Sculpt *sd);
-
int sculpt_mode_poll(struct bContext *C);
int sculpt_mode_poll_view3d(struct bContext *C);
int sculpt_poll(struct bContext *C);
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index b6d2d31f0ad..eb755e162a3 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -277,7 +277,7 @@ static void borderselect_action(bAnimContext *ac, rcti rect, short mode, short s
Mask *mask = ale->data;
MaskLayer *masklay;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ ED_masklayer_frames_select_border(masklay, rectf.xmin, rectf.xmax, selectmode);
}
break;
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index b108f9fa4b5..5a7d70d279c 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -205,7 +205,6 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
/* particle systems */
if (psys) {
- /* todo: these slots are not in the UI */
for (a = 0; a < MAX_MTEX; a++) {
mtex = psys->part->mtex[a];
@@ -333,6 +332,17 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)
tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL;
ct->texture = tex;
+
+ if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) {
+ /* stupid exception for particle systems which still uses influence
+ * from the old texture system, set the active texture slots as well */
+ ParticleSettings *part = user->ptr.id.data;
+ int a;
+
+ for (a = 0; a < MAX_MTEX; a++)
+ if (user->ptr.data == part->mtex[a])
+ part->texact = a;
+ }
}
ct->user = user;
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index cbca2f0c46e..1000aced3a9 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -248,53 +248,6 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
ED_region_info_draw(ar, str, block, 0.6f);
}
-static void draw_movieclip_buffer_glsl(SpaceClip *sc, ImBuf *ibuf, int x, int y,
- float zoomx, float zoomy)
-{
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int filter = GL_LINEAR;
-
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
- glScalef(zoomx, zoomy, 1.0f);
-
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- glColor4f(1.0, 1.0, 1.0, 1.0);
-
- /* non-scaled proxy shouldn;t use diltering */
- if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
- ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
- {
- filter = GL_NEAREST;
- }
-
- glaDrawPixelsTex(0, 0, ibuf->x, ibuf->y, GL_FLOAT, filter, ibuf->rect_float);
-
- glPopMatrix();
-}
-
-static void draw_movieclip_buffer_fallback(const bContext *C, ImBuf *ibuf, int x, int y,
- int width, int height, float zoomx, float zoomy)
-{
- unsigned char *display_buffer;
- void *cache_handle;
-
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- if (display_buffer) {
- /* set zoom */
- glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
-
- glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
-
- /* reset zoom */
- glPixelZoom(1.0f, 1.0f);
- }
-
- IMB_display_buffer_release(cache_handle);
-}
-
static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
int width, int height, float zoomx, float zoomy)
{
@@ -308,7 +261,8 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
glRectf(x, y, x + zoomx * width, y + zoomy * height);
}
else {
- bool need_fallback = true;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int filter = GL_LINEAR;
/* checkerboard for case alpha */
if (ibuf->planes == 32) {
@@ -318,19 +272,20 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
}
- /* GLSL display transform for byte buffers is not supported yet */
- if (ibuf->rect_float && IMB_coloemanagement_setup_glsl_draw_from_ctx(C)) {
- draw_movieclip_buffer_glsl(sc, ibuf, x, y, zoomx, zoomy);
+ /* non-scaled proxy shouldn't use filtering */
+ if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
+ ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
+ {
+ filter = GL_NEAREST;
+ }
- IMB_coloemanagement_finish_glsl_draw();
+ /* set zoom */
+ glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
- need_fallback = false;
- }
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter);
- /* if GLSL display failed, fallback to regular glaDrawPixelsAuto method */
- if (need_fallback) {
- draw_movieclip_buffer_fallback(C, ibuf, x, y, width, height, zoomx, zoomy);
- }
+ /* reset zoom */
+ glPixelZoom(1.0f, 1.0f);
if (ibuf->planes == 32)
glDisable(GL_BLEND);
@@ -1501,8 +1456,6 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
if (ibuf) {
draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
IMB_freeImBuf(ibuf);
-
- clip_start_prefetch_job(C);
}
else {
ED_region_grid_draw(ar, zoomx, zoomy);
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index d297d0485e3..08d0af817a8 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -528,6 +528,7 @@ MovieClip *ED_space_clip_get_clip(SpaceClip *sc)
void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip)
{
MovieClip *old_clip;
+ bool old_clip_visible = false;
if (!screen && C)
screen = CTX_wm_screen(C);
@@ -546,9 +547,15 @@ void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieCl
if (sl->spacetype == SPACE_CLIP) {
SpaceClip *cur_sc = (SpaceClip *) sl;
- if (cur_sc != sc && cur_sc->view != SC_VIEW_CLIP) {
- if (cur_sc->clip == old_clip || cur_sc->clip == NULL) {
- cur_sc->clip = clip;
+ if (cur_sc != sc) {
+ if (cur_sc->view == SC_VIEW_CLIP) {
+ if (cur_sc->clip == old_clip)
+ old_clip_visible = true;
+ }
+ else {
+ if (cur_sc->clip == old_clip || cur_sc->clip == NULL) {
+ cur_sc->clip = clip;
+ }
}
}
}
@@ -556,6 +563,11 @@ void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieCl
}
}
+ /* If clip is no longer visible on screen, free memory used by it's cache */
+ if (old_clip && old_clip != clip && !old_clip_visible) {
+ BKE_movieclip_clear_cache(old_clip);
+ }
+
if (C)
WM_event_add_notifier(C, NC_MOVIECLIP | NA_SELECTED, sc->clip);
}
@@ -605,26 +617,9 @@ typedef struct PrefetchThread {
} PrefetchThread;
/* check whether pre-fetching is allowed */
-static bool check_prefetch_allowed(void)
+static bool check_prefetch_break(void)
{
- wmWindowManager *wm;
-
- /* if there's any job started, better to leave all CPU and
- * HDD bandwidth to it
- *
- * also, display transform could be needed during playback,
- * so better to avoid prefetching in this case and reserve
- * all the power for display transform
- */
- for (wm = G.main->wm.first; wm; wm = wm->id.next) {
- if (WM_jobs_has_running_except(wm, WM_JOB_TYPE_CLIP_PREFETCH))
- return false;
-
- if (ED_screen_animation_playing(wm))
- return false;
- }
-
- return true;
+ return G.is_break;
}
/* read file for specified frame number to the memory */
@@ -706,7 +701,7 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip
unsigned char *mem = NULL;
BLI_spin_lock(&queue->spin);
- if (!*queue->stop && check_prefetch_allowed() &&
+ if (!*queue->stop && !check_prefetch_break() &&
IN_RANGE_INCL(queue->current_frame, queue->start_frame, queue->end_frame))
{
int current_frame;
@@ -848,7 +843,7 @@ static bool prefetch_movie_frame(MovieClip *clip, int frame, short render_size,
MovieClipUser user = {0};
ImBuf *ibuf;
- if (!check_prefetch_allowed() || *stop)
+ if (check_prefetch_break() || *stop)
return false;
user.framenr = frame;
@@ -968,26 +963,6 @@ static bool prefetch_check_early_out(const bContext *C)
int first_uncached_frame, end_frame;
int clip_len;
- if (clip->prefetch_ok)
- return true;
-
- if (clip->source == MCLIP_SRC_MOVIE) {
- /* for movies we only prefetch undistorted proxy,
- * in other cases prefetching could lead to issues
- * due to timecodes issues.
- */
-
- if (clip->flag & MCLIP_USE_PROXY) {
- MovieClipUser *user = &sc->user;
-
- if ((user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) == 0)
- return true;
- }
- else {
- return true;
- }
- }
-
clip_len = BKE_movieclip_get_duration(clip);
/* check whether all the frames from prefetch range are cached */
@@ -1016,7 +991,6 @@ void clip_start_prefetch_job(const bContext *C)
wmJob *wm_job;
PrefetchJob *pj;
SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
if (prefetch_check_early_out(C))
return;
@@ -1024,17 +998,6 @@ void clip_start_prefetch_job(const bContext *C)
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_area(C), "Prefetching",
WM_JOB_PROGRESS, WM_JOB_TYPE_CLIP_PREFETCH);
- if (WM_jobs_is_running(wm_job)) {
- /* if job is already running, it'll call clip editor redraw when
- * it's finished, so cache line is nicely updated
- * this will also trigger call of this function, which will ensure
- * all needed frames are prefetched
- */
- return;
- }
-
- clip->prefetch_ok = true;
-
/* create new job */
pj = MEM_callocN(sizeof(PrefetchJob), "prefetch job");
pj->clip = ED_space_clip_get_clip(sc);
@@ -1045,9 +1008,11 @@ void clip_start_prefetch_job(const bContext *C)
pj->render_flag = sc->user.render_flag;
WM_jobs_customdata_set(wm_job, pj, prefetch_freejob);
- WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP, 0);
+ WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | ND_DISPLAY, 0);
WM_jobs_callbacks(wm_job, prefetch_startjob, NULL, NULL, NULL);
+ G.is_break = FALSE;
+
/* and finally start the job */
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index 99222ec63ac..3d589ff120c 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -108,6 +108,8 @@ void CLIP_OT_mode_set(struct wmOperatorType *ot);
void CLIP_OT_view_ndof(struct wmOperatorType *ot);
+void CLIP_OT_prefetch(struct wmOperatorType *ot);
+
/* clip_toolbar.c */
struct ARegion *ED_clip_has_properties_region(struct ScrArea *sa);
void CLIP_OT_tools(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 8e03691e64f..ab00c078226 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -1378,6 +1378,47 @@ void CLIP_OT_view_ndof(wmOperatorType *ot)
ot->invoke = clip_view_ndof_invoke;
}
+/********************** Prefetch operator *********************/
+
+static int clip_prefetch_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_CLIP_PREFETCH))
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+
+ /* running render */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ break;
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int clip_prefetch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(_event))
+{
+ clip_start_prefetch_job(C);
+
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void CLIP_OT_prefetch(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Prefetch Frames";
+ ot->idname = "CLIP_OT_prefetch";
+ ot->description = "Prefetch frames from disk for faster playback/tracking";
+
+ /* api callbacks */
+ ot->poll = ED_space_clip_view_clip_poll;
+ ot->invoke = clip_prefetch_invoke;
+ ot->modal = clip_prefetch_modal;
+}
+
/********************** macroses *********************/
void ED_operatormacros_clip(void)
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 64b643f8a58..96e127cfde6 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -236,16 +236,6 @@ static void clip_stabilization_tag_refresh(ScrArea *sa)
}
}
-static void clip_prefetch_tag_refresh(ScrArea *sa)
-{
- SpaceClip *sc = (SpaceClip *) sa->spacedata.first;
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (clip) {
- clip->prefetch_ok = FALSE;
- }
-}
-
/* ******************** default callbacks for clip space ***************** */
static SpaceLink *clip_new(const bContext *C)
@@ -358,7 +348,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
switch (wmn->data) {
case ND_FRAME:
clip_scopes_tag_refresh(sa);
- clip_prefetch_tag_refresh(sa);
/* no break! */
case ND_FRAME_RANGE:
@@ -367,19 +356,11 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
}
break;
case NC_MOVIECLIP:
- if (wmn->data == 0 && wmn->action == 0) {
- /* a nit funky, happens from prefetch job to update
- * cache line and job progress
- */
- ED_area_tag_redraw(sa);
- }
-
switch (wmn->data) {
case ND_DISPLAY:
case ND_SELECT:
clip_scopes_tag_refresh(sa);
ED_area_tag_redraw(sa);
- clip_prefetch_tag_refresh(sa);
break;
}
switch (wmn->action) {
@@ -423,7 +404,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
case NC_SCREEN:
switch (wmn->data) {
case ND_ANIMPLAY:
- clip_prefetch_tag_refresh(sa);
ED_area_tag_redraw(sa);
break;
}
@@ -432,7 +412,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
if (wmn->data == ND_SPACE_CLIP) {
clip_scopes_tag_refresh(sa);
clip_stabilization_tag_refresh(sa);
- clip_prefetch_tag_refresh(sa);
ED_area_tag_redraw(sa);
}
break;
@@ -442,10 +421,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
}
break;
- case NC_WM:
- if (wmn->data == ND_FILEREAD)
- clip_prefetch_tag_refresh(sa);
- break;
}
}
@@ -465,6 +440,7 @@ static void clip_operatortypes(void)
WM_operatortype_append(CLIP_OT_rebuild_proxy);
WM_operatortype_append(CLIP_OT_mode_set);
WM_operatortype_append(CLIP_OT_view_ndof);
+ WM_operatortype_append(CLIP_OT_prefetch);
/* ** clip_toolbar.c ** */
WM_operatortype_append(CLIP_OT_tools);
@@ -598,6 +574,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "CLIP_OT_set_solver_keyframe", EKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "keyframe", 1);
+ /* io/playback */
+ WM_keymap_add_item(keymap, "CLIP_OT_prefetch", PKEY, KM_PRESS, 0, 0);
+
/* ******** Hotkeys avalaible for main region only ******** */
keymap = WM_keymap_find(keyconf, "Clip Editor", SPACE_CLIP, 0);
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 1c677d7c006..4a0665d663e 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -376,7 +376,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int
/* the image */
glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale);
+ glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale);
/* border */
if (dropshadow) {
@@ -538,7 +538,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
uiButSetRenameFunc(but, renamebutton_cb, file);
uiButSetFlag(but, UI_BUT_NO_UTF8); /* allow non utf8 names */
uiButClearFlag(but, UI_BUT_UNDO);
- if (0 == uiButActiveOnly(C, ar, block, but)) {
+ if (false == uiButActiveOnly(C, ar, block, but)) {
file->selflag &= ~EDITING_FILE;
}
}
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index f27a99ac44b..7fc83809b60 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -505,9 +505,6 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float);
}
else {
- unsigned char *display_buffer;
- void *cache_handle;
-
if (sima->flag & SI_USE_ALPHA) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -515,12 +512,7 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
}
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- if (display_buffer)
- glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
-
- IMB_display_buffer_release(cache_handle);
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST);
if (sima->flag & SI_USE_ALPHA)
glDisable(GL_BLEND);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 761becdbf8e..1b4ff44bb6b 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -435,6 +435,12 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn)
/* context changes */
switch (wmn->category) {
+ case NC_WINDOW:
+ /* notifier comes from editing color space */
+ image_scopes_tag_refresh(sa);
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ break;
case NC_SCENE:
switch (wmn->data) {
case ND_FRAME:
@@ -801,11 +807,15 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar)
Scene *scene = CTX_data_scene(C);
void *lock;
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+
if (ibuf) {
if (!sima->scopes.ok) {
BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings);
}
- scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
+ if (sima->image->flag & IMA_VIEW_AS_RENDER)
+ scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
+ else
+ scopes_update(&sima->scopes, ibuf, NULL, &scene->display_settings);
}
ED_space_image_release_buffer(sima, ibuf, lock);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 5e5b2ece8c9..d7206c9b111 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -3011,7 +3011,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPixelZoom(snode->zoom, snode->zoom);
- glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
+ glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
@@ -3019,7 +3019,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
else {
glPixelZoom(snode->zoom, snode->zoom);
- glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
+ glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
glPixelZoom(1.0f, 1.0f);
}
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index f1915a82f69..39b12b321dd 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -710,7 +710,7 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
glColor4f(1.0, 1.0, 1.0, 1.0);
glPixelZoom(scale, scale);
- glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
+ glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index cba807a436f..25b2180dbb1 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -1978,7 +1978,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
bNodeLink *link;
int num_nodes;
float center[2];
- int is_clipboard_valid;
+ int is_clipboard_valid, all_nodes_valid;
/* validate pointers in the clipboard */
is_clipboard_valid = BKE_node_clipboard_validate();
@@ -2000,6 +2000,17 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_WARNING, "Some nodes references could not be restored, will be left empty");
}
+ /* make sure all clipboard nodes would be valid in the target tree */
+ all_nodes_valid = TRUE;
+ for (node = clipboard_nodes_lb->first; node; node = node->next) {
+ if (!node->typeinfo->poll_instance(node, ntree)) {
+ all_nodes_valid = FALSE;
+ BKE_reportf(op->reports, RPT_ERROR, "Cannot add node %s into node tree %s", node->name, ntree->id.name + 2);
+ }
+ }
+ if (!all_nodes_valid)
+ return OPERATOR_CANCELLED;
+
ED_preview_kill_jobs(C);
/* deselect old nodes */
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 7e4397a6cb0..b45ca8b228f 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -122,6 +122,7 @@ void NODE_OT_select_border(struct wmOperatorType *ot);
void NODE_OT_select_lasso(struct wmOperatorType *ot);
void NODE_OT_select_same_type(struct wmOperatorType *ot);
void NODE_OT_select_same_type_step(struct wmOperatorType *ot);
+void NODE_OT_find_node(struct wmOperatorType *ot);
/* node_view.c */
int space_node_view_flag(struct bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag);
@@ -154,10 +155,6 @@ void NODE_OT_group_insert(struct wmOperatorType *ot);
void NODE_OT_group_ungroup(struct wmOperatorType *ot);
void NODE_OT_group_separate(struct wmOperatorType *ot);
void NODE_OT_group_edit(struct wmOperatorType *ot);
-void NODE_OT_group_socket_add(struct wmOperatorType *ot);
-void NODE_OT_group_socket_remove(struct wmOperatorType *ot);
-void NODE_OT_group_socket_move_up(struct wmOperatorType *ot);
-void NODE_OT_group_socket_move_down(struct wmOperatorType *ot);
/* node_relationships.c */
@@ -180,9 +177,7 @@ void snode_notify(struct bContext *C, struct SpaceNode *snode);
void snode_dag_update(struct bContext *C, struct SpaceNode *snode);
void snode_set_context(const struct bContext *C);
-bNode *node_tree_get_editgroup(bNodeTree *ntree);
void snode_update(struct SpaceNode *snode, struct bNode *node);
-bNode *editnode_get_active(bNodeTree *ntree);
int composite_node_active(struct bContext *C);
int node_has_hidden_sockets(bNode *node);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 4d229c6fe18..513bde4375c 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -60,6 +60,8 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_select_same_type);
WM_operatortype_append(NODE_OT_select_same_type_step);
+ WM_operatortype_append(NODE_OT_find_node);
+
WM_operatortype_append(NODE_OT_view_all);
WM_operatortype_append(NODE_OT_view_selected);
@@ -280,7 +282,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "replace", FALSE);
- kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "replace", TRUE);
WM_keymap_add_menu(keymap, "NODE_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
@@ -323,6 +325,8 @@ void node_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "NODE_OT_select_same_type_step", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "prev", TRUE);
+ WM_keymap_add_item(keymap, "NODE_OT_find_node", FKEY, KM_PRESS, KM_CTRL, 0);
+
node_group_operators(keymap, "ShaderNodeGroup");
node_group_operators(keymap, "CompositorNodeGroup");
node_group_operators(keymap, "TextureNodeGroup");
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 8ff964aa932..b552aff27f9 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -1408,17 +1408,23 @@ void ED_node_link_insert(ScrArea *sa)
break;
if (link) {
- node = link->tonode;
- sockto = link->tosock;
-
- link->tonode = select;
- link->tosock = socket_best_match(&select->inputs);
- node_remove_extra_links(snode, link->tosock, link);
- link->flag &= ~NODE_LINKFLAG_HILITE;
-
- nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto);
- ntreeUpdateTree(snode->edittree); /* needed for pointers */
- snode_update(snode, select);
- ED_node_tag_update_id(snode->id);
+ bNodeSocket *best_input = socket_best_match(&select->inputs);
+ bNodeSocket *best_output = socket_best_match(&select->outputs);
+
+ if (best_input && best_output) {
+ node = link->tonode;
+ sockto = link->tosock;
+
+ link->tonode = select;
+ link->tosock = best_input;
+ node_remove_extra_links(snode, link->tosock, link);
+ link->flag &= ~NODE_LINKFLAG_HILITE;
+
+ nodeAddLink(snode->edittree, select, best_output, node, sockto);
+
+ ntreeUpdateTree(snode->edittree); /* needed for pointers */
+ snode_update(snode, select);
+ ED_node_tag_update_id(snode->id);
+ }
}
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 62537fb713f..366fcce3dd5 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -28,10 +28,13 @@
* \ingroup spnode
*/
+#include <stdlib.h>
+
#include "DNA_node_types.h"
#include "BLI_rect.h"
#include "BLI_lasso.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -48,6 +51,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
#include "UI_view2d.h"
#include "MEM_guardedalloc.h"
@@ -853,3 +858,104 @@ void NODE_OT_select_same_type_step(wmOperatorType *ot)
}
+/* *************** find a node **************** */
+
+/* generic search invoke */
+static void node_find_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node;
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+
+ if (BLI_strcasestr(node->name, str) || BLI_strcasestr(node->label, str)) {
+ char name[256];
+
+ if (node->label[0])
+ BLI_snprintf(name, 256, "%s (%s)", node->name, node->label);
+ else
+ BLI_strncpy(name, node->name, 256);
+ if (false == uiSearchItemAdd(items, name, node, 0))
+ break;
+ }
+ }
+}
+
+static void node_find_call_cb(struct bContext *C, void *UNUSED(arg1), void *arg2)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *active = arg2;
+
+ if (active) {
+ ARegion *ar = CTX_wm_region(C);
+ node_select_single(C, active);
+
+ /* is note outside view? */
+ if (active->totr.xmax < ar->v2d.cur.xmin || active->totr.xmin > ar->v2d.cur.xmax ||
+ active->totr.ymax < ar->v2d.cur.ymin || active->totr.ymin > ar->v2d.cur.ymax)
+ {
+ space_node_view_flag(C, snode, ar, NODE_SELECT);
+ }
+
+ }
+}
+
+static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
+{
+ static char search[256] = "";
+ wmEvent event;
+ wmWindow *win = CTX_wm_window(C);
+ uiBlock *block;
+ uiBut *but;
+ wmOperator *op = (wmOperator *)arg_op;
+
+ block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+
+ but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, 9 * UI_UNIT_X, UI_UNIT_Y, 0, 0, "");
+ uiButSetSearchFunc(but, node_find_cb, op->type, node_find_call_cb, NULL);
+
+ /* fake button, it holds space for search items */
+ uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL);
+
+ uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
+ uiEndBlock(C, block);
+
+ // uiButActiveOnly(C, ar, block, but); XXX using this here makes Blender hang - investigate
+ event = *(win->eventstate); /* XXX huh huh? make api call */
+ event.type = EVT_BUT_OPEN;
+ event.val = KM_PRESS;
+ event.customdata = but;
+ event.customdatafree = FALSE;
+ wm_event_add(win, &event);
+
+ return block;
+}
+
+
+static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ uiPupBlock(C, node_find_menu, op);
+ return OPERATOR_CANCELLED;
+}
+
+
+void NODE_OT_find_node(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Find Node";
+ ot->description = "Search for named node and allow to select and activate it";
+ ot->idname = "NODE_OT_find_node";
+
+ /* api callbacks */
+ ot->invoke = node_find_node_invoke;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "prev", 0, "Previous", "");
+
+}
+
+
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 418d4ff04a4..d22ea674668 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -754,7 +754,7 @@ static void operator_search_cb(const struct bContext *UNUSED(C), void *UNUSED(ar
/* display name for menu */
WM_operator_py_idname(name, ot->idname);
- if (0 == uiSearchItemAdd(items, name, ot, 0))
+ if (false == uiSearchItemAdd(items, name, ot, 0))
break;
}
}
@@ -1043,8 +1043,9 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa
uiButSetRenameFunc(bt, namebutton_cb, tselem);
/* returns false if button got removed */
- if (0 == uiButActiveOnly(C, ar, block, bt) )
+ if (false == uiButActiveOnly(C, ar, block, bt)) {
tselem->flag &= ~TSE_TEXTBUT;
+ }
}
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 1e67e099508..0a1d3a63f2c 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -113,6 +113,37 @@ static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *te
}
#endif
+static TreeElement *outliner_dropzone_element(const SpaceOops *soops, TreeElement *te, const float fmval[2], const int children)
+{
+ if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
+ /* name and first icon */
+ if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend))
+ return te;
+ }
+ /* Not it. Let's look at its children. */
+ if (children && (TREESTORE(te)->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
+ for (te = te->subtree.first; te; te = te->next) {
+ TreeElement *te_valid = outliner_dropzone_element(soops, te, fmval, children);
+ if (te_valid)
+ return te_valid;
+ }
+ }
+ return NULL;
+}
+
+/* Used for drag and drop parenting */
+TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const int children)
+{
+ TreeElement *te;
+
+ for (te = soops->tree.first; te; te = te->next) {
+ TreeElement *te_valid = outliner_dropzone_element(soops, te, fmval, children);
+ if (te_valid)
+ return te_valid;
+ }
+ return NULL;
+}
+
/* ************************************************************** */
/* Click Activated */
@@ -1447,36 +1478,6 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* Used for drag and drop parenting */
-TreeElement *outliner_dropzone_parent(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2])
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeStoreElem *tselem = TREESTORE(te);
-
- if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
- /* name and first icon */
- if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) {
- /* always makes active object */
- if (te->idcode == ID_OB && tselem->type == 0) {
- return te;
- }
- else {
- return NULL;
- }
- }
- }
-
- /* Not it. Let's look at its children. */
- if ((tselem->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
- for (te = te->subtree.first; te; te = te->next) {
- TreeElement *te_valid;
- te_valid = outliner_dropzone_parent(C, event, te, fmval);
- if (te_valid) return te_valid;
- }
- }
- return NULL;
-}
-
static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *par = NULL;
@@ -1486,7 +1487,6 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Main *bmain = CTX_data_main(C);
Scene *scene = NULL;
TreeElement *te = NULL;
- TreeElement *te_found = NULL;
char childname[MAX_ID_NAME];
char parname[MAX_ID_NAME];
int partype = 0;
@@ -1495,13 +1495,10 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- for (te = soops->tree.first; te; te = te->next) {
- te_found = outliner_dropzone_parent(C, event, te, fmval);
- if (te_found) break;
- }
+ te = outliner_dropzone_find(soops, fmval, 1);
- if (te_found) {
- RNA_string_set(op->ptr, "parent", te_found->name);
+ if (te) {
+ RNA_string_set(op->ptr, "parent", te->name);
/* Identify parent and child */
RNA_string_get(op->ptr, "child", childname);
ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
@@ -1516,7 +1513,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- scene = (Scene *)outliner_search_back(soops, te_found, ID_SCE);
+ scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (scene == NULL) {
/* currently outlier organized in a way, that if there's no parent scene
@@ -1651,44 +1648,6 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
}
-int outliner_dropzone_parent_clear(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2])
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeStoreElem *tselem = TREESTORE(te);
-
- /* Check for row */
- if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
- /* Ignore drop on scene tree elements */
- if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) {
- if ((te->idcode == ID_SCE) &&
- !ELEM3(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS))
- {
- return 0;
- }
- // Other codes to ignore?
- }
-
- /* Left or right of: (+), first icon, and name */
- if ((fmval[0] < (te->xs + UI_UNIT_X)) || (fmval[0] > te->xend)) {
- return 1;
- }
- else if (te->idcode != ID_OB || ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE)) {
- return 1;
- }
-
- return 0; // ID_OB, but mouse in undefined dropzone.
- }
-
- /* Not this row. Let's look at its children. */
- if ((tselem->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
- for (te = te->subtree.first; te; te = te->next) {
- if (outliner_dropzone_parent_clear(C, event, te, fmval))
- return 1;
- }
- }
- return 0;
-}
-
static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Main *bmain = CTX_data_main(C);
@@ -1738,22 +1697,6 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
}
-TreeElement *outliner_dropzone_scene(bContext *C, const wmEvent *UNUSED(event), TreeElement *te, const float fmval[2])
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeStoreElem *tselem = TREESTORE(te);
-
- if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
- /* name and first icon */
- if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) {
- if (te->idcode == ID_SCE && tselem->type == 0) {
- return te;
- }
- }
- }
- return NULL;
-}
-
static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = NULL;
@@ -1762,24 +1705,19 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ARegion *ar = CTX_wm_region(C);
Main *bmain = CTX_data_main(C);
TreeElement *te = NULL;
- TreeElement *te_found = NULL;
char obname[MAX_ID_NAME];
float fmval[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- for (te = soops->tree.first; te; te = te->next) {
- te_found = outliner_dropzone_scene(C, event, te, fmval);
- if (te_found)
- break;
- }
+ te = outliner_dropzone_find(soops, fmval, 0);
- if (te_found) {
+ if (te) {
Base *base;
- RNA_string_set(op->ptr, "scene", te_found->name);
- scene = (Scene *)BKE_libblock_find_name(ID_SCE, te_found->name);
+ RNA_string_set(op->ptr, "scene", te->name);
+ scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name);
RNA_string_get(op->ptr, "object", obname);
ob = (Object *)BKE_libblock_find_name(ID_OB, obname);
@@ -1837,22 +1775,17 @@ static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *even
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
TreeElement *te = NULL;
- TreeElement *te_found = NULL;
char mat_name[MAX_ID_NAME - 2];
float fmval[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- for (te = soops->tree.first; te; te = te->next) {
- te_found = outliner_dropzone_parent(C, event, te, fmval);
- if (te_found)
- break;
- }
+ te = outliner_dropzone_find(soops, fmval, 1);
- if (te_found) {
- RNA_string_set(op->ptr, "object", te_found->name);
- ob = (Object *)BKE_libblock_find_name(ID_OB, te_found->name);
+ if (te) {
+ RNA_string_set(op->ptr, "object", te->name);
+ ob = (Object *)BKE_libblock_find_name(ID_OB, te->name);
RNA_string_get(op->ptr, "material", mat_name);
ma = (Material *)BKE_libblock_find_name(ID_MA, mat_name);
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index a918357ced2..3ab412f0ddc 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -190,9 +190,7 @@ void group_toggle_renderability_cb(struct bContext *C, struct Scene *scene, Tree
void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem);
-TreeElement *outliner_dropzone_parent(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
-int outliner_dropzone_parent_clear(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
-TreeElement *outliner_dropzone_scene(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
+TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const int children);
/* ...................................................... */
void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 3849aaf78c1..76a3da23d57 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -94,7 +94,6 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeElement *te = NULL;
float fmval[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
@@ -102,25 +101,25 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
ID *id = (ID *)drag->poin;
if (GS(id->name) == ID_OB) {
/* Ensure item under cursor is valid drop target */
- /* Find object hovered over */
- for (te = soops->tree.first; te; te = te->next) {
- TreeElement *te_valid;
- te_valid = outliner_dropzone_parent(C, event, te, fmval);
- if (te_valid) {
- /* check that parent/child are both in the same scene */
- Scene *scene = (Scene *)outliner_search_back(soops, te_valid, ID_SCE);
-
- if (!scene) {
- /* currently outlier organized in a way, that if there's no parent scene
- * element for object it means that all displayed objects belong to
- * active scene and parenting them is allowed (sergey)
- */
- return 1;
- }
+ TreeElement *te = outliner_dropzone_find(soops, fmval, 1);
- if (scene && BKE_scene_base_find(scene, (Object *)id)) {
- return 1;
- }
+ if (te && te->idcode == ID_OB && TREESTORE(te)->type == 0) {
+ Scene *scene;
+ ID *te_id = TREESTORE(te)->id;
+
+ /* check if dropping self or parent */
+ if (te_id == id || (Object *)te_id == ((Object *)id)->parent)
+ return 0;
+
+ /* check that parent/child are both in the same scene */
+ scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
+
+ /* currently outliner organized in a way that if there's no parent scene
+ * element for object it means that all displayed objects belong to
+ * active scene and parenting them is allowed (sergey)
+ */
+ if (!scene || BKE_scene_base_find(scene, (Object *)id)) {
+ return 1;
}
}
}
@@ -147,19 +146,20 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
if (drag->type == WM_DRAG_ID) {
ID *id = (ID *)drag->poin;
if (GS(id->name) == ID_OB) {
- if (((Object *)id)->parent == NULL) {
- return 0;
- }
- /* Ensure location under cursor is valid dropzone */
- for (te = soops->tree.first; te; te = te->next) {
- if (outliner_dropzone_parent_clear(C, event, te, fmval)) return 1;
- }
- /* Check if mouse cursor is below the tree */
- te = soops->tree.last;
- while (((te->flag & TE_LAZY_CLOSED) == 0) && (te->subtree.last)) {
- te = te->subtree.last;
+ if (((Object *)id)->parent) {
+ if ((te = outliner_dropzone_find(soops, fmval, 1))) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ switch (te->idcode) {
+ case ID_SCE:
+ return (ELEM3(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS));
+ case ID_OB:
+ return (ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE));
+ /* Other codes to ignore? */
+ }
+ }
+ return (te == NULL);
}
- if (fmval[1] < te->ys) return 1;
}
}
return 0;
@@ -180,7 +180,6 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeElement *te = NULL;
float fmval[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
@@ -188,11 +187,8 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
ID *id = (ID *)drag->poin;
if (GS(id->name) == ID_OB) {
/* Ensure item under cursor is valid drop target */
- /* Find object hovered over */
- for (te = soops->tree.first; te; te = te->next) {
- if (outliner_dropzone_scene(C, event, te, fmval))
- return 1;
- }
+ TreeElement *te = outliner_dropzone_find(soops, fmval, 0);
+ return (te && te->idcode == ID_SCE && TREESTORE(te)->type == 0);
}
}
return 0;
@@ -209,7 +205,6 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeElement *te = NULL;
float fmval[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
@@ -217,11 +212,8 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
ID *id = (ID *)drag->poin;
if (GS(id->name) == ID_MA) {
/* Ensure item under cursor is valid drop target */
- /* Find object hovered over */
- for (te = soops->tree.first; te; te = te->next) {
- if (outliner_dropzone_parent(C, event, te, fmval))
- return 1;
- }
+ TreeElement *te = outliner_dropzone_find(soops, fmval, 1);
+ return (te && te->idcode == ID_OB && TREESTORE(te)->type == 0);
}
}
return 0;
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 3c2c715efc2..141af5d5ba4 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -896,11 +896,9 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop
{
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
ImBuf *scope;
-
- if (display_ibuf->rect_float) {
- IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
+
+ IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
&scene->display_settings);
- }
scope = make_scope_cb(display_ibuf);
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 32a6c49da89..a0212bd17fa 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -54,7 +54,8 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, int draw_overlay);
-void seq_reset_imageofs(struct SpaceSeq *sseq);
+/* UNUSED */
+// void seq_reset_imageofs(struct SpaceSeq *sseq);
struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs);
@@ -69,7 +70,8 @@ int seq_effect_find_selected(struct Scene *scene, struct Sequence *activeseq, in
/* operator helpers */
int sequencer_edit_poll(struct bContext *C);
-int sequencer_strip_poll(struct bContext *C);
+/* UNUSED */
+//int sequencer_strip_poll(struct bContext *C);
int sequencer_strip_has_path_poll(struct bContext *C);
int sequencer_view_poll(struct bContext *C);
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index c8b70c0ce4a..79b50f2d3ae 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -531,7 +531,7 @@ BLI_INLINE int get_bin_float(float f)
static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
- int n, c, x, y;
+ int nr, ng, nb, x, y;
float *src = ibuf->rect_float;
unsigned int bins[3][HIS_STEPS];
@@ -563,23 +563,30 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
}
}
- draw_histogram_marker(rval, get_bin_float(0.0));
- draw_histogram_marker(rval, get_bin_float(1.0));
-
- n = 0;
- for (c = 0; c < 3; c++) {
- for (x = 0; x < HIS_STEPS; x++) {
- if (bins[c][x] > n) {
- n = bins[c][x];
- }
- }
+ nr = nb = ng = 0;
+ for (x = 0; x < HIS_STEPS; x++) {
+ if (bins[0][x] > nr)
+ nr = bins[0][x];
+ if (bins[1][x] > ng)
+ ng = bins[1][x];
+ if (bins[2][x] > nb)
+ nb = bins[2][x];
}
- for (c = 0; c < 3; c++) {
- for (x = 0; x < HIS_STEPS; x++) {
- draw_histogram_bar(rval, x + 1, (float) bins[c][x] / n, c);
+
+ for (x = 0; x < HIS_STEPS; x++) {
+ if (nr) {
+ draw_histogram_bar(rval, x + 1, ((float) bins[0][x]) / nr, 0);
+ }
+ if (ng) {
+ draw_histogram_bar(rval, x + 1, ((float) bins[1][x]) / ng, 1);
+ }
+ if (nb) {
+ draw_histogram_bar(rval, x + 1, ((float) bins[2][x]) / nb, 2);
}
}
-
+
+ draw_histogram_marker(rval, get_bin_float(0.0));
+ draw_histogram_marker(rval, get_bin_float(1.0));
wform_put_border((unsigned char *) rval->rect, rval->x, rval->y);
return rval;
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index ffe89407715..c933bbff0b3 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -330,6 +330,7 @@ static void sequencer_listener(ScrArea *sa, wmNotifier *wmn)
break;
}
break;
+ case NC_WINDOW:
case NC_SPACE:
if (wmn->data == ND_SPACE_SEQUENCER)
sequencer_scopes_tag_refresh(sa);
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index cb685b59b64..2ff52b51069 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -1573,8 +1573,8 @@ static void draw_pose_dofs(Object *ob)
for (i = 0; i < 3; i++) {
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
- amin[i] = (float)sin(pchan->limitmin[i] * 0.5f);
- amax[i] = (float)sin(pchan->limitmax[i] * 0.5f);
+ amin[i] = sinf(pchan->limitmin[i] * 0.5f);
+ amax[i] = sinf(pchan->limitmax[i] * 0.5f);
}
glScalef(1.0f, -1.0f, 1.0f);
@@ -1605,8 +1605,8 @@ static void draw_pose_dofs(Object *ob)
phi = fac * (pchan->limitmax[2] - pchan->limitmin[2]);
i = (a == -16) ? 0 : 1;
- corner[i][0] = (float)sin(phi);
- corner[i][1] = (float)cos(phi);
+ corner[i][0] = sinf(phi);
+ corner[i][1] = cosf(phi);
corner[i][2] = 0.0f;
glVertex3fv(corner[i]);
}
@@ -1629,8 +1629,8 @@ static void draw_pose_dofs(Object *ob)
i = (a == -16) ? 2 : 3;
corner[i][0] = 0.0f;
- corner[i][1] = (float)sin(phi);
- corner[i][2] = (float)cos(phi);
+ corner[i][1] = sinf(phi);
+ corner[i][2] = cosf(phi);
glVertex3fv(corner[i]);
}
glEnd();
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 265fef0f59b..cd68fbf126e 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -622,7 +622,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
glColor4fv(ob->col);
/* Draw the Image on the screen */
- glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
+ glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
glDisable(GL_BLEND);
@@ -6452,6 +6452,14 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag);
return;
}
+
+ /* allow transp option for empty images */
+ if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
+ if (!v3d->xray && !v3d->transp && !(ob->dtx & OB_DRAWXRAY) && (ob->dtx & OB_DRAWTRANSP)) {
+ ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
+ return;
+ }
+ }
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index b6d46f82e6a..d0437c77af7 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1831,7 +1831,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
* glaDrawPixelsSafe in some cases, which will end up in misssing
* alpha transparency for the background image (sergey)
*/
- glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
+ glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
glPixelZoom(1.0, 1.0);
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 9dbdd8a9789..3767f3011ff 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -365,7 +365,8 @@ typedef struct ViewOpsData {
float viewquat[4]; /* working copy of rv3d->viewquat */
float trackvec[3];
float mousevec[3]; /* dolly only */
- float reverse, dist0, camzoom0;
+ float reverse;
+ float dist_prev, camzoom_prev;
float grid, far;
bool axis_snap; /* view rotate only */
float zfac;
@@ -425,8 +426,8 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even
* we may want to make this optional but for now its needed always */
ED_view3d_camera_lock_init(vod->v3d, vod->rv3d);
- vod->dist0 = rv3d->dist;
- vod->camzoom0 = rv3d->camzoom;
+ vod->dist_prev = rv3d->dist;
+ vod->camzoom_prev = rv3d->camzoom;
copy_qt_qt(vod->viewquat, rv3d->viewquat);
copy_qt_qt(vod->oldquat, rv3d->viewquat);
vod->origx = vod->oldx = event->x;
@@ -439,7 +440,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even
Scene *scene = CTX_data_scene(C);
Object *ob = OBACT;
- if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ if (ob && (ob->mode & OB_MODE_ALL_PAINT) && (BKE_object_pose_armature_get(ob) == NULL)) {
/* transformation is disabled for painting modes, which will make it
* so previous offset is used. This is annoying when you open file
* saved with active object in painting mode
@@ -484,7 +485,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even
/* find a new ofs value that is along the view axis (rather than the mouse location) */
closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin);
- vod->dist0 = rv3d->dist = len_v3v3(my_pivot, dvec);
+ vod->dist_prev = rv3d->dist = len_v3v3(my_pivot, dvec);
negate_v3_v3(rv3d->ofs, dvec);
}
@@ -1711,7 +1712,7 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho
if (use_cam_zoom) {
float delta;
delta = (x - vod->origx + y - vod->origy) / 10.0f;
- vod->rv3d->camzoom = vod->camzoom0 + (zoom_invert ? -delta : delta);
+ vod->rv3d->camzoom = vod->camzoom_prev + (zoom_invert ? -delta : delta);
CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
}
@@ -1746,7 +1747,7 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho
len1 = (int)sqrt((ctr[0] - x) * (ctr[0] - x) + (ctr[1] - y) * (ctr[1] - y)) + 5;
len2 = (int)sqrt((ctr[0] - vod->origx) * (ctr[0] - vod->origx) + (ctr[1] - vod->origy) * (ctr[1] - vod->origy)) + 5;
- zfac = vod->dist0 * ((float)len2 / len1) / vod->rv3d->dist;
+ zfac = vod->dist_prev * ((float)len2 / len1) / vod->rv3d->dist;
}
else { /* USER_ZOOM_DOLLY */
float len1, len2;
@@ -1766,11 +1767,11 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho
if (use_cam_zoom) {
/* zfac is ignored in this case, see below */
#if 0
- zfac = vod->camzoom0 * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom;
+ zfac = vod->camzoom_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom;
#endif
}
else {
- zfac = vod->dist0 * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist;
+ zfac = vod->dist_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index ef8c2b5eff6..ad3f941bd17 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -59,43 +59,53 @@
/* Snapping (could be own function) */
/* NOTE - this is not very nice use of transform snapping */
#include "ED_transform.h"
-#include "../transform/transform.h"
-static bool ED_view3d_snap_co(bContext *C, float r_co[3], const float co_ss[2],
+static bool ED_view3d_snap_co(bContext *C, float r_co[3], const float co_ss[2], float r_no[3],
bool use_vert, bool use_edge, bool use_face)
{
- TransInfo t = {0};
- int dist = 12; /* snap dist */
+ float dist_px = 12; /* snap dist */
float r_no_dummy[3];
bool ret = false;
- char backup_snap_mode;
- Base *backup_baseact;
+ float *r_no_ptr = r_no ? r_no : r_no_dummy;
- t.scene = CTX_data_scene(C);
- t.view = CTX_wm_view3d(C);
- t.ar = CTX_wm_region(C);
- t.obedit = CTX_data_edit_object(C);
-
- backup_snap_mode = t.scene->toolsettings->snap_mode;
- backup_baseact = t.scene->basact;
- t.scene->basact = NULL;
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ struct Object *obedit = CTX_data_edit_object(C);
/* try snap edge, then face if it fails */
if (use_vert) {
- t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_VERTEX;
- ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ ret = snapObjectsEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_VERTEX,
+ co_ss, &dist_px, r_co, r_no_ptr, SNAP_ALL);
}
if (use_edge && (ret == false)) {
- t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_EDGE;
- ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ ret = snapObjectsEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_EDGE,
+ co_ss, &dist_px, r_co, r_no_ptr, SNAP_ALL);
}
if (use_face && (ret == false)) {
- t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_FACE;
- ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ ret = snapObjectsEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_FACE,
+ co_ss, &dist_px, r_co, r_no_ptr, SNAP_ALL);
}
- t.scene->toolsettings->snap_mode = backup_snap_mode;
- t.scene->basact = backup_baseact;
+ return ret;
+}
+
+static bool ED_view3d_snap_ray(bContext *C, float r_co[3],
+ const float ray_start[3], const float ray_normal[3])
+{
+ float dist_px = 12; /* snap dist */
+ float r_no_dummy[3];
+ bool ret = false;
+
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ struct Object *obedit = CTX_data_edit_object(C);
+
+ /* try snap edge, then face if it fails */
+ ret = snapObjectsRayEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_FACE,
+ ray_start, ray_normal,
+ NULL, &dist_px, r_co, r_no_dummy, SNAP_ALL);
return ret;
}
@@ -657,16 +667,36 @@ static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3],
}
/* use for mousemove events */
-static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, const int mval[2], const bool do_snap)
+static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, const int mval[2],
+ const bool do_thickness, const bool do_snap)
{
RulerItem *ruler_item = ruler_item_active_get(ruler_info);
if (ruler_item) {
float *co = ruler_item->co[ruler_item->co_index];
view3d_ruler_item_project(ruler_info, co, mval);
- if (do_snap) {
+ if (do_thickness && ruler_item->co_index != 1) {
+ const float mval_fl[2] = {UNPACK2(mval)};
+ float ray_normal[3];
+ float ray_start[3];
+ float *co_other;
+
+ co_other = ruler_item->co[ruler_item->co_index == 0 ? 2 : 0];
+
+ if (ED_view3d_snap_co(C, co, mval_fl, ray_normal,
+ false, false, true))
+ {
+ negate_v3(ray_normal);
+ /* add some bias */
+ madd_v3_v3v3fl(ray_start, co, ray_normal, 0.0001f);
+ ED_view3d_snap_ray(C, co_other,
+ ray_start, ray_normal);
+ }
+ }
+ else if (do_snap) {
const float mval_fl[2] = {UNPACK2(mval)};
- ED_view3d_snap_co(C, co, mval_fl, true, true, true);
+ ED_view3d_snap_co(C, co, mval_fl, NULL,
+ true, true, true);
}
return true;
}
@@ -680,6 +710,7 @@ static void view3d_ruler_header_update(ScrArea *sa)
const char *text = "Ctrl+LMB: Add, "
"Del: Remove, "
"Ctrl+Drag: Snap, "
+ "Shift+Drag: Thickness, "
"Ctrl+C: Copy Value, "
"Enter: Store, "
"Esc: Cancel";
@@ -774,7 +805,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* snap the first point added, not essential but handy */
{
ruler_item->co_index = 0;
- view3d_ruler_item_mousemove(C, ruler_info, event->mval, true);
+ view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->shift != 0, true);
}
copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
@@ -814,7 +845,8 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* update the new location */
- view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0);
+ view3d_ruler_item_mousemove(C, ruler_info, event->mval,
+ event->shift != 0, event->ctrl != 0);
do_draw = true;
}
}
@@ -857,7 +889,9 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE:
{
if (ruler_info->state == RULER_STATE_DRAG) {
- if (view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0)) {
+ if (view3d_ruler_item_mousemove(C, ruler_info, event->mval,
+ event->shift != 0, event->ctrl != 0))
+ {
do_draw = true;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index 603d9a1595c..d30c1699d65 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -162,7 +162,7 @@ static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), cons
if (BLI_strcasestr(ot->name, str)) {
if (WM_operator_poll((bContext *)C, ot)) {
- if (0 == uiSearchItemAdd(items, ot->name, ot, 0))
+ if (false == uiSearchItemAdd(items, ot->name, ot, 0))
break;
}
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 64e49abd761..be296025624 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -112,6 +112,7 @@ static bool transdata_check_local_center(TransInfo *t)
return ((t->around == V3D_LOCAL) && (
(t->flag & (T_OBJECT | T_POSE)) ||
(t->obedit && t->obedit->type == OB_MESH && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) ||
+ (t->obedit && t->obedit->type == OB_MBALL) ||
(t->obedit && t->obedit->type == OB_ARMATURE) ||
(t->spacetype == SPACE_IPO))
);
@@ -2757,8 +2758,8 @@ int Warp(TransInfo *t, const int UNUSED(mval[2]))
vec[1] = (vec[1] - cursor[1]);
- co = (float)cos(phi0);
- si = (float)sin(phi0);
+ co = cosf(phi0);
+ si = sinf(phi0);
loc[0] = -si * vec[1] + cursor[0];
loc[1] = co * vec[1] + cursor[1];
loc[2] = vec[2];
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index a551ef5008e..1f08bfda6a6 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -72,7 +72,7 @@ typedef struct TransSnap {
short target;
short modePoint;
short modeSelect;
- short align;
+ bool align;
char project;
char snap_self;
short peel;
@@ -593,7 +593,7 @@ void flushTransGraphData(TransInfo *t);
void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data);
void flushTransUVs(TransInfo *t);
void flushTransParticles(TransInfo *t);
-int clipUVTransform(TransInfo *t, float *vec, int resize);
+bool clipUVTransform(TransInfo *t, float vec[2], const bool resize);
void clipUVData(TransInfo *t);
void flushTransNodes(TransInfo *t);
void flushTransSeq(TransInfo *t);
@@ -628,8 +628,8 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char tex
void constraintNumInput(TransInfo *t, float vec[3]);
-int isLockConstraint(TransInfo *t);
-int getConstraintSpaceDimension(TransInfo *t);
+bool isLockConstraint(TransInfo *t);
+int getConstraintSpaceDimension(TransInfo *t);
char constraintModeToChar(TransInfo *t);
void startConstraint(TransInfo *t);
@@ -652,21 +652,21 @@ typedef enum {
void snapGrid(TransInfo *t, float *val);
void snapGridAction(TransInfo *t, float *val, GearsType action);
-int activeSnap(TransInfo *t);
-int validSnap(TransInfo *t);
+bool activeSnap(TransInfo *t);
+bool validSnap(TransInfo *t);
void initSnapping(struct TransInfo *t, struct wmOperator *op);
void applyProject(TransInfo *t);
void applySnapping(TransInfo *t, float *vec);
void resetSnapping(TransInfo *t);
-int handleSnapping(TransInfo *t, const struct wmEvent *event);
+bool handleSnapping(TransInfo *t, const struct wmEvent *event);
void drawSnapping(const struct bContext *C, TransInfo *t);
-int usingSnappingNormal(TransInfo *t);
-int validSnappingNormal(TransInfo *t);
+bool usingSnappingNormal(TransInfo *t);
+bool validSnappingNormal(TransInfo *t);
void getSnapPoint(TransInfo *t, float vec[3]);
void addSnapPoint(TransInfo *t);
-int updateSelectedSnapPoint(TransInfo *t);
+bool updateSelectedSnapPoint(TransInfo *t);
void removeSnapPoint(TransInfo *t);
/********************** Mouse Input ******************************/
@@ -729,8 +729,8 @@ struct TransformOrientation *createMeshSpace(struct bContext *C, struct ReportLi
struct TransformOrientation *createBoneSpace(struct bContext *C, struct ReportList *reports, char *name, int overwrite);
/* Those two fill in mat and return non-zero on success */
-int createSpaceNormal(float mat[3][3], float normal[3]);
-int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]);
+bool createSpaceNormal(float mat[3][3], const float normal[3]);
+bool createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]);
struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], char name[], int overwrite);
void applyTransformOrientation(const struct bContext *C, float mat[3][3], char *name);
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index f3026205ea2..7678051fd38 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -557,13 +557,17 @@ void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[])
void setLocalConstraint(TransInfo *t, int mode, const char text[])
{
+ /* edit-mode now allows local transforms too */
+#if 0
if (t->flag & T_EDIT) {
float obmat[3][3];
copy_m3_m4(obmat, t->scene->obedit->obmat);
normalize_m3(obmat);
setConstraint(t, obmat, mode, text);
}
- else {
+ else
+#endif
+ {
if (t->total == 1) {
setConstraint(t, t->data->axismtx, mode, text);
}
@@ -743,37 +747,42 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
static void drawObjectConstraint(TransInfo *t)
{
- int i;
- TransData *td = t->data;
-
/* Draw the first one lighter because that's the one who controls the others.
* Meaning the transformation is projected on that one and just copied on the others
* constraint space.
* In a nutshell, the object with light axis is controlled by the user and the others follow.
* Without drawing the first light, users have little clue what they are doing.
*/
- if (t->con.mode & CON_AXIS0) {
- drawLine(t, td->ob->obmat[3], td->axismtx[0], 'X', DRAWLIGHT);
- }
- if (t->con.mode & CON_AXIS1) {
- drawLine(t, td->ob->obmat[3], td->axismtx[1], 'Y', DRAWLIGHT);
- }
- if (t->con.mode & CON_AXIS2) {
- drawLine(t, td->ob->obmat[3], td->axismtx[2], 'Z', DRAWLIGHT);
- }
+ short options = DRAWLIGHT;
+ TransData *td = t->data;
+ int i;
- td++;
+ for (i = 0; i < t->total; i++, td++) {
+ float co[3];
+
+ if (t->flag & T_OBJECT) {
+ copy_v3_v3(co, td->ob->obmat[3]);
+ }
+ else if (t->flag & T_EDIT) {
+ mul_v3_m4v3(co, t->obedit->obmat, td->center);
+ }
+ else if (t->flag & T_POSE) {
+ mul_v3_m4v3(co, t->poseobj->obmat, td->center);
+ }
+ else {
+ copy_v3_v3(co, td->center);
+ }
- for (i = 1; i < t->total; i++, td++) {
if (t->con.mode & CON_AXIS0) {
- drawLine(t, td->ob->obmat[3], td->axismtx[0], 'X', 0);
+ drawLine(t, td->center, td->axismtx[0], 'X', options);
}
if (t->con.mode & CON_AXIS1) {
- drawLine(t, td->ob->obmat[3], td->axismtx[1], 'Y', 0);
+ drawLine(t, td->center, td->axismtx[1], 'Y', options);
}
if (t->con.mode & CON_AXIS2) {
- drawLine(t, td->ob->obmat[3], td->axismtx[2], 'Z', 0);
+ drawLine(t, td->center, td->axismtx[2], 'Z', options);
}
+ options &= ~DRAWLIGHT;
}
}
@@ -992,20 +1001,20 @@ char constraintModeToChar(TransInfo *t)
}
-int isLockConstraint(TransInfo *t)
+bool isLockConstraint(TransInfo *t)
{
int mode = t->con.mode;
if ((mode & (CON_AXIS0 | CON_AXIS1)) == (CON_AXIS0 | CON_AXIS1))
- return 1;
+ return true;
if ((mode & (CON_AXIS1 | CON_AXIS2)) == (CON_AXIS1 | CON_AXIS2))
- return 1;
+ return true;
if ((mode & (CON_AXIS0 | CON_AXIS2)) == (CON_AXIS0 | CON_AXIS2))
- return 1;
+ return true;
- return 0;
+ return false;
}
/*
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index f84c967711c..661d7055036 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -125,7 +125,7 @@
/* local function prototype - for Object/Bone Constraints */
-static short constraints_list_needinv(TransInfo *t, ListBase *list);
+static bool constraints_list_needinv(TransInfo *t, ListBase *list);
/* ************************** Functions *************************** */
@@ -1236,6 +1236,8 @@ static void createTransMBallVerts(TransInfo *t)
copy_v3_v3(td->iloc, td->loc);
copy_v3_v3(td->center, td->loc);
+ quat_to_mat3(td->axismtx, ml->quat);
+
if (ml->flag & SELECT) td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
else td->flag = TD_USEQUAT;
@@ -1858,32 +1860,29 @@ static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[3][3],
MEM_freeN(tots);
}
-/* loop-in-a-loop I know, but we need it! (ton) */
-static void get_face_center(float r_cent[3], BMVert *eve)
-
+static BMElem *bm_vert_single_select_face(BMVert *eve)
{
- BMFace *efa;
+ BMElem *ele;
BMIter iter;
- BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_calc_center_mean(efa, r_cent);
- break;
+ BM_ITER_ELEM (ele, &iter, eve, BM_FACES_OF_VERT) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ return ele;
}
}
+ return NULL;
}
-
-static void get_edge_center(float r_cent[3], BMVert *eve)
+static BMElem *bm_vert_single_select_edge(BMVert *eve)
{
- BMEdge *eed;
+ BMElem *ele;
BMIter iter;
- BM_ITER_ELEM (eed, &iter, eve, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- mid_v3_v3v3(r_cent, eed->v1->co, eed->v2->co);
- break;
+ BM_ITER_ELEM (ele, &iter, eve, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ return ele;
}
}
+ return NULL;
}
/* way to overwrite what data is edited with transform */
@@ -1895,25 +1894,51 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
// td->loc = key->co;
//else
td->loc = eve->co;
-
+ copy_v3_v3(td->iloc, td->loc);
copy_v3_v3(td->center, td->loc);
if (t->around == V3D_LOCAL) {
- if (em->selectmode & SCE_SELECT_FACE)
- get_face_center(td->center, eve);
- else if (em->selectmode & SCE_SELECT_EDGE)
- get_edge_center(td->center, eve);
+ BMElem *ele;
+ bool is_axismat_set = false;
+
+ if (em->selectmode & (SCE_SELECT_FACE | SCE_SELECT_EDGE) &&
+ (ele = ((em->selectmode & SCE_SELECT_FACE) ?
+ bm_vert_single_select_face(eve) :
+ bm_vert_single_select_edge(eve))))
+ {
+ float normal[3], tangent[3];
+
+ BMEditSelection ese;
+ ese.next = ese.prev = NULL;
+ ese.ele = ele;
+ ese.htype = ele->head.htype;
+
+ BM_editselection_center(&ese, td->center);
+ BM_editselection_normal(&ese, normal);
+ BM_editselection_plane(&ese, tangent);
+
+ if (createSpaceNormalTangent(td->axismtx, normal, tangent)) {
+ is_axismat_set = true;
+ }
+ }
+
+ /* for verts or fallback when createSpaceNormalTangent fails */
+ if (is_axismat_set == false) {
+ axis_dominant_v3_to_m3(td->axismtx, eve->no);
+ invert_m3(td->axismtx);
+ }
+ }
+ else {
+ /* Setting normals */
+ copy_v3_v3(td->axismtx[2], eve->no);
+ td->axismtx[0][0] =
+ td->axismtx[0][1] =
+ td->axismtx[0][2] =
+ td->axismtx[1][0] =
+ td->axismtx[1][1] =
+ td->axismtx[1][2] = 0.0f;
}
- copy_v3_v3(td->iloc, td->loc);
- // Setting normals
- copy_v3_v3(td->axismtx[2], eve->no);
- td->axismtx[0][0] =
- td->axismtx[0][1] =
- td->axismtx[0][2] =
- td->axismtx[1][0] =
- td->axismtx[1][1] =
- td->axismtx[1][2] = 0.0f;
td->ext = NULL;
td->val = NULL;
@@ -2503,7 +2528,7 @@ void flushTransUVs(TransInfo *t)
}
}
-int clipUVTransform(TransInfo *t, float *vec, int resize)
+bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
{
TransData *td;
int a, clipx = 1, clipy = 1;
@@ -2574,16 +2599,16 @@ void clipUVData(TransInfo *t)
/* ********************* ANIMATION EDITORS (GENERAL) ************************* */
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
-static short FrameOnMouseSide(char side, float frame, float cframe)
+static bool FrameOnMouseSide(char side, float frame, float cframe)
{
/* both sides, so it doesn't matter */
- if (side == 'B') return 1;
+ if (side == 'B') return true;
/* only on the named side */
if (side == 'R')
- return (frame >= cframe) ? 1 : 0;
+ return (frame >= cframe);
else
- return (frame <= cframe) ? 1 : 0;
+ return (frame <= cframe);
}
/* ********************* NLA EDITOR ************************* */
@@ -4523,7 +4548,7 @@ static void createTransSeqData(bContext *C, TransInfo *t)
* These particular constraints benefit from this, but others don't, hence
* this semi-hack ;-) - Aligorith
*/
-static short constraints_list_needinv(TransInfo *t, ListBase *list)
+static bool constraints_list_needinv(TransInfo *t, ListBase *list)
{
bConstraint *con;
@@ -4536,26 +4561,30 @@ static short constraints_list_needinv(TransInfo *t, ListBase *list)
if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
/* (affirmative) returns for specific constraints here... */
/* constraints that require this regardless */
- if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
- if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
- if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
- if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) return 1;
- if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) return 1;
-
+ if (ELEM5(con->type,
+ CONSTRAINT_TYPE_CHILDOF,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_CLAMPTO,
+ CONSTRAINT_TYPE_OBJECTSOLVER,
+ CONSTRAINT_TYPE_FOLLOWTRACK))
+ {
+ return true;
+ }
+
/* constraints that require this only under special conditions */
if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
/* CopyRot constraint only does this when rotating, and offset is on */
bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
- return 1;
+ return true;
}
}
}
}
/* no appropriate candidates found */
- return 0;
+ return false;
}
/* transcribe given object into TransData for Transforming */
@@ -4563,8 +4592,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
{
Scene *scene = t->scene;
float obmtx[3][3];
- short constinv;
- short skip_invert = 0;
+ bool constinv;
+ bool skip_invert = false;
if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
float rot[3][3], scale[3];
@@ -4602,15 +4631,15 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
/* disable constraints inversion for dummy pass */
if (t->mode == TFM_DUMMY)
- skip_invert = 1;
+ skip_invert = true;
- if (skip_invert == 0 && constinv == 0) {
- if (constinv == 0)
+ if (skip_invert == false && constinv == false) {
+ if (constinv == false)
ob->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc_time checks this */
BKE_object_where_is_calc(t->scene, ob);
- if (constinv == 0)
+ if (constinv == false)
ob->transflag &= ~OB_NO_CONSTRAINTS;
}
else
@@ -4762,19 +4791,19 @@ static void set_trans_object_base_flags(TransInfo *t)
}
}
-static int mark_children(Object *ob)
+static bool mark_children(Object *ob)
{
if (ob->flag & (SELECT | BA_TRANSFORM_CHILD))
- return 1;
+ return true;
if (ob->parent) {
if (mark_children(ob->parent)) {
ob->flag |= BA_TRANSFORM_CHILD;
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
static int count_proportional_objects(TransInfo *t)
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 41a3418ada9..889e4f01fc7 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -719,13 +719,13 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i
side_delta = 2.0f * (float)M_PI / (float)nsides;
theta = (float)M_PI + 0.5f * ring_delta;
- cos_theta = (float)cos(theta);
- sin_theta = (float)sin(theta);
+ cos_theta = cosf(theta);
+ sin_theta = sinf(theta);
for (i = nrings - 1; i >= 0; i--) {
theta1 = theta + ring_delta;
- cos_theta1 = (float)cos(theta1);
- sin_theta1 = (float)sin(theta1);
+ cos_theta1 = cosf(theta1);
+ sin_theta1 = sinf(theta1);
if (do_caps && i == start) { // cap
glBegin(GL_POLYGON);
@@ -766,8 +766,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i
float cos_phi, sin_phi, dist;
phi -= side_delta;
- cos_phi = (float)cos(phi);
- sin_phi = (float)sin(phi);
+ cos_phi = cosf(phi);
+ sin_phi = sinf(phi);
dist = radhole + radring * cos_phi;
glVertex3f(cos_theta * dist, -sin_theta * dist, radring * sin_phi);
@@ -841,27 +841,6 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned c
glColor4ubv(col);
}
-static void axis_sort_v3(const float axis_values[3], int r_axis_order[3])
-{
- float v[3];
- copy_v3_v3(v, axis_values);
-
-#define SWAP_AXIS(a, b) { \
- SWAP(float, v[a], v[b]); \
- SWAP(int, r_axis_order[a], r_axis_order[b]); \
-} (void)0
-
- if (v[0] < v[1]) {
- if (v[2] < v[0]) { SWAP_AXIS(0, 2); }
- }
- else {
- if (v[1] < v[2]) { SWAP_AXIS(0, 1); }
- else { SWAP_AXIS(0, 2); }
- }
- if (v[2] < v[1]) { SWAP_AXIS(1, 2); }
-
-#undef SWAP_AXIS
-}
static void manipulator_axis_order(RegionView3D *rv3d, int r_axis_order[3])
{
float axis_values[3];
@@ -1635,15 +1614,18 @@ void BIF_draw_manipulator(const bContext *C)
switch (v3d->around) {
case V3D_CENTER:
case V3D_ACTIVE:
- rv3d->twmat[3][0] = (scene->twmin[0] + scene->twmax[0]) / 2.0f;
- rv3d->twmat[3][1] = (scene->twmin[1] + scene->twmax[1]) / 2.0f;
- rv3d->twmat[3][2] = (scene->twmin[2] + scene->twmax[2]) / 2.0f;
- if (v3d->around == V3D_ACTIVE && scene->obedit == NULL) {
- Object *ob = OBACT;
- if (ob && !(ob->mode & OB_MODE_POSE))
- copy_v3_v3(rv3d->twmat[3], ob->obmat[3]);
+ {
+ Object *ob;
+ if (((v3d->around == V3D_ACTIVE) && (scene->obedit == NULL)) &&
+ ((ob = OBACT) && !(ob->mode & OB_MODE_POSE)))
+ {
+ copy_v3_v3(rv3d->twmat[3], ob->obmat[3]);
+ }
+ else {
+ mid_v3_v3v3(rv3d->twmat[3], scene->twmin, scene->twmax);
}
break;
+ }
case V3D_LOCAL:
case V3D_CENTROID:
copy_v3_v3(rv3d->twmat[3], scene->twcent);
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 0c1f169935a..023083a98ff 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -213,13 +213,13 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na
return addMatrixSpace(C, mat, name, overwrite);
}
-int createSpaceNormal(float mat[3][3], float normal[3])
+bool createSpaceNormal(float mat[3][3], const float normal[3])
{
float tangent[3] = {0.0f, 0.0f, 1.0f};
copy_v3_v3(mat[2], normal);
if (normalize_v3(mat[2]) == 0.0f) {
- return 0; /* error return */
+ return false; /* error return */
}
cross_v3_v3v3(mat[0], mat[2], tangent);
@@ -233,14 +233,14 @@ int createSpaceNormal(float mat[3][3], float normal[3])
normalize_m3(mat);
- return 1;
+ return true;
}
-int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
+bool createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
{
copy_v3_v3(mat[2], normal);
if (normalize_v3(mat[2]) == 0.0f) {
- return 0; /* error return */
+ return false; /* error return */
}
/* preempt zero length tangent from causing trouble */
@@ -250,14 +250,14 @@ int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3])
cross_v3_v3v3(mat[0], mat[2], tangent);
if (normalize_v3(mat[0]) == 0.0f) {
- return 0; /* error return */
+ return false; /* error return */
}
cross_v3_v3v3(mat[1], mat[2], mat[0]);
normalize_m3(mat);
- return 1;
+ return true;
}
TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3], char name[], int overwrite)
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index fdbfdfc8675..c6ab33124ef 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -78,7 +78,11 @@
#include "transform.h"
-#define TRANSFORM_DIST_MAX_PX 1000
+/* this should be passed as an arg for use in snap functions */
+#undef BASACT
+
+#define TRANSFORM_DIST_MAX_PX 1000.0f
+#define TRANSFORM_SNAP_MAX_PX 100.0f
/********************* PROTOTYPES ***********************/
@@ -120,13 +124,13 @@ int BIF_snappingSupported(Object *obedit)
}
#endif
-int validSnap(TransInfo *t)
+bool validSnap(TransInfo *t)
{
return (t->tsnap.status & (POINT_INIT | TARGET_INIT)) == (POINT_INIT | TARGET_INIT) ||
(t->tsnap.status & (MULTI_POINTS | TARGET_INIT)) == (MULTI_POINTS | TARGET_INIT);
}
-int activeSnap(TransInfo *t)
+bool activeSnap(TransInfo *t)
{
return (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP || (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT;
}
@@ -260,9 +264,9 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
}
}
-int handleSnapping(TransInfo *t, const wmEvent *event)
+bool handleSnapping(TransInfo *t, const wmEvent *event)
{
- int status = 0;
+ bool status = false;
#if 0 // XXX need a proper selector for all snap mode
if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) {
@@ -295,8 +299,8 @@ void applyProject(TransInfo *t)
for (i = 0; i < t->total; i++, td++) {
float iloc[3], loc[3], no[3];
- float mval[2];
- int dist = TRANSFORM_DIST_MAX_PX;
+ float mval_fl[2];
+ float dist_px = TRANSFORM_DIST_MAX_PX;
if (td->flag & TD_NOACTION)
break;
@@ -318,8 +322,8 @@ void applyProject(TransInfo *t)
copy_v3_v3(iloc, td->ob->obmat[3]);
}
- if (ED_view3d_project_float_global(t->ar, iloc, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- if (snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect)) {
+ if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (snapObjectsTransform(t, mval_fl, &dist_px, loc, no, t->tsnap.modeSelect)) {
// if (t->flag & (T_EDIT|T_POSE)) {
// mul_m4_v3(imat, loc);
// }
@@ -368,7 +372,7 @@ void applySnapping(TransInfo *t, float *vec)
void resetSnapping(TransInfo *t)
{
t->tsnap.status = 0;
- t->tsnap.align = 0;
+ t->tsnap.align = false;
t->tsnap.project = 0;
t->tsnap.mode = 0;
t->tsnap.modeSelect = 0;
@@ -383,20 +387,20 @@ void resetSnapping(TransInfo *t)
t->tsnap.snapNodeBorder = 0;
}
-int usingSnappingNormal(TransInfo *t)
+bool usingSnappingNormal(TransInfo *t)
{
return t->tsnap.align;
}
-int validSnappingNormal(TransInfo *t)
+bool validSnappingNormal(TransInfo *t)
{
if (validSnap(t)) {
if (dot_v3v3(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
static void initSnappingMode(TransInfo *t)
@@ -404,6 +408,7 @@ static void initSnappingMode(TransInfo *t)
ToolSettings *ts = t->settings;
Object *obedit = t->obedit;
Scene *scene = t->scene;
+ Base *base_act = scene->basact;
if (t->spacetype == SPACE_NODE) {
/* force project off when not supported */
@@ -444,7 +449,7 @@ static void initSnappingMode(TransInfo *t)
}
/* Particles edit mode*/
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (obedit == NULL && BASACT && BASACT->object && BASACT->object->mode & OB_MODE_PARTICLE_EDIT))
+ (obedit == NULL && base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT))
{
t->tsnap.modeSelect = SNAP_ALL;
}
@@ -598,35 +603,32 @@ void addSnapPoint(TransInfo *t)
}
}
-int updateSelectedSnapPoint(TransInfo *t)
+bool updateSelectedSnapPoint(TransInfo *t)
{
- int status = 0;
+ bool status = false;
if (t->tsnap.status & MULTI_POINTS) {
TransSnapPoint *p, *closest_p = NULL;
- int closest_dist = 0;
- int screen_loc[2];
+ float closest_dist = TRANSFORM_SNAP_MAX_PX;
+ const float mval_fl[2] = {t->mval[0], t->mval[1]};
+ float screen_loc[2];
for (p = t->tsnap.points.first; p; p = p->next) {
- int dx, dy;
- int dist;
+ float dist;
- if (ED_view3d_project_int_global(t->ar, p->co, screen_loc, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_global(t->ar, p->co, screen_loc, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
continue;
}
- dx = t->mval[0] - screen_loc[0];
- dy = t->mval[1] - screen_loc[1];
-
- dist = dx * dx + dy * dy;
+ dist = len_squared_v2v2(mval_fl, screen_loc);
- if (dist < 100 && (closest_p == NULL || closest_dist > dist)) {
+ if (dist < closest_dist) {
closest_p = p;
closest_dist = dist;
}
}
if (closest_p) {
- status = t->tsnap.selectedPoint == closest_p ? 0 : 1;
+ status = (t->tsnap.selectedPoint != closest_p);
t->tsnap.selectedPoint = closest_p;
}
}
@@ -819,7 +821,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
float no[3];
float mval[2];
bool found = false;
- int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
+ float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
mval[0] = t->mval[0];
mval[1] = t->mval[1];
@@ -907,7 +909,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
BLI_freelistN(&depth_peels);
}
else {
- found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect);
+ found = snapObjectsTransform(t, mval, &dist_px, loc, no, t->tsnap.modeSelect);
}
if (found == true) {
@@ -949,10 +951,10 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
}
else if (t->spacetype == SPACE_NODE) {
float loc[2];
- int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
+ float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
char node_border;
- if (snapNodesTransform(t, t->mval, &dist, loc, &node_border, t->tsnap.modeSelect)) {
+ if (snapNodesTransform(t, t->mval, &dist_px, loc, &node_border, t->tsnap.modeSelect)) {
copy_v2_v2(t->tsnap.snapPoint, loc);
t->tsnap.snapNodeBorder = node_border;
@@ -1145,8 +1147,8 @@ static void TargetSnapClosest(TransInfo *t)
}
static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3],
- const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2],
- float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
+ const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2],
+ float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
{
float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
int result;
@@ -1182,8 +1184,8 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s
if (dot_v3v3(ray_normal_local, dvec) > 0) {
float location[3];
float new_depth;
- int screen_loc[2];
- int new_dist;
+ float screen_loc[2];
+ float new_dist;
copy_v3_v3(location, intersect);
@@ -1191,8 +1193,8 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s
new_depth = len_v3v3(location, ray_start);
- if (ED_view3d_project_int_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]);
+ if (ED_view3d_project_float_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ new_dist = len_manhattan_v2v2(mval_fl, screen_loc);
}
else {
new_dist = TRANSFORM_DIST_MAX_PX;
@@ -1202,7 +1204,7 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s
* this takes care of series of connected edges a bit slanted w.r.t the viewport
* otherwise, it would stick to the verts of the closest edge and not slide along merrily
* */
- if (new_dist <= *r_dist && new_depth < *r_depth * 1.001f) {
+ if (new_dist <= *r_dist_px && new_depth < *r_depth * 1.001f) {
float n1[3], n2[3];
*r_depth = new_depth;
@@ -1223,7 +1225,7 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s
copy_v3_v3(r_loc, location);
- *r_dist = new_dist;
+ *r_dist_px = new_dist;
}
}
}
@@ -1232,8 +1234,8 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s
}
static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3],
- const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2],
- float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
+ const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2],
+ float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
{
bool retval = false;
float dvec[3];
@@ -1243,8 +1245,8 @@ static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4
if (dot_v3v3(ray_normal_local, dvec) > 0) {
float location[3];
float new_depth;
- int screen_loc[2];
- int new_dist;
+ float screen_loc[2];
+ float new_dist;
copy_v3_v3(location, vco);
@@ -1252,15 +1254,15 @@ static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4
new_depth = len_v3v3(location, ray_start);
- if (ED_view3d_project_int_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]);
+ if (ED_view3d_project_float_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ new_dist = len_manhattan_v2v2(mval_fl, screen_loc);
}
else {
new_dist = TRANSFORM_DIST_MAX_PX;
}
- if (new_dist <= *r_dist && new_depth < *r_depth) {
+ if (new_dist <= *r_dist_px && new_depth < *r_depth) {
*r_depth = new_depth;
retval = true;
@@ -1272,7 +1274,7 @@ static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4
normalize_v3(r_no);
}
- *r_dist = new_dist;
+ *r_dist_px = new_dist;
}
}
@@ -1281,7 +1283,7 @@ static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4
static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth)
+ float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth)
{
float imat[4][4];
float ray_start_local[3], ray_normal_local[3];
@@ -1304,11 +1306,11 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
switch (snap_mode) {
case SCE_SNAP_MODE_VERTEX:
- retval |= snapVertex(ar, eBone->head, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth);
- retval |= snapVertex(ar, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth);
+ retval |= snapVertex(ar, eBone->head, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
break;
case SCE_SNAP_MODE_EDGE:
- retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth);
+ retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
break;
}
}
@@ -1328,11 +1330,11 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
switch (snap_mode) {
case SCE_SNAP_MODE_VERTEX:
- retval |= snapVertex(ar, head_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth);
- retval |= snapVertex(ar, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth);
+ retval |= snapVertex(ar, head_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
break;
case SCE_SNAP_MODE_EDGE:
- retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth);
+ retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
break;
}
}
@@ -1344,7 +1346,7 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
+ float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
{
bool retval = false;
int totvert = dm->getNumVerts(dm);
@@ -1451,7 +1453,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
if (test) {
- retval |= snapVertex(ar, v->co, v->no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist, r_depth);
+ retval |= snapVertex(ar, v->co, v->no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist_px, r_depth);
}
}
@@ -1501,7 +1503,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
}
if (test) {
- retval |= snapEdge(ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist, r_depth);
+ retval |= snapEdge(ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist_px, r_depth);
}
}
@@ -1514,11 +1516,10 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
return retval;
}
-static bool snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[4][4],
+static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, int editobject, float obmat[4][4],
const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
+ float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
{
- ToolSettings *ts = scene->toolsettings;
bool retval = false;
if (ob->type == OB_MESH) {
@@ -1535,31 +1536,29 @@ static bool snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, fl
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
}
- retval = snapDerivedMesh(ts->snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, r_depth);
+ retval = snapDerivedMesh(snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
dm->release(dm);
}
else if (ob->type == OB_ARMATURE) {
- retval = snapArmature(ts->snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, r_depth);
+ retval = snapArmature(snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
}
return retval;
}
-static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2],
- int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
+static bool snapObjectsRay(Scene *scene, short snap_mode, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit,
+ const float ray_start[3], const float ray_normal[3],
+ const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
{
Base *base;
float depth = (FLT_MAX / 2.0f); /* use half of flt-max so we can scale up without an exception */
bool retval = false;
- float ray_start[3], ray_normal[3];
-
- ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal);
if (mode == SNAP_ALL && obedit) {
Object *ob = obedit;
- retval |= snapObject(scene, ar, ob, 1, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth);
+ retval |= snapObject(scene, snap_mode, ar, ob, 1, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, &depth);
}
/* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
@@ -1567,10 +1566,10 @@ static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
*
* To solve that problem, we do it first as an exception.
* */
- base = BASACT;
+ base = base_act;
if (base && base->object && base->object->mode & OB_MODE_PARTICLE_EDIT) {
Object *ob = base->object;
- retval |= snapObject(scene, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth);
+ retval |= snapObject(scene, snap_mode, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, &depth);
}
for (base = FIRSTBASE; base != NULL; base = base->next) {
@@ -1578,7 +1577,7 @@ static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
(base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) ||
- (ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT) && base != BASACT)))
+ (ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT) && base != base_act)))
{
Object *ob = base->object;
@@ -1589,30 +1588,58 @@ static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
Object *dob = dupli_ob->ob;
- retval |= snapObject(scene, ar, dob, 0, dupli_ob->mat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth);
+ retval |= snapObject(scene, snap_mode, ar, dob, 0, dupli_ob->mat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, &depth);
}
free_object_duplilist(lb);
}
- retval |= snapObject(scene, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth);
+ retval |= snapObject(scene, snap_mode, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, &depth);
}
}
return retval;
}
+static bool snapObjects(Scene *scene, short snap_mode, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit,
+ const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
+{
+ float ray_start[3], ray_normal[3];
+
+ ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal);
+
+ return snapObjectsRay(scene, snap_mode, base_act, v3d, ar, obedit,
+ ray_start, ray_normal,
+ mval, r_dist_px, r_loc, r_no, mode);
+}
-bool snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
+bool snapObjectsTransform(TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
{
- return snapObjects(t->scene, t->view, t->ar, t->obedit, mval, r_dist, r_loc, r_no, mode);
+ return snapObjects(t->scene, t->scene->toolsettings->snap_mode, t->scene->basact, t->view, t->ar, t->obedit,
+ mval, r_dist_px, r_loc, r_no, mode);
}
-bool snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
+bool snapObjectsContext(bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
{
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
+ Scene *scene = CTX_data_scene(C);
- return snapObjects(CTX_data_scene(C), v3d, CTX_wm_region(C), CTX_data_edit_object(C), mval, r_dist, r_loc, r_no, mode);
+ return snapObjects(scene, scene->toolsettings->snap_mode, scene->basact, v3d, CTX_wm_region(C), CTX_data_edit_object(C), mval, r_dist_px, r_loc, r_no, mode);
+}
+
+bool snapObjectsEx(Scene *scene, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit, short snap_mode,
+ const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
+{
+ return snapObjects(scene, snap_mode, base_act, v3d, ar, obedit,
+ mval, r_dist_px, r_loc, r_no, mode);
+}
+bool snapObjectsRayEx(Scene *scene, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit, short snap_mode,
+ const float ray_start[3], const float ray_normal[3],
+ const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
+{
+ return snapObjectsRay(scene, snap_mode, base_act, v3d, ar, obedit,
+ ray_start, ray_normal,
+ mval, r_dist_px, r_loc, r_no, mode);
}
/******************** PEELING *********************************/
@@ -1889,7 +1916,7 @@ static NodeBorder snapNodeBorder(int snap_node_mode)
}
static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2],
- float r_loc[2], int *r_dist, char *r_node_border)
+ float r_loc[2], float *r_dist_px, char *r_node_border)
{
View2D *v2d = &ar->v2d;
NodeBorder border = snapNodeBorder(ts->snap_node_mode);
@@ -1902,9 +1929,9 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN
if (border & NODE_LEFT) {
new_dist = abs(totr.xmin - mval[0]);
- if (new_dist < *r_dist) {
+ if (new_dist < *r_dist_px) {
UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]);
- *r_dist = new_dist;
+ *r_dist_px = new_dist;
*r_node_border = NODE_LEFT;
retval = true;
}
@@ -1912,9 +1939,9 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN
if (border & NODE_RIGHT) {
new_dist = abs(totr.xmax - mval[0]);
- if (new_dist < *r_dist) {
+ if (new_dist < *r_dist_px) {
UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]);
- *r_dist = new_dist;
+ *r_dist_px = new_dist;
*r_node_border = NODE_RIGHT;
retval = true;
}
@@ -1922,9 +1949,9 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN
if (border & NODE_BOTTOM) {
new_dist = abs(totr.ymin - mval[1]);
- if (new_dist < *r_dist) {
+ if (new_dist < *r_dist_px) {
UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]);
- *r_dist = new_dist;
+ *r_dist_px = new_dist;
*r_node_border = NODE_BOTTOM;
retval = true;
}
@@ -1932,9 +1959,9 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN
if (border & NODE_TOP) {
new_dist = abs(totr.ymax - mval[1]);
- if (new_dist < *r_dist) {
+ if (new_dist < *r_dist_px) {
UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]);
- *r_dist = new_dist;
+ *r_dist_px = new_dist;
*r_node_border = NODE_TOP;
retval = true;
}
@@ -1944,7 +1971,7 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN
}
static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2],
- int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
+ float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode)
{
bNodeTree *ntree = snode->edittree;
bNode *node;
@@ -1954,21 +1981,21 @@ static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int
for (node = ntree->nodes.first; node; node = node->next) {
if (snapNodeTest(&ar->v2d, node, mode))
- retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist, r_node_border);
+ retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist_px, r_node_border);
}
return retval;
}
-bool snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
+bool snapNodesTransform(TransInfo *t, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode)
{
- return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist, r_loc, r_node_border, mode);
+ return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist_px, r_loc, r_node_border, mode);
}
-bool snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
+bool snapNodesContext(bContext *C, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode)
{
Scene *scene = CTX_data_scene(C);
- return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist, r_loc, r_node_border, mode);
+ return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist_px, r_loc, r_node_border, mode);
}
/*================================================================*/
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index e0991c48fa6..bcc55c4ea6e 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -32,7 +32,7 @@ set(INC
)
set(INC_SYS
-
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
@@ -90,6 +90,8 @@ set(SRC
../include/UI_view2d.h
)
+add_definitions(-DGLEW_STATIC)
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
diff --git a/source/blender/editors/util/SConscript b/source/blender/editors/util/SConscript
index 1c1a8e46dd7..8460b307f0d 100644
--- a/source/blender/editors/util/SConscript
+++ b/source/blender/editors/util/SConscript
@@ -28,7 +28,7 @@
Import ('env')
sources = env.Glob('*.c')
-defs = []
+defs = [ 'GLEW_STATIC' ]
incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 73062c57526..35e6c40c36b 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -37,11 +37,15 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_packedFile_types.h"
#include "BLI_blenlib.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
#include "BLF_translation.h"
#include "BKE_context.h"
@@ -54,6 +58,7 @@
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_sculpt.h"
+#include "ED_space_api.h"
#include "ED_util.h"
#include "UI_interface.h"
@@ -157,17 +162,6 @@ void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, fl
}
}
-#if 0 /* UNUSED */
-int GetButStringLength(const char *str)
-{
- int rt;
-
- rt = UI_GetStringWidth(str);
-
- return rt + 15;
-}
-#endif
-
void unpack_menu(bContext *C, const char *opname, const char *id_name, const char *abs_name, const char *folder, struct PackedFile *pf)
{
PointerRNA props_ptr;
@@ -255,3 +249,24 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
uiPupMenuEnd(C, pup);
}
+
+/* ********************* generic callbacks for drawcall api *********************** */
+
+/**
+ * Callback that draws a line between the mouse and a position given as the initial argument.
+ */
+void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info)
+{
+ wmWindow *win = CTX_wm_window(C);
+ const int *mval_src = (int *)arg_info;
+ const int mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
+ win->eventstate->y - ar->winrct.ymin};
+
+ UI_ThemeColor(TH_WIRE);
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ glVertex2iv(mval_dst);
+ glVertex2iv(mval_src);
+ glEnd();
+ setlinestyle(0);
+}
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 17d3ce3cd73..29da72a00fe 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -129,8 +129,8 @@ void GPU_material_free(struct Material *ma);
void GPU_materials_free(void);
-void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap);
-void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float viewinv[4][4], float obcol[4], float autobumpscale);
+void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4]);
+void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale);
void GPU_material_unbind(GPUMaterial *material);
int GPU_material_bound(GPUMaterial *material);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index ae1eb62bc18..f1b631192af 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -680,12 +680,6 @@ void GPU_code_generate_glsl_lib(void)
ds = BLI_dynstr_new();
- if (GPU_bicubic_bump_support()) {
- BLI_dynstr_append(ds, "/* These are needed for high quality bump mapping */\n"
- "#version 130\n"
- "#extension GL_ARB_texture_query_lod: enable\n"
- "#define BUMP_BICUBIC\n");
- }
BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index b772507e0cc..c78961e6308 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -1457,10 +1457,10 @@ int GPU_enable_material(int nr, void *attribs)
gpumat = GPU_material_from_blender(GMS.gscene, mat);
GPU_material_vertex_attributes(gpumat, gattribs);
- GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT));
+ GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv);
auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col, auto_bump_scale);
+ GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale);
GMS.gboundmat= mat;
/* for glsl use alpha blend mode, unless it's set to solid and
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index e8d28877043..7ac852f551a 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -1136,6 +1136,18 @@ static void shader_print_errors(const char *task, char *log, const char *code)
fprintf(stderr, "%s\n", log);
}
+static const char *gpu_shader_standard_extensions(void)
+{
+ /* need this extensions for high quality bump mapping */
+ if(GPU_bicubic_bump_support()) {
+ return "#version 130\n"
+ "#extension GL_ARB_texture_query_lod: enable\n"
+ "#define BUMP_BICUBIC\n";
+ }
+
+ return "";
+}
+
static const char *gpu_shader_standard_defines(void)
{
/* some useful defines to detect GPU type */
@@ -1177,9 +1189,10 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
}
if (vertexcode) {
- const char *source[3];
+ const char *source[4];
int num_source = 0;
+ source[num_source++] = gpu_shader_standard_extensions();
source[num_source++] = gpu_shader_standard_defines();
if (defines) source[num_source++] = defines;
@@ -1201,9 +1214,10 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
}
if (fragcode) {
- const char *source[4];
+ const char *source[5];
int num_source = 0;
+ source[num_source++] = gpu_shader_standard_extensions();
source[num_source++] = gpu_shader_standard_defines();
if (defines) source[num_source++] = defines;
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 999e3b5c20e..075a670e06e 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -257,11 +257,12 @@ void GPU_material_free(Material *ma)
BLI_freelistN(&ma->gpumaterial);
}
-void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap)
+void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4])
{
if (material->pass) {
LinkData *nlink;
GPULamp *lamp;
+ GPUShader *shader = GPU_pass_shader(material->pass);
/* handle layer lamps */
for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
@@ -275,29 +276,52 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
lamp->dynenergy = 0.0f;
lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
}
+
+ if (material->dynproperty & DYN_LAMP_VEC) {
+ copy_v3_v3(lamp->dynvec, lamp->vec);
+ normalize_v3(lamp->dynvec);
+ negate_v3(lamp->dynvec);
+ mul_mat3_m4_v3(viewmat, lamp->dynvec);
+ }
+
+ if (material->dynproperty & DYN_LAMP_CO) {
+ copy_v3_v3(lamp->dynco, lamp->co);
+ mul_m4_v3(viewmat, lamp->dynco);
+ }
+
+ if (material->dynproperty & DYN_LAMP_IMAT) {
+ mult_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
+ }
+
+ if (material->dynproperty & DYN_LAMP_PERSMAT) {
+ if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
+ GPU_lamp_update_buffer_mats(lamp);
+ mult_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
+ }
+ }
+
+ /* handle per material built-ins */
+ if (material->builtins & GPU_VIEW_MATRIX) {
+ GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat);
+ }
+ if (material->builtins & GPU_INVERSE_VIEW_MATRIX) {
+ GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv);
}
GPU_pass_bind(material->pass, time, mipmap);
GPU_pass_update_uniforms(material->pass);
+
material->bound = 1;
}
}
-void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float viewinv[4][4], float obcol[4], float autobumpscale)
+void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale)
{
if (material->pass) {
GPUShader *shader = GPU_pass_shader(material->pass);
- LinkData *nlink;
- GPULamp *lamp;
float invmat[4][4], col[4];
- /* handle builtins */
- if (material->builtins & GPU_VIEW_MATRIX) {
- GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat);
- }
- if (material->builtins & GPU_INVERSE_VIEW_MATRIX) {
- GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv);
- }
+ /* handle per object builtins */
if (material->builtins & GPU_OBJECT_MATRIX) {
GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat);
}
@@ -313,32 +337,6 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float
if (material->builtins & GPU_AUTO_BUMPSCALE) {
GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale);
}
- /* update lamps */
- for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
- lamp= nlink->data;
-
- if (material->dynproperty & DYN_LAMP_VEC) {
- copy_v3_v3(lamp->dynvec, lamp->vec);
- normalize_v3(lamp->dynvec);
- negate_v3(lamp->dynvec);
- mul_mat3_m4_v3(viewmat, lamp->dynvec);
- }
-
- if (material->dynproperty & DYN_LAMP_CO) {
- copy_v3_v3(lamp->dynco, lamp->co);
- mul_m4_v3(viewmat, lamp->dynco);
- }
-
- if (material->dynproperty & DYN_LAMP_IMAT) {
- mult_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
- }
-
- if (material->dynproperty & DYN_LAMP_PERSMAT) {
- if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
- GPU_lamp_update_buffer_mats(lamp);
- mult_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
- }
- }
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 147d002475b..08747b19df2 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2074,6 +2074,11 @@ void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result)
node_bsdf_diffuse(color, 0.0, N, result);
}
+void node_subsurface_scattering(vec4 color, float roughness, vec3 N, out vec4 result)
+{
+ node_bsdf_diffuse(color, 0.0, N, result);
+}
+
/* emission */
void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 473bd7d0c7a..58b55b0f137 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -28,8 +28,8 @@
*
*/
-#ifndef IMB_COLORMANAGEMENT_H
-#define IMB_COLORMANAGEMENT_H
+#ifndef __IMB_COLORMANAGEMENT_H__
+#define __IMB_COLORMANAGEMENT_H__
#define BCM_CONFIG_FILE "config.ocio"
@@ -150,11 +150,26 @@ void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processo
/* ** OpenGL drawing routines using GLSL for color space transform ** */
-int IMB_coloemanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings,
- const struct ColorManagedDisplaySettings *display_settings);
-
-int IMB_coloemanagement_setup_glsl_draw_from_ctx(const struct bContext *C);
-void IMB_coloemanagement_finish_glsl_draw(void);
+/* Configures GLSL shader for conversion from scene linear to display space */
+int IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings,
+ int predivide);
+/* Same as above, but display space conversion happens from a specified space */
+int IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings,
+ struct ColorSpace *colorspace,
+ int predivide);
+/* Same as setup_glsl_draw, but color management settings are guessing from a given context */
+int IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, int predivide);
+/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */
+int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, int predivide);
+/* Finish GLSL-based display space conversion */
+void IMB_colormanagement_finish_glsl_draw(void);
+
+/* Configures GLSL shader for conversion from space defined by role to scene linear space */
+int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide);
+/* Finish GLSL-based color space conversion */
+void IMB_colormanagement_finish_glsl_transform(void);
/* Roles */
enum {
@@ -166,4 +181,4 @@ enum {
COLOR_ROLE_DEFAULT_FLOAT,
};
-#endif /* IMB_COLORMANAGEMENT_H */
+#endif /* __IMB_COLORMANAGEMENT_H__ */
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 95f67b9b21d..a74f28e79c9 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -109,10 +109,12 @@ static struct global_glsl_state {
/* Settings of processor for comparison. */
char view[MAX_COLORSPACE_NAME];
char display[MAX_COLORSPACE_NAME];
+ char input[MAX_COLORSPACE_NAME];
float exposure, gamma;
/* Container for GLSL state needed for OCIO module. */
struct OCIO_GLSLDrawState *ocio_glsl_state;
+ struct OCIO_GLSLDrawState *transform_ocio_glsl_state;
} global_glsl_state;
/*********************** Color managed cache *************************/
@@ -626,6 +628,9 @@ void colormanagement_exit(void)
if (global_glsl_state.ocio_glsl_state)
OCIO_freeOGLState(global_glsl_state.ocio_glsl_state);
+ if (global_glsl_state.transform_ocio_glsl_state)
+ OCIO_freeOGLState(global_glsl_state.transform_ocio_glsl_state);
+
colormanage_free_config();
}
@@ -699,8 +704,10 @@ static ColorSpace *display_transform_get_colorspace(const ColorManagedViewSettin
return NULL;
}
-static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display,
- float exposure, float gamma)
+static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform,
+ const char *display,
+ float exposure, float gamma,
+ const char *from_colorspace)
{
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
OCIO_DisplayTransformRcPtr *dt;
@@ -708,8 +715,7 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *vie
dt = OCIO_createDisplayTransform();
- /* assuming handling buffer was already converted to scene linear space */
- OCIO_displayTransformSetInputColorSpaceName(dt, global_role_scene_linear);
+ OCIO_displayTransformSetInputColorSpaceName(dt, from_colorspace);
OCIO_displayTransformSetView(dt, view_transform);
OCIO_displayTransformSetDisplay(dt, display);
@@ -1843,10 +1849,10 @@ static void imbuf_verify_float(ImBuf *ibuf)
*/
BLI_lock_thread(LOCK_COLORMANAGE);
- if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) {
+ if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & (IB_DISPLAY_BUFFER_INVALID | IB_RECT_INVALID)))) {
IMB_rect_from_float(ibuf);
- ibuf->userflags &= ~IB_RECT_INVALID;
+ ibuf->userflags &= ~(IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID);
}
BLI_unlock_thread(LOCK_COLORMANAGE);
@@ -2617,7 +2623,8 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag
cm_processor->is_data_result = display_space->is_data;
cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device,
- applied_view_settings->exposure, applied_view_settings->gamma);
+ applied_view_settings->exposure, applied_view_settings->gamma,
+ global_role_scene_linear);
if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping);
@@ -2714,26 +2721,30 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
/* **** OpenGL drawing routines using GLSL for color space transform ***** */
static bool check_glsl_display_processor_changed(const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings)
+ const ColorManagedDisplaySettings *display_settings,
+ const char *from_colorspace)
{
return !(global_glsl_state.exposure == view_settings->exposure &&
global_glsl_state.gamma == view_settings->gamma &&
STREQ(global_glsl_state.view, view_settings->view_transform) &&
- STREQ(global_glsl_state.display, display_settings->display_device));
+ STREQ(global_glsl_state.display, display_settings->display_device) &&
+ STREQ(global_glsl_state.input, from_colorspace));
}
static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings)
+ const ColorManagedDisplaySettings *display_settings,
+ const char *from_colorspace)
{
/* Update state if there's no processor yet or
* processor settings has been changed.
*/
if (global_glsl_state.processor == NULL ||
- check_glsl_display_processor_changed(view_settings, display_settings))
+ check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace))
{
/* Store settings of processor for further comparison. */
strcpy(global_glsl_state.view, view_settings->view_transform);
strcpy(global_glsl_state.display, display_settings->display_device);
+ strcpy(global_glsl_state.input, from_colorspace);
global_glsl_state.exposure = view_settings->exposure;
global_glsl_state.gamma = view_settings->gamma;
@@ -2746,12 +2757,27 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
create_display_buffer_processor(global_glsl_state.view,
global_glsl_state.display,
global_glsl_state.exposure,
- global_glsl_state.gamma);
+ global_glsl_state.gamma,
+ global_glsl_state.input);
}
}
-int IMB_coloemanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings)
+/**
+ * Configures GLSL shader for conversion from specified to
+ * display color space
+ *
+ * Will create appropriate OCIO processor and setup GLSL shader,
+ * so further 2D texture usage will use this conversion.
+ *
+ * When there's no need to apply transform on 2D textures, use
+ * IMB_colormanagement_finish_glsl_draw().
+ *
+ * This is low-level function, use glaDrawImBuf_glsl_ctx if you
+ * only need to display given image buffer
+ */
+int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings,
+ struct ColorSpace *from_colorspace, int predivide)
{
ColorManagedViewSettings default_view_settings;
const ColorManagedViewSettings *applied_view_settings;
@@ -2773,24 +2799,73 @@ int IMB_coloemanagement_setup_glsl_draw(const ColorManagedViewSettings *view_set
return FALSE;
/* Make sure OCIO processor is up-to-date. */
- update_glsl_display_processor(applied_view_settings, display_settings);
+ update_glsl_display_processor(applied_view_settings, display_settings,
+ from_colorspace ? from_colorspace->name : global_role_scene_linear);
- OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor);
+ return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, predivide);
+}
- return TRUE;
+/* Configures GLSL shader for conversion from scene linear to display space */
+int IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings,
+ int predivide)
+{
+ return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
+ NULL, predivide);
}
-int IMB_coloemanagement_setup_glsl_draw_from_ctx(const bContext *C)
+/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */
+int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *from_colorspace, int predivide)
{
ColorManagedViewSettings *view_settings;
ColorManagedDisplaySettings *display_settings;
display_transform_get_from_ctx(C, &view_settings, &display_settings);
- return IMB_coloemanagement_setup_glsl_draw(view_settings, display_settings);
+ return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide);
}
-void IMB_coloemanagement_finish_glsl_draw(void)
+/* Same as setup_glsl_draw, but color management settings are guessing from a given context */
+int IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, int predivide)
+{
+ return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, predivide);
+}
+
+/* Finish GLSL-based display space conversion */
+void IMB_colormanagement_finish_glsl_draw(void)
{
OCIO_finishGLSLDraw(global_glsl_state.ocio_glsl_state);
}
+
+/* ** Color space conversion using GLSL shader ** */
+
+/**
+ * Configures GLSL shader for conversion from space defined by role
+ * to scene linear space
+ *
+ * Will create appropriate OCIO processor and setup GLSL shader,
+ * so further 2D texture usage will use this conversion.
+ *
+ * Role is an pseudonym for a color space, see bottom of file
+ * IMB_colormanagement.h for list of available roles.
+ *
+ * When there's no need to apply transform on 2D textures, use
+ * IMB_colormanagement_finish_glsl_transform().
+ */
+int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide)
+{
+ OCIO_ConstProcessorRcPtr *processor;
+ ColorSpace *colorspace;
+
+ colorspace = colormanage_colorspace_get_roled(role);
+
+ processor = colorspace_to_scene_linear_processor(colorspace);
+
+ return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, predivide);
+}
+
+/* Finish GLSL-based color space conversion */
+void IMB_colormanagement_finish_glsl_transform(void)
+{
+ OCIO_finishGLSLDraw(global_glsl_state.transform_ocio_glsl_state);
+}
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 20d51fddb35..e69460de040 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -664,13 +664,13 @@ void IMB_float_from_rect(ImBuf *ibuf)
/* no profile conversion */
void IMB_color_to_bw(ImBuf *ibuf)
{
- float *rctf = ibuf->rect_float;
+ float *rct_fl = ibuf->rect_float;
uchar *rct = (uchar *)ibuf->rect;
int i;
- if (rctf) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rctf += 4)
- rctf[0] = rctf[1] = rctf[2] = rgb_to_grayscale(rctf);
+ if (rct_fl) {
+ for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4)
+ rct_fl[0] = rct_fl[1] = rct_fl[2] = rgb_to_grayscale(rct_fl);
}
if (rct) {
@@ -713,7 +713,7 @@ void IMB_saturation(ImBuf *ibuf, float sat)
{
int i;
unsigned char *rct = (unsigned char *)ibuf->rect;
- float *rctf = ibuf->rect_float;
+ float *rct_fl = ibuf->rect_float;
float hsv[3];
if (rct) {
@@ -726,10 +726,10 @@ void IMB_saturation(ImBuf *ibuf, float sat)
}
}
- if (rctf) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rctf += 4) {
- rgb_to_hsv_v(rctf, hsv);
- hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rctf, rctf + 1, rctf + 2);
+ if (rct_fl) {
+ for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) {
+ rgb_to_hsv_v(rct_fl, hsv);
+ hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2);
}
}
}
diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h
index 119d2cdfdf7..499f1c50155 100644
--- a/source/blender/makesdna/DNA_movieclip_types.h
+++ b/source/blender/makesdna/DNA_movieclip_types.h
@@ -98,11 +98,6 @@ typedef struct MovieClip {
/* color management */
ColorManagedColorspaceSettings colorspace_settings;
-
- /* runtime prefetching stuff */
- char prefetch_ok;
-
- char pad[7];
} MovieClip;
typedef struct MovieClipScopes {
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 68a5ac5f639..00ee1b49da2 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -609,6 +609,9 @@ bool RNA_struct_is_a(StructRNA *type, StructRNA *srna)
{
StructRNA *base;
+ if (srna == &RNA_AnyType)
+ return true;
+
if (!type)
return false;
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index 1ac59f9caed..45bb5c613d5 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -54,7 +54,7 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter)
static void rna_Group_objects_link(Group *group, bContext *C, ReportList *reports, Object *object)
{
- if (!add_to_group(group, object, CTX_data_scene(C), NULL)) {
+ if (!BKE_group_object_add(group, object, CTX_data_scene(C), NULL)) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' already in group '%s'", object->id.name + 2, group->id.name + 2);
return;
}
@@ -64,7 +64,7 @@ static void rna_Group_objects_link(Group *group, bContext *C, ReportList *report
static void rna_Group_objects_unlink(Group *group, bContext *C, ReportList *reports, Object *object)
{
- if (!rem_from_group(group, object, CTX_data_scene(C), NULL)) {
+ if (!BKE_group_object_unlink(group, object, CTX_data_scene(C), NULL)) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' not in group '%s'", object->id.name + 2, group->id.name + 2);
return;
}
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index fb0aeffcffb..d504585f738 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -681,7 +681,7 @@ static void rna_Main_worlds_remove(Main *bmain, ReportList *reports, PointerRNA
static Group *rna_Main_groups_new(Main *bmain, const char *name)
{
- return add_group(bmain, name);
+ return BKE_group_add(bmain, name);
}
static void rna_Main_groups_remove(Main *bmain, PointerRNA *group_ptr)
{
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index cc3d5e5ca5e..9b2bcab4604 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -49,6 +49,11 @@
#include "BKE_depsgraph.h"
+#include "ED_clip.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
static void rna_MovieClip_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -65,6 +70,39 @@ static void rna_MovieClip_size_get(PointerRNA *ptr, int *values)
values[1] = clip->lastsize[1];
}
+static void rna_MovieClipUser_proxy_render_settings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ ID *id = (ID *) ptr->id.data;
+ MovieClipUser *user = (MovieClipUser *) ptr->data;
+
+ /* when changing render settings of space clip user
+ * clear cache for clip, so all the memory is available
+ * for new render settings
+ */
+ if (GS(id->name) == ID_SCR) {
+ bScreen *screen = (bScreen *) id;
+ ScrArea *area;
+ SpaceLink *sl;
+
+ for (area = screen->areabase.first; area; area = area->next) {
+ for (sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = (SpaceClip *) sl;
+
+ if (&sc->user == user) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip && (clip->flag & MCLIP_USE_PROXY))
+ BKE_movieclip_clear_cache(clip);
+
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
#else
static void rna_def_movieclip_proxy(BlenderRNA *brna)
@@ -197,13 +235,13 @@ static void rna_def_moviecliUser(BlenderRNA *brna)
RNA_def_property_enum_items(prop, clip_render_size_items);
RNA_def_property_ui_text(prop, "Proxy render size",
"Draw preview using full resolution or different proxy resolutions");
- RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
+ RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClipUser_proxy_render_settings_update");
/* render undistorted */
prop = RNA_def_property(srna, "use_render_undistorted", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "render_flag", MCLIP_PROXY_RENDER_UNDISTORT);
RNA_def_property_ui_text(prop, "Render Undistorted", "Render preview using undistorted proxy");
- RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
+ RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClipUser_proxy_render_settings_update");
}
static void rna_def_movieClipScopes(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 594b86f000c..0c01d03888d 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -43,7 +43,7 @@
#include "BKE_paint.h"
#include "BKE_tessmesh.h"
-#include "BKE_group.h" /* needed for object_in_group() */
+#include "BKE_group.h" /* needed for BKE_group_object_exists() */
#include "RNA_access.h"
#include "RNA_define.h"
@@ -520,7 +520,7 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value)
/* must not let this be set if the object belongs in this group already,
* thus causing a cycle/infinite-recursion leading to crashes on load [#25298]
*/
- if (object_in_group(ob, grp) == 0)
+ if (BKE_group_object_exists(grp, ob) == 0)
ob->dup_group = grp;
else
BKE_report(NULL, RPT_ERROR,
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 309de9c7fd1..e036bb1c999 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -536,6 +536,21 @@ static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
}
}
+static int rna_SpaceView3D_viewport_shade_get(PointerRNA *ptr)
+{
+ Scene *scene = ((bScreen *)ptr->id.data)->scene;
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ View3D *v3d = (View3D *)ptr->data;
+ int drawtype = v3d->drawtype;
+
+ if (drawtype == OB_MATERIAL && !BKE_scene_use_new_shading_nodes(scene))
+ return OB_SOLID;
+ else if (drawtype == OB_RENDER && !(type && type->view_draw))
+ return OB_SOLID;
+
+ return drawtype;
+}
+
static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), int *free)
{
@@ -553,7 +568,7 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C
if (BKE_scene_use_new_shading_nodes(scene))
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_MATERIAL);
- if (type->view_draw)
+ if (type && type->view_draw)
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_RENDER);
RNA_enum_item_end(&item, &totitem);
@@ -1696,7 +1711,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "viewport_shade", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "drawtype");
RNA_def_property_enum_items(prop, viewport_shade_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceView3D_viewport_shade_itemf");
+ RNA_def_property_enum_funcs(prop, "rna_SpaceView3D_viewport_shade_get", NULL, "rna_SpaceView3D_viewport_shade_itemf");
RNA_def_property_ui_text(prop, "Viewport Shading", "Method to display/shade objects in the 3D View");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_viewport_shade_update");
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index b2f17bfed8b..9c354e7f70e 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -269,7 +269,7 @@ static void rna_uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const c
static int rna_ui_get_rnaptr_icon(bContext *C, PointerRNA *ptr_icon)
{
- return UI_rnaptr_icon_get(C, ptr_icon, RNA_struct_ui_icon(ptr_icon->type), FALSE);
+ return UI_rnaptr_icon_get(C, ptr_icon, RNA_struct_ui_icon(ptr_icon->type), false);
}
static const char *rna_ui_get_enum_name(bContext *C, PointerRNA *ptr, const char *propname, const char *identifier)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index f3b3d6b1f53..f2ce9665e2b 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -175,6 +175,7 @@ set(SRC
shader/nodes/node_shader_output_world.c
shader/nodes/node_shader_particle_info.c
shader/nodes/node_shader_script.c
+ shader/nodes/node_shader_subsurface_scattering.c
shader/nodes/node_shader_tangent.c
shader/nodes/node_shader_tex_brick.c
shader/nodes/node_shader_tex_checker.c
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index f272ec670e7..896714338e5 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -52,7 +52,6 @@ void register_node_type_cmp_value(void);
void register_node_type_cmp_rgb(void);
void register_node_type_cmp_curve_time(void);
void register_node_type_cmp_movieclip(void);
-void register_node_type_cmp_usermask(struct bNodeTreeType *ttype);
void register_node_type_cmp_composite(void);
void register_node_type_cmp_viewer(void);
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 9561fe00409..eb324182e39 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -101,6 +101,7 @@ void register_node_type_sh_emission(void);
void register_node_type_sh_holdout(void);
void register_node_type_sh_volume_transparent(void);
void register_node_type_sh_volume_isotropic(void);
+void register_node_type_sh_subsurface_scattering(void);
void register_node_type_sh_mix_shader(void);
void register_node_type_sh_add_shader(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 9d044772274..811cd3f3b4a 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -84,6 +84,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BS
DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" )
+DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, 0, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","")
DefNode( ShaderNode, SH_NODE_VOLUME_TRANSPARENT, 0, "VOLUME_TRANSPARENT", VolumeTransparent,"Transparent Volume","" )
DefNode( ShaderNode, SH_NODE_VOLUME_ISOTROPIC, 0, "VOLUME_ISOTROPIC", VolumeIsotropic, "Isotropic Volume", "" )
DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" )
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c
index 44643724073..df1c5d3316b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.c
+++ b/source/blender/nodes/composite/nodes/node_composite_common.c
@@ -51,6 +51,7 @@ void register_node_type_cmp_group(void)
node_type_base_custom(&ntype, "CompositorNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
ntype.type = NODE_GROUP;
ntype.poll = cmp_node_poll_default;
+ ntype.poll_instance = node_group_poll_instance;
ntype.update_internal_links = node_update_internal_links_default;
ntype.ext.srna = RNA_struct_find("CompositorNodeGroup");
BLI_assert(ntype.ext.srna != NULL);
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index 4e4443f7c3f..24f35cc81af 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -89,11 +89,15 @@ const char *node_group_label(bNode *node)
int node_group_poll_instance(bNode *node, bNodeTree *nodetree)
{
- bNodeTree *grouptree = (bNodeTree*)node->id;
- if (grouptree)
- return nodeGroupPoll(nodetree, grouptree);
+ if (node->typeinfo->poll(node->typeinfo, nodetree)) {
+ bNodeTree *grouptree = (bNodeTree*)node->id;
+ if (grouptree)
+ return nodeGroupPoll(nodetree, grouptree);
+ else
+ return TRUE; /* without a linked node tree, group node is always ok */
+ }
else
- return 1;
+ return FALSE;
}
int nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree)
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 74d44fe5f53..f28d6a20dab 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -420,6 +420,9 @@ static bNodeSocketType *make_socket_type_virtual(void)
/* associate the RNA type with the socket type */
RNA_struct_blender_type_set(srna, stype);
+ /* extra type info for standard socket types */
+ stype->type = SOCK_CUSTOM;
+
ED_init_node_socket_type_virtual(stype);
return stype;
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index 57b129335bb..cfd97ab0d9e 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -92,7 +92,6 @@ typedef struct ShaderCallData {
} ShaderCallData;
-extern void node_ID_title_cb(void *node_v, void *unused_v);
void nodestack_get_vec(float *in, short type_in, bNodeStack *ns);
void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, struct bNodeStack *ns);
diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c
index 155aa508ed9..cd2953c839a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_common.c
+++ b/source/blender/nodes/shader/nodes/node_shader_common.c
@@ -231,6 +231,7 @@ void register_node_type_sh_group(void)
node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
ntype.type = NODE_GROUP;
ntype.poll = sh_node_poll_default;
+ ntype.poll_instance = node_group_poll_instance;
ntype.update_internal_links = node_update_internal_links_default;
ntype.ext.srna = RNA_struct_find("ShaderNodeGroup");
BLI_assert(ntype.ext.srna != NULL);
diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
new file mode 100644
index 00000000000..cde6ec8be45
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
@@ -0,0 +1,69 @@
+/*
+ * ***** 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): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_subsurface_scattering_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Scale"), 1.0, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f},
+ { SOCK_VECTOR, 1, N_("Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f},
+ //{ SOCK_FLOAT, 1, N_("IOR"), 1.3f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f},
+ { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_subsurface_scattering_out[] = {
+ { SOCK_SHADER, 0, N_("BSSRDF")},
+ { -1, 0, "" }
+};
+
+static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ if (!in[1].link)
+ in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
+
+ return GPU_stack_link(mat, "node_subsurface_scattering", in, out);
+}
+
+/* node type definition */
+void register_node_type_sh_subsurface_scattering(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_SUBSURFACE_SCATTERING, "Subsurface Scattering", NODE_CLASS_SHADER, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_subsurface_scattering_in, sh_node_subsurface_scattering_out);
+ node_type_size(&ntype, 150, 60, 200);
+ node_type_init(&ntype, NULL);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering);
+
+ nodeRegisterType(&ntype);
+}
+
diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c
index e884d50dc05..ee03323fb5d 100644
--- a/source/blender/nodes/texture/nodes/node_texture_common.c
+++ b/source/blender/nodes/texture/nodes/node_texture_common.c
@@ -159,6 +159,7 @@ void register_node_type_tex_group(void)
node_type_base_custom(&ntype, "TextureNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
ntype.type = NODE_GROUP;
ntype.poll = tex_node_poll_default;
+ ntype.poll_instance = node_group_poll_instance;
ntype.update_internal_links = node_update_internal_links_default;
ntype.ext.srna = RNA_struct_find("TextureNodeGroup");
BLI_assert(ntype.ext.srna != NULL);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 735df7aeb10..d6a82ce43ea 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1778,8 +1778,10 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
if (flag & PROP_THICK_WRAP) {
if (value == Py_None)
memset(data, 0, sizeof(PointerRNA));
- else
+ else if (RNA_struct_is_a(param->ptr.type, ptr_type))
*((PointerRNA *)data) = param->ptr;
+ else
+ raise_error = true;
}
else {
/* for function calls, we sometimes want to pass the 'ptr' directly,
@@ -1787,8 +1789,10 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
BLI_assert(value_new == NULL);
if (value == Py_None)
*((void **)data) = NULL;
- else
+ else if (RNA_struct_is_a(param->ptr.type, ptr_type))
*((PointerRNA **)data) = &param->ptr;
+ else
+ raise_error = true;
}
}
else if (value == Py_None) {
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 2bcd39ab71b..96106296443 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -158,9 +158,6 @@ typedef struct RenderStats {
struct Render *RE_NewRender (const char *name);
struct Render *RE_GetRender(const char *name);
-/* returns 1 while render is working (or renders called from within render) */
-int RE_RenderInProgress(struct Render *re);
-
/* assign default dummy callbacks */
void RE_InitRenderCB(struct Render *re);
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 2dfbdd0d6f5..eb861d440d8 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -37,20 +37,12 @@
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* called by meshtools */
-struct View3D;
-struct Scene;
+struct DerivedMesh;
+struct ImagePool;
struct LinkNode;
-
-void RE_make_sticky(struct Scene *scene, struct Object *camera, struct LinkNode *objects);
-
-/* for radiosity module */
-struct RadView;
-struct RNode;
-struct Render;
struct MTex;
-struct ImBuf;
-struct ImagePool;
-struct DerivedMesh;
+struct Scene;
+struct View3D;
/* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool);
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 003e74bd69a..7505b0fa567 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1743,15 +1743,15 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
shr->col[0]= shr->col[1]= shr->col[2]= shr->col[3]= 1.0f;
}
else {
- shi->r= pow(shi->r, ma->sss_texfac);
- shi->g= pow(shi->g, ma->sss_texfac);
- shi->b= pow(shi->b, ma->sss_texfac);
- shi->alpha= pow(shi->alpha, ma->sss_texfac);
+ shi->r= pow(max_ff(shi->r, 0.0f), ma->sss_texfac);
+ shi->g= pow(max_ff(shi->g, 0.0f), ma->sss_texfac);
+ shi->b= pow(max_ff(shi->b, 0.0f), ma->sss_texfac);
+ shi->alpha= pow(max_ff(shi->alpha, 0.0f), ma->sss_texfac);
- shr->col[0]= pow(shr->col[0], ma->sss_texfac);
- shr->col[1]= pow(shr->col[1], ma->sss_texfac);
- shr->col[2]= pow(shr->col[2], ma->sss_texfac);
- shr->col[3]= pow(shr->col[3], ma->sss_texfac);
+ shr->col[0]= pow(max_ff(shr->col[0], 0.0f), ma->sss_texfac);
+ shr->col[1]= pow(max_ff(shr->col[1], 0.0f), ma->sss_texfac);
+ shr->col[2]= pow(max_ff(shr->col[2], 0.0f), ma->sss_texfac);
+ shr->col[3]= pow(max_ff(shr->col[3], 0.0f), ma->sss_texfac);
}
}
}
@@ -1841,9 +1841,9 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
else {
copy_v3_v3(col, shr->col);
mul_v3_fl(col, invalpha);
- col[0]= pow(col[0], 1.0f-texfac);
- col[1]= pow(col[1], 1.0f-texfac);
- col[2]= pow(col[2], 1.0f-texfac);
+ col[0]= pow(max_ff(col[0], 0.0f), 1.0f-texfac);
+ col[1]= pow(max_ff(col[1], 0.0f), 1.0f-texfac);
+ col[2]= pow(max_ff(col[2], 0.0f), 1.0f-texfac);
}
shr->diff[0]= sss[0]*col[0];
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 25c8c5db0a1..2af513cebe6 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -70,7 +70,7 @@ typedef struct wmJob wmJob;
void WM_init_state_size_set (int stax, int stay, int sizx, int sizy);
void WM_init_state_fullscreen_set(void);
void WM_init_state_normal_set(void);
-void WM_init_native_pixels(int do_it);
+void WM_init_native_pixels(bool do_it);
void WM_init (struct bContext *C, int argc, const char **argv);
void WM_exit_ext (struct bContext *C, const short do_python);
@@ -87,7 +87,7 @@ __attribute__((noreturn))
#endif
;
-int WM_init_game (struct bContext *C);
+bool WM_init_game (struct bContext *C);
void WM_init_splash (struct bContext *C);
@@ -106,7 +106,7 @@ int WM_window_pixels_y (struct wmWindow *win);
void WM_window_open_temp (struct bContext *C, struct rcti *position, int type);
/* returns true if draw method is triple buffer */
-int WM_is_draw_triple(struct wmWindow *win);
+bool WM_is_draw_triple(struct wmWindow *win);
@@ -118,7 +118,7 @@ void WM_autosave_init(struct wmWindowManager *wm);
void WM_cursor_set (struct wmWindow *win, int curs);
void WM_cursor_modal (struct wmWindow *win, int curs);
void WM_cursor_restore (struct wmWindow *win);
-void WM_cursor_wait (int val);
+void WM_cursor_wait (bool val);
void WM_cursor_grab_enable(struct wmWindow *win, int wrap, int hide, int bounds[4]);
void WM_cursor_grab_disable(struct wmWindow *win, int mouse_ungrab_xy[2]);
void WM_cursor_time (struct wmWindow *win, int nr);
@@ -204,7 +204,7 @@ void WM_operator_free (struct wmOperator *op);
void WM_operator_stack_clear(struct wmWindowManager *wm);
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot);
-struct wmOperatorType *WM_operatortype_find(const char *idnamem, int quiet);
+struct wmOperatorType *WM_operatortype_find(const char *idnamem, bool quiet);
struct GHashIterator *WM_operatortype_iter(void);
void WM_operatortype_append(void (*opfunc)(struct wmOperatorType *));
void WM_operatortype_append_ptr(void (*opfunc)(struct wmOperatorType *, void *), void *userdata);
@@ -225,8 +225,8 @@ int WM_operator_name_call (struct bContext *C, const char *opstring, short con
int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties, struct ReportList *reports, short is_undo);
void WM_operator_properties_alloc(struct PointerRNA **ptr, struct IDProperty **properties, const char *opstring); /* used for keymap and macro items */
-void WM_operator_properties_sanitize(struct PointerRNA *ptr, const short no_context); /* make props context sensitive or not */
-int WM_operator_properties_default(struct PointerRNA *ptr, const int do_update);
+void WM_operator_properties_sanitize(struct PointerRNA *ptr, const bool no_context); /* make props context sensitive or not */
+int WM_operator_properties_default(struct PointerRNA *ptr, const bool do_update);
void WM_operator_properties_reset(struct wmOperator *op);
void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring);
void WM_operator_properties_create_ptr(struct PointerRNA *ptr, struct wmOperatorType *ot);
@@ -239,11 +239,11 @@ void WM_operator_properties_mouse_select(struct wmOperatorType *ot);
void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, bool cursor);
void WM_operator_properties_select_all(struct wmOperatorType *ot);
-int WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
+bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
wmOperator *WM_operator_last_redo(const struct bContext *C);
-int WM_operator_last_properties_init(struct wmOperator *op);
-int WM_operator_last_properties_store(struct wmOperator *op);
+bool WM_operator_last_properties_init(struct wmOperator *op);
+bool WM_operator_last_properties_store(struct wmOperator *op);
/* MOVE THIS SOMEWHERE ELSE */
#define SEL_TOGGLE 0
@@ -269,14 +269,14 @@ void WM_operator_py_idname(char *to, const char *from);
/* *************** uilist types ******************** */
void WM_uilisttype_init(void);
-struct uiListType *WM_uilisttype_find(const char *idname, int quiet);
+struct uiListType *WM_uilisttype_find(const char *idname, bool quiet);
int WM_uilisttype_add(struct uiListType *ult);
void WM_uilisttype_freelink(struct uiListType *ult);
void WM_uilisttype_free(void);
/* *************** menu types ******************** */
void WM_menutype_init(void);
-struct MenuType *WM_menutype_find(const char *idname, int quiet);
+struct MenuType *WM_menutype_find(const char *idname, bool quiet);
int WM_menutype_add(struct MenuType *mt);
void WM_menutype_freelink(struct MenuType *mt);
void WM_menutype_free(void);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 29e0fcf302f..f7b7aa87cf8 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -179,7 +179,7 @@ void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot)
static GHash *uilisttypes_hash = NULL;
-uiListType *WM_uilisttype_find(const char *idname, int quiet)
+uiListType *WM_uilisttype_find(const char *idname, bool quiet)
{
uiListType *ult;
@@ -234,7 +234,7 @@ void WM_uilisttype_free(void)
static GHash *menutypes_hash = NULL;
-MenuType *WM_menutype_find(const char *idname, int quiet)
+MenuType *WM_menutype_find(const char *idname, bool quiet)
{
MenuType *mt;
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 2e15d6158e8..f8081cb8012 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -164,7 +164,7 @@ void WM_cursor_restore(wmWindow *win)
}
/* to allow usage all over, we do entire WM */
-void WM_cursor_wait(int val)
+void WM_cursor_wait(bool val)
{
if (!G.background) {
wmWindowManager *wm = G.main->wm.first;
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index ed066117b28..0c78338c18a 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -323,7 +323,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy);
else {
glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */
- glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale);
+ glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale);
}
}
else {
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 173a8237c02..1e3c2479e66 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -769,12 +769,12 @@ static int wm_automatic_draw_method(wmWindow *win)
return win->drawmethod;
}
-int WM_is_draw_triple(wmWindow *win)
+bool WM_is_draw_triple(wmWindow *win)
{
/* function can get called before this variable is set in drawing code below */
if (win->drawmethod != U.wmdrawmethod)
win->drawmethod = U.wmdrawmethod;
- return USER_DRAW_TRIPLE == wm_automatic_draw_method(win);
+ return (USER_DRAW_TRIPLE == wm_automatic_draw_method(win));
}
void wm_tag_redraw_overlay(wmWindow *win, ARegion *ar)
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 6c129ec0a92..d7b642fc5cf 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -796,10 +796,10 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event)
}
}
-#if 1 /* disabling for 2.63 release, since we keep getting reports some menu items are leaving props undefined */
-int WM_operator_last_properties_init(wmOperator *op)
+#if 1 /* may want to disable operator remembering previous state for testing */
+bool WM_operator_last_properties_init(wmOperator *op)
{
- int change = FALSE;
+ bool change = false;
if (op->type->last_properties) {
PropertyRNA *iterprop;
@@ -825,7 +825,7 @@ int WM_operator_last_properties_init(wmOperator *op)
idp_dst->flag |= IDP_FLAG_GHOST;
IDP_ReplaceInGroup(op->properties, idp_dst);
- change = TRUE;
+ change = true;
}
}
}
@@ -836,7 +836,7 @@ int WM_operator_last_properties_init(wmOperator *op)
return change;
}
-int WM_operator_last_properties_store(wmOperator *op)
+bool WM_operator_last_properties_store(wmOperator *op)
{
if (op->type->last_properties) {
IDP_FreeProperty(op->type->last_properties);
@@ -849,10 +849,10 @@ int WM_operator_last_properties_store(wmOperator *op)
printf("%s: storing properties for '%s'\n", __func__, op->type->idname);
}
op->type->last_properties = IDP_CopyProperty(op->properties);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 193af2f92c6..16afad88069 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -248,7 +248,7 @@ void WM_init_splash(bContext *C)
}
}
-int WM_init_game(bContext *C)
+bool WM_init_game(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win;
@@ -318,7 +318,7 @@ int WM_init_game(bContext *C)
sound_exit();
- return 1;
+ return true;
}
else {
ReportTimerInfo *rti;
@@ -333,8 +333,9 @@ int WM_init_game(bContext *C)
rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo");
wm->reports.reporttimer->customdata = rti;
+
+ return false;
}
- return 0;
}
/* free strings of open recent files */
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 20e715c18d0..ff711c5ca4d 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -958,7 +958,7 @@ static wmKeyMapItem *wm_keymap_item_find(
RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
- if (WM_operator_properties_default(&opptr, TRUE)) {
+ if (WM_operator_properties_default(&opptr, true)) {
found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, 0, hotkey, keymap_r);
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index b4a4e4612e3..d0f258dc375 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -115,7 +115,7 @@ static GHash *global_ops_hash = NULL;
/* ************ operator API, exported ********** */
-wmOperatorType *WM_operatortype_find(const char *idname, int quiet)
+wmOperatorType *WM_operatortype_find(const char *idname, bool quiet)
{
if (idname[0]) {
wmOperatorType *ot;
@@ -779,7 +779,7 @@ void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, con
}
-void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context)
+void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
{
RNA_STRUCT_BEGIN(ptr, prop)
{
@@ -815,7 +815,7 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context)
* \note, theres nothing specific to operators here.
* this could be made a general function.
*/
-int WM_operator_properties_default(PointerRNA *ptr, const int do_update)
+int WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
{
int is_change = FALSE;
RNA_STRUCT_BEGIN(ptr, prop)
@@ -831,7 +831,7 @@ int WM_operator_properties_default(PointerRNA *ptr, const int do_update)
break;
}
default:
- if ((do_update == FALSE) || (RNA_property_is_set(ptr, prop) == FALSE)) {
+ if ((do_update == false) || (RNA_property_is_set(ptr, prop) == FALSE)) {
if (RNA_property_reset(ptr, prop, -1)) {
is_change = 1;
}
@@ -964,7 +964,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *arg_ot, cons
for (item = item_array; item->identifier; item++) {
/* note: need to give the index rather than the identifier because the enum can be freed */
if (BLI_strcasestr(item->name, str))
- if (0 == uiSearchItemAdd(items, item->name, SET_INT_IN_POINTER(item->value), 0))
+ if (false == uiSearchItemAdd(items, item->name, SET_INT_IN_POINTER(item->value), 0))
break;
}
@@ -1226,7 +1226,7 @@ int WM_operator_winactive(bContext *C)
}
/* return FALSE, if the UI should be disabled */
-int WM_operator_check_ui_enabled(const bContext *C, const char *idname)
+bool WM_operator_check_ui_enabled(const bContext *C, const char *idname)
{
wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 53698ca7e9e..70cb10476d7 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -97,8 +97,8 @@ static struct WMInitStruct {
int windowstate;
WinOverrideFlag override_flag;
- int native_pixels;
-} wm_init_state = {0, 0, 0, 0, GHOST_kWindowStateNormal, 0, 1};
+ bool native_pixels;
+} wm_init_state = {0, 0, 0, 0, GHOST_kWindowStateNormal, 0, true};
/* ******** win open & close ************ */
@@ -1332,7 +1332,7 @@ void WM_init_state_normal_set(void)
wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE;
}
-void WM_init_native_pixels(int do_it)
+void WM_init_native_pixels(bool do_it)
{
wm_init_state.native_pixels = do_it;
}
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index de40f7d6d3c..40eb9c673e2 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -413,11 +413,11 @@ void uiItemR(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, in
struct PointerRNA uiItemFullO(struct uiLayout *layout, char *idname, char *name, int icon, struct IDProperty *properties, int context, int flag) {struct PointerRNA a = {{0}}; return a;}
PointerRNA uiItemFullO_ptr(struct uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, struct IDProperty *properties, int context, int flag) {struct PointerRNA a = {{0}}; return a;}
-struct uiLayout *uiLayoutRow(struct uiLayout *layout, int align) {return (struct uiLayout *) NULL;}
-struct uiLayout *uiLayoutColumn(struct uiLayout *layout, int align) {return (struct uiLayout *) NULL;}
-struct uiLayout *uiLayoutColumnFlow(struct uiLayout *layout, int number, int align) {return (struct uiLayout *) NULL;}
+struct uiLayout *uiLayoutRow(struct uiLayout *layout, bool align) {return (struct uiLayout *) NULL;}
+struct uiLayout *uiLayoutColumn(struct uiLayout *layout, bool align) {return (struct uiLayout *) NULL;}
+struct uiLayout *uiLayoutColumnFlow(struct uiLayout *layout, int number, bool align) {return (struct uiLayout *) NULL;}
struct uiLayout *uiLayoutBox(struct uiLayout *layout) {return (struct uiLayout *) NULL;}
-struct uiLayout *uiLayoutSplit(struct uiLayout *layout, float percentage, int align) {return (struct uiLayout *) NULL;}
+struct uiLayout *uiLayoutSplit(struct uiLayout *layout, float percentage, bool align) {return (struct uiLayout *) NULL;}
int uiLayoutGetRedAlert(struct uiLayout *layout) {return 0;}
void uiLayoutSetRedAlert(struct uiLayout *layout, int redalert) {}
void uiItemsEnumR(struct uiLayout *layout, struct PointerRNA *ptr, char *propname) {}
@@ -439,7 +439,7 @@ void uiItemFullR(struct uiLayout *layout, struct PointerRNA *ptr, struct Propert
void uiLayoutSetContextPointer(struct uiLayout *layout, char *name, struct PointerRNA *ptr) {}
char *uiLayoutIntrospect(struct uiLayout *layout) {return (char *)NULL;}
void UI_reinit_font(void) {}
-int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big) {return 0;}
+int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big) {return 0;}
struct bTheme *UI_GetTheme(void) {return (struct bTheme *) NULL;};
/* rna template */
@@ -462,9 +462,7 @@ void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {}
void uiTemplateOperatorSearch(struct uiLayout *layout) {}
void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) {}
void uiTemplateEditModeSelection(struct uiLayout *layout, struct bContext *C) {}
-void uiTemplateTextureImage(struct uiLayout *layout, struct bContext *C, struct Tex *tex) {}
void uiTemplateImage(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *userptr, int compact) {}
-void uiTemplateDopeSheetFilter(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr) {}
void uiTemplateColorPicker(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {}
void uiTemplateHistogram(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {}
void uiTemplateReportsBanner(struct uiLayout *layout, struct bContext *C, struct wmOperator *op) {}
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 7abb653e9b8..1fec281a71c 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -660,7 +660,7 @@ static int prefsize(int argc, const char **argv, void *UNUSED(data))
static int native_pixels(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
- WM_init_native_pixels(0);
+ WM_init_native_pixels(false);
return 0;
}
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index f5f9b344b87..3f2a9a6df6a 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -46,11 +46,20 @@ void BL_BlenderShader::ReloadMaterial()
mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL;
}
-void BL_BlenderShader::SetProg(bool enable, double time)
+void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty)
{
if (VerifyShader()) {
- if (enable)
- GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1);
+ if (enable) {
+ assert(rasty != NULL); // XXX Kinda hacky, but SetProg() should always have the rasterizer if enable is true
+
+ float viewmat[4][4], viewinvmat[4][4];
+ const MT_Matrix4x4& view = rasty->GetViewMatrix();
+ const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix();
+ view.getValue((float*)viewmat);
+ viewinv.getValue((float*)viewinvmat);
+
+ GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat);
+ }
else
GPU_material_unbind(mGPUMat);
}
@@ -120,7 +129,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat)
void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
{
- float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4];
+ float obmat[4][4], obcol[4];
GPUMaterial *gpumat;
gpumat = mGPUMat;
@@ -130,13 +139,9 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
MT_Matrix4x4 model;
model.setValue(ms.m_OpenGLMatrix);
- const MT_Matrix4x4& view = rasty->GetViewMatrix();
- const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix();
// note: getValue gives back column major as needed by OpenGL
model.getValue((float*)obmat);
- view.getValue((float*)viewmat);
- viewinv.getValue((float*)viewinvmat);
if (ms.m_bObjectColor)
ms.m_RGBAcolor.getValue((float *)obcol);
@@ -144,7 +149,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
obcol[0] = obcol[1] = obcol[2] = obcol[3] = 1.0f;
float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol, auto_bump_scale);
+ GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale);
mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
}
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h
index 626c65baadd..71f66c2a49d 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.h
+++ b/source/gameengine/Ketsji/BL_BlenderShader.h
@@ -78,7 +78,7 @@ public:
// same as VerifyShared
return (NULL != mGPUMat);
}
- void SetProg(bool enable, double time=0.0);
+ void SetProg(bool enable, double time=0.0, RAS_IRasterizer* rasty=NULL);
int GetAttribNum();
void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat);
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 231ec27030d..853cfa53da2 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -314,7 +314,7 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras
else
BL_Texture::DisableAllTextures();
- mBlenderShader->SetProg(true, ras->GetTime());
+ mBlenderShader->SetProg(true, ras->GetTime(), ras);
mLastBlenderShader= mBlenderShader;
}
}