Merge branch 'master' into blender2.8

Conflicts:
	intern/cycles/blender/addon/properties.py
This commit is contained in:
Bastien Montagne 2016-11-07 15:46:27 +01:00
commit c1ba58c44d
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)
if(APPLE)
option(WITH_CODEC_QUICKTIME "Enable Quicktime Support" ON)
option(WITH_CODEC_QUICKTIME "Enable Quicktime Support" OFF)
endif()
# 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})
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
option(WITH_LEGACY_DEPSGRAPH "Build Blender with legacy dependency graph" ON)
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
else()
# 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
set(WITH_BOOST OFF)
endif()

View File

@ -4015,9 +4015,6 @@ install_OTHER() {
fi
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 ""
compile_LLVM
have_llvm=true
@ -4036,7 +4033,6 @@ install_OTHER() {
if [ "$_do_compile_osl" = true ]; then
if [ "$have_llvm" = true ]; then
install_packages_DEB flex bison libtbb-dev
PRINT ""
compile_OSL
else
@ -4055,7 +4051,6 @@ install_OTHER() {
fi
if [ "$_do_compile_osd" = true ]; then
install_packages_DEB flex bison libtbb-dev
PRINT ""
compile_OSD
fi
@ -4072,10 +4067,6 @@ install_OTHER() {
fi
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 ""
compile_OpenCOLLADA
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-addons.git': 'blender-addons',
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',
}
@ -128,6 +129,7 @@ def schedule_force_build(name):
forcesched.CodebaseParameter(hide=True, codebase="blender-translations"),
forcesched.CodebaseParameter(hide=True, codebase="blender-addons"),
forcesched.CodebaseParameter(hide=True, codebase="blender-addons-contrib"),
forcesched.CodebaseParameter(hide=True, codebase="blender-dev-tools"),
forcesched.CodebaseParameter(hide=True, codebase="lib svn")],
properties=[]))
@ -143,6 +145,7 @@ def schedule_build(name, hour, minute=0):
"blender-translations": {"repository": "", "branch": "master"},
"blender-addons": {"repository": "", "branch": "master"},
"blender-addons-contrib": {"repository": "", "branch": "master"},
"blender-dev-tools": {"repository": "", "branch": "master"},
"lib svn": {"repository": "", "branch": "trunk"}},
branch=current_branch,
builderNames=[name],
@ -264,7 +267,8 @@ def generic_builder(id, libdir='', branch='', rsync=False):
for submodule in ('blender-translations',
'blender-addons',
'blender-addons-contrib'):
'blender-addons-contrib',
'blender-dev-tools'):
f.addStep(git_submodule_step(submodule))
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, '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_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
#

View File

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

View File

@ -21,17 +21,6 @@
extern "C" {
#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 */
void *CCL_python_module_init(void);

View File

@ -21,7 +21,8 @@ from bpy.props import (BoolProperty,
EnumProperty,
FloatProperty,
IntProperty,
PointerProperty)
PointerProperty,
StringProperty)
# enums
@ -122,6 +123,12 @@ enum_volume_interpolation = (
('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):
@classmethod
@ -1087,6 +1094,103 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
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():
bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings)
@ -1097,6 +1201,8 @@ def register():
bpy.utils.register_class(CyclesMeshSettings)
bpy.utils.register_class(CyclesObjectSettings)
bpy.utils.register_class(CyclesCurveRenderSettings)
bpy.utils.register_class(CyclesDeviceSettings)
bpy.utils.register_class(CyclesPreferences)
def unregister():
@ -1109,3 +1215,5 @@ def unregister():
bpy.utils.unregister_class(CyclesObjectSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings)
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
def get_device_type(context):
return context.user_preferences.addons[__package__].preferences.compute_device_type
def use_cpu(context):
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):
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):
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):
@ -85,6 +86,14 @@ def use_sample_all_lights(context):
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):
cscene = context.scene.cycles
@ -141,7 +150,6 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
device_type = context.user_preferences.system.compute_device_type
row = layout.row(align=True)
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()
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="")
row.prop(cscene, "use_square_samples")
@ -1542,9 +1550,13 @@ def draw_device(self, context):
layout.prop(cscene, "feature_set")
device_type = context.user_preferences.system.compute_device_type
if device_type in {'CUDA', 'OPENCL', 'NETWORK'}:
layout.prop(cscene, "device")
split = layout.split(percentage=1/3)
split.label("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):
layout.prop(cscene, "shading_system")

View File

@ -40,10 +40,6 @@ CCL_NAMESPACE_BEGIN
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. */
bool debug_flags_set = false;
@ -195,7 +191,6 @@ static PyObject *exit_func(PyObject * /*self*/, PyObject * /*args*/)
ShaderManager::free_memory();
TaskScheduler::free_memory();
Device::free_memory();
device_list.free_memory();
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++) {
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;
@ -676,6 +676,20 @@ static PyObject *set_resumable_chunks_func(PyObject * /*self*/, PyObject *args)
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[] = {
{"init", init_func, METH_VARARGS, ""},
{"exit", exit_func, METH_VARARGS, ""},
@ -703,6 +717,9 @@ static PyMethodDef methods[] = {
/* Resumable render */
{"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},
};
@ -715,47 +732,6 @@ static struct PyModuleDef module = {
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
void *CCL_python_module_init()
@ -794,24 +770,3 @@ void *CCL_python_module_init()
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();
/* 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) {
/* find network device */
@ -532,17 +537,39 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
params.device = info;
}
else if(get_enum(cscene, "device") == 1) {
/* find GPU device with given id */
PointerRNA systemptr = b_userpref.system().ptr;
PropertyRNA *deviceprop = RNA_struct_find_property(&systemptr, "compute_device");
int device_id = b_userpref.system().compute_device();
PointerRNA b_preferences;
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)) {
foreach(DeviceInfo& info, devices)
if(info.id == id)
params.device = info;
int compute_device = get_enum(b_preferences, "compute_device_type");
if(compute_device != 0) {
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()
message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES")
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()

View File

@ -258,33 +258,33 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
DeviceType Device::type_from_string(const char *name)
{
if(strcmp(name, "cpu") == 0)
if(strcmp(name, "CPU") == 0)
return DEVICE_CPU;
else if(strcmp(name, "cuda") == 0)
else if(strcmp(name, "CUDA") == 0)
return DEVICE_CUDA;
else if(strcmp(name, "opencl") == 0)
else if(strcmp(name, "OPENCL") == 0)
return DEVICE_OPENCL;
else if(strcmp(name, "network") == 0)
else if(strcmp(name, "NETWORK") == 0)
return DEVICE_NETWORK;
else if(strcmp(name, "multi") == 0)
else if(strcmp(name, "MULTI") == 0)
return DEVICE_MULTI;
return DEVICE_NONE;
}
string Device::string_from_type(DeviceType type)
{
if(type == DEVICE_CPU)
return "cpu";
return "CPU";
else if(type == DEVICE_CUDA)
return "cuda";
return "CUDA";
else if(type == DEVICE_OPENCL)
return "opencl";
return "OPENCL";
else if(type == DEVICE_NETWORK)
return "network";
return "NETWORK";
else if(type == DEVICE_MULTI)
return "multi";
return "MULTI";
return "";
}
@ -307,9 +307,6 @@ vector<DeviceType>& Device::available_types()
#ifdef WITH_NETWORK
types.push_back(DEVICE_NETWORK);
#endif
#ifdef WITH_MULTI
types.push_back(DEVICE_MULTI);
#endif
need_types_update = false;
}
@ -331,10 +328,6 @@ vector<DeviceInfo>& Device::available_devices()
device_opencl_info(devices);
#endif
#ifdef WITH_MULTI
device_multi_info(devices);
#endif
device_cpu_info(devices);
#ifdef WITH_NETWORK
@ -368,6 +361,29 @@ string Device::device_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()
{
need_types_update = true;

View File

@ -49,7 +49,7 @@ class DeviceInfo {
public:
DeviceType type;
string description;
string id;
string id; /* used for user preferences, should stay fixed with changing hardware config */
int num;
bool display_device;
bool advanced_shading;
@ -69,6 +69,12 @@ public:
has_bindless_textures = 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 {
@ -282,6 +288,7 @@ public:
static vector<DeviceType>& available_types();
static vector<DeviceInfo>& available_devices();
static string device_capabilities();
static DeviceInfo get_multi_device(vector<DeviceInfo> subdevices);
/* Tag devices lists for update. */
static void tag_update();

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <climits>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -213,7 +214,8 @@ public:
return;
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;
cuda_pop_context();
@ -233,7 +235,8 @@ public:
bool support_device(const DeviceRequestedFeatures& /*requested_features*/)
{
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 */
if(major < 2) {
@ -315,7 +318,8 @@ public:
{
/* Compute cubin name. */
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. */
if(!use_adaptive_compilation()) {
@ -1394,8 +1398,8 @@ void device_cuda_info(vector<DeviceInfo>& devices)
if(cuDeviceGetName(name, 256, num) != CUDA_SUCCESS)
continue;
int major, minor;
cuDeviceComputeCapability(&major, &minor, num);
int major;
cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, num);
if(major < 2) {
continue;
}
@ -1404,13 +1408,18 @@ void device_cuda_info(vector<DeviceInfo>& devices)
info.type = DEVICE_CUDA;
info.description = string(name);
info.id = string_printf("CUDA_%d", num);
info.num = num;
info.advanced_shading = (major >= 2);
info.has_bindless_textures = (major >= 3);
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(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) {
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_cuda_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_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);
}
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

View File

@ -83,17 +83,22 @@ void device_opencl_info(vector<DeviceInfo>& devices)
const string& platform_name = platform_device.platform_name;
const cl_device_type device_type = platform_device.device_type;
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;
info.type = DEVICE_OPENCL;
info.description = string_remove_trademark(string(device_name));
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. */
info.display_device = true;
info.advanced_shading = OpenCLInfo::kernel_use_advanced_shading(platform_name);
info.pack_images = true;
info.use_split_kernel = OpenCLInfo::kernel_use_split(platform_name,
device_type);
info.id = string("OPENCL_") + platform_name + "_" + device_name + "_" + hardware_id;
devices.push_back(info);
num_devices++;
}

View File

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

View File

@ -661,6 +661,27 @@ bool OpenCLInfo::device_version_check(cl_device_id device,
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,
bool force_all)
{
@ -773,11 +794,13 @@ void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices
continue;
}
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,
platform_name,
device_id,
device_type,
device_name));
device_name,
hardware_id));
}
else {
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)
{
#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
Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
if(ccl_fetch(sd, object) != OBJECT_NONE) {
Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
}
#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. */
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) {
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__
shader_setup_object_transforms(kg, sd, time);
#endif
ccl_fetch(sd, time) = time;
}
else if(lamp != LAMP_NONE) {
ccl_fetch(sd, ob_tfm) = lamp_fetch_transform(kg, lamp, false);
ccl_fetch(sd, ob_itfm) = lamp_fetch_transform(kg, lamp, true);
}
#ifdef __OBJECT_MOTION__
ccl_fetch(sd, time) = time;
#endif
}
/* transform into world 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);
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 */
N.x = fabsf(N.x);

View File

@ -49,8 +49,7 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg,
}
case NODE_TEXCO_NORMAL: {
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;
}
case NODE_TEXCO_CAMERA: {
@ -131,8 +130,7 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg,
}
case NODE_TEXCO_NORMAL: {
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;
}
case NODE_TEXCO_CAMERA: {
@ -216,8 +214,7 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg,
}
case NODE_TEXCO_NORMAL: {
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;
}
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 x = 0; x < width; x++) {
float u = x/(float)width;
float v = y/(float)height;
float u = (x + 0.5f)/width;
float v = (y + 0.5f)/height;
uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0);
d_input_data[x + y*width] = in;

View File

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

View File

@ -65,9 +65,9 @@ TEST(ModalSolver, SyntheticCubeSceneMotion) {
NULL);
Mat3 expected_rotation;
expected_rotation << 0.98215101299251, 0.17798357184544, 0.06083778292258,
-0.16875286001759, 0.97665299913606, -0.13293378620359,
-0.08307743323957, 0.12029450291547, 0.98925596922871;
expected_rotation << 0.98215101743472, 0.17798354937546, 0.06083777694542,
-0.16875283983360, 0.97665300495333, -0.13293376908719,
-0.08307742172243, 0.12029448893171, 0.98925597189636;
Mat3 &first_camera_R = reconstruction.CameraForImage(1)->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
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_TYPE=Release
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)
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"]
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)
sub = row.row(align=True)
sub.scale_x = 0.1
sub.prop(rbc, "use_spring_x", toggle=True, text="X")
sub.scale_x = 0.5
sub.prop(rbc, "use_spring_x", toggle=True, text="X Axis")
sub = row.row(align=True)
sub.active = rbc.use_spring_x
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)
sub = row.row(align=True)
sub.scale_x = 0.1
sub.prop(rbc, "use_spring_y", toggle=True, text="Y")
sub.scale_x = 0.5
sub.prop(rbc, "use_spring_y", toggle=True, text="Y Axis")
sub = row.row(align=True)
sub.active = rbc.use_spring_y
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)
sub = row.row(align=True)
sub.scale_x = 0.1
sub.prop(rbc, "use_spring_z", toggle=True, text="Z")
sub.scale_x = 0.5
sub.prop(rbc, "use_spring_z", toggle=True, text="Z Axis")
sub = row.row(align=True)
sub.active = rbc.use_spring_z
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.
bpy.utils.register_module(__name__)

View File

@ -428,13 +428,6 @@ class USERPREF_PT_system(Panel):
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"):
col.label(text="OpenSubdiv compute:")
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.operator("mesh.normals_make_consistent", text="Recalculate")
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):

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_pose_clear_pointers(struct bPose *pose);
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_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);

View File

@ -1781,6 +1781,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
BLI_duplicatelist(&pose->agroups, &frompose->agroups);
pose->active_group = frompose->active_group;
BKE_pose_channels_hash_make(frompose);
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
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 */
/* 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;
bPose *pose;
@ -1963,8 +1964,9 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
#ifdef WITH_LEGACY_DEPSGRAPH
/* the sorting */
/* Sorting for new dependnecy graph is done on the scene graph level. */
if (counter > 1)
if (counter > 1 && sort_bones) {
DAG_pose_sort(ob);
}
#endif
ob->pose->flag &= ~POSE_RECALC;
@ -1973,6 +1975,11 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
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 ******************* */
/* 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);
#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);
}

View File

@ -1761,7 +1761,8 @@ void BKE_library_make_local(
it->link = NULL;
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
* later we can skip it in lib-dependency cycles search later. */
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_free(bmain, id);
#endif
((LinkNode *)it->link)->link = NULL; /* Not strictly necessary, but safer (see T49903)... */
it->link = NULL;
}
}

View File

@ -58,6 +58,7 @@
#include "BLI_strict_flags.h"
#include "atomic_ops.h"
#include "mikktspace.h"
// #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));
/* 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;
}
}

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_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);
/* fall-through */
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_y = 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_y = 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_target_velocity = 1.0f;

View File

@ -52,6 +52,7 @@
#include "DNA_actuator_types.h"
#include "DNA_view3d_types.h"
#include "DNA_smoke_types.h"
#include "DNA_rigidbody_types.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);
break;
}
case BC_TRANSFORMATION_TYPE_BOTH:
{
node.addMatrix("transform",d_obmat);
/* fall-through */
}
case BC_TRANSFORMATION_TYPE_TRANSROTLOC:
{
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 {
BC_TRANSFORMATION_TYPE_MATRIX,
BC_TRANSFORMATION_TYPE_TRANSROTLOC,
BC_TRANSFORMATION_TYPE_BOTH
BC_TRANSFORMATION_TYPE_TRANSROTLOC
} BC_export_transformation_type;
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
* 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;
v += 0.5f / cy;
}

View File

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

View File

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

View File

@ -34,7 +34,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
@ -129,8 +128,7 @@ RootDepsNode *DepsgraphNodeBuilder::add_root_node()
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, string(id->name + 2) + "[" + idtype_name + "]");
return m_graph->add_id_node(id, id->name);
}
TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id)
@ -177,7 +175,7 @@ TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id)
ComponentDepsNode *DepsgraphNodeBuilder::add_component_node(
ID *id,
eDepsNode_Type comp_type,
const string &comp_name)
const char *comp_name)
{
IDDepsNode *id_node = add_id_node(id);
ComponentDepsNode *comp_node = id_node->add_component(comp_type, comp_name);
@ -190,15 +188,19 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
eDepsOperation_Type optype,
DepsEvalOperationCb op,
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) {
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);
}
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(),
op_node->identifier().c_str(),
op_node);
@ -210,14 +212,15 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
ID *id,
eDepsNode_Type comp_type,
const string &comp_name,
const char *comp_name,
eDepsOperation_Type optype,
DepsEvalOperationCb op,
eDepsOperation_Code opcode,
const string &description)
const char *name,
int name_tag)
{
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(
@ -226,38 +229,54 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
eDepsOperation_Type optype,
DepsEvalOperationCb op,
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,
eDepsNode_Type comp_type,
const string &comp_name,
const char *comp_name,
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(
ID *id,
eDepsNode_Type comp_type,
const string &comp_name,
const char *comp_name,
eDepsOperation_Code opcode,
const string &description)
const char *name,
int name_tag)
{
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(
ID *id,
eDepsNode_Type comp_type,
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 **** */
@ -610,12 +629,17 @@ OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
OperationDepsNode *driver_op = find_operation_node(id,
DEPSNODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
deg_fcurve_id_name(fcu));
fcu->rna_path,
fcu->array_index);
if (driver_op == NULL) {
driver_op = add_operation_node(id, DEPSNODE_TYPE_PARAMETERS,
DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_driver, _1, id, fcu),
DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu));
driver_op = add_operation_node(id,
DEPSNODE_TYPE_PARAMETERS,
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.) */
@ -760,7 +784,7 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
/* Rebuild pose if not up to date. */
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
* after loading file. Need to investigate further since it does
* not happen with simple scenes..
@ -1124,15 +1148,20 @@ void DepsgraphNodeBuilder::build_nodetree(DepsNode *owner_node, bNodeTree *ntree
/* nodetree's nodes... */
for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) {
if (bnode->id) {
if (GS(bnode->id->name) == ID_MA) {
build_material(owner_node, (Material *)bnode->id);
ID *id = bnode->id;
if (id != NULL) {
short id_type = GS(id->name);
if (id_type == ID_MA) {
build_material(owner_node, (Material *)id);
}
else if (bnode->type == ID_TE) {
build_texture(owner_node, (Tex *)bnode->id);
else if (id_type == ID_TE) {
build_texture(owner_node, (Tex *)id);
}
else if (id_type == ID_IM) {
build_image((Image *)id);
}
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) {
build_nodetree(owner_node, group_ntree);
}
@ -1189,10 +1218,33 @@ void DepsgraphNodeBuilder::build_texture(DepsNode *owner_node, Tex *tex)
return;
}
tex_id->tag |= LIB_TAG_DOIT;
/* texture itself */
/* Texture itself. */
build_animdata(tex_id);
/* texture's nodetree */
/* Texture's 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)

View File

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

View File

@ -34,13 +34,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstring> /* required for STREQ later on. */
#include "MEM_guardedalloc.h"
extern "C" {
#include "BLI_blenlib.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "DNA_action_types.h"
@ -209,10 +208,12 @@ OperationDepsNode *DepsgraphRelationBuilder::find_node(
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) {
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;
}
@ -234,7 +235,7 @@ OperationDepsNode *DepsgraphRelationBuilder::has_node(
if (!comp_node) {
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,
@ -483,7 +484,7 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
build_animdata(&ob->id);
// 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);
add_relation(adt_key, local_transform_key, DEPSREL_TYPE_OPERATION, "Object Animation");
}
@ -815,11 +816,66 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
/* drivers */
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 */
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... */
if (adt->action || adt->nla_tracks.first) {
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)
{
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;
/* create dependency between driver and data affected by it */
@ -1384,7 +1444,7 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
"Armature Eval");
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);
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.
*/
/* 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);
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);
if (adt != NULL) {
return adt->action != NULL;
return (adt->action != NULL) || (adt->nla_tracks.first != NULL);
}
return false;
}

View File

@ -81,108 +81,83 @@ struct ComponentDepsNode;
struct OperationDepsNode;
struct RootPChanMap;
struct RootKey
{
RootKey() {}
struct RootKey {
RootKey();
};
struct TimeSourceKey
{
TimeSourceKey() : id(NULL) {}
TimeSourceKey(ID *id) : id(id) {}
TimeSourceKey();
TimeSourceKey(ID *id);
string identifier() const
{
return string("TimeSourceKey");
}
string identifier() const;
ID *id;
};
struct ComponentKey
{
ComponentKey() :
id(NULL), type(DEPSNODE_TYPE_UNDEFINED), name("")
{}
ComponentKey(ID *id, eDepsNode_Type type, const string &name = "") :
id(id), type(type), name(name)
{}
ComponentKey();
ComponentKey(ID *id, eDepsNode_Type type, const char *name = "");
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 + "')";
}
string identifier() const;
ID *id;
eDepsNode_Type type;
string name;
const char *name;
};
struct OperationKey
{
OperationKey() :
id(NULL), component_type(DEPSNODE_TYPE_UNDEFINED), component_name(""), opcode(DEG_OPCODE_OPERATION), name("")
{}
OperationKey();
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) :
id(id), component_type(component_type), component_name(""), opcode(DEG_OPCODE_OPERATION), name(name)
{}
OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, const string &name) :
id(id), component_type(component_type), component_name(component_name), opcode(DEG_OPCODE_OPERATION), name(name)
{}
OperationKey(ID *id,
eDepsNode_Type component_type,
eDepsOperation_Code opcode);
OperationKey(ID *id,
eDepsNode_Type component_type,
const char *component_name,
eDepsOperation_Code opcode);
OperationKey(ID *id, eDepsNode_Type component_type, eDepsOperation_Code opcode) :
id(id), component_type(component_type), component_name(""), opcode(opcode), name("")
{}
OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, eDepsOperation_Code opcode) :
id(id), component_type(component_type), component_name(component_name), opcode(opcode), name("")
{}
OperationKey(ID *id, eDepsNode_Type component_type, eDepsOperation_Code opcode, const string &name) :
id(id), component_type(component_type), component_name(""), opcode(opcode), name(name)
{}
OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, eDepsOperation_Code opcode, const string &name) :
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 + "')";
}
OperationKey(ID *id,
eDepsNode_Type component_type,
eDepsOperation_Code opcode,
const char *name,
int name_tag = -1);
OperationKey(ID *id,
eDepsNode_Type component_type,
const char *component_name,
eDepsOperation_Code opcode,
const char *name,
int name_tag = -1);
string identifier() const;
ID *id;
eDepsNode_Type component_type;
string component_name;
const char *component_name;
eDepsOperation_Code opcode;
string name;
const char *name;
int name_tag;
};
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 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 + "')";
}
RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop);
string identifier() const;
ID *id;
PointerRNA ptr;
@ -270,7 +245,7 @@ protected:
template <typename KeyType>
DepsNodeHandle create_node_handle(const KeyType& key,
const string& default_name = "");
const char *default_name = "");
bool needs_animdata_node(ID *id);
@ -280,7 +255,7 @@ private:
struct DepsNodeHandle
{
DepsNodeHandle(DepsgraphRelationBuilder *builder, OperationDepsNode *node, const string &default_name = "") :
DepsNodeHandle(DepsgraphRelationBuilder *builder, OperationDepsNode *node, const char *default_name = "") :
builder(builder),
node(node),
default_name(default_name)
@ -290,7 +265,7 @@ struct DepsNodeHandle
DepsgraphRelationBuilder *builder;
OperationDepsNode *node;
const string &default_name;
const char *default_name;
};
/* Utilities for Builders ----------------------------------------------------- */
@ -318,6 +293,7 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
else {
if (!op_from) {
/* 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",
type, description, key_from.identifier().c_str());
}
@ -383,7 +359,7 @@ void DepsgraphRelationBuilder::add_node_handle_relation(
template <typename KeyType>
DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(
const KeyType &key,
const string &default_name)
const char *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,
const DepsNode *node)
{
string name = node->identifier().c_str();
string name = node->identifier();
if (node->type == DEPSNODE_TYPE_ID_REF) {
IDDepsNode *id_node = (IDDepsNode *)node;
char buf[256];

View File

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

View File

@ -100,22 +100,6 @@ struct 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.
*
@ -136,7 +120,7 @@ struct Depsgraph {
void clear_subgraph_nodes();
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 clear_id_nodes();

View File

@ -32,6 +32,8 @@
#include "MEM_guardedalloc.h"
// #define DEBUG_TIME
extern "C" {
#include "DNA_cachefile_types.h"
#include "DNA_object_types.h"
@ -41,6 +43,11 @@ extern "C" {
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#ifdef DEBUG_TIME
# include "PIL_time.h"
# include "PIL_time_utildefines.h"
#endif
#include "BKE_main.h"
#include "BKE_collision.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)
{
#ifdef DEBUG_TIME
TIMEIT_START(DEG_graph_build_from_scene);
#endif
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
/* 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();
}
#endif
#ifdef DEBUG_TIME
TIMEIT_END(DEG_graph_build_from_scene);
#endif
}
/* Tag graph relations for update. */

View File

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

View File

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

View File

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

View File

@ -66,10 +66,10 @@ struct DepsgraphDebug {
static DepsgraphStatsID *get_id_stats(ID *id, bool create);
static DepsgraphStatsComponent *get_component_stats(DepsgraphStatsID *id_stats,
const string &name,
const char *name,
bool create);
static DepsgraphStatsComponent *get_component_stats(ID *id,
const string &name,
const char *name,
bool 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 <stdio.h>
#include <string.h>
#include <cstring> /* required for STREQ later on. */
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@ -72,7 +72,7 @@ DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname)
DepsNode::DepsNode()
{
name[0] = '\0';
name = "";
}
DepsNode::~DepsNode()
@ -122,7 +122,7 @@ RootDepsNode::~RootDepsNode()
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) {
DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_TIMESOURCE);
@ -142,12 +142,24 @@ static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
/* 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)
{
const IDDepsNode::ComponentIDKey *key =
reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v);
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)
@ -173,7 +185,7 @@ static void id_deps_node_hash_value_free(void *value_v)
}
/* 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. */
BLI_assert(id != NULL);
@ -204,14 +216,14 @@ IDDepsNode::~IDDepsNode()
}
ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
const string &name) const
const char *name) const
{
ComponentIDKey key(type, name);
return reinterpret_cast<ComponentDepsNode *>(BLI_ghash_lookup(components, &key));
}
ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
const string &name)
const char *name)
{
ComponentDepsNode *comp_node = find_component(type, name);
if (!comp_node) {
@ -226,7 +238,7 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
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);
if (comp_node) {
@ -281,7 +293,7 @@ static DepsNodeFactoryImpl<IDDepsNode> DNTI_ID_REF;
/* Subgraph Node ========================================== */
/* 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. */
this->root_id = (ID *)id;

View File

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

View File

@ -31,7 +31,7 @@
#include "intern/nodes/deg_node_component.h"
#include <stdio.h>
#include <string.h>
#include <cstring> /* required for STREQ later on. */
extern "C" {
#include "BLI_utildefines.h"
@ -53,12 +53,50 @@ namespace DEG {
/* 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)
{
const ComponentDepsNode::OperationIDKey *key =
reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v);
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)
@ -95,7 +133,7 @@ ComponentDepsNode::ComponentDepsNode() :
/* Initialize 'component' node - from pointer data given */
void ComponentDepsNode::init(const ID * /*id*/,
const string & /*subdata*/)
const char * /*subdata*/)
{
/* hook up eval context? */
// XXX: maybe this needs a special API?
@ -114,7 +152,7 @@ ComponentDepsNode::~ComponentDepsNode()
string ComponentDepsNode::identifier() const
{
string &idname = this->owner->name;
string idname = this->owner->name;
char typebuf[16];
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);
}
@ -151,21 +191,26 @@ OperationDepsNode *ComponentDepsNode::has_operation(OperationIDKey key) const
}
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);
}
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) {
DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_OPERATION);
op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
/* 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);
/* set as entry/exit node of component (if appropriate) */
@ -197,16 +242,6 @@ OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
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()
{
if (operations_map != NULL) {
@ -337,7 +372,7 @@ static DepsNodeFactoryImpl<PoseComponentDepsNode> DNTI_EVAL_POSE;
/* Bone Component ========================================= */
/* 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... */
ComponentDepsNode::init(id, subdata);
@ -350,7 +385,7 @@ void BoneComponentDepsNode::init(const ID *id, const string &subdata)
/* bone-specific node data */
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");

View File

@ -53,50 +53,38 @@ struct ComponentDepsNode : public DepsNode {
struct OperationIDKey
{
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() :
opcode(DEG_OPCODE_OPERATION), name("")
{}
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);
}
string identifier() const;
bool operator==(const OperationIDKey &other) const;
};
/* Typedef for container of operations */
ComponentDepsNode();
~ComponentDepsNode();
void init(const ID *id, const string &subdata);
void init(const ID *id, const char *subdata);
string identifier() const;
/* Find an existing operation, will throw an assert() if it does not exist. */
OperationDepsNode *find_operation(OperationIDKey key) const;
OperationDepsNode *find_operation(eDepsOperation_Code opcode,
const string &name) const;
const char *name,
int name_tag) const;
/* Check operation exists and return it. */
OperationDepsNode *has_operation(OperationIDKey key) const;
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
@ -114,9 +102,9 @@ struct ComponentDepsNode : public DepsNode {
OperationDepsNode *add_operation(eDepsOperation_Type optype,
DepsEvalOperationCb op,
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 tag_update(Depsgraph *graph);
@ -194,7 +182,7 @@ struct PoseComponentDepsNode : public ComponentDepsNode {
/* Bone Component */
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 */

View File

@ -68,7 +68,7 @@ string OperationDepsNode::full_identifier() const
{
string owner_str = "";
if (owner->type == DEPSNODE_TYPE_BONE) {
owner_str = owner->owner->name + "." + owner->name;
owner_str = string(owner->owner->name) + "." + owner->name;
}
else {
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[] = {
{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_BOTH, "both", 0, "Both", "Use <matrix> AND <translate>, <rotate>, <scale> to specify transformations"},
{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) {
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) {
@ -1343,10 +1345,17 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
copy_m4_m4(ob->obmat, dob->mat);
BKE_object_apply_mat4(ob, ob->obmat, false, false);
if (dupli_gh)
if (dupli_gh) {
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);
}

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 */
/* newid may still have some trash from Outliner tree building,
* so clear that first to avoid errors [#26002] */
for (ob = bmain->object.first; ob; ob = ob->id.next)
ob->id.newid = NULL;
/* newid may still have some trash from Outliner tree building, so clear that first to avoid errors, see T26002.
* We have to clear whole datablocks, not only Object one may be accessed here, see T49905. */
ListBase *lbarray[MAX_LIBARRAY];
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) */
for (base = FIRSTBASE; base; base = base->next) {

View File

@ -223,10 +223,16 @@ typedef struct RigidBodyCon {
float spring_stiffness_x;
float spring_stiffness_y;
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 */
float spring_damping_x;
float spring_damping_y;
float spring_damping_z;
float spring_damping_ang_x;
float spring_damping_ang_y;
float spring_damping_ang_z;
/* motor settings */
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),
/* motors */
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;
/* ******************************** */

View File

@ -504,6 +504,45 @@ static void rna_RigidBodyCon_spring_stiffness_z_set(PointerRNA *ptr, float value
#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)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
@ -541,6 +580,43 @@ static void rna_RigidBodyCon_spring_damping_z_set(PointerRNA *ptr, float value)
#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)
{
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_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);
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");
@ -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_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);
RNA_def_property_float_sdna(prop, NULL, "spring_damping_x");
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_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);
RNA_def_property_float_sdna(prop, NULL, "motor_lin_target_velocity");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);

View File

@ -52,15 +52,6 @@
#include "BLT_lang.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
static EnumPropertyItem opensubdiv_compute_type_items[] = {
{USER_OPENSUBDIV_COMPUTE_NONE, "NONE", 0, "None", ""},
@ -124,8 +115,6 @@ static EnumPropertyItem rna_enum_language_default_items[] = {
#include "UI_interface.h"
#include "CCL_api.h"
#ifdef WITH_OPENSUBDIV
# include "opensubdiv_capi.h"
#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
static EnumPropertyItem *rna_userdef_opensubdiv_compute_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *r_free)
@ -3973,13 +3890,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{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[] = {
{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"},
@ -4271,23 +4181,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
"Draw tool/property regions over the main region, when using Triple Buffer");
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
prop = RNA_def_property(srna, "opensubdiv_compute_type", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);

View File

@ -145,12 +145,9 @@ static void updateDepsgraph(ModifierData *md,
HookModifierData *hmd = (HookModifierData *)md;
if (hmd->object != NULL) {
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");
}
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. */
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"
#endif
#include "../../intern/cycles/blender/CCL_api.h"
#include "../../intern/dualcon/dualcon.h"
#include "../../intern/elbeem/extern/elbeem.h"
#include "../blender/blenkernel/BKE_modifier.h"
@ -767,10 +766,6 @@ void *dualcon(const DualConInput *input_mesh,
float scale,
int depth) RET_ZERO
/* intern/cycles */
struct CCLDeviceInfo;
struct CCLDeviceInfo *CCL_compute_device_list(int opencl) RET_NULL
/* compositor */
void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering,
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,

View File

@ -1153,13 +1153,12 @@ if(WIN32 AND NOT WITH_PYTHON_MODULE)
COMPONENT Blender
DESTINATION "."
)
if(CMAKE_CL_64)
set(_WIN_PLATFORM x64)
else()
set(_WIN_PLATFORM x86)
endif()
if(MSVC12_REDIST_DIR)
if(CMAKE_CL_64)
set(_WIN_PLATFORM x64)
else()
set(_WIN_PLATFORM x86)
endif()
install(
FILES
${MSVC12_REDIST_DIR}/${_WIN_PLATFORM}/Microsoft.VC120.CRT/msvcp120.dll
@ -1173,4 +1172,51 @@ if(WIN32 AND NOT WITH_PYTHON_MODULE)
)
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()

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\)
--md5_source=${TEST_OUT_DIR}/export_obj_cube.obj
--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}