Merge branch 'master' into blender2.8

Conflicts:
	intern/cycles/blender/addon/properties.py
This commit is contained in:
2016-11-07 15:46:27 +01:00
72 changed files with 1359 additions and 719 deletions

View File

@@ -333,7 +333,7 @@ option(WITH_ALEMBIC "Enable Alembic Support" OFF)
option(WITH_ALEMBIC_HDF5 "Enable Legacy Alembic Support (not officially supported)" OFF) option(WITH_ALEMBIC_HDF5 "Enable Legacy Alembic Support (not officially supported)" OFF)
if(APPLE) if(APPLE)
option(WITH_CODEC_QUICKTIME "Enable Quicktime Support" ON) option(WITH_CODEC_QUICKTIME "Enable Quicktime Support" OFF)
endif() endif()
# 3D format support # 3D format support
@@ -508,6 +508,12 @@ mark_as_advanced(WITH_C11)
option(WITH_CXX11 "Build with C++11 standard enabled, for development use only!" ${_cxx11_init}) option(WITH_CXX11 "Build with C++11 standard enabled, for development use only!" ${_cxx11_init})
mark_as_advanced(WITH_CXX11) mark_as_advanced(WITH_CXX11)
# Compiler toolchain
if(CMAKE_COMPILER_IS_GNUCC)
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
mark_as_advanced(WITH_LINKER_GOLD)
endif()
# Dependency graph # Dependency graph
option(WITH_LEGACY_DEPSGRAPH "Build Blender with legacy dependency graph" ON) option(WITH_LEGACY_DEPSGRAPH "Build Blender with legacy dependency graph" ON)
mark_as_advanced(WITH_LEGACY_DEPSGRAPH) mark_as_advanced(WITH_LEGACY_DEPSGRAPH)
@@ -731,7 +737,7 @@ elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_AUDASPACE OR WITH_INTERNATIONAL O
# Keep enabled # Keep enabled
else() else()
# New dependency graph needs either Boost or C++11 for function bindings. # New dependency graph needs either Boost or C++11 for function bindings.
if(NOT USE_CXX11) if(NOT WITH_CXX11)
# Enabled but we don't need it # Enabled but we don't need it
set(WITH_BOOST OFF) set(WITH_BOOST OFF)
endif() endif()

View File

@@ -4015,9 +4015,6 @@ install_OTHER() {
fi fi
if [ "$_do_compile_llvm" = true ]; then if [ "$_do_compile_llvm" = true ]; then
install_packages_DEB libffi-dev
# LLVM can't find the debian ffi header dir
_FFI_INCLUDE_DIR=`dpkg -L libffi-dev | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'`
PRINT "" PRINT ""
compile_LLVM compile_LLVM
have_llvm=true have_llvm=true
@@ -4036,7 +4033,6 @@ install_OTHER() {
if [ "$_do_compile_osl" = true ]; then if [ "$_do_compile_osl" = true ]; then
if [ "$have_llvm" = true ]; then if [ "$have_llvm" = true ]; then
install_packages_DEB flex bison libtbb-dev
PRINT "" PRINT ""
compile_OSL compile_OSL
else else
@@ -4055,7 +4051,6 @@ install_OTHER() {
fi fi
if [ "$_do_compile_osd" = true ]; then if [ "$_do_compile_osd" = true ]; then
install_packages_DEB flex bison libtbb-dev
PRINT "" PRINT ""
compile_OSD compile_OSD
fi fi
@@ -4072,10 +4067,6 @@ install_OTHER() {
fi fi
if [ "$_do_compile_collada" = true ]; then if [ "$_do_compile_collada" = true ]; then
install_packages_DEB libpcre3-dev
# Find path to libxml shared lib...
_XML2_LIB=`dpkg -L libxml2-dev | grep -e ".*/libxml2.so"`
# No package
PRINT "" PRINT ""
compile_OpenCOLLADA compile_OpenCOLLADA
fi fi

View File

@@ -94,6 +94,7 @@ all_repositories = {
r'git://git.blender.org/blender-translations.git': 'blender-translations', r'git://git.blender.org/blender-translations.git': 'blender-translations',
r'git://git.blender.org/blender-addons.git': 'blender-addons', r'git://git.blender.org/blender-addons.git': 'blender-addons',
r'git://git.blender.org/blender-addons-contrib.git': 'blender-addons-contrib', r'git://git.blender.org/blender-addons-contrib.git': 'blender-addons-contrib',
r'git://git.blender.org/blender-dev-tools.git': 'blender-dev-tools',
r'https://svn.blender.org/svnroot/bf-blender/': 'lib svn', r'https://svn.blender.org/svnroot/bf-blender/': 'lib svn',
} }
@@ -128,6 +129,7 @@ def schedule_force_build(name):
forcesched.CodebaseParameter(hide=True, codebase="blender-translations"), forcesched.CodebaseParameter(hide=True, codebase="blender-translations"),
forcesched.CodebaseParameter(hide=True, codebase="blender-addons"), forcesched.CodebaseParameter(hide=True, codebase="blender-addons"),
forcesched.CodebaseParameter(hide=True, codebase="blender-addons-contrib"), forcesched.CodebaseParameter(hide=True, codebase="blender-addons-contrib"),
forcesched.CodebaseParameter(hide=True, codebase="blender-dev-tools"),
forcesched.CodebaseParameter(hide=True, codebase="lib svn")], forcesched.CodebaseParameter(hide=True, codebase="lib svn")],
properties=[])) properties=[]))
@@ -143,6 +145,7 @@ def schedule_build(name, hour, minute=0):
"blender-translations": {"repository": "", "branch": "master"}, "blender-translations": {"repository": "", "branch": "master"},
"blender-addons": {"repository": "", "branch": "master"}, "blender-addons": {"repository": "", "branch": "master"},
"blender-addons-contrib": {"repository": "", "branch": "master"}, "blender-addons-contrib": {"repository": "", "branch": "master"},
"blender-dev-tools": {"repository": "", "branch": "master"},
"lib svn": {"repository": "", "branch": "trunk"}}, "lib svn": {"repository": "", "branch": "trunk"}},
branch=current_branch, branch=current_branch,
builderNames=[name], builderNames=[name],
@@ -264,7 +267,8 @@ def generic_builder(id, libdir='', branch='', rsync=False):
for submodule in ('blender-translations', for submodule in ('blender-translations',
'blender-addons', 'blender-addons',
'blender-addons-contrib'): 'blender-addons-contrib',
'blender-dev-tools'):
f.addStep(git_submodule_step(submodule)) f.addStep(git_submodule_step(submodule))
f.addStep(git_step(branch)) f.addStep(git_step(branch))
@@ -299,7 +303,8 @@ add_builder(c, 'linux_glibc219_i686_cmake', '', generic_builder, hour=3)
add_builder(c, 'linux_glibc219_x86_64_cmake', '', generic_builder, hour=4) add_builder(c, 'linux_glibc219_x86_64_cmake', '', generic_builder, hour=4)
add_builder(c, 'win32_cmake_vc2013', 'windows_vc12', generic_builder, hour=3) add_builder(c, 'win32_cmake_vc2013', 'windows_vc12', generic_builder, hour=3)
add_builder(c, 'win64_cmake_vc2013', 'win64_vc12', generic_builder, hour=4) add_builder(c, 'win64_cmake_vc2013', 'win64_vc12', generic_builder, hour=4)
add_builder(c, 'win64_cmake_vc2015', 'win64_vc14', generic_builder, hour=5) add_builder(c, 'win32_cmake_vc2015', 'windows_vc14', generic_builder, hour=5)
add_builder(c, 'win64_cmake_vc2015', 'win64_vc14', generic_builder, hour=6)
# STATUS TARGETS # STATUS TARGETS
# #

View File

@@ -384,17 +384,18 @@ add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
if(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_COMPILER_IS_GNUCC)
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
# use ld.gold linker if available, could make optional if(WITH_LINKER_GOLD)
execute_process( execute_process(
COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
if("${LD_VERSION}" MATCHES "GNU gold") if("${LD_VERSION}" MATCHES "GNU gold")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold")
else() else()
message(STATUS "GNU gold linker isn't available, using the default system linker.") message(STATUS "GNU gold linker isn't available, using the default system linker.")
endif()
unset(LD_VERSION)
endif() endif()
unset(LD_VERSION)
# CLang is the same as GCC for now. # CLang is the same as GCC for now.
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")

View File

@@ -21,17 +21,6 @@
extern "C" { extern "C" {
#endif #endif
/* returns a list of devices for selection, array is empty identifier
* terminated and must not be freed */
typedef struct CCLDeviceInfo {
char identifier[128];
char name[512];
int value;
} CCLDeviceInfo;
CCLDeviceInfo *CCL_compute_device_list(int device_type);
/* create python module _cycles used by addon */ /* create python module _cycles used by addon */
void *CCL_python_module_init(void); void *CCL_python_module_init(void);

View File

@@ -21,7 +21,8 @@ from bpy.props import (BoolProperty,
EnumProperty, EnumProperty,
FloatProperty, FloatProperty,
IntProperty, IntProperty,
PointerProperty) PointerProperty,
StringProperty)
# enums # enums
@@ -122,6 +123,12 @@ enum_volume_interpolation = (
('CUBIC', "Cubic", "Smoothed high quality interpolation, but slower") ('CUBIC', "Cubic", "Smoothed high quality interpolation, but slower")
) )
enum_device_type = (
('CPU', "CPU", "CPU", 0),
('CUDA', "CUDA", "CUDA", 1),
('OPENCL', "OpenCL", "OpenCL", 2)
)
class CyclesRenderSettings(bpy.types.PropertyGroup): class CyclesRenderSettings(bpy.types.PropertyGroup):
@classmethod @classmethod
@@ -1087,6 +1094,103 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
del bpy.types.Scene.cycles_curves del bpy.types.Scene.cycles_curves
class CyclesDeviceSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
cls.id = StringProperty(name="ID")
cls.name = StringProperty(name="Name")
cls.use = BoolProperty(name="Use", default=True)
cls.type = EnumProperty(name="Type", items=enum_device_type, default='CUDA')
class CyclesPreferences(bpy.types.AddonPreferences):
bl_idname = __package__
def get_device_types(self, context):
import _cycles
has_cuda, has_opencl = _cycles.get_device_types()
list = [('NONE', "None", "Don't use compute device", 0)]
if has_cuda:
list.append(('CUDA', "CUDA", "Use CUDA for GPU acceleration", 1))
if has_opencl:
list.append(('OPENCL', "OpenCL", "Use OpenCL for GPU acceleration", 2))
return list
compute_device_type = EnumProperty(
name="Compute Device Type",
description="Device to use for computation (rendering with Cycles)",
items=get_device_types,
)
devices = bpy.props.CollectionProperty(type=CyclesDeviceSettings)
def get_devices(self):
import _cycles
# Layout of the device tuples: (Name, Type, Internal ID, Persistent ID)
device_list = _cycles.available_devices()
cuda_devices = []
opencl_devices = []
for device in device_list:
if not device[1] in {'CUDA', 'OPENCL'}:
continue
entry = None
# Try to find existing Device entry
for dev in self.devices:
if dev.id == device[2] and dev.type == device[1]:
entry = dev
break
# Create new entry if no existing one was found
if not entry:
entry = self.devices.add()
entry.id = device[2]
entry.name = device[0]
entry.type = device[1]
# Sort entries into lists
if entry.type == 'CUDA':
cuda_devices.append(entry)
elif entry.type == 'OPENCL':
opencl_devices.append(entry)
return cuda_devices, opencl_devices
def has_active_device(self):
import _cycles
device_list = _cycles.available_devices()
for device in device_list:
if device[1] != self.compute_device_type:
continue
if any(dev.use and dev.id == device[2] for dev in self.devices):
return True
return False
def draw_impl(self, layout, context):
layout.label(text="Compute Device:")
layout.row().prop(self, "compute_device_type", expand=True)
cuda_devices, opencl_devices = self.get_devices()
row = layout.row()
if cuda_devices:
col = row.column(align=True)
col.label(text="CUDA devices:")
for device in cuda_devices:
col.prop(device, "use", text=device.name, toggle=True)
if opencl_devices:
col = row.column(align=True)
col.label(text="OpenCL devices:")
for device in opencl_devices:
col.prop(device, "use", text=device.name, toggle=True)
def draw(self, context):
self.draw_impl(self.layout, context)
def register(): def register():
bpy.utils.register_class(CyclesRenderSettings) bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings) bpy.utils.register_class(CyclesCameraSettings)
@@ -1097,6 +1201,8 @@ def register():
bpy.utils.register_class(CyclesMeshSettings) bpy.utils.register_class(CyclesMeshSettings)
bpy.utils.register_class(CyclesObjectSettings) bpy.utils.register_class(CyclesObjectSettings)
bpy.utils.register_class(CyclesCurveRenderSettings) bpy.utils.register_class(CyclesCurveRenderSettings)
bpy.utils.register_class(CyclesDeviceSettings)
bpy.utils.register_class(CyclesPreferences)
def unregister(): def unregister():
@@ -1109,3 +1215,5 @@ def unregister():
bpy.utils.unregister_class(CyclesObjectSettings) bpy.utils.unregister_class(CyclesObjectSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings) bpy.utils.unregister_class(CyclesVisibilitySettings)
bpy.utils.unregister_class(CyclesCurveRenderSettings) bpy.utils.unregister_class(CyclesCurveRenderSettings)
bpy.utils.unregister_class(CyclesDeviceSettings)
bpy.utils.unregister_class(CyclesPreferences)

View File

@@ -53,25 +53,26 @@ class CyclesButtonsPanel:
return rd.engine in cls.COMPAT_ENGINES return rd.engine in cls.COMPAT_ENGINES
def get_device_type(context):
return context.user_preferences.addons[__package__].preferences.compute_device_type
def use_cpu(context): def use_cpu(context):
cscene = context.scene.cycles cscene = context.scene.cycles
device_type = context.user_preferences.system.compute_device_type
return (device_type == 'NONE' or cscene.device == 'CPU') return (get_device_type(context) == 'NONE' or cscene.device == 'CPU')
def use_opencl(context): def use_opencl(context):
cscene = context.scene.cycles cscene = context.scene.cycles
device_type = context.user_preferences.system.compute_device_type
return (device_type == 'OPENCL' and cscene.device == 'GPU') return (get_device_type(context) == 'OPENCL' and cscene.device == 'GPU')
def use_cuda(context): def use_cuda(context):
cscene = context.scene.cycles cscene = context.scene.cycles
device_type = context.user_preferences.system.compute_device_type
return (device_type == 'CUDA' and cscene.device == 'GPU') return (get_device_type(context) == 'CUDA' and cscene.device == 'GPU')
def use_branched_path(context): def use_branched_path(context):
@@ -85,6 +86,14 @@ def use_sample_all_lights(context):
return cscene.sample_all_lights_direct or cscene.sample_all_lights_indirect return cscene.sample_all_lights_direct or cscene.sample_all_lights_indirect
def show_device_selection(context):
type = get_device_type(context)
if type == 'NETWORK':
return True
if not type in {'CUDA', 'OPENCL'}:
return False
return context.user_preferences.addons[__package__].preferences.has_active_device()
def draw_samples_info(layout, context): def draw_samples_info(layout, context):
cscene = context.scene.cycles cscene = context.scene.cycles
@@ -141,7 +150,6 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
scene = context.scene scene = context.scene
cscene = scene.cycles cscene = scene.cycles
device_type = context.user_preferences.system.compute_device_type
row = layout.row(align=True) row = layout.row(align=True)
row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label) row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
@@ -150,7 +158,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
row = layout.row() row = layout.row()
sub = row.row() sub = row.row()
sub.active = device_type != 'OPENCL' or use_cpu(context) sub.active = get_device_type(context) != 'OPENCL' or use_cpu(context)
sub.prop(cscene, "progressive", text="") sub.prop(cscene, "progressive", text="")
row.prop(cscene, "use_square_samples") row.prop(cscene, "use_square_samples")
@@ -1542,9 +1550,13 @@ def draw_device(self, context):
layout.prop(cscene, "feature_set") layout.prop(cscene, "feature_set")
device_type = context.user_preferences.system.compute_device_type split = layout.split(percentage=1/3)
if device_type in {'CUDA', 'OPENCL', 'NETWORK'}: split.label("Device:")
layout.prop(cscene, "device") row = split.row(align=True)
sub = row.split(align=True)
sub.active = show_device_selection(context)
sub.prop(cscene, "device", text="")
row.operator("wm.addon_userpref_show", text="Preferences", icon='PREFERENCES').module = __package__
if engine.with_osl() and use_cpu(context): if engine.with_osl() and use_cpu(context):
layout.prop(cscene, "shading_system") layout.prop(cscene, "shading_system")

View File

@@ -40,10 +40,6 @@ CCL_NAMESPACE_BEGIN
namespace { namespace {
/* Device list stored static (used by compute_device_list()). */
static ccl::vector<CCLDeviceInfo> device_list;
static ccl::DeviceType device_type = DEVICE_NONE;
/* Flag describing whether debug flags were synchronized from scene. */ /* Flag describing whether debug flags were synchronized from scene. */
bool debug_flags_set = false; bool debug_flags_set = false;
@@ -195,7 +191,6 @@ static PyObject *exit_func(PyObject * /*self*/, PyObject * /*args*/)
ShaderManager::free_memory(); ShaderManager::free_memory();
TaskScheduler::free_memory(); TaskScheduler::free_memory();
Device::free_memory(); Device::free_memory();
device_list.free_memory();
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -389,7 +384,12 @@ static PyObject *available_devices_func(PyObject * /*self*/, PyObject * /*args*/
for(size_t i = 0; i < devices.size(); i++) { for(size_t i = 0; i < devices.size(); i++) {
DeviceInfo& device = devices[i]; DeviceInfo& device = devices[i];
PyTuple_SET_ITEM(ret, i, PyUnicode_FromString(device.description.c_str())); string type_name = Device::string_from_type(device.type);
PyObject *device_tuple = PyTuple_New(3);
PyTuple_SET_ITEM(device_tuple, 0, PyUnicode_FromString(device.description.c_str()));
PyTuple_SET_ITEM(device_tuple, 1, PyUnicode_FromString(type_name.c_str()));
PyTuple_SET_ITEM(device_tuple, 2, PyUnicode_FromString(device.id.c_str()));
PyTuple_SET_ITEM(ret, i, device_tuple);
} }
return ret; return ret;
@@ -676,6 +676,20 @@ static PyObject *set_resumable_chunks_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
{
vector<DeviceInfo>& devices = Device::available_devices();
bool has_cuda = false, has_opencl = false;
for(int i = 0; i < devices.size(); i++) {
has_cuda |= (devices[i].type == DEVICE_CUDA);
has_opencl |= (devices[i].type == DEVICE_OPENCL);
}
PyObject *list = PyTuple_New(2);
PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_opencl));
return list;
}
static PyMethodDef methods[] = { static PyMethodDef methods[] = {
{"init", init_func, METH_VARARGS, ""}, {"init", init_func, METH_VARARGS, ""},
{"exit", exit_func, METH_VARARGS, ""}, {"exit", exit_func, METH_VARARGS, ""},
@@ -703,6 +717,9 @@ static PyMethodDef methods[] = {
/* Resumable render */ /* Resumable render */
{"set_resumable_chunks", set_resumable_chunks_func, METH_VARARGS, ""}, {"set_resumable_chunks", set_resumable_chunks_func, METH_VARARGS, ""},
/* Compute Device selection */
{"get_device_types", get_device_types_func, METH_VARARGS, ""},
{NULL, NULL, 0, NULL}, {NULL, NULL, 0, NULL},
}; };
@@ -715,47 +732,6 @@ static struct PyModuleDef module = {
NULL, NULL, NULL, NULL NULL, NULL, NULL, NULL
}; };
static CCLDeviceInfo *compute_device_list(DeviceType type)
{
/* create device list if it's not already done */
if(type != device_type) {
ccl::vector<DeviceInfo>& devices = ccl::Device::available_devices();
device_type = type;
device_list.clear();
/* add devices */
int i = 0;
foreach(DeviceInfo& info, devices) {
if(info.type == type ||
(info.type == DEVICE_MULTI && info.multi_devices[0].type == type))
{
CCLDeviceInfo cinfo;
strncpy(cinfo.identifier, info.id.c_str(), sizeof(cinfo.identifier));
cinfo.identifier[info.id.length()] = '\0';
strncpy(cinfo.name, info.description.c_str(), sizeof(cinfo.name));
cinfo.name[info.description.length()] = '\0';
cinfo.value = i++;
device_list.push_back(cinfo);
}
}
/* null terminate */
if(!device_list.empty()) {
CCLDeviceInfo cinfo = {"", "", 0};
device_list.push_back(cinfo);
}
}
return (device_list.empty())? NULL: &device_list[0];
}
CCL_NAMESPACE_END CCL_NAMESPACE_END
void *CCL_python_module_init() void *CCL_python_module_init()
@@ -794,24 +770,3 @@ void *CCL_python_module_init()
return (void*)mod; return (void*)mod;
} }
CCLDeviceInfo *CCL_compute_device_list(int device_type)
{
ccl::DeviceType type;
switch(device_type) {
case 0:
type = ccl::DEVICE_CUDA;
break;
case 1:
type = ccl::DEVICE_OPENCL;
break;
case 2:
type = ccl::DEVICE_NETWORK;
break;
default:
type = ccl::DEVICE_NONE;
break;
}
return ccl::compute_device_list(type);
}

View File

@@ -523,7 +523,12 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
vector<DeviceInfo>& devices = Device::available_devices(); vector<DeviceInfo>& devices = Device::available_devices();
/* device default CPU */ /* device default CPU */
params.device = devices[0]; foreach(DeviceInfo& device, devices) {
if(device.type == DEVICE_CPU) {
params.device = device;
break;
}
}
if(get_enum(cscene, "device") == 2) { if(get_enum(cscene, "device") == 2) {
/* find network device */ /* find network device */
@@ -532,17 +537,39 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
params.device = info; params.device = info;
} }
else if(get_enum(cscene, "device") == 1) { else if(get_enum(cscene, "device") == 1) {
/* find GPU device with given id */ PointerRNA b_preferences;
PointerRNA systemptr = b_userpref.system().ptr;
PropertyRNA *deviceprop = RNA_struct_find_property(&systemptr, "compute_device");
int device_id = b_userpref.system().compute_device();
const char *id; BL::UserPreferences::addons_iterator b_addon_iter;
for(b_userpref.addons.begin(b_addon_iter); b_addon_iter != b_userpref.addons.end(); ++b_addon_iter) {
if(b_addon_iter->module() == "cycles") {
b_preferences = b_addon_iter->preferences().ptr;
break;
}
}
if(RNA_property_enum_identifier(NULL, &systemptr, deviceprop, device_id, &id)) { int compute_device = get_enum(b_preferences, "compute_device_type");
foreach(DeviceInfo& info, devices)
if(info.id == id) if(compute_device != 0) {
params.device = info; vector<DeviceInfo> used_devices;
RNA_BEGIN(&b_preferences, device, "devices") {
if(get_enum(device, "type") == compute_device && get_boolean(device, "use")) {
string id = get_string(device, "id");
foreach(DeviceInfo& info, devices) {
if(info.id == id) {
used_devices.push_back(info);
break;
}
}
}
} RNA_END
if(used_devices.size() == 1) {
params.device = used_devices[0];
}
else if(used_devices.size() > 1) {
params.device = Device::get_multi_device(used_devices);
}
/* Else keep using the CPU device that was set before. */
} }
} }

View File

@@ -44,6 +44,10 @@ if(WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD)
else() else()
message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES") message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES")
set(WITH_CYCLES_CUDA_BINARIES OFF) set(WITH_CYCLES_CUDA_BINARIES OFF)
if(NOT WITH_CUDA_DYNLOAD)
message(STATUS "Additionally falling back to dynamic CUDA load")
set(WITH_CUDA_DYNLOAD ON)
endif()
endif() endif()
endif() endif()

View File

@@ -258,33 +258,33 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
DeviceType Device::type_from_string(const char *name) DeviceType Device::type_from_string(const char *name)
{ {
if(strcmp(name, "cpu") == 0) if(strcmp(name, "CPU") == 0)
return DEVICE_CPU; return DEVICE_CPU;
else if(strcmp(name, "cuda") == 0) else if(strcmp(name, "CUDA") == 0)
return DEVICE_CUDA; return DEVICE_CUDA;
else if(strcmp(name, "opencl") == 0) else if(strcmp(name, "OPENCL") == 0)
return DEVICE_OPENCL; return DEVICE_OPENCL;
else if(strcmp(name, "network") == 0) else if(strcmp(name, "NETWORK") == 0)
return DEVICE_NETWORK; return DEVICE_NETWORK;
else if(strcmp(name, "multi") == 0) else if(strcmp(name, "MULTI") == 0)
return DEVICE_MULTI; return DEVICE_MULTI;
return DEVICE_NONE; return DEVICE_NONE;
} }
string Device::string_from_type(DeviceType type) string Device::string_from_type(DeviceType type)
{ {
if(type == DEVICE_CPU) if(type == DEVICE_CPU)
return "cpu"; return "CPU";
else if(type == DEVICE_CUDA) else if(type == DEVICE_CUDA)
return "cuda"; return "CUDA";
else if(type == DEVICE_OPENCL) else if(type == DEVICE_OPENCL)
return "opencl"; return "OPENCL";
else if(type == DEVICE_NETWORK) else if(type == DEVICE_NETWORK)
return "network"; return "NETWORK";
else if(type == DEVICE_MULTI) else if(type == DEVICE_MULTI)
return "multi"; return "MULTI";
return ""; return "";
} }
@@ -307,9 +307,6 @@ vector<DeviceType>& Device::available_types()
#ifdef WITH_NETWORK #ifdef WITH_NETWORK
types.push_back(DEVICE_NETWORK); types.push_back(DEVICE_NETWORK);
#endif #endif
#ifdef WITH_MULTI
types.push_back(DEVICE_MULTI);
#endif
need_types_update = false; need_types_update = false;
} }
@@ -331,10 +328,6 @@ vector<DeviceInfo>& Device::available_devices()
device_opencl_info(devices); device_opencl_info(devices);
#endif #endif
#ifdef WITH_MULTI
device_multi_info(devices);
#endif
device_cpu_info(devices); device_cpu_info(devices);
#ifdef WITH_NETWORK #ifdef WITH_NETWORK
@@ -368,6 +361,29 @@ string Device::device_capabilities()
return capabilities; return capabilities;
} }
DeviceInfo Device::get_multi_device(vector<DeviceInfo> subdevices)
{
assert(subdevices.size() > 1);
DeviceInfo info;
info.type = DEVICE_MULTI;
info.id = "MULTI";
info.description = "Multi Device";
info.multi_devices = subdevices;
info.num = 0;
info.has_bindless_textures = true;
info.pack_images = false;
foreach(DeviceInfo &device, subdevices) {
assert(device.type == info.multi_devices[0].type);
info.pack_images |= device.pack_images;
info.has_bindless_textures &= device.has_bindless_textures;
}
return info;
}
void Device::tag_update() void Device::tag_update()
{ {
need_types_update = true; need_types_update = true;

View File

@@ -49,7 +49,7 @@ class DeviceInfo {
public: public:
DeviceType type; DeviceType type;
string description; string description;
string id; string id; /* used for user preferences, should stay fixed with changing hardware config */
int num; int num;
bool display_device; bool display_device;
bool advanced_shading; bool advanced_shading;
@@ -69,6 +69,12 @@ public:
has_bindless_textures = false; has_bindless_textures = false;
use_split_kernel = false; use_split_kernel = false;
} }
bool operator==(const DeviceInfo &info) {
/* Multiple Devices with the same ID would be very bad. */
assert(id != info.id || (type == info.type && num == info.num && description == info.description));
return id == info.id;
}
}; };
class DeviceRequestedFeatures { class DeviceRequestedFeatures {
@@ -282,6 +288,7 @@ public:
static vector<DeviceType>& available_types(); static vector<DeviceType>& available_types();
static vector<DeviceInfo>& available_devices(); static vector<DeviceInfo>& available_devices();
static string device_capabilities(); static string device_capabilities();
static DeviceInfo get_multi_device(vector<DeviceInfo> subdevices);
/* Tag devices lists for update. */ /* Tag devices lists for update. */
static void tag_update(); static void tag_update();

View File

@@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include <climits>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -213,7 +214,8 @@ public:
return; return;
int major, minor; int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId); cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
cuDevArchitecture = major*100 + minor*10; cuDevArchitecture = major*100 + minor*10;
cuda_pop_context(); cuda_pop_context();
@@ -233,7 +235,8 @@ public:
bool support_device(const DeviceRequestedFeatures& /*requested_features*/) bool support_device(const DeviceRequestedFeatures& /*requested_features*/)
{ {
int major, minor; int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId); cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
/* We only support sm_20 and above */ /* We only support sm_20 and above */
if(major < 2) { if(major < 2) {
@@ -315,7 +318,8 @@ public:
{ {
/* Compute cubin name. */ /* Compute cubin name. */
int major, minor; int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId); cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
/* Attempt to use kernel provided with Blender. */ /* Attempt to use kernel provided with Blender. */
if(!use_adaptive_compilation()) { if(!use_adaptive_compilation()) {
@@ -1394,8 +1398,8 @@ void device_cuda_info(vector<DeviceInfo>& devices)
if(cuDeviceGetName(name, 256, num) != CUDA_SUCCESS) if(cuDeviceGetName(name, 256, num) != CUDA_SUCCESS)
continue; continue;
int major, minor; int major;
cuDeviceComputeCapability(&major, &minor, num); cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, num);
if(major < 2) { if(major < 2) {
continue; continue;
} }
@@ -1404,13 +1408,18 @@ void device_cuda_info(vector<DeviceInfo>& devices)
info.type = DEVICE_CUDA; info.type = DEVICE_CUDA;
info.description = string(name); info.description = string(name);
info.id = string_printf("CUDA_%d", num);
info.num = num; info.num = num;
info.advanced_shading = (major >= 2); info.advanced_shading = (major >= 2);
info.has_bindless_textures = (major >= 3); info.has_bindless_textures = (major >= 3);
info.pack_images = false; info.pack_images = false;
int pci_location[3] = {0, 0, 0};
cuDeviceGetAttribute(&pci_location[0], CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, num);
cuDeviceGetAttribute(&pci_location[1], CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, num);
cuDeviceGetAttribute(&pci_location[2], CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, num);
info.id = string_printf("CUDA_%s_%04x:%02x:%02x", name, pci_location[0], pci_location[1], pci_location[2]);
/* if device has a kernel timeout, assume it is used for display */ /* if device has a kernel timeout, assume it is used for display */
if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) { if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) {
info.description += " (Display)"; info.description += " (Display)";

View File

@@ -33,7 +33,6 @@ void device_cpu_info(vector<DeviceInfo>& devices);
void device_opencl_info(vector<DeviceInfo>& devices); void device_opencl_info(vector<DeviceInfo>& devices);
void device_cuda_info(vector<DeviceInfo>& devices); void device_cuda_info(vector<DeviceInfo>& devices);
void device_network_info(vector<DeviceInfo>& devices); void device_network_info(vector<DeviceInfo>& devices);
void device_multi_info(vector<DeviceInfo>& devices);
string device_cpu_capabilities(void); string device_cpu_capabilities(void);
string device_opencl_capabilities(void); string device_opencl_capabilities(void);

View File

@@ -350,120 +350,5 @@ Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background)
return new MultiDevice(info, stats, background); return new MultiDevice(info, stats, background);
} }
static bool device_multi_add(vector<DeviceInfo>& devices, DeviceType type, bool with_display, bool with_advanced_shading, const char *id_fmt, int num)
{
DeviceInfo info;
/* create map to find duplicate descriptions */
map<string, int> dupli_map;
map<string, int>::iterator dt;
int num_added = 0, num_display = 0;
info.advanced_shading = with_advanced_shading;
info.pack_images = false;
info.has_bindless_textures = true;
foreach(DeviceInfo& subinfo, devices) {
if(subinfo.type == type) {
if(subinfo.advanced_shading != info.advanced_shading)
continue;
if(subinfo.display_device) {
if(with_display)
num_display++;
else
continue;
}
string key = subinfo.description;
if(dupli_map.find(key) == dupli_map.end())
dupli_map[key] = 1;
else
dupli_map[key]++;
info.multi_devices.push_back(subinfo);
if(subinfo.display_device)
info.display_device = true;
info.pack_images = info.pack_images || subinfo.pack_images;
info.has_bindless_textures = info.has_bindless_textures && subinfo.has_bindless_textures;
num_added++;
}
}
if(num_added <= 1 || (with_display && num_display == 0))
return false;
/* generate string */
stringstream desc;
vector<string> last_tokens;
bool first = true;
for(dt = dupli_map.begin(); dt != dupli_map.end(); dt++) {
if(!first) desc << " + ";
first = false;
/* get name and count */
string name = dt->first;
int count = dt->second;
/* strip common prefixes */
vector<string> tokens;
string_split(tokens, dt->first);
if(tokens.size() > 1) {
int i;
for(i = 0; i < tokens.size() && i < last_tokens.size(); i++)
if(tokens[i] != last_tokens[i])
break;
name = "";
for(; i < tokens.size(); i++) {
name += tokens[i];
if(i != tokens.size() - 1)
name += " ";
}
}
last_tokens = tokens;
/* add */
if(count > 1)
desc << name << " (" << count << "x)";
else
desc << name;
}
/* add info */
info.type = DEVICE_MULTI;
info.description = desc.str();
info.id = string_printf(id_fmt, num);
info.display_device = with_display;
info.num = 0;
if(with_display)
devices.push_back(info);
else
devices.insert(devices.begin(), info);
return true;
}
void device_multi_info(vector<DeviceInfo>& devices)
{
int num = 0;
if(!device_multi_add(devices, DEVICE_CUDA, false, true, "CUDA_MULTI_%d", num++))
device_multi_add(devices, DEVICE_CUDA, false, false, "CUDA_MULTI_%d", num++);
if(!device_multi_add(devices, DEVICE_CUDA, true, true, "CUDA_MULTI_%d", num++))
device_multi_add(devices, DEVICE_CUDA, true, false, "CUDA_MULTI_%d", num++);
num = 0;
if(!device_multi_add(devices, DEVICE_OPENCL, false, true, "OPENCL_MULTI_%d", num++))
device_multi_add(devices, DEVICE_OPENCL, false, false, "OPENCL_MULTI_%d", num++);
if(!device_multi_add(devices, DEVICE_OPENCL, true, true, "OPENCL_MULTI_%d", num++))
device_multi_add(devices, DEVICE_OPENCL, true, false, "OPENCL_MULTI_%d", num++);
}
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -83,17 +83,22 @@ void device_opencl_info(vector<DeviceInfo>& devices)
const string& platform_name = platform_device.platform_name; const string& platform_name = platform_device.platform_name;
const cl_device_type device_type = platform_device.device_type; const cl_device_type device_type = platform_device.device_type;
const string& device_name = platform_device.device_name; const string& device_name = platform_device.device_name;
string hardware_id = platform_device.hardware_id;
if(hardware_id == "") {
hardware_id = string_printf("ID_%d", num_devices);
}
DeviceInfo info; DeviceInfo info;
info.type = DEVICE_OPENCL; info.type = DEVICE_OPENCL;
info.description = string_remove_trademark(string(device_name)); info.description = string_remove_trademark(string(device_name));
info.num = num_devices; info.num = num_devices;
info.id = string_printf("OPENCL_%d", info.num);
/* We don't know if it's used for display, but assume it is. */ /* We don't know if it's used for display, but assume it is. */
info.display_device = true; info.display_device = true;
info.advanced_shading = OpenCLInfo::kernel_use_advanced_shading(platform_name); info.advanced_shading = OpenCLInfo::kernel_use_advanced_shading(platform_name);
info.pack_images = true; info.pack_images = true;
info.use_split_kernel = OpenCLInfo::kernel_use_split(platform_name, info.use_split_kernel = OpenCLInfo::kernel_use_split(platform_name,
device_type); device_type);
info.id = string("OPENCL_") + platform_name + "_" + device_name + "_" + hardware_id;
devices.push_back(info); devices.push_back(info);
num_devices++; num_devices++;
} }

View File

@@ -55,17 +55,20 @@ struct OpenCLPlatformDevice {
const string& platform_name, const string& platform_name,
cl_device_id device_id, cl_device_id device_id,
cl_device_type device_type, cl_device_type device_type,
const string& device_name) const string& device_name,
const string& hardware_id)
: platform_id(platform_id), : platform_id(platform_id),
platform_name(platform_name), platform_name(platform_name),
device_id(device_id), device_id(device_id),
device_type(device_type), device_type(device_type),
device_name(device_name) {} device_name(device_name),
hardware_id(hardware_id) {}
cl_platform_id platform_id; cl_platform_id platform_id;
string platform_name; string platform_name;
cl_device_id device_id; cl_device_id device_id;
cl_device_type device_type; cl_device_type device_type;
string device_name; string device_name;
string hardware_id;
}; };
/* Contains all static OpenCL helper functions. */ /* Contains all static OpenCL helper functions. */
@@ -83,6 +86,8 @@ public:
string *error = NULL); string *error = NULL);
static bool device_version_check(cl_device_id device, static bool device_version_check(cl_device_id device,
string *error = NULL); string *error = NULL);
static string get_hardware_id(string platform_name,
cl_device_id device_id);
static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices, static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
bool force_all = false); bool force_all = false);
}; };

View File

@@ -661,6 +661,27 @@ bool OpenCLInfo::device_version_check(cl_device_id device,
return true; return true;
} }
string OpenCLInfo::get_hardware_id(string platform_name, cl_device_id device_id)
{
if(platform_name == "AMD Accelerated Parallel Processing" || platform_name == "Apple") {
/* Use cl_amd_device_topology extension. */
cl_char topology[24];
if(clGetDeviceInfo(device_id, 0x4037, sizeof(topology), topology, NULL) == CL_SUCCESS && topology[0] == 1) {
return string_printf("%02x:%02x.%01x", topology[21], topology[22], topology[23]);
}
}
else if(platform_name == "NVIDIA CUDA") {
/* Use two undocumented options of the cl_nv_device_attribute_query extension. */
cl_int bus_id, slot_id;
if(clGetDeviceInfo(device_id, 0x4008, sizeof(cl_int), &bus_id, NULL) == CL_SUCCESS &&
clGetDeviceInfo(device_id, 0x4009, sizeof(cl_int), &slot_id, NULL) == CL_SUCCESS) {
return string_printf("%02x:%02x.%01x", bus_id, slot_id>>3, slot_id & 0x7);
}
}
/* No general way to get a hardware ID from OpenCL => give up. */
return "";
}
void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices, void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
bool force_all) bool force_all)
{ {
@@ -773,11 +794,13 @@ void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices
continue; continue;
} }
FIRST_VLOG(2) << "Adding new device " << device_name << "."; FIRST_VLOG(2) << "Adding new device " << device_name << ".";
string hardware_id = get_hardware_id(platform_name, device_id);
usable_devices->push_back(OpenCLPlatformDevice(platform_id, usable_devices->push_back(OpenCLPlatformDevice(platform_id,
platform_name, platform_name,
device_id, device_id,
device_type, device_type,
device_name)); device_name,
hardware_id));
} }
else { else {
FIRST_VLOG(2) << "Ignoring device " << device_name FIRST_VLOG(2) << "Ignoring device " << device_name

View File

@@ -162,10 +162,14 @@ ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, cons
ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N) ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
{ {
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
*N = normalize(transform_direction_transposed_auto(&ccl_fetch(sd, ob_tfm), *N)); if((ccl_fetch(sd, object) != OBJECT_NONE) || (ccl_fetch(sd, type) == PRIMITIVE_LAMP)) {
*N = normalize(transform_direction_transposed_auto(&ccl_fetch(sd, ob_tfm), *N));
}
#else #else
Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); if(ccl_fetch(sd, object) != OBJECT_NONE) {
*N = normalize(transform_direction_transposed(&tfm, *N)); Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
}
#endif #endif
} }

View File

@@ -301,7 +301,7 @@ ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, ccl_addr_space RN
} }
/* Utitility functions to get light termination value, since it might not be needed in many cases. */ /* Utitility functions to get light termination value, since it might not be needed in many cases. */
ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state) ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state)
{ {
if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) { if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
return path_state_rng_1D_for_decision(kg, rng, state, PRNG_LIGHT_TERMINATE); return path_state_rng_1D_for_decision(kg, rng, state, PRNG_LIGHT_TERMINATE);

View File

@@ -276,16 +276,13 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, time); shader_setup_object_transforms(kg, sd, time);
#endif ccl_fetch(sd, time) = time;
} }
else if(lamp != LAMP_NONE) { else if(lamp != LAMP_NONE) {
ccl_fetch(sd, ob_tfm) = lamp_fetch_transform(kg, lamp, false); ccl_fetch(sd, ob_tfm) = lamp_fetch_transform(kg, lamp, false);
ccl_fetch(sd, ob_itfm) = lamp_fetch_transform(kg, lamp, true); ccl_fetch(sd, ob_itfm) = lamp_fetch_transform(kg, lamp, true);
}
#ifdef __OBJECT_MOTION__
ccl_fetch(sd, time) = time;
#endif #endif
}
/* transform into world space */ /* transform into world space */
if(object_space) { if(object_space) {

View File

@@ -241,8 +241,7 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float
float3 N = ccl_fetch(sd, N); float3 N = ccl_fetch(sd, N);
N = ccl_fetch(sd, N); N = ccl_fetch(sd, N);
if(ccl_fetch(sd, object) != OBJECT_NONE) object_inverse_normal_transform(kg, sd, &N);
object_inverse_normal_transform(kg, sd, &N);
/* project from direction vector to barycentric coordinates in triangles */ /* project from direction vector to barycentric coordinates in triangles */
N.x = fabsf(N.x); N.x = fabsf(N.x);

View File

@@ -49,8 +49,7 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg,
} }
case NODE_TEXCO_NORMAL: { case NODE_TEXCO_NORMAL: {
data = ccl_fetch(sd, N); data = ccl_fetch(sd, N);
if((ccl_fetch(sd, object) != OBJECT_NONE) || (ccl_fetch(sd, type) == PRIMITIVE_LAMP)) object_inverse_normal_transform(kg, sd, &data);
object_inverse_normal_transform(kg, sd, &data);
break; break;
} }
case NODE_TEXCO_CAMERA: { case NODE_TEXCO_CAMERA: {
@@ -131,8 +130,7 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg,
} }
case NODE_TEXCO_NORMAL: { case NODE_TEXCO_NORMAL: {
data = ccl_fetch(sd, N); data = ccl_fetch(sd, N);
if((ccl_fetch(sd, object) != OBJECT_NONE) || (ccl_fetch(sd, type) == PRIMITIVE_LAMP)) object_inverse_normal_transform(kg, sd, &data);
object_inverse_normal_transform(kg, sd, &data);
break; break;
} }
case NODE_TEXCO_CAMERA: { case NODE_TEXCO_CAMERA: {
@@ -216,8 +214,7 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg,
} }
case NODE_TEXCO_NORMAL: { case NODE_TEXCO_NORMAL: {
data = ccl_fetch(sd, N); data = ccl_fetch(sd, N);
if((ccl_fetch(sd, object) != OBJECT_NONE) || (ccl_fetch(sd, type) == PRIMITIVE_LAMP)) object_inverse_normal_transform(kg, sd, &data);
object_inverse_normal_transform(kg, sd, &data);
break; break;
} }
case NODE_TEXCO_CAMERA: { case NODE_TEXCO_CAMERA: {

View File

@@ -43,8 +43,8 @@ static void shade_background_pixels(Device *device, DeviceScene *dscene, int res
for(int y = 0; y < height; y++) { for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) { for(int x = 0; x < width; x++) {
float u = x/(float)width; float u = (x + 0.5f)/width;
float v = y/(float)height; float v = (y + 0.5f)/height;
uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0); uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0);
d_input_data[x + y*width] = in; d_input_data[x + y*width] = in;

View File

@@ -89,8 +89,7 @@ public:
} }
bool modified(const SessionParams& params) bool modified(const SessionParams& params)
{ return !(device.type == params.device.type { return !(device == params.device
&& device.id == params.device.id
&& background == params.background && background == params.background
&& progressive_refine == params.progressive_refine && progressive_refine == params.progressive_refine
&& output_path == params.output_path && output_path == params.output_path

View File

@@ -65,9 +65,9 @@ TEST(ModalSolver, SyntheticCubeSceneMotion) {
NULL); NULL);
Mat3 expected_rotation; Mat3 expected_rotation;
expected_rotation << 0.98215101299251, 0.17798357184544, 0.06083778292258, expected_rotation << 0.98215101743472, 0.17798354937546, 0.06083777694542,
-0.16875286001759, 0.97665299913606, -0.13293378620359, -0.16875283983360, 0.97665300495333, -0.13293376908719,
-0.08307743323957, 0.12029450291547, 0.98925596922871; -0.08307742172243, 0.12029448893171, 0.98925597189636;
Mat3 &first_camera_R = reconstruction.CameraForImage(1)->R; Mat3 &first_camera_R = reconstruction.CameraForImage(1)->R;
Mat3 &second_camera_R = reconstruction.CameraForImage(2)->R; Mat3 &second_camera_R = reconstruction.CameraForImage(2)->R;

View File

@@ -4,6 +4,11 @@ REM This is for users who like to configure & build Blender with a single comman
setlocal ENABLEEXTENSIONS setlocal ENABLEEXTENSIONS
set BLENDER_DIR=%~dp0 set BLENDER_DIR=%~dp0
set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =%
if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
goto EOF
)
set BUILD_DIR=%BLENDER_DIR%..\build_windows set BUILD_DIR=%BLENDER_DIR%..\build_windows
set BUILD_TYPE=Release set BUILD_TYPE=Release
rem reset all variables so they do not get accidentally get carried over from previous builds rem reset all variables so they do not get accidentally get carried over from previous builds

View File

@@ -198,3 +198,53 @@ class MeshSelectPrev(Operator):
bmesh.update_edit_mesh(me, False) bmesh.update_edit_mesh(me, False)
return {'FINISHED'} return {'FINISHED'}
# XXX This is hackish (going forth and back from Object mode...), to be redone once we have proper support of
# custom normals in BMesh/edit mode.
class MehsSetNormalsFromFaces(Operator):
"""Set the custom vertex normals from the selected faces ones"""
bl_idname = "mesh.set_normals_from_faces"
bl_label = "Set Normals From Faces"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return (context.mode == 'EDIT_MESH' and context.edit_object.data.polygons)
def execute(self, context):
import mathutils
bpy.ops.object.mode_set(mode='OBJECT')
obj = context.active_object
me = obj.data
v2nors = {}
for p in me.polygons:
if not p.select:
continue
for lidx, vidx in zip(p.loop_indices, p.vertices):
assert(me.loops[lidx].vertex_index == vidx)
v2nors.setdefault(vidx, []).append(p.normal)
for nors in v2nors.values():
nors[:] = [sum(nors, mathutils.Vector((0, 0, 0))).normalized()]
if not me.has_custom_normals:
me.create_normals_split()
me.calc_normals_split()
normals = []
for l in me.loops:
nor = v2nors.get(l.vertex_index, [None])[0]
if nor is None:
nor = l.normal
normals.append(nor.to_tuple())
me.normals_split_custom_set(normals)
me.free_normals_split()
bpy.ops.object.mode_set(mode='EDIT')
return {'FINISHED'}

View File

@@ -2163,3 +2163,32 @@ class WM_OT_addon_expand(Operator):
info["show_expanded"] = not info["show_expanded"] info["show_expanded"] = not info["show_expanded"]
return {'FINISHED'} return {'FINISHED'}
class WM_OT_addon_userpref_show(Operator):
"Show add-on user preferences"
bl_idname = "wm.addon_userpref_show"
bl_label = ""
bl_options = {'INTERNAL'}
module = StringProperty(
name="Module",
description="Module name of the add-on to expand",
)
def execute(self, context):
import addon_utils
module_name = self.module
modules = addon_utils.modules(refresh=False)
mod = addon_utils.addons_fake_modules.get(module_name)
if mod is not None:
info = addon_utils.module_bl_info(mod)
info["show_expanded"] = True
bpy.context.user_preferences.active_section = 'ADDONS'
context.window_manager.addon_filter = 'All'
context.window_manager.addon_search = info["name"]
bpy.ops.screen.userpref_show('INVOKE_DEFAULT')
return {'FINISHED'}

View File

@@ -205,30 +205,60 @@ class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Pa
row = col.row(align=True) row = col.row(align=True)
sub = row.row(align=True) sub = row.row(align=True)
sub.scale_x = 0.1 sub.scale_x = 0.5
sub.prop(rbc, "use_spring_x", toggle=True, text="X") sub.prop(rbc, "use_spring_x", toggle=True, text="X Axis")
sub = row.row(align=True) sub = row.row(align=True)
sub.active = rbc.use_spring_x sub.active = rbc.use_spring_x
sub.prop(rbc, "spring_stiffness_x", text="Stiffness") sub.prop(rbc, "spring_stiffness_x", text="Stiffness")
sub.prop(rbc, "spring_damping_x") sub.prop(rbc, "spring_damping_x", text="Damping")
row = col.row(align=True) row = col.row(align=True)
sub = row.row(align=True) sub = row.row(align=True)
sub.scale_x = 0.1 sub.scale_x = 0.5
sub.prop(rbc, "use_spring_y", toggle=True, text="Y") sub.prop(rbc, "use_spring_y", toggle=True, text="Y Axis")
sub = row.row(align=True) sub = row.row(align=True)
sub.active = rbc.use_spring_y sub.active = rbc.use_spring_y
sub.prop(rbc, "spring_stiffness_y", text="Stiffness") sub.prop(rbc, "spring_stiffness_y", text="Stiffness")
sub.prop(rbc, "spring_damping_y") sub.prop(rbc, "spring_damping_y", text="Damping")
row = col.row(align=True) row = col.row(align=True)
sub = row.row(align=True) sub = row.row(align=True)
sub.scale_x = 0.1 sub.scale_x = 0.5
sub.prop(rbc, "use_spring_z", toggle=True, text="Z") sub.prop(rbc, "use_spring_z", toggle=True, text="Z Axis")
sub = row.row(align=True) sub = row.row(align=True)
sub.active = rbc.use_spring_z sub.active = rbc.use_spring_z
sub.prop(rbc, "spring_stiffness_z", text="Stiffness") sub.prop(rbc, "spring_stiffness_z", text="Stiffness")
sub.prop(rbc, "spring_damping_z") sub.prop(rbc, "spring_damping_z", text="Damping")
col = layout.column(align=True)
row = col.row(align=True)
sub = row.row(align=True)
sub.scale_x = 0.5
sub.prop(rbc, "use_spring_ang_x", toggle=True, text="X Angle")
sub = row.row(align=True)
sub.active = rbc.use_spring_ang_x
sub.prop(rbc, "spring_stiffness_ang_x", text="Stiffness")
sub.prop(rbc, "spring_damping_ang_x", text="Damping")
row = col.row(align=True)
sub = row.row(align=True)
sub.scale_x = 0.5
sub.prop(rbc, "use_spring_ang_y", toggle=True, text="Y Angle")
sub = row.row(align=True)
sub.active = rbc.use_spring_ang_y
sub.prop(rbc, "spring_stiffness_ang_y", text="Stiffness")
sub.prop(rbc, "spring_damping_ang_y", text="Damping")
row = col.row(align=True)
sub = row.row(align=True)
sub.scale_x = 0.5
sub.prop(rbc, "use_spring_ang_z", toggle=True, text="Z Angle")
sub = row.row(align=True)
sub.active = rbc.use_spring_ang_z
sub.prop(rbc, "spring_stiffness_ang_z", text="Stiffness")
sub.prop(rbc, "spring_damping_ang_z", text="Damping")
if __name__ == "__main__": # only for live edit. if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__) bpy.utils.register_module(__name__)

View File

@@ -428,13 +428,6 @@ class USERPREF_PT_system(Panel):
col.separator() col.separator()
if hasattr(system, "compute_device_type"):
col.label(text="Compute Device:")
col.row().prop(system, "compute_device_type", expand=True)
sub = col.row()
sub.active = system.compute_device_type != 'CPU'
sub.prop(system, "compute_device", text="")
if hasattr(system, "opensubdiv_compute_type"): if hasattr(system, "opensubdiv_compute_type"):
col.label(text="OpenSubdiv compute:") col.label(text="OpenSubdiv compute:")
col.row().prop(system, "opensubdiv_compute_type", text="") col.row().prop(system, "opensubdiv_compute_type", text="")

View File

@@ -431,6 +431,7 @@ class VIEW3D_PT_tools_shading(View3DPanel, Panel):
col.label(text="Normals:") col.label(text="Normals:")
col.operator("mesh.normals_make_consistent", text="Recalculate") col.operator("mesh.normals_make_consistent", text="Recalculate")
col.operator("mesh.flip_normals", text="Flip Direction") col.operator("mesh.flip_normals", text="Flip Direction")
col.operator("mesh.set_normals_from_faces", text="Set From Faces")
class VIEW3D_PT_tools_uvs(View3DPanel, Panel): class VIEW3D_PT_tools_uvs(View3DPanel, Panel):

View File

@@ -97,6 +97,7 @@ void BKE_armature_where_is(struct bArmature *arm);
void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion); void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
void BKE_pose_clear_pointers(struct bPose *pose); void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm); void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
void BKE_pose_rebuild_ex(struct Object *ob, struct bArmature *arm, const bool sort_bones);
void BKE_pose_where_is(struct Scene *scene, struct Object *ob); void BKE_pose_where_is(struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra); void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan); void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);

View File

@@ -1781,6 +1781,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
BLI_duplicatelist(&pose->agroups, &frompose->agroups); BLI_duplicatelist(&pose->agroups, &frompose->agroups);
pose->active_group = frompose->active_group; pose->active_group = frompose->active_group;
BKE_pose_channels_hash_make(frompose);
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
pchanp = BKE_pose_channel_find_name(frompose, pchan->name); pchanp = BKE_pose_channel_find_name(frompose, pchan->name);
@@ -1916,7 +1917,7 @@ void BKE_pose_clear_pointers(bPose *pose)
/* only after leave editmode, duplicating, validating older files, library syncing */ /* only after leave editmode, duplicating, validating older files, library syncing */
/* NOTE: pose->flag is set for it */ /* NOTE: pose->flag is set for it */
void BKE_pose_rebuild(Object *ob, bArmature *arm) void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones)
{ {
Bone *bone; Bone *bone;
bPose *pose; bPose *pose;
@@ -1963,8 +1964,9 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
#ifdef WITH_LEGACY_DEPSGRAPH #ifdef WITH_LEGACY_DEPSGRAPH
/* the sorting */ /* the sorting */
/* Sorting for new dependnecy graph is done on the scene graph level. */ /* Sorting for new dependnecy graph is done on the scene graph level. */
if (counter > 1) if (counter > 1 && sort_bones) {
DAG_pose_sort(ob); DAG_pose_sort(ob);
}
#endif #endif
ob->pose->flag &= ~POSE_RECALC; ob->pose->flag &= ~POSE_RECALC;
@@ -1973,6 +1975,11 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
BKE_pose_channels_hash_make(ob->pose); BKE_pose_channels_hash_make(ob->pose);
} }
void BKE_pose_rebuild(Object *ob, bArmature *arm)
{
BKE_pose_rebuild_ex(ob, arm, true);
}
/* ********************** THE POSE SOLVER ******************* */ /* ********************** THE POSE SOLVER ******************* */
/* loc/rot/size to given mat4 */ /* loc/rot/size to given mat4 */

View File

@@ -93,7 +93,9 @@ void BKE_cachefile_free(CacheFile *cache_file)
ABC_free_handle(cache_file->handle); ABC_free_handle(cache_file->handle);
#endif #endif
BLI_mutex_free(cache_file->handle_mutex); if (cache_file->handle_mutex) {
BLI_mutex_free(cache_file->handle_mutex);
}
BLI_freelistN(&cache_file->object_paths); BLI_freelistN(&cache_file->object_paths);
} }

View File

@@ -1761,7 +1761,8 @@ void BKE_library_make_local(
it->link = NULL; it->link = NULL;
do_loop = true; do_loop = true;
} }
else { /* Only used by linked data, potential candidate to ugly lib-only dependency cycles... */ /* Only used by linked data, potential candidate to ugly lib-only dependency cycles... */
else if ((id->tag & LIB_TAG_DOIT) == 0) { /* Check TAG_DOIT to avoid adding same ID several times... */
/* Note that we store the node, not directly ID pointer, that way if it->link is set to NULL /* Note that we store the node, not directly ID pointer, that way if it->link is set to NULL
* later we can skip it in lib-dependency cycles search later. */ * later we can skip it in lib-dependency cycles search later. */
BLI_linklist_prepend_arena(&linked_loop_candidates, it, linklist_mem); BLI_linklist_prepend_arena(&linked_loop_candidates, it, linklist_mem);
@@ -1804,6 +1805,7 @@ void BKE_library_make_local(
BKE_libblock_unlink(bmain, id, false, false); BKE_libblock_unlink(bmain, id, false, false);
BKE_libblock_free(bmain, id); BKE_libblock_free(bmain, id);
#endif #endif
((LinkNode *)it->link)->link = NULL; /* Not strictly necessary, but safer (see T49903)... */
it->link = NULL; it->link = NULL;
} }
} }

View File

@@ -58,6 +58,7 @@
#include "BLI_strict_flags.h" #include "BLI_strict_flags.h"
#include "atomic_ops.h"
#include "mikktspace.h" #include "mikktspace.h"
// #define DEBUG_TIME // #define DEBUG_TIME
@@ -236,7 +237,9 @@ static void mesh_calc_normals_poly_accum_task_cb(void *userdata, const int pidx)
const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
/* accumulate */ /* accumulate */
madd_v3_v3fl(vnors[ml[i].v], pnor, fac); for (int k = 3; k--; ) {
atomic_add_fl(&vnors[ml[i].v][k], pnor[k] * fac);
}
prev_edge = cur_edge; prev_edge = cur_edge;
} }
} }

View File

@@ -799,6 +799,18 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z); RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z);
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z); RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z);
RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->flag & RBC_FLAG_USE_SPRING_ANG_X);
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_stiffness_ang_x);
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_damping_ang_x);
RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y);
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_stiffness_ang_y);
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_damping_ang_y);
RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z);
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_stiffness_ang_z);
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z);
RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint); RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
/* fall-through */ /* fall-through */
case RBC_TYPE_6DOF: case RBC_TYPE_6DOF:
@@ -1057,9 +1069,15 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *UNUSED(scene), Object *ob,
rbc->spring_damping_x = 0.5f; rbc->spring_damping_x = 0.5f;
rbc->spring_damping_y = 0.5f; rbc->spring_damping_y = 0.5f;
rbc->spring_damping_z = 0.5f; rbc->spring_damping_z = 0.5f;
rbc->spring_damping_ang_x = 0.5f;
rbc->spring_damping_ang_y = 0.5f;
rbc->spring_damping_ang_z = 0.5f;
rbc->spring_stiffness_x = 10.0f; rbc->spring_stiffness_x = 10.0f;
rbc->spring_stiffness_y = 10.0f; rbc->spring_stiffness_y = 10.0f;
rbc->spring_stiffness_z = 10.0f; rbc->spring_stiffness_z = 10.0f;
rbc->spring_stiffness_ang_x = 10.0f;
rbc->spring_stiffness_ang_y = 10.0f;
rbc->spring_stiffness_ang_z = 10.0f;
rbc->motor_lin_max_impulse = 1.0f; rbc->motor_lin_max_impulse = 1.0f;
rbc->motor_lin_target_velocity = 1.0f; rbc->motor_lin_target_velocity = 1.0f;

View File

@@ -52,6 +52,7 @@
#include "DNA_actuator_types.h" #include "DNA_actuator_types.h"
#include "DNA_view3d_types.h" #include "DNA_view3d_types.h"
#include "DNA_smoke_types.h" #include "DNA_smoke_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_genfile.h" #include "DNA_genfile.h"
@@ -1359,5 +1360,20 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
} }
} }
} }
if (!DNA_struct_elem_find(fd->filesdna, "RigidBodyCon", "float", "spring_stiffness_ang_x")) {
Object *ob;
for (ob = main->object.first; ob; ob = ob->id.next) {
RigidBodyCon *rbc = ob->rigidbody_constraint;
if (rbc) {
rbc->spring_stiffness_ang_x = 10.0;
rbc->spring_stiffness_ang_y = 10.0;
rbc->spring_stiffness_ang_z = 10.0;
rbc->spring_damping_ang_x = 0.5;
rbc->spring_damping_ang_y = 0.5;
rbc->spring_damping_ang_z = 0.5;
}
}
}
} }
} }

View File

@@ -113,11 +113,6 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B
node.addMatrix("transform",d_obmat); node.addMatrix("transform",d_obmat);
break; break;
} }
case BC_TRANSFORMATION_TYPE_BOTH:
{
node.addMatrix("transform",d_obmat);
/* fall-through */
}
case BC_TRANSFORMATION_TYPE_TRANSROTLOC: case BC_TRANSFORMATION_TYPE_TRANSROTLOC:
{ {
float loc[3], rot[3], scale[3]; float loc[3], rot[3], scale[3];

View File

@@ -43,8 +43,7 @@ typedef enum BC_export_mesh_type {
typedef enum BC_export_transformation_type { typedef enum BC_export_transformation_type {
BC_TRANSFORMATION_TYPE_MATRIX, BC_TRANSFORMATION_TYPE_MATRIX,
BC_TRANSFORMATION_TYPE_TRANSROTLOC, BC_TRANSFORMATION_TYPE_TRANSROTLOC
BC_TRANSFORMATION_TYPE_BOTH
} BC_export_transformation_type; } BC_export_transformation_type;
struct bContext; struct bContext;

View File

@@ -118,7 +118,7 @@ void TextureBaseOperation::executePixelSampled(float output[4], float x, float y
* interpolaiton and (b) in such configuration multitex() sinply floor's the value * interpolaiton and (b) in such configuration multitex() sinply floor's the value
* which often produces artifacts. * which often produces artifacts.
*/ */
if ((m_texture->imaflag & TEX_INTERPOL) == 0) { if (m_texture != NULL && (m_texture->imaflag & TEX_INTERPOL) == 0) {
u += 0.5f / cx; u += 0.5f / cx;
v += 0.5f / cy; v += 0.5f / cy;
} }

View File

@@ -45,6 +45,7 @@ set(SRC
intern/builder/deg_builder_nodes.cc intern/builder/deg_builder_nodes.cc
intern/builder/deg_builder_pchanmap.cc intern/builder/deg_builder_pchanmap.cc
intern/builder/deg_builder_relations.cc intern/builder/deg_builder_relations.cc
intern/builder/deg_builder_relations_keys.cc
intern/builder/deg_builder_transitive.cc intern/builder/deg_builder_transitive.cc
intern/debug/deg_debug_graphviz.cc intern/debug/deg_debug_graphviz.cc
intern/eval/deg_eval.cc intern/eval/deg_eval.cc

View File

@@ -56,12 +56,14 @@ struct StackEntry {
void deg_graph_detect_cycles(Depsgraph *graph) void deg_graph_detect_cycles(Depsgraph *graph)
{ {
/* Not is not visited at all during traversal. */ enum {
const int NODE_NOT_VISITED = 0; /* Not is not visited at all during traversal. */
/* Node has been visited during traversal and not in current stack. */ NODE_NOT_VISITED = 0,
const int NODE_VISITED = 1; /* Node has been visited during traversal and not in current stack. */
/* Node has been visited during traversal and is in current stack. */ NODE_VISITED = 1,
const int NODE_IN_STACK = 2; /* Node has been visited during traversal and is in current stack. */
NODE_IN_STACK = 2,
};
std::stack<StackEntry> traversal_stack; std::stack<StackEntry> traversal_stack;
foreach (OperationDepsNode *node, graph->operations) { foreach (OperationDepsNode *node, graph->operations) {
@@ -77,21 +79,23 @@ void deg_graph_detect_cycles(Depsgraph *graph)
entry.from = NULL; entry.from = NULL;
entry.via_relation = NULL; entry.via_relation = NULL;
traversal_stack.push(entry); traversal_stack.push(entry);
node->done = NODE_IN_STACK; node->tag = NODE_IN_STACK;
} }
else { else {
node->done = NODE_NOT_VISITED; node->tag = NODE_NOT_VISITED;
} }
node->done = 0;
} }
while (!traversal_stack.empty()) { while (!traversal_stack.empty()) {
StackEntry &entry = traversal_stack.top(); StackEntry entry = traversal_stack.top();
OperationDepsNode *node = entry.node; OperationDepsNode *node = entry.node;
bool all_child_traversed = true; bool all_child_traversed = true;
foreach (DepsRelation *rel, node->outlinks) { for (int i = node->done; i < node->outlinks.size(); ++i) {
DepsRelation *rel = node->outlinks[i];
if (rel->to->type == DEPSNODE_TYPE_OPERATION) { if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
OperationDepsNode *to = (OperationDepsNode *)rel->to; OperationDepsNode *to = (OperationDepsNode *)rel->to;
if (to->done == NODE_IN_STACK) { if (to->tag == NODE_IN_STACK) {
printf("Dependency cycle detected:\n"); printf("Dependency cycle detected:\n");
printf(" '%s' depends on '%s' through '%s'\n", printf(" '%s' depends on '%s' through '%s'\n",
to->full_identifier().c_str(), to->full_identifier().c_str(),
@@ -107,23 +111,24 @@ void deg_graph_detect_cycles(Depsgraph *graph)
current->via_relation->name); current->via_relation->name);
current = current->from; current = current->from;
} }
/* TODO(sergey): So called roussian rlette cycle solver. */ /* TODO(sergey): So called russian roulette cycle solver. */
rel->flag |= DEPSREL_FLAG_CYCLIC; rel->flag |= DEPSREL_FLAG_CYCLIC;
} }
else if (to->done == NODE_NOT_VISITED) { else if (to->tag == NODE_NOT_VISITED) {
StackEntry new_entry; StackEntry new_entry;
new_entry.node = to; new_entry.node = to;
new_entry.from = &entry; new_entry.from = &entry;
new_entry.via_relation = rel; new_entry.via_relation = rel;
traversal_stack.push(new_entry); traversal_stack.push(new_entry);
to->done = NODE_IN_STACK; to->tag = NODE_IN_STACK;
all_child_traversed = false; all_child_traversed = false;
node->done = i;
break; break;
} }
} }
} }
if (all_child_traversed) { if (all_child_traversed) {
node->done = NODE_VISITED; node->tag = NODE_VISITED;
traversal_stack.pop(); traversal_stack.pop();
} }
} }

View File

@@ -34,7 +34,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
@@ -129,8 +128,7 @@ RootDepsNode *DepsgraphNodeBuilder::add_root_node()
IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id) IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
{ {
const char *idtype_name = BKE_idcode_to_name(GS(id->name)); return m_graph->add_id_node(id, id->name);
return m_graph->add_id_node(id, string(id->name + 2) + "[" + idtype_name + "]");
} }
TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id) TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id)
@@ -177,7 +175,7 @@ TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id)
ComponentDepsNode *DepsgraphNodeBuilder::add_component_node( ComponentDepsNode *DepsgraphNodeBuilder::add_component_node(
ID *id, ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
const string &comp_name) const char *comp_name)
{ {
IDDepsNode *id_node = add_id_node(id); IDDepsNode *id_node = add_id_node(id);
ComponentDepsNode *comp_node = id_node->add_component(comp_type, comp_name); ComponentDepsNode *comp_node = id_node->add_component(comp_type, comp_name);
@@ -190,15 +188,19 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
eDepsOperation_Type optype, eDepsOperation_Type optype,
DepsEvalOperationCb op, DepsEvalOperationCb op,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string &description) const char *name,
int name_tag)
{ {
OperationDepsNode *op_node = comp_node->has_operation(opcode, description); OperationDepsNode *op_node = comp_node->has_operation(opcode,
name,
name_tag);
if (op_node == NULL) { if (op_node == NULL) {
op_node = comp_node->add_operation(optype, op, opcode, description); op_node = comp_node->add_operation(optype, op, opcode, name, name_tag);
m_graph->operations.push_back(op_node); m_graph->operations.push_back(op_node);
} }
else { else {
fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n", fprintf(stderr,
"add_operation: Operation already exists - %s has %s at %p\n",
comp_node->identifier().c_str(), comp_node->identifier().c_str(),
op_node->identifier().c_str(), op_node->identifier().c_str(),
op_node); op_node);
@@ -210,14 +212,15 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
ID *id, ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
const string &comp_name, const char *comp_name,
eDepsOperation_Type optype, eDepsOperation_Type optype,
DepsEvalOperationCb op, DepsEvalOperationCb op,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string &description) const char *name,
int name_tag)
{ {
ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name); ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name);
return add_operation_node(comp_node, optype, op, opcode, description); return add_operation_node(comp_node, optype, op, opcode, name, name_tag);
} }
OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
@@ -226,38 +229,54 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
eDepsOperation_Type optype, eDepsOperation_Type optype,
DepsEvalOperationCb op, DepsEvalOperationCb op,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string& description) const char *name,
int name_tag)
{ {
return add_operation_node(id, comp_type, "", optype, op, opcode, description); return add_operation_node(id,
comp_type,
"",
optype,
op,
opcode,
name,
name_tag);
} }
bool DepsgraphNodeBuilder::has_operation_node(ID *id, bool DepsgraphNodeBuilder::has_operation_node(ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
const string &comp_name, const char *comp_name,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string &description) const char *name,
int name_tag)
{ {
return find_operation_node(id, comp_type, comp_name, opcode, description) != NULL; return find_operation_node(id,
comp_type,
comp_name,
opcode,
name,
name_tag) != NULL;
} }
OperationDepsNode *DepsgraphNodeBuilder::find_operation_node( OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
ID *id, ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
const string &comp_name, const char *comp_name,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string &description) const char *name,
int name_tag)
{ {
ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name); ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name);
return comp_node->has_operation(opcode, description); return comp_node->has_operation(opcode, name, name_tag);
} }
OperationDepsNode *DepsgraphNodeBuilder::find_operation_node( OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
ID *id, ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string& description) const char *name,
int name_tag)
{ {
return find_operation_node(id, comp_type, "", opcode, description); return find_operation_node(id, comp_type, "", opcode, name, name_tag);
} }
/* **** Build functions for entity nodes **** */ /* **** Build functions for entity nodes **** */
@@ -610,12 +629,17 @@ OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
OperationDepsNode *driver_op = find_operation_node(id, OperationDepsNode *driver_op = find_operation_node(id,
DEPSNODE_TYPE_PARAMETERS, DEPSNODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER, DEG_OPCODE_DRIVER,
deg_fcurve_id_name(fcu)); fcu->rna_path,
fcu->array_index);
if (driver_op == NULL) { if (driver_op == NULL) {
driver_op = add_operation_node(id, DEPSNODE_TYPE_PARAMETERS, driver_op = add_operation_node(id,
DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_driver, _1, id, fcu), DEPSNODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu)); DEPSOP_TYPE_EXEC,
function_bind(BKE_animsys_eval_driver, _1, id, fcu),
DEG_OPCODE_DRIVER,
fcu->rna_path,
fcu->array_index);
} }
/* tag "scripted expression" drivers as needing Python (due to GIL issues, etc.) */ /* tag "scripted expression" drivers as needing Python (due to GIL issues, etc.) */
@@ -760,7 +784,7 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
/* Rebuild pose if not up to date. */ /* Rebuild pose if not up to date. */
if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) { if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
BKE_pose_rebuild(ob, arm); BKE_pose_rebuild_ex(ob, arm, false);
/* XXX: Without this animation gets lost in certain circumstances /* XXX: Without this animation gets lost in certain circumstances
* after loading file. Need to investigate further since it does * after loading file. Need to investigate further since it does
* not happen with simple scenes.. * not happen with simple scenes..
@@ -1124,15 +1148,20 @@ void DepsgraphNodeBuilder::build_nodetree(DepsNode *owner_node, bNodeTree *ntree
/* nodetree's nodes... */ /* nodetree's nodes... */
for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) { for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) {
if (bnode->id) { ID *id = bnode->id;
if (GS(bnode->id->name) == ID_MA) { if (id != NULL) {
build_material(owner_node, (Material *)bnode->id); short id_type = GS(id->name);
if (id_type == ID_MA) {
build_material(owner_node, (Material *)id);
} }
else if (bnode->type == ID_TE) { else if (id_type == ID_TE) {
build_texture(owner_node, (Tex *)bnode->id); build_texture(owner_node, (Tex *)id);
}
else if (id_type == ID_IM) {
build_image((Image *)id);
} }
else if (bnode->type == NODE_GROUP) { else if (bnode->type == NODE_GROUP) {
bNodeTree *group_ntree = (bNodeTree *)bnode->id; bNodeTree *group_ntree = (bNodeTree *)id;
if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) { if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
build_nodetree(owner_node, group_ntree); build_nodetree(owner_node, group_ntree);
} }
@@ -1189,10 +1218,33 @@ void DepsgraphNodeBuilder::build_texture(DepsNode *owner_node, Tex *tex)
return; return;
} }
tex_id->tag |= LIB_TAG_DOIT; tex_id->tag |= LIB_TAG_DOIT;
/* texture itself */ /* Texture itself. */
build_animdata(tex_id); build_animdata(tex_id);
/* texture's nodetree */ /* Texture's nodetree. */
build_nodetree(owner_node, tex->nodetree); build_nodetree(owner_node, tex->nodetree);
/* Special cases for different IDs which texture uses. */
if (tex->type == TEX_IMAGE) {
if (tex->ima != NULL) {
build_image(tex->ima);
}
}
}
void DepsgraphNodeBuilder::build_image(Image *image) {
ID *image_id = &image->id;
if (image_id->tag & LIB_TAG_DOIT) {
return;
}
image_id->tag |= LIB_TAG_DOIT;
/* Image ID node itself. */
add_id_node(image_id);
/* Placeholder so we can add relations and tag ID node for update. */
add_operation_node(image_id,
DEPSNODE_TYPE_PARAMETERS,
DEPSOP_TYPE_EXEC,
NULL,
DEG_OPCODE_PLACEHOLDER,
"Image Eval");
} }
void DepsgraphNodeBuilder::build_compositor(Scene *scene) void DepsgraphNodeBuilder::build_compositor(Scene *scene)

View File

@@ -38,6 +38,7 @@ struct bGPdata;
struct ListBase; struct ListBase;
struct GHash; struct GHash;
struct ID; struct ID;
struct Image;
struct FCurve; struct FCurve;
struct Group; struct Group;
struct Key; struct Key;
@@ -75,43 +76,49 @@ struct DepsgraphNodeBuilder {
ComponentDepsNode *add_component_node(ID *id, ComponentDepsNode *add_component_node(ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
const string& comp_name = ""); const char *comp_name = "");
OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node, OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node,
eDepsOperation_Type optype, eDepsOperation_Type optype,
DepsEvalOperationCb op, DepsEvalOperationCb op,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string& description = ""); const char *name = "",
int name_tag = -1);
OperationDepsNode *add_operation_node(ID *id, OperationDepsNode *add_operation_node(ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
const string& comp_name, const char *comp_name,
eDepsOperation_Type optype, eDepsOperation_Type optype,
DepsEvalOperationCb op, DepsEvalOperationCb op,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string& description = ""); const char *name = "",
int name_tag = -1);
OperationDepsNode *add_operation_node(ID *id, OperationDepsNode *add_operation_node(ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
eDepsOperation_Type optype, eDepsOperation_Type optype,
DepsEvalOperationCb op, DepsEvalOperationCb op,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string& description = ""); const char *name = "",
int name_tag = -1);
bool has_operation_node(ID *id, bool has_operation_node(ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
const string& comp_name, const char *comp_name,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string& description = ""); const char *name = "",
int name_tag = -1);
OperationDepsNode *find_operation_node(ID *id, OperationDepsNode *find_operation_node(ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
const string &comp_name, const char *comp_name,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string &description = ""); const char *name = "",
int name_tag = -1);
OperationDepsNode *find_operation_node(ID *id, OperationDepsNode *find_operation_node(ID *id,
eDepsNode_Type comp_type, eDepsNode_Type comp_type,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string &description = ""); const char *name = "",
int name_tag = -1);
void build_scene(Main *bmain, Scene *scene); void build_scene(Main *bmain, Scene *scene);
SubgraphDepsNode *build_subgraph(Group *group); SubgraphDepsNode *build_subgraph(Group *group);
@@ -142,6 +149,7 @@ struct DepsgraphNodeBuilder {
void build_material(DepsNode *owner_node, Material *ma); void build_material(DepsNode *owner_node, Material *ma);
void build_texture(DepsNode *owner_node, Tex *tex); void build_texture(DepsNode *owner_node, Tex *tex);
void build_texture_stack(DepsNode *owner_node, MTex **texture_stack); void build_texture_stack(DepsNode *owner_node, MTex **texture_stack);
void build_image(Image *image);
void build_world(World *world); void build_world(World *world);
void build_compositor(Scene *scene); void build_compositor(Scene *scene);
void build_gpencil(bGPdata *gpd); void build_gpencil(bGPdata *gpd);

View File

@@ -34,13 +34,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <cstring> /* required for STREQ later on. */
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
extern "C" { extern "C" {
#include "BLI_blenlib.h" #include "BLI_blenlib.h"
#include "BLI_string.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "DNA_action_types.h" #include "DNA_action_types.h"
@@ -209,10 +208,12 @@ OperationDepsNode *DepsgraphRelationBuilder::find_node(
return NULL; return NULL;
} }
OperationDepsNode *op_node = comp_node->find_operation(key.opcode, key.name); OperationDepsNode *op_node = comp_node->find_operation(key.opcode,
key.name,
key.name_tag);
if (!op_node) { if (!op_node) {
fprintf(stderr, "find_node_operation: Failed for (%s, '%s')\n", fprintf(stderr, "find_node_operation: Failed for (%s, '%s')\n",
DEG_OPNAMES[key.opcode], key.name.c_str()); DEG_OPNAMES[key.opcode], key.name);
} }
return op_node; return op_node;
} }
@@ -234,7 +235,7 @@ OperationDepsNode *DepsgraphRelationBuilder::has_node(
if (!comp_node) { if (!comp_node) {
return NULL; return NULL;
} }
return comp_node->has_operation(key.opcode, key.name); return comp_node->has_operation(key.opcode, key.name, key.name_tag);
} }
void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc, void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
@@ -483,7 +484,7 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
build_animdata(&ob->id); build_animdata(&ob->id);
// XXX: This should be hooked up by the build_animdata code // XXX: This should be hooked up by the build_animdata code
if (ob->adt && (ob->adt->action || ob->adt->nla_tracks.first)) { if (needs_animdata_node(&ob->id)) {
ComponentKey adt_key(&ob->id, DEPSNODE_TYPE_ANIMATION); ComponentKey adt_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
add_relation(adt_key, local_transform_key, DEPSREL_TYPE_OPERATION, "Object Animation"); add_relation(adt_key, local_transform_key, DEPSREL_TYPE_OPERATION, "Object Animation");
} }
@@ -815,11 +816,66 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
/* drivers */ /* drivers */
for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) { for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) {
OperationKey driver_key(id, DEPSNODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu)); OperationKey driver_key(id,
DEPSNODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu->rna_path,
fcu->array_index);
/* create the driver's relations to targets */ /* create the driver's relations to targets */
build_driver(id, fcu); build_driver(id, fcu);
/* Special case for array drivers: we can not multithread them because
* of the way how they work internally: animation system will write the
* whole array back to RNA even when changing individual array value.
*
* Some tricky things here:
* - array_index is -1 for single channel drivers, meaning we only have
* to do some magic when array_index is not -1.
* - We do relation from next array index to a previous one, so we don't
* have to deal with array index 0.
*
* TODO(sergey): Avoid liner lookup somehow.
*/
if (fcu->array_index > 0) {
FCurve *fcu_prev = NULL;
for (FCurve *fcu_candidate = (FCurve *)adt->drivers.first;
fcu_candidate != NULL;
fcu_candidate = fcu_candidate->next)
{
/* Writing to different RNA paths is */
if (!STREQ(fcu_candidate->rna_path, fcu->rna_path)) {
continue;
}
/* We only do relation from previous fcurve to previous one. */
if (fcu_candidate->array_index >= fcu->array_index) {
continue;
}
/* Choose fcurve with highest possible array index. */
if (fcu_prev == NULL ||
fcu_candidate->array_index > fcu_prev->array_index)
{
fcu_prev = fcu_candidate;
}
}
if (fcu_prev != NULL) {
OperationKey prev_driver_key(id,
DEPSNODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu_prev->rna_path,
fcu_prev->array_index);
OperationKey driver_key(id,
DEPSNODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu->rna_path,
fcu->array_index);
add_relation(prev_driver_key,
driver_key,
DEPSREL_TYPE_OPERATION,
"[Driver Order]");
}
}
/* prevent driver from occurring before own animation... */ /* prevent driver from occurring before own animation... */
if (adt->action || adt->nla_tracks.first) { if (adt->action || adt->nla_tracks.first) {
add_relation(adt_key, driver_key, DEPSREL_TYPE_OPERATION, add_relation(adt_key, driver_key, DEPSREL_TYPE_OPERATION,
@@ -831,7 +887,11 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
{ {
ChannelDriver *driver = fcu->driver; ChannelDriver *driver = fcu->driver;
OperationKey driver_key(id, DEPSNODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu)); OperationKey driver_key(id,
DEPSNODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
fcu->rna_path,
fcu->array_index);
bPoseChannel *pchan = NULL; bPoseChannel *pchan = NULL;
/* create dependency between driver and data affected by it */ /* create dependency between driver and data affected by it */
@@ -1384,7 +1444,7 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
"Armature Eval"); "Armature Eval");
add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency"); add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency");
if (ob->adt && (ob->adt->action || ob->adt->nla_tracks.first)) { if (needs_animdata_node(&ob->id)) {
ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION); ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation"); add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation");
} }
@@ -1622,7 +1682,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
* for either the modifier needing time, or that it is animated. * for either the modifier needing time, or that it is animated.
*/ */
/* XXX: Remove this hack when these links are added as part of build_animdata() instead */ /* XXX: Remove this hack when these links are added as part of build_animdata() instead */
if (modifier_dependsOnTime(md) == false) { if (modifier_dependsOnTime(md) == false && needs_animdata_node(&ob->id)) {
ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION); ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
add_relation(animation_key, mod_key, DEPSREL_TYPE_OPERATION, "Modifier Animation"); add_relation(animation_key, mod_key, DEPSREL_TYPE_OPERATION, "Modifier Animation");
} }
@@ -1920,7 +1980,7 @@ bool DepsgraphRelationBuilder::needs_animdata_node(ID *id)
{ {
AnimData *adt = BKE_animdata_from_id(id); AnimData *adt = BKE_animdata_from_id(id);
if (adt != NULL) { if (adt != NULL) {
return adt->action != NULL; return (adt->action != NULL) || (adt->nla_tracks.first != NULL);
} }
return false; return false;
} }

View File

@@ -81,108 +81,83 @@ struct ComponentDepsNode;
struct OperationDepsNode; struct OperationDepsNode;
struct RootPChanMap; struct RootPChanMap;
struct RootKey struct RootKey {
{ RootKey();
RootKey() {}
}; };
struct TimeSourceKey struct TimeSourceKey
{ {
TimeSourceKey() : id(NULL) {} TimeSourceKey();
TimeSourceKey(ID *id) : id(id) {} TimeSourceKey(ID *id);
string identifier() const string identifier() const;
{
return string("TimeSourceKey");
}
ID *id; ID *id;
}; };
struct ComponentKey struct ComponentKey
{ {
ComponentKey() : ComponentKey();
id(NULL), type(DEPSNODE_TYPE_UNDEFINED), name("") ComponentKey(ID *id, eDepsNode_Type type, const char *name = "");
{}
ComponentKey(ID *id, eDepsNode_Type type, const string &name = "") :
id(id), type(type), name(name)
{}
string identifier() const string identifier() const;
{
const char *idname = (id) ? id->name : "<None>";
char typebuf[5];
BLI_snprintf(typebuf, sizeof(typebuf), "%d", type);
return string("ComponentKey(") + idname + ", " + typebuf + ", '" + name + "')";
}
ID *id; ID *id;
eDepsNode_Type type; eDepsNode_Type type;
string name; const char *name;
}; };
struct OperationKey struct OperationKey
{ {
OperationKey() : OperationKey();
id(NULL), component_type(DEPSNODE_TYPE_UNDEFINED), component_name(""), opcode(DEG_OPCODE_OPERATION), name("") OperationKey(ID *id,
{} eDepsNode_Type component_type,
const char *name,
int name_tag = -1);
OperationKey(ID *id,
eDepsNode_Type component_type,
const char *component_name,
const char *name,
int name_tag);
OperationKey(ID *id, eDepsNode_Type component_type, const string &name) : OperationKey(ID *id,
id(id), component_type(component_type), component_name(""), opcode(DEG_OPCODE_OPERATION), name(name) eDepsNode_Type component_type,
{} eDepsOperation_Code opcode);
OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, const string &name) : OperationKey(ID *id,
id(id), component_type(component_type), component_name(component_name), opcode(DEG_OPCODE_OPERATION), name(name) eDepsNode_Type component_type,
{} const char *component_name,
eDepsOperation_Code opcode);
OperationKey(ID *id, eDepsNode_Type component_type, eDepsOperation_Code opcode) : OperationKey(ID *id,
id(id), component_type(component_type), component_name(""), opcode(opcode), name("") eDepsNode_Type component_type,
{} eDepsOperation_Code opcode,
OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, eDepsOperation_Code opcode) : const char *name,
id(id), component_type(component_type), component_name(component_name), opcode(opcode), name("") int name_tag = -1);
{} OperationKey(ID *id,
eDepsNode_Type component_type,
OperationKey(ID *id, eDepsNode_Type component_type, eDepsOperation_Code opcode, const string &name) : const char *component_name,
id(id), component_type(component_type), component_name(""), opcode(opcode), name(name) eDepsOperation_Code opcode,
{} const char *name,
OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, eDepsOperation_Code opcode, const string &name) : int name_tag = -1);
id(id), component_type(component_type), component_name(component_name), opcode(opcode), name(name)
{}
string identifier() const
{
char typebuf[5];
BLI_snprintf(typebuf, sizeof(typebuf), "%d", component_type);
return string("OperationKey(") + "t: " + typebuf + ", cn: '" + component_name + "', c: " + DEG_OPNAMES[opcode] + ", n: '" + name + "')";
}
string identifier() const;
ID *id; ID *id;
eDepsNode_Type component_type; eDepsNode_Type component_type;
string component_name; const char *component_name;
eDepsOperation_Code opcode; eDepsOperation_Code opcode;
string name; const char *name;
int name_tag;
}; };
struct RNAPathKey struct RNAPathKey
{ {
// Note: see depsgraph_build.cpp for implementation /* NOTE: see depsgraph_build.cpp for implementation */
RNAPathKey(ID *id, const char *path); RNAPathKey(ID *id, const char *path);
RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop) : RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop);
id(id), ptr(ptr), prop(prop)
{}
string identifier() const
{
const char *id_name = (id) ? id->name : "<No ID>";
const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>";
return string("RnaPathKey(") + "id: " + id_name + ", prop: " + prop_name + "')";
}
string identifier() const;
ID *id; ID *id;
PointerRNA ptr; PointerRNA ptr;
@@ -270,7 +245,7 @@ protected:
template <typename KeyType> template <typename KeyType>
DepsNodeHandle create_node_handle(const KeyType& key, DepsNodeHandle create_node_handle(const KeyType& key,
const string& default_name = ""); const char *default_name = "");
bool needs_animdata_node(ID *id); bool needs_animdata_node(ID *id);
@@ -280,7 +255,7 @@ private:
struct DepsNodeHandle struct DepsNodeHandle
{ {
DepsNodeHandle(DepsgraphRelationBuilder *builder, OperationDepsNode *node, const string &default_name = "") : DepsNodeHandle(DepsgraphRelationBuilder *builder, OperationDepsNode *node, const char *default_name = "") :
builder(builder), builder(builder),
node(node), node(node),
default_name(default_name) default_name(default_name)
@@ -290,7 +265,7 @@ struct DepsNodeHandle
DepsgraphRelationBuilder *builder; DepsgraphRelationBuilder *builder;
OperationDepsNode *node; OperationDepsNode *node;
const string &default_name; const char *default_name;
}; };
/* Utilities for Builders ----------------------------------------------------- */ /* Utilities for Builders ----------------------------------------------------- */
@@ -318,6 +293,7 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
else { else {
if (!op_from) { if (!op_from) {
/* XXX TODO handle as error or report if needed */ /* XXX TODO handle as error or report if needed */
node_from = find_node(key_from);
fprintf(stderr, "add_relation(%d, %s) - Could not find op_from (%s)\n", fprintf(stderr, "add_relation(%d, %s) - Could not find op_from (%s)\n",
type, description, key_from.identifier().c_str()); type, description, key_from.identifier().c_str());
} }
@@ -383,7 +359,7 @@ void DepsgraphRelationBuilder::add_node_handle_relation(
template <typename KeyType> template <typename KeyType>
DepsNodeHandle DepsgraphRelationBuilder::create_node_handle( DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(
const KeyType &key, const KeyType &key,
const string &default_name) const char *default_name)
{ {
return DepsNodeHandle(this, find_node(key), default_name); return DepsNodeHandle(this, find_node(key), default_name);
} }

View File

@@ -0,0 +1,211 @@
/*
* ***** 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) 2013 Blender Foundation.
* All rights reserved.
*
* Original Author: Joshua Leung
* Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/depsgraph/intern/builder/deg_builder_relations.cc
* \ingroup depsgraph
*
* Methods for constructing depsgraph
*/
#include "intern/builder/deg_builder_relations.h"
namespace DEG {
/////////////////////////////////////////
// Root.
RootKey::RootKey()
{
}
/////////////////////////////////////////
// Time source.
TimeSourceKey::TimeSourceKey()
: id(NULL)
{
}
TimeSourceKey::TimeSourceKey(ID *id)
: id(id)
{
}
string TimeSourceKey::identifier() const
{
return string("TimeSourceKey");
}
/////////////////////////////////////////
// Component.
ComponentKey::ComponentKey()
: id(NULL),
type(DEPSNODE_TYPE_UNDEFINED),
name("")
{
}
ComponentKey::ComponentKey(ID *id, eDepsNode_Type type, const char *name)
: id(id),
type(type),
name(name)
{
}
string ComponentKey::identifier() const
{
const char *idname = (id) ? id->name : "<None>";
char typebuf[5];
BLI_snprintf(typebuf, sizeof(typebuf), "%d", type);
return string("ComponentKey(") +
idname + ", " + typebuf + ", '" + name + "')";
}
/////////////////////////////////////////
// Operation.
OperationKey::OperationKey()
: id(NULL),
component_type(DEPSNODE_TYPE_UNDEFINED),
component_name(""),
opcode(DEG_OPCODE_OPERATION),
name(""),
name_tag(-1)
{
}
OperationKey::OperationKey(ID *id,
eDepsNode_Type component_type,
const char *name,
int name_tag)
: id(id),
component_type(component_type),
component_name(""),
opcode(DEG_OPCODE_OPERATION),
name(name),
name_tag(name_tag)
{
}
OperationKey::OperationKey(ID *id,
eDepsNode_Type component_type,
const char *component_name,
const char *name,
int name_tag)
: id(id),
component_type(component_type),
component_name(component_name),
opcode(DEG_OPCODE_OPERATION),
name(name),
name_tag(name_tag)
{
}
OperationKey::OperationKey(ID *id,
eDepsNode_Type component_type,
eDepsOperation_Code opcode)
: id(id),
component_type(component_type),
component_name(""),
opcode(opcode),
name(""),
name_tag(-1)
{
}
OperationKey::OperationKey(ID *id,
eDepsNode_Type component_type,
const char *component_name,
eDepsOperation_Code opcode)
: id(id),
component_type(component_type),
component_name(component_name),
opcode(opcode),
name(""),
name_tag(-1)
{
}
OperationKey::OperationKey(ID *id,
eDepsNode_Type component_type,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
: id(id),
component_type(component_type),
component_name(""),
opcode(opcode),
name(name),
name_tag(name_tag)
{
}
OperationKey::OperationKey(ID *id,
eDepsNode_Type component_type,
const char *component_name,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
: id(id),
component_type(component_type),
component_name(component_name),
opcode(opcode),
name(name),
name_tag(name_tag)
{
}
string OperationKey::identifier() const
{
char typebuf[5];
BLI_snprintf(typebuf, sizeof(typebuf), "%d", component_type);
return string("OperationKey(") +
"t: " + typebuf +
", cn: '" + component_name +
"', c: " + DEG_OPNAMES[opcode] +
", n: '" + name + "')";
}
/////////////////////////////////////////
// RNA path.
RNAPathKey::RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop)
: id(id),
ptr(ptr),
prop(prop)
{
}
string RNAPathKey::identifier() const
{
const char *id_name = (id) ? id->name : "<No ID>";
const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>";
return string("RnaPathKey(") + "id: " + id_name +
", prop: " + prop_name + "')";
}
} // namespace DEG

View File

@@ -321,7 +321,7 @@ static void deg_debug_graphviz_node_single(const DebugContext &ctx,
static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx, static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
const DepsNode *node) const DepsNode *node)
{ {
string name = node->identifier().c_str(); string name = node->identifier();
if (node->type == DEPSNODE_TYPE_ID_REF) { if (node->type == DEPSNODE_TYPE_ID_REF) {
IDDepsNode *id_node = (IDDepsNode *)node; IDDepsNode *id_node = (IDDepsNode *)node;
char buf[256]; char buf[256];

View File

@@ -32,8 +32,6 @@
#include "intern/depsgraph.h" /* own include */ #include "intern/depsgraph.h" /* own include */
#include <string.h>
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
@@ -53,6 +51,8 @@ extern "C" {
#include "RNA_access.h" #include "RNA_access.h"
} }
#include <cstring>
#include "DEG_depsgraph.h" #include "DEG_depsgraph.h"
#include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node.h"
@@ -116,7 +116,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
const PropertyRNA *prop, const PropertyRNA *prop,
ID **id, ID **id,
eDepsNode_Type *type, eDepsNode_Type *type,
string *subdata) const char **subdata)
{ {
if (!ptr->type) if (!ptr->type)
return false; return false;
@@ -232,7 +232,7 @@ DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr,
{ {
ID *id; ID *id;
eDepsNode_Type type; eDepsNode_Type type;
string name; const char *name;
/* Get querying conditions. */ /* Get querying conditions. */
if (pointer_to_id_node_criteria(ptr, prop, &id)) { if (pointer_to_id_node_criteria(ptr, prop, &id)) {
@@ -240,8 +240,9 @@ DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr,
} }
else if (pointer_to_component_node_criteria(ptr, prop, &id, &type, &name)) { else if (pointer_to_component_node_criteria(ptr, prop, &id, &type, &name)) {
IDDepsNode *id_node = find_id_node(id); IDDepsNode *id_node = find_id_node(id);
if (id_node) if (id_node != NULL) {
return id_node->find_component(type, name); return id_node->find_component(type, name);
}
} }
return NULL; return NULL;
@@ -328,7 +329,7 @@ IDDepsNode *Depsgraph::find_id_node(const ID *id) const
return reinterpret_cast<IDDepsNode *>(BLI_ghash_lookup(id_hash, id)); return reinterpret_cast<IDDepsNode *>(BLI_ghash_lookup(id_hash, id));
} }
IDDepsNode *Depsgraph::add_id_node(ID *id, const string &name) IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name)
{ {
IDDepsNode *id_node = find_id_node(id); IDDepsNode *id_node = find_id_node(id);
if (!id_node) { if (!id_node) {

View File

@@ -100,22 +100,6 @@ struct Depsgraph {
Depsgraph(); Depsgraph();
~Depsgraph(); ~Depsgraph();
/**
* Find node which matches the specified description.
*
* \param id: ID block that is associated with this
* \param subdata: identifier used for sub-ID data (e.g. bone)
* \param type: type of node we're dealing with
* \param name: custom identifier assigned to node
*
* \return A node matching the required characteristics if it exists
* or NULL if no such node exists in the graph.
*/
DepsNode *find_node(const ID *id,
eDepsNode_Type type,
const string &subdata,
const string &name);
/** /**
* Convenience wrapper to find node given just pointer + property. * Convenience wrapper to find node given just pointer + property.
* *
@@ -136,7 +120,7 @@ struct Depsgraph {
void clear_subgraph_nodes(); void clear_subgraph_nodes();
IDDepsNode *find_id_node(const ID *id) const; IDDepsNode *find_id_node(const ID *id) const;
IDDepsNode *add_id_node(ID *id, const string &name = ""); IDDepsNode *add_id_node(ID *id, const char *name = "");
void remove_id_node(const ID *id); void remove_id_node(const ID *id);
void clear_id_nodes(); void clear_id_nodes();

View File

@@ -32,6 +32,8 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
// #define DEBUG_TIME
extern "C" { extern "C" {
#include "DNA_cachefile_types.h" #include "DNA_cachefile_types.h"
#include "DNA_object_types.h" #include "DNA_object_types.h"
@@ -41,6 +43,11 @@ extern "C" {
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BLI_ghash.h" #include "BLI_ghash.h"
#ifdef DEBUG_TIME
# include "PIL_time.h"
# include "PIL_time_utildefines.h"
#endif
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_collision.h" #include "BKE_collision.h"
#include "BKE_effect.h" #include "BKE_effect.h"
@@ -190,6 +197,10 @@ void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag)
*/ */
void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene) void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
{ {
#ifdef DEBUG_TIME
TIMEIT_START(DEG_graph_build_from_scene);
#endif
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph); DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
/* 1) Generate all the nodes in the graph first */ /* 1) Generate all the nodes in the graph first */
@@ -239,6 +250,10 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
abort(); abort();
} }
#endif #endif
#ifdef DEBUG_TIME
TIMEIT_END(DEG_graph_build_from_scene);
#endif
} }
/* Tag graph relations for update. */ /* Tag graph relations for update. */

View File

@@ -63,8 +63,8 @@ struct DepsNodeFactory {
virtual const char *tname() const = 0; virtual const char *tname() const = 0;
virtual DepsNode *create_node(const ID *id, virtual DepsNode *create_node(const ID *id,
const string &subdata, const char *subdata,
const string &name) const = 0; const char *name) const = 0;
}; };
template <class NodeType> template <class NodeType>
@@ -73,7 +73,7 @@ struct DepsNodeFactoryImpl : public DepsNodeFactory {
eDepsNode_Class tclass() const { return NodeType::typeinfo.tclass; } eDepsNode_Class tclass() const { return NodeType::typeinfo.tclass; }
const char *tname() const { return NodeType::typeinfo.tname; } const char *tname() const { return NodeType::typeinfo.tname; }
DepsNode *create_node(const ID *id, const string &subdata, const string &name) const DepsNode *create_node(const ID *id, const char *subdata, const char *name) const
{ {
DepsNode *node = OBJECT_GUARDED_NEW(NodeType); DepsNode *node = OBJECT_GUARDED_NEW(NodeType);
@@ -81,12 +81,14 @@ struct DepsNodeFactoryImpl : public DepsNodeFactory {
node->type = type(); node->type = type();
node->tclass = tclass(); node->tclass = tclass();
if (!name.empty()) if (name[0] != '\0') {
/* set name if provided ... */ /* set name if provided ... */
node->name = name; node->name = name;
else }
else {
/* ... otherwise use default type name */ /* ... otherwise use default type name */
node->name = tname(); node->name = tname();
}
node->init(id, subdata); node->init(id, subdata);

View File

@@ -31,7 +31,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <cstring> #include <cstring> /* required for memset */
#include <queue> #include <queue>
extern "C" { extern "C" {

View File

@@ -30,10 +30,10 @@
* Implementation of tools for debugging the depsgraph * Implementation of tools for debugging the depsgraph
*/ */
#include <cstring>
#include "intern/eval/deg_eval_debug.h" #include "intern/eval/deg_eval_debug.h"
#include <cstring> /* required for STREQ later on. */
extern "C" { extern "C" {
#include "BLI_listbase.h" #include "BLI_listbase.h"
#include "BLI_ghash.h" #include "BLI_ghash.h"
@@ -53,10 +53,10 @@ namespace DEG {
DepsgraphStats *DepsgraphDebug::stats = NULL; DepsgraphStats *DepsgraphDebug::stats = NULL;
static string get_component_name(eDepsNode_Type type, const string &name = "") static string get_component_name(eDepsNode_Type type, const char *name = "")
{ {
DepsNodeFactory *factory = deg_get_node_factory(type); DepsNodeFactory *factory = deg_get_node_factory(type);
if (name.empty()) { if (name[0] != '\0') {
return string(factory->tname()); return string(factory->tname());
} }
else { else {
@@ -116,7 +116,7 @@ void DepsgraphDebug::task_started(Depsgraph *graph,
*/ */
DepsgraphStatsComponent *comp_stats = DepsgraphStatsComponent *comp_stats =
get_component_stats(id, get_component_name(comp->type, get_component_stats(id, get_component_name(comp->type,
comp->name), comp->name).c_str(),
true); true);
times_clear(comp_stats->times); times_clear(comp_stats->times);
} }
@@ -146,7 +146,7 @@ void DepsgraphDebug::task_completed(Depsgraph *graph,
DepsgraphStatsComponent *comp_stats = DepsgraphStatsComponent *comp_stats =
get_component_stats(id, get_component_stats(id,
get_component_name(comp->type, get_component_name(comp->type,
comp->name), comp->name).c_str(),
true); true);
times_add(comp_stats->times, time); times_add(comp_stats->times, time);
} }
@@ -226,7 +226,7 @@ DepsgraphStatsID *DepsgraphDebug::get_id_stats(ID *id, bool create)
DepsgraphStatsComponent *DepsgraphDebug::get_component_stats( DepsgraphStatsComponent *DepsgraphDebug::get_component_stats(
DepsgraphStatsID *id_stats, DepsgraphStatsID *id_stats,
const string &name, const char *name,
bool create) bool create)
{ {
DepsgraphStatsComponent *comp_stats; DepsgraphStatsComponent *comp_stats;
@@ -234,13 +234,14 @@ DepsgraphStatsComponent *DepsgraphDebug::get_component_stats(
comp_stats != NULL; comp_stats != NULL;
comp_stats = comp_stats->next) comp_stats = comp_stats->next)
{ {
if (STREQ(comp_stats->name, name.c_str())) if (STREQ(comp_stats->name, name)) {
break; break;
}
} }
if (!comp_stats && create) { if (!comp_stats && create) {
comp_stats = (DepsgraphStatsComponent *)MEM_callocN(sizeof(DepsgraphStatsComponent), comp_stats = (DepsgraphStatsComponent *)MEM_callocN(sizeof(DepsgraphStatsComponent),
"Depsgraph Component Stats"); "Depsgraph Component Stats");
BLI_strncpy(comp_stats->name, name.c_str(), sizeof(comp_stats->name)); BLI_strncpy(comp_stats->name, name, sizeof(comp_stats->name));
BLI_addtail(&id_stats->components, comp_stats); BLI_addtail(&id_stats->components, comp_stats);
} }
return comp_stats; return comp_stats;

View File

@@ -66,10 +66,10 @@ struct DepsgraphDebug {
static DepsgraphStatsID *get_id_stats(ID *id, bool create); static DepsgraphStatsID *get_id_stats(ID *id, bool create);
static DepsgraphStatsComponent *get_component_stats(DepsgraphStatsID *id_stats, static DepsgraphStatsComponent *get_component_stats(DepsgraphStatsID *id_stats,
const string &name, const char *name,
bool create); bool create);
static DepsgraphStatsComponent *get_component_stats(ID *id, static DepsgraphStatsComponent *get_component_stats(ID *id,
const string &name, const char *name,
bool create) bool create)
{ {
return get_component_stats(get_id_stats(id, create), name, create); return get_component_stats(get_id_stats(id, create), name, create);

View File

@@ -31,7 +31,7 @@
#include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <cstring> /* required for STREQ later on. */
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BLI_ghash.h" #include "BLI_ghash.h"
@@ -72,7 +72,7 @@ DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname)
DepsNode::DepsNode() DepsNode::DepsNode()
{ {
name[0] = '\0'; name = "";
} }
DepsNode::~DepsNode() DepsNode::~DepsNode()
@@ -122,7 +122,7 @@ RootDepsNode::~RootDepsNode()
OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode); OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
} }
TimeSourceDepsNode *RootDepsNode::add_time_source(const string &name) TimeSourceDepsNode *RootDepsNode::add_time_source(const char *name)
{ {
if (!time_source) { if (!time_source) {
DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_TIMESOURCE); DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_TIMESOURCE);
@@ -142,12 +142,24 @@ static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
/* ID Node ================================================ */ /* ID Node ================================================ */
IDDepsNode::ComponentIDKey::ComponentIDKey(eDepsNode_Type type,
const char *name)
: type(type), name(name)
{
}
bool IDDepsNode::ComponentIDKey::operator== (const ComponentIDKey &other) const
{
return type == other.type &&
STREQ(name, other.name);
}
static unsigned int id_deps_node_hash_key(const void *key_v) static unsigned int id_deps_node_hash_key(const void *key_v)
{ {
const IDDepsNode::ComponentIDKey *key = const IDDepsNode::ComponentIDKey *key =
reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v); reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v);
return hash_combine(BLI_ghashutil_uinthash(key->type), return hash_combine(BLI_ghashutil_uinthash(key->type),
BLI_ghashutil_strhash_p(key->name.c_str())); BLI_ghashutil_strhash_p(key->name));
} }
static bool id_deps_node_hash_key_cmp(const void *a, const void *b) static bool id_deps_node_hash_key_cmp(const void *a, const void *b)
@@ -173,7 +185,7 @@ static void id_deps_node_hash_value_free(void *value_v)
} }
/* Initialize 'id' node - from pointer data given. */ /* Initialize 'id' node - from pointer data given. */
void IDDepsNode::init(const ID *id, const string &UNUSED(subdata)) void IDDepsNode::init(const ID *id, const char *UNUSED(subdata))
{ {
/* Store ID-pointer. */ /* Store ID-pointer. */
BLI_assert(id != NULL); BLI_assert(id != NULL);
@@ -204,14 +216,14 @@ IDDepsNode::~IDDepsNode()
} }
ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type, ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
const string &name) const const char *name) const
{ {
ComponentIDKey key(type, name); ComponentIDKey key(type, name);
return reinterpret_cast<ComponentDepsNode *>(BLI_ghash_lookup(components, &key)); return reinterpret_cast<ComponentDepsNode *>(BLI_ghash_lookup(components, &key));
} }
ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type, ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
const string &name) const char *name)
{ {
ComponentDepsNode *comp_node = find_component(type, name); ComponentDepsNode *comp_node = find_component(type, name);
if (!comp_node) { if (!comp_node) {
@@ -226,7 +238,7 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
return comp_node; return comp_node;
} }
void IDDepsNode::remove_component(eDepsNode_Type type, const string &name) void IDDepsNode::remove_component(eDepsNode_Type type, const char *name)
{ {
ComponentDepsNode *comp_node = find_component(type, name); ComponentDepsNode *comp_node = find_component(type, name);
if (comp_node) { if (comp_node) {
@@ -281,7 +293,7 @@ static DepsNodeFactoryImpl<IDDepsNode> DNTI_ID_REF;
/* Subgraph Node ========================================== */ /* Subgraph Node ========================================== */
/* Initialize 'subgraph' node - from pointer data given. */ /* Initialize 'subgraph' node - from pointer data given. */
void SubgraphDepsNode::init(const ID *id, const string &UNUSED(subdata)) void SubgraphDepsNode::init(const ID *id, const char *UNUSED(subdata))
{ {
/* Store ID-ref if provided. */ /* Store ID-ref if provided. */
this->root_id = (ID *)id; this->root_id = (ID *)id;

View File

@@ -32,6 +32,8 @@
#include "intern/depsgraph_types.h" #include "intern/depsgraph_types.h"
#include "BLI_utildefines.h"
struct ID; struct ID;
struct GHash; struct GHash;
struct Scene; struct Scene;
@@ -57,7 +59,7 @@ struct DepsNode {
}; };
/* Identifier - mainly for debugging purposes. */ /* Identifier - mainly for debugging purposes. */
string name; const char *name;
/* Structural type of node. */ /* Structural type of node. */
eDepsNode_Type type; eDepsNode_Type type;
@@ -78,8 +80,9 @@ struct DepsNode {
/* Nodes which depend on this one. */ /* Nodes which depend on this one. */
Relations outlinks; Relations outlinks;
/* Generic tag for traversal algorithms */ /* Generic tags for traversal algorithms. */
int done; int done;
int tag;
/* Methods. */ /* Methods. */
@@ -90,7 +93,7 @@ struct DepsNode {
string full_identifier() const; string full_identifier() const;
virtual void init(const ID * /*id*/, virtual void init(const ID * /*id*/,
const string &/*subdata*/) {} const char * /*subdata*/) {}
virtual void tag_update(Depsgraph * /*graph*/) {} virtual void tag_update(Depsgraph * /*graph*/) {}
@@ -129,7 +132,7 @@ struct RootDepsNode : public DepsNode {
RootDepsNode(); RootDepsNode();
~RootDepsNode(); ~RootDepsNode();
TimeSourceDepsNode *add_time_source(const string &name = ""); TimeSourceDepsNode *add_time_source(const char *name = "");
/* scene that this corresponds to */ /* scene that this corresponds to */
Scene *scene; Scene *scene;
@@ -143,26 +146,21 @@ struct RootDepsNode : public DepsNode {
/* ID-Block Reference */ /* ID-Block Reference */
struct IDDepsNode : public DepsNode { struct IDDepsNode : public DepsNode {
struct ComponentIDKey { struct ComponentIDKey {
ComponentIDKey(eDepsNode_Type type, const string &name = "") ComponentIDKey(eDepsNode_Type type, const char *name = "");
: type(type), name(name) {} bool operator==(const ComponentIDKey &other) const;
bool operator== (const ComponentIDKey &other) const
{
return type == other.type && name == other.name;
}
eDepsNode_Type type; eDepsNode_Type type;
string name; const char *name;
}; };
void init(const ID *id, const string &subdata); void init(const ID *id, const char *subdata);
~IDDepsNode(); ~IDDepsNode();
ComponentDepsNode *find_component(eDepsNode_Type type, ComponentDepsNode *find_component(eDepsNode_Type type,
const string &name = "") const; const char *name = "") const;
ComponentDepsNode *add_component(eDepsNode_Type type, ComponentDepsNode *add_component(eDepsNode_Type type,
const string &name = ""); const char *name = "");
void remove_component(eDepsNode_Type type, const string &name = ""); void remove_component(eDepsNode_Type type, const char *name = "");
void clear_components(); void clear_components();
void tag_update(Depsgraph *graph); void tag_update(Depsgraph *graph);
@@ -189,7 +187,7 @@ struct IDDepsNode : public DepsNode {
/* Subgraph Reference. */ /* Subgraph Reference. */
struct SubgraphDepsNode : public DepsNode { struct SubgraphDepsNode : public DepsNode {
void init(const ID *id, const string &subdata); void init(const ID *id, const char *subdata);
~SubgraphDepsNode(); ~SubgraphDepsNode();
/* Instanced graph. */ /* Instanced graph. */

View File

@@ -31,7 +31,7 @@
#include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_component.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <cstring> /* required for STREQ later on. */
extern "C" { extern "C" {
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
@@ -53,12 +53,50 @@ namespace DEG {
/* Standard Component Methods ============================= */ /* Standard Component Methods ============================= */
ComponentDepsNode::OperationIDKey::OperationIDKey()
: opcode(DEG_OPCODE_OPERATION),
name(""),
name_tag(-1)
{
}
ComponentDepsNode::OperationIDKey::OperationIDKey(eDepsOperation_Code opcode)
: opcode(opcode),
name(""),
name_tag(-1)
{
}
ComponentDepsNode::OperationIDKey::OperationIDKey(eDepsOperation_Code opcode,
const char *name,
int name_tag)
: opcode(opcode),
name(name),
name_tag(name_tag)
{
}
string ComponentDepsNode::OperationIDKey::identifier() const
{
char codebuf[5];
BLI_snprintf(codebuf, sizeof(codebuf), "%d", opcode);
return string("OperationIDKey(") + codebuf + ", " + name + ")";
}
bool ComponentDepsNode::OperationIDKey::operator==(
const OperationIDKey &other) const
{
return (opcode == other.opcode) &&
(STREQ(name, other.name)) &&
(name_tag == other.name_tag);
}
static unsigned int comp_node_hash_key(const void *key_v) static unsigned int comp_node_hash_key(const void *key_v)
{ {
const ComponentDepsNode::OperationIDKey *key = const ComponentDepsNode::OperationIDKey *key =
reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v); reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v);
return hash_combine(BLI_ghashutil_uinthash(key->opcode), return hash_combine(BLI_ghashutil_uinthash(key->opcode),
BLI_ghashutil_strhash_p(key->name.c_str())); BLI_ghashutil_strhash_p(key->name));
} }
static bool comp_node_hash_key_cmp(const void *a, const void *b) static bool comp_node_hash_key_cmp(const void *a, const void *b)
@@ -95,7 +133,7 @@ ComponentDepsNode::ComponentDepsNode() :
/* Initialize 'component' node - from pointer data given */ /* Initialize 'component' node - from pointer data given */
void ComponentDepsNode::init(const ID * /*id*/, void ComponentDepsNode::init(const ID * /*id*/,
const string & /*subdata*/) const char * /*subdata*/)
{ {
/* hook up eval context? */ /* hook up eval context? */
// XXX: maybe this needs a special API? // XXX: maybe this needs a special API?
@@ -114,7 +152,7 @@ ComponentDepsNode::~ComponentDepsNode()
string ComponentDepsNode::identifier() const string ComponentDepsNode::identifier() const
{ {
string &idname = this->owner->name; string idname = this->owner->name;
char typebuf[16]; char typebuf[16];
sprintf(typebuf, "(%d)", type); sprintf(typebuf, "(%d)", type);
@@ -139,9 +177,11 @@ OperationDepsNode *ComponentDepsNode::find_operation(OperationIDKey key) const
} }
} }
OperationDepsNode *ComponentDepsNode::find_operation(eDepsOperation_Code opcode, const string &name) const OperationDepsNode *ComponentDepsNode::find_operation(eDepsOperation_Code opcode,
const char *name,
int name_tag) const
{ {
OperationIDKey key(opcode, name); OperationIDKey key(opcode, name, name_tag);
return find_operation(key); return find_operation(key);
} }
@@ -151,21 +191,26 @@ OperationDepsNode *ComponentDepsNode::has_operation(OperationIDKey key) const
} }
OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode, OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode,
const string &name) const const char *name,
int name_tag) const
{ {
OperationIDKey key(opcode, name); OperationIDKey key(opcode, name, name_tag);
return has_operation(key); return has_operation(key);
} }
OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype, DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &name) OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
DepsEvalOperationCb op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
{ {
OperationDepsNode *op_node = has_operation(opcode, name); OperationDepsNode *op_node = has_operation(opcode, name, name_tag);
if (!op_node) { if (!op_node) {
DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_OPERATION); DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_OPERATION);
op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name); op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
/* register opnode in this component's operation set */ /* register opnode in this component's operation set */
OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name); OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
BLI_ghash_insert(operations_map, key, op_node); BLI_ghash_insert(operations_map, key, op_node);
/* set as entry/exit node of component (if appropriate) */ /* set as entry/exit node of component (if appropriate) */
@@ -197,16 +242,6 @@ OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
return op_node; return op_node;
} }
void ComponentDepsNode::remove_operation(eDepsOperation_Code opcode, const string &name)
{
/* unregister */
OperationIDKey key(opcode, name);
BLI_ghash_remove(operations_map,
&key,
comp_node_hash_key_free,
comp_node_hash_key_free);
}
void ComponentDepsNode::clear_operations() void ComponentDepsNode::clear_operations()
{ {
if (operations_map != NULL) { if (operations_map != NULL) {
@@ -337,7 +372,7 @@ static DepsNodeFactoryImpl<PoseComponentDepsNode> DNTI_EVAL_POSE;
/* Bone Component ========================================= */ /* Bone Component ========================================= */
/* Initialize 'bone component' node - from pointer data given */ /* Initialize 'bone component' node - from pointer data given */
void BoneComponentDepsNode::init(const ID *id, const string &subdata) void BoneComponentDepsNode::init(const ID *id, const char *subdata)
{ {
/* generic component-node... */ /* generic component-node... */
ComponentDepsNode::init(id, subdata); ComponentDepsNode::init(id, subdata);
@@ -350,7 +385,7 @@ void BoneComponentDepsNode::init(const ID *id, const string &subdata)
/* bone-specific node data */ /* bone-specific node data */
Object *ob = (Object *)id; Object *ob = (Object *)id;
this->pchan = BKE_pose_channel_find_name(ob->pose, subdata.c_str()); this->pchan = BKE_pose_channel_find_name(ob->pose, subdata);
} }
DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEPSNODE_TYPE_BONE, "Bone Component"); DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEPSNODE_TYPE_BONE, "Bone Component");

View File

@@ -53,50 +53,38 @@ struct ComponentDepsNode : public DepsNode {
struct OperationIDKey struct OperationIDKey
{ {
eDepsOperation_Code opcode; eDepsOperation_Code opcode;
string name; const char *name;
int name_tag;
OperationIDKey();
OperationIDKey(eDepsOperation_Code opcode);
OperationIDKey(eDepsOperation_Code opcode,
const char *name,
int name_tag);
OperationIDKey() : string identifier() const;
opcode(DEG_OPCODE_OPERATION), name("") bool operator==(const OperationIDKey &other) const;
{}
OperationIDKey(eDepsOperation_Code opcode) :
opcode(opcode), name("")
{}
OperationIDKey(eDepsOperation_Code opcode, const string &name) :
opcode(opcode), name(name)
{}
string identifier() const
{
char codebuf[5];
BLI_snprintf(codebuf, sizeof(codebuf), "%d", opcode);
return string("OperationIDKey(") + codebuf + ", " + name + ")";
}
bool operator==(const OperationIDKey &other) const
{
return (opcode == other.opcode) && (name == other.name);
}
}; };
/* Typedef for container of operations */ /* Typedef for container of operations */
ComponentDepsNode(); ComponentDepsNode();
~ComponentDepsNode(); ~ComponentDepsNode();
void init(const ID *id, const string &subdata); void init(const ID *id, const char *subdata);
string identifier() const; string identifier() const;
/* Find an existing operation, will throw an assert() if it does not exist. */ /* Find an existing operation, will throw an assert() if it does not exist. */
OperationDepsNode *find_operation(OperationIDKey key) const; OperationDepsNode *find_operation(OperationIDKey key) const;
OperationDepsNode *find_operation(eDepsOperation_Code opcode, OperationDepsNode *find_operation(eDepsOperation_Code opcode,
const string &name) const; const char *name,
int name_tag) const;
/* Check operation exists and return it. */ /* Check operation exists and return it. */
OperationDepsNode *has_operation(OperationIDKey key) const; OperationDepsNode *has_operation(OperationIDKey key) const;
OperationDepsNode *has_operation(eDepsOperation_Code opcode, OperationDepsNode *has_operation(eDepsOperation_Code opcode,
const string &name) const; const char *name,
int name_tag) const;
/** /**
* Create a new node for representing an operation and add this to graph * Create a new node for representing an operation and add this to graph
@@ -114,9 +102,9 @@ struct ComponentDepsNode : public DepsNode {
OperationDepsNode *add_operation(eDepsOperation_Type optype, OperationDepsNode *add_operation(eDepsOperation_Type optype,
DepsEvalOperationCb op, DepsEvalOperationCb op,
eDepsOperation_Code opcode, eDepsOperation_Code opcode,
const string &name); const char *name,
int name_tag);
void remove_operation(eDepsOperation_Code opcode, const string &name);
void clear_operations(); void clear_operations();
void tag_update(Depsgraph *graph); void tag_update(Depsgraph *graph);
@@ -194,7 +182,7 @@ struct PoseComponentDepsNode : public ComponentDepsNode {
/* Bone Component */ /* Bone Component */
struct BoneComponentDepsNode : public ComponentDepsNode { struct BoneComponentDepsNode : public ComponentDepsNode {
void init(const ID *id, const string &subdata); void init(const ID *id, const char *subdata);
struct bPoseChannel *pchan; /* the bone that this component represents */ struct bPoseChannel *pchan; /* the bone that this component represents */

View File

@@ -68,7 +68,7 @@ string OperationDepsNode::full_identifier() const
{ {
string owner_str = ""; string owner_str = "";
if (owner->type == DEPSNODE_TYPE_BONE) { if (owner->type == DEPSNODE_TYPE_BONE) {
owner_str = owner->owner->name + "." + owner->name; owner_str = string(owner->owner->name) + "." + owner->name;
} }
else { else {
owner_str = owner->owner->name; owner_str = owner->owner->name;

View File

@@ -305,7 +305,6 @@ void WM_OT_collada_export(wmOperatorType *ot)
static EnumPropertyItem prop_bc_export_transformation_type[] = { static EnumPropertyItem prop_bc_export_transformation_type[] = {
{BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"}, {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"},
{BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"}, {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"},
{BC_TRANSFORMATION_TYPE_BOTH, "both", 0, "Both", "Use <matrix> AND <translate>, <rotate>, <scale> to specify transformations"},
{0, NULL, 0, NULL, NULL} {0, NULL, 0, NULL, NULL}
}; };

View File

@@ -1306,7 +1306,9 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (use_hierarchy || use_base_parent) { if (use_hierarchy || use_base_parent) {
dupli_gh = BLI_ghash_ptr_new(__func__); dupli_gh = BLI_ghash_ptr_new(__func__);
parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__); if (use_hierarchy) {
parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
}
} }
for (dob = lb->first; dob; dob = dob->next) { for (dob = lb->first; dob; dob = dob->next) {
@@ -1343,10 +1345,17 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
copy_m4_m4(ob->obmat, dob->mat); copy_m4_m4(ob->obmat, dob->mat);
BKE_object_apply_mat4(ob, ob->obmat, false, false); BKE_object_apply_mat4(ob, ob->obmat, false, false);
if (dupli_gh) if (dupli_gh) {
BLI_ghash_insert(dupli_gh, dob, ob); BLI_ghash_insert(dupli_gh, dob, ob);
if (parent_gh) }
BLI_ghash_insert(parent_gh, dob, ob); if (parent_gh) {
void **val;
/* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as 'the same',
* this avoids trying to insert same key several time and raise asserts in debug builds... */
if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
*val = ob;
}
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA); DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
} }

View File

@@ -1739,10 +1739,16 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
clear_sca_new_poins(); /* sensor/contr/act */ clear_sca_new_poins(); /* sensor/contr/act */
/* newid may still have some trash from Outliner tree building, /* newid may still have some trash from Outliner tree building, so clear that first to avoid errors, see T26002.
* so clear that first to avoid errors [#26002] */ * We have to clear whole datablocks, not only Object one may be accessed here, see T49905. */
for (ob = bmain->object.first; ob; ob = ob->id.next) ListBase *lbarray[MAX_LIBARRAY];
ob->id.newid = NULL; int a = set_listbasepointers(bmain, lbarray);
while (a--) {
ListBase *lb = lbarray[a];
for (ID *id = lb->first; id; id = id->next) {
id->newid = NULL;
}
}
/* duplicate (must set newid) */ /* duplicate (must set newid) */
for (base = FIRSTBASE; base; base = base->next) { for (base = FIRSTBASE; base; base = base->next) {

View File

@@ -223,10 +223,16 @@ typedef struct RigidBodyCon {
float spring_stiffness_x; float spring_stiffness_x;
float spring_stiffness_y; float spring_stiffness_y;
float spring_stiffness_z; float spring_stiffness_z;
float spring_stiffness_ang_x;
float spring_stiffness_ang_y;
float spring_stiffness_ang_z;
/* amount of velocity lost over time */ /* amount of velocity lost over time */
float spring_damping_x; float spring_damping_x;
float spring_damping_y; float spring_damping_y;
float spring_damping_z; float spring_damping_z;
float spring_damping_ang_x;
float spring_damping_ang_y;
float spring_damping_ang_z;
/* motor settings */ /* motor settings */
float motor_lin_target_velocity; /* linear velocity the motor tries to hold */ float motor_lin_target_velocity; /* linear velocity the motor tries to hold */
@@ -292,7 +298,11 @@ typedef enum eRigidBodyCon_Flag {
RBC_FLAG_USE_SPRING_Z = (1 << 13), RBC_FLAG_USE_SPRING_Z = (1 << 13),
/* motors */ /* motors */
RBC_FLAG_USE_MOTOR_LIN = (1 << 14), RBC_FLAG_USE_MOTOR_LIN = (1 << 14),
RBC_FLAG_USE_MOTOR_ANG = (1 << 15) RBC_FLAG_USE_MOTOR_ANG = (1 << 15),
/* angular springs */
RBC_FLAG_USE_SPRING_ANG_X = (1 << 16),
RBC_FLAG_USE_SPRING_ANG_Y = (1 << 17),
RBC_FLAG_USE_SPRING_ANG_Z = (1 << 18)
} eRigidBodyCon_Flag; } eRigidBodyCon_Flag;
/* ******************************** */ /* ******************************** */

View File

@@ -504,6 +504,45 @@ static void rna_RigidBodyCon_spring_stiffness_z_set(PointerRNA *ptr, float value
#endif #endif
} }
static void rna_RigidBodyCon_spring_stiffness_ang_x_set(PointerRNA *ptr, float value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
rbc->spring_stiffness_ang_x = value;
#ifdef WITH_BULLET
if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_X)) {
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, value);
}
#endif
}
static void rna_RigidBodyCon_spring_stiffness_ang_y_set(PointerRNA *ptr, float value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
rbc->spring_stiffness_ang_y = value;
#ifdef WITH_BULLET
if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y)) {
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, value);
}
#endif
}
static void rna_RigidBodyCon_spring_stiffness_ang_z_set(PointerRNA *ptr, float value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
rbc->spring_stiffness_ang_z = value;
#ifdef WITH_BULLET
if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z)) {
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, value);
}
#endif
}
static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value) static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value)
{ {
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
@@ -541,6 +580,43 @@ static void rna_RigidBodyCon_spring_damping_z_set(PointerRNA *ptr, float value)
#endif #endif
} }
static void rna_RigidBodyCon_spring_damping_ang_x_set(PointerRNA *ptr, float value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
rbc->spring_damping_ang_x = value;
#ifdef WITH_BULLET
if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_X)) {
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, value);
}
#endif
}
static void rna_RigidBodyCon_spring_damping_ang_y_set(PointerRNA *ptr, float value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
rbc->spring_damping_ang_y = value;
#ifdef WITH_BULLET
if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y)) {
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, value);
}
#endif
}
static void rna_RigidBodyCon_spring_damping_ang_z_set(PointerRNA *ptr, float value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
rbc->spring_damping_ang_z = value;
#ifdef WITH_BULLET
if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z)) {
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, value);
}
#endif
}
static void rna_RigidBodyCon_motor_lin_max_impulse_set(PointerRNA *ptr, float value) static void rna_RigidBodyCon_motor_lin_max_impulse_set(PointerRNA *ptr, float value)
{ {
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
@@ -1052,6 +1128,21 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Z Spring", "Enable spring on Z axis"); RNA_def_property_ui_text(prop, "Z Spring", "Enable spring on Z axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "use_spring_ang_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_ANG_X);
RNA_def_property_ui_text(prop, "X Angle Spring", "Enable spring on X rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "use_spring_ang_y", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_ANG_Y);
RNA_def_property_ui_text(prop, "Y Angle Spring", "Enable spring on Y rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "use_spring_ang_z", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_ANG_Z);
RNA_def_property_ui_text(prop, "Z Angle Spring", "Enable spring on Z rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "use_motor_lin", PROP_BOOLEAN, PROP_NONE); prop = RNA_def_property(srna, "use_motor_lin", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_MOTOR_LIN); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_MOTOR_LIN);
RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_use_motor_lin_set"); RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_use_motor_lin_set");
@@ -1169,6 +1260,33 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Z Axis Stiffness", "Stiffness on the Z axis"); RNA_def_property_ui_text(prop, "Z Axis Stiffness", "Stiffness on the Z axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "spring_stiffness_ang_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_ang_x");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
RNA_def_property_float_default(prop, 10.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_ang_x_set", NULL);
RNA_def_property_ui_text(prop, "X Angle Stiffness", "Stiffness on the X rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "spring_stiffness_ang_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_ang_y");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
RNA_def_property_float_default(prop, 10.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_ang_y_set", NULL);
RNA_def_property_ui_text(prop, "Y Angle Stiffness", "Stiffness on the Y rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "spring_stiffness_ang_z", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_ang_z");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
RNA_def_property_float_default(prop, 10.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_ang_z_set", NULL);
RNA_def_property_ui_text(prop, "Z Angle Stiffness", "Stiffness on the Z rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "spring_damping_x", PROP_FLOAT, PROP_FACTOR); prop = RNA_def_property(srna, "spring_damping_x", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_x"); RNA_def_property_float_sdna(prop, NULL, "spring_damping_x");
RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -1193,6 +1311,30 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Damping Z", "Damping on the Z axis"); RNA_def_property_ui_text(prop, "Damping Z", "Damping on the Z axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "spring_damping_ang_x", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_ang_x");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_ang_x_set", NULL);
RNA_def_property_ui_text(prop, "Damping X Angle", "Damping on the X rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "spring_damping_ang_y", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_ang_y");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_ang_y_set", NULL);
RNA_def_property_ui_text(prop, "Damping Y Angle", "Damping on the Y rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "spring_damping_ang_z", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_ang_z");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_ang_z_set", NULL);
RNA_def_property_ui_text(prop, "Damping Z Angle", "Damping on the Z rotational axis");
RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "motor_lin_target_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY); prop = RNA_def_property(srna, "motor_lin_target_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY);
RNA_def_property_float_sdna(prop, NULL, "motor_lin_target_velocity"); RNA_def_property_float_sdna(prop, NULL, "motor_lin_target_velocity");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);

View File

@@ -52,15 +52,6 @@
#include "BLT_lang.h" #include "BLT_lang.h"
#include "GPU_buffers.h" #include "GPU_buffers.h"
#ifdef WITH_CYCLES
static EnumPropertyItem compute_device_type_items[] = {
{USER_COMPUTE_DEVICE_NONE, "NONE", 0, "None", "Don't use compute device"},
{USER_COMPUTE_DEVICE_CUDA, "CUDA", 0, "CUDA", "Use CUDA for GPU acceleration"},
{USER_COMPUTE_DEVICE_OPENCL, "OPENCL", 0, "OpenCL", "Use OpenCL for GPU acceleration"},
{ 0, NULL, 0, NULL, NULL}
};
#endif
#ifdef WITH_OPENSUBDIV #ifdef WITH_OPENSUBDIV
static EnumPropertyItem opensubdiv_compute_type_items[] = { static EnumPropertyItem opensubdiv_compute_type_items[] = {
{USER_OPENSUBDIV_COMPUTE_NONE, "NONE", 0, "None", ""}, {USER_OPENSUBDIV_COMPUTE_NONE, "NONE", 0, "None", ""},
@@ -124,8 +115,6 @@ static EnumPropertyItem rna_enum_language_default_items[] = {
#include "UI_interface.h" #include "UI_interface.h"
#include "CCL_api.h"
#ifdef WITH_OPENSUBDIV #ifdef WITH_OPENSUBDIV
# include "opensubdiv_capi.h" # include "opensubdiv_capi.h"
#endif #endif
@@ -476,78 +465,6 @@ static PointerRNA rna_Theme_space_list_generic_get(PointerRNA *ptr)
} }
#ifdef WITH_CYCLES
static EnumPropertyItem *rna_userdef_compute_device_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem *item = NULL;
int totitem = 0;
/* add supported device types */
RNA_enum_items_add_value(&item, &totitem, compute_device_type_items, USER_COMPUTE_DEVICE_NONE);
if (CCL_compute_device_list(0))
RNA_enum_items_add_value(&item, &totitem, compute_device_type_items, USER_COMPUTE_DEVICE_CUDA);
if (CCL_compute_device_list(1))
RNA_enum_items_add_value(&item, &totitem, compute_device_type_items, USER_COMPUTE_DEVICE_OPENCL);
RNA_enum_item_end(&item, &totitem);
*r_free = true;
return item;
}
static int rna_userdef_compute_device_get(PointerRNA *UNUSED(ptr))
{
if (U.compute_device_type == USER_COMPUTE_DEVICE_NONE)
return 0;
return U.compute_device_id;
}
static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem tmp = {0, "", 0, "", ""};
EnumPropertyItem *item = NULL;
int totitem = 0;
if (U.compute_device_type == USER_COMPUTE_DEVICE_NONE) {
/* only add a single CPU device */
tmp.value = 0;
tmp.name = "CPU";
tmp.identifier = "CPU";
RNA_enum_item_add(&item, &totitem, &tmp);
}
else {
/* get device list from cycles. it would be good to make this generic
* once we have more subsystems using opencl, for now this is easiest */
int opencl = (U.compute_device_type == USER_COMPUTE_DEVICE_OPENCL);
CCLDeviceInfo *devices = CCL_compute_device_list(opencl);
int a;
if (devices) {
for (a = 0; devices[a].identifier[0]; a++) {
tmp.value = devices[a].value;
tmp.identifier = devices[a].identifier;
tmp.name = devices[a].name;
RNA_enum_item_add(&item, &totitem, &tmp);
}
}
else {
tmp.value = 0;
tmp.name = "CPU";
tmp.identifier = "CPU";
RNA_enum_item_add(&item, &totitem, &tmp);
}
}
RNA_enum_item_end(&item, &totitem);
*r_free = true;
return item;
}
#endif
#ifdef WITH_OPENSUBDIV #ifdef WITH_OPENSUBDIV
static EnumPropertyItem *rna_userdef_opensubdiv_compute_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), static EnumPropertyItem *rna_userdef_opensubdiv_compute_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *r_free) PropertyRNA *UNUSED(prop), bool *r_free)
@@ -3973,13 +3890,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL} {0, NULL, 0, NULL, NULL}
}; };
#ifdef WITH_CYCLES
static EnumPropertyItem compute_device_items[] = {
{0, "CPU", 0, "CPU", ""},
{ 0, NULL, 0, NULL, NULL}
};
#endif
static EnumPropertyItem image_draw_methods[] = { static EnumPropertyItem image_draw_methods[] = {
{IMAGE_DRAW_METHOD_2DTEXTURE, "2DTEXTURE", 0, "2D Texture", "Use CPU for display transform and draw image with 2D texture"}, {IMAGE_DRAW_METHOD_2DTEXTURE, "2DTEXTURE", 0, "2D Texture", "Use CPU for display transform and draw image with 2D texture"},
{IMAGE_DRAW_METHOD_GLSL, "GLSL", 0, "GLSL", "Use GLSL shaders for display transform and draw image with 2D texture"}, {IMAGE_DRAW_METHOD_GLSL, "GLSL", 0, "GLSL", "Use GLSL shaders for display transform and draw image with 2D texture"},
@@ -4271,23 +4181,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
"Draw tool/property regions over the main region, when using Triple Buffer"); "Draw tool/property regions over the main region, when using Triple Buffer");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
#ifdef WITH_CYCLES
prop = RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
RNA_def_property_enum_sdna(prop, NULL, "compute_device_type");
RNA_def_property_enum_items(prop, compute_device_type_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_userdef_compute_device_type_itemf");
RNA_def_property_ui_text(prop, "Compute Device Type", "Device to use for computation (rendering with Cycles)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
prop = RNA_def_property(srna, "compute_device", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
RNA_def_property_enum_sdna(prop, NULL, "compute_device_id");
RNA_def_property_enum_items(prop, compute_device_items);
RNA_def_property_enum_funcs(prop, "rna_userdef_compute_device_get", NULL, "rna_userdef_compute_device_itemf");
RNA_def_property_ui_text(prop, "Compute Device", "Device to use for computation");
#endif
#ifdef WITH_OPENSUBDIV #ifdef WITH_OPENSUBDIV
prop = RNA_def_property(srna, "opensubdiv_compute_type", PROP_ENUM, PROP_NONE); prop = RNA_def_property(srna, "opensubdiv_compute_type", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);

View File

@@ -145,12 +145,9 @@ static void updateDepsgraph(ModifierData *md,
HookModifierData *hmd = (HookModifierData *)md; HookModifierData *hmd = (HookModifierData *)md;
if (hmd->object != NULL) { if (hmd->object != NULL) {
if (hmd->subtarget[0]) { if (hmd->subtarget[0]) {
DEG_add_bone_relation(node, hmd->object, hmd->subtarget, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
DEG_add_bone_relation(node, hmd->object, hmd->subtarget, DEG_OB_COMP_BONE, "Hook Modifier"); DEG_add_bone_relation(node, hmd->object, hmd->subtarget, DEG_OB_COMP_BONE, "Hook Modifier");
} }
else { DEG_add_object_relation(node, hmd->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
DEG_add_object_relation(node, hmd->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
}
} }
/* We need own transformation as well. */ /* We need own transformation as well. */
DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Hook Modifier"); DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Hook Modifier");

View File

@@ -142,7 +142,6 @@ struct wmWindowManager;
# pragma GCC diagnostic ignored "-Wunused-parameter" # pragma GCC diagnostic ignored "-Wunused-parameter"
#endif #endif
#include "../../intern/cycles/blender/CCL_api.h"
#include "../../intern/dualcon/dualcon.h" #include "../../intern/dualcon/dualcon.h"
#include "../../intern/elbeem/extern/elbeem.h" #include "../../intern/elbeem/extern/elbeem.h"
#include "../blender/blenkernel/BKE_modifier.h" #include "../blender/blenkernel/BKE_modifier.h"
@@ -767,10 +766,6 @@ void *dualcon(const DualConInput *input_mesh,
float scale, float scale,
int depth) RET_ZERO int depth) RET_ZERO
/* intern/cycles */
struct CCLDeviceInfo;
struct CCLDeviceInfo *CCL_compute_device_list(int opencl) RET_NULL
/* compositor */ /* compositor */
void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering, void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering,
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,

View File

@@ -1153,13 +1153,12 @@ if(WIN32 AND NOT WITH_PYTHON_MODULE)
COMPONENT Blender COMPONENT Blender
DESTINATION "." DESTINATION "."
) )
if(CMAKE_CL_64)
set(_WIN_PLATFORM x64)
else()
set(_WIN_PLATFORM x86)
endif()
if(MSVC12_REDIST_DIR) if(MSVC12_REDIST_DIR)
if(CMAKE_CL_64)
set(_WIN_PLATFORM x64)
else()
set(_WIN_PLATFORM x86)
endif()
install( install(
FILES FILES
${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.CRT/msvcp120.dll ${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.CRT/msvcp120.dll
@@ -1173,4 +1172,51 @@ if(WIN32 AND NOT WITH_PYTHON_MODULE)
) )
endif() endif()
endif() endif()
if(MSVC14_REDIST_DIR)
set(KITSDIRx86 "$ENV{${ProgramFilesX86_NAME}}/Windows Kits/10/")
set(KITSDIR "$ENV{ProgramFiles}/Windows Kits/10/")
if(IS_DIRECTORY ${KITSDIR})
set(KITSPATH "${KITSDIR}/Redist/ucrt/DLLs/${_WIN_PLATFORM}")
else()
if(IS_DIRECTORY ${KITSDIRx86})
set(KITSPATH "${KITSDIRx86}/Redist/ucrt/DLLs/${_WIN_PLATFORM}")
else()
message(FATAL_ERROR "Windows 10 SDK directory not found")
endif()
endif()
install(
FILES
${KITSPATH}/api-ms-win-core-file-l1-2-0.dll
${KITSPATH}/api-ms-win-core-file-l2-1-0.dll
${KITSPATH}/api-ms-win-core-localization-l1-2-0.dll
${KITSPATH}/api-ms-win-core-processthreads-l1-1-0.dll
${KITSPATH}/api-ms-win-core-processthreads-l1-1-1.dll
${KITSPATH}/api-ms-win-core-synch-l1-1-0.dll
${KITSPATH}/api-ms-win-core-synch-l1-2-0.dll
${KITSPATH}/api-ms-win-core-timezone-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-conio-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-convert-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-environment-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-filesystem-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-heap-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-locale-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-math-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-process-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-runtime-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-stdio-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-string-l1-1-0.dll
${KITSPATH}/api-ms-win-crt-time-l1-1-0.dll
${KITSPATH}/ucrtbase.dll
${MSVC14_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC140.CRT/vcruntime140.dll
DESTINATION "."
)
if(WITH_OPENMP)
install(
FILES ${MSVC14_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC140.OpenMP/vcomp140.dll
DESTINATION "."
)
endif()
endif()
endif() endif()

View File

@@ -130,7 +130,7 @@ add_test(export_obj_cube ${TEST_BLENDER_EXE}
--run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_cube.obj',use_selection=False\) --run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_cube.obj',use_selection=False\)
--md5_source=${TEST_OUT_DIR}/export_obj_cube.obj --md5_source=${TEST_OUT_DIR}/export_obj_cube.obj
--md5_source=${TEST_OUT_DIR}/export_obj_cube.mtl --md5_source=${TEST_OUT_DIR}/export_obj_cube.mtl
--md5=826f74e6b7a2128b0b61a52071ada36e --md5_method=FILE --md5=e80660437ad9bfe082849641c361a233 --md5_method=FILE
) )
add_test(export_obj_nurbs ${TEST_BLENDER_EXE} add_test(export_obj_nurbs ${TEST_BLENDER_EXE}