Compare commits
48 Commits
temp-node-
...
blender-v2
Author | SHA1 | Date | |
---|---|---|---|
3e85bb34d0 | |||
6f28e6998b | |||
9743a58f7d | |||
60fbed3dba | |||
9ec325b59d | |||
![]() |
be8935852b | ||
c65e4f4e39 | |||
![]() |
918ef5f835 | ||
41e4079365 | |||
a5b6d6de0a | |||
8ab98d0ed7 | |||
0f72e7c3eb | |||
7347228d56 | |||
adcb3c6ee1 | |||
1442827a4f | |||
f822cd511c | |||
27ea086242 | |||
2c8f8765a1 | |||
9d290c9fc6 | |||
39af4d8bfe | |||
4f6e51aa52 | |||
bff56477c9 | |||
3ff6541c5d | |||
5d10814ccc | |||
21e3b89634 | |||
5f66510a21 | |||
7447233f76 | |||
9f473e2275 | |||
8b953fa83d | |||
d52d56e83d | |||
6de33ee656 | |||
961bcf9e50 | |||
0ed4fa6541 | |||
ea2d025a98 | |||
90312da85a | |||
56076e0492 | |||
293acae922 | |||
![]() |
211b390871 | ||
0e9a3882be | |||
0da0b5984a | |||
cb1875c6f5 | |||
0f21e3b688 | |||
![]() |
0330d1af29 | ||
cb0b0416f4 | |||
defe21a7bb | |||
834613a50e | |||
9e0a4fcaad | |||
1558c006fb |
@@ -40,9 +40,9 @@ FIND_PATH(EMBREE_INCLUDE_DIR
|
||||
|
||||
SET(_embree_FIND_COMPONENTS
|
||||
embree3
|
||||
embree_sse42
|
||||
embree_avx
|
||||
embree_avx2
|
||||
embree_sse42
|
||||
lexers
|
||||
math
|
||||
simd
|
||||
|
@@ -392,6 +392,16 @@ endif()
|
||||
if(WITH_CYCLES_EMBREE)
|
||||
find_package(Embree 3.8.0 REQUIRED)
|
||||
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Xlinker -stack_size -Xlinker 0x100000")
|
||||
|
||||
# Embree static library linking can mix up SSE and AVX symbols, causing
|
||||
# crashes on macOS systems with older CPUs that don't have AVX. Using
|
||||
# force load avoids that. The Embree shared library does not suffer from
|
||||
# this problem, precisely because linking a shared library uses force load.
|
||||
set(_embree_libraries_force_load)
|
||||
foreach(_embree_library ${EMBREE_LIBRARIES})
|
||||
list(APPEND _embree_libraries_force_load "-Wl,-force_load,${_embree_library}")
|
||||
endforeach()
|
||||
set(EMBREE_LIBRARIES ${_embree_libraries_force_load})
|
||||
endif()
|
||||
|
||||
if(WITH_OPENIMAGEDENOISE)
|
||||
|
@@ -717,7 +717,11 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
|
||||
* footprint during synchronization process.
|
||||
*/
|
||||
const bool is_interface_locked = b_engine.render() && b_engine.render().use_lock_interface();
|
||||
const bool can_free_caches = BlenderSession::headless || is_interface_locked;
|
||||
const bool can_free_caches = (BlenderSession::headless || is_interface_locked) &&
|
||||
/* Baking re-uses the depsgraph multiple times, clearing crashes
|
||||
* reading un-evaluated mesh data which isn't aligned with the
|
||||
* geometry we're baking, see T71012. */
|
||||
!scene->bake_manager->get_baking();
|
||||
if (!can_free_caches) {
|
||||
return;
|
||||
}
|
||||
|
@@ -98,14 +98,15 @@ BVH::BVH(const BVHParams ¶ms_,
|
||||
|
||||
BVH *BVH::create(const BVHParams ¶ms,
|
||||
const vector<Geometry *> &geometry,
|
||||
const vector<Object *> &objects)
|
||||
const vector<Object *> &objects,
|
||||
const Device *device)
|
||||
{
|
||||
switch (params.bvh_layout) {
|
||||
case BVH_LAYOUT_BVH2:
|
||||
return new BVH2(params, geometry, objects);
|
||||
case BVH_LAYOUT_EMBREE:
|
||||
#ifdef WITH_EMBREE
|
||||
return new BVHEmbree(params, geometry, objects);
|
||||
return new BVHEmbree(params, geometry, objects, device);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
|
@@ -89,7 +89,8 @@ class BVH {
|
||||
|
||||
static BVH *create(const BVHParams ¶ms,
|
||||
const vector<Geometry *> &geometry,
|
||||
const vector<Object *> &objects);
|
||||
const vector<Object *> &objects,
|
||||
const Device *device);
|
||||
virtual ~BVH()
|
||||
{
|
||||
}
|
||||
|
@@ -36,6 +36,8 @@
|
||||
|
||||
# include "bvh/bvh_embree.h"
|
||||
|
||||
# include "device/device.h"
|
||||
|
||||
/* Kernel includes are necessary so that the filter function for Embree can access the packed BVH.
|
||||
*/
|
||||
# include "kernel/bvh/bvh_embree.h"
|
||||
@@ -298,12 +300,6 @@ static bool rtc_progress_func(void *user_ptr, const double n)
|
||||
return !progress->get_cancel();
|
||||
}
|
||||
|
||||
/* This is to have a shared device between all BVH instances.
|
||||
It would be useful to actually to use a separte RTCDevice per Cycles instance. */
|
||||
RTCDevice BVHEmbree::rtc_shared_device = NULL;
|
||||
int BVHEmbree::rtc_shared_users = 0;
|
||||
thread_mutex BVHEmbree::rtc_shared_mutex;
|
||||
|
||||
static size_t count_primitives(Geometry *geom)
|
||||
{
|
||||
if (geom->type == Geometry::MESH) {
|
||||
@@ -320,11 +316,13 @@ static size_t count_primitives(Geometry *geom)
|
||||
|
||||
BVHEmbree::BVHEmbree(const BVHParams ¶ms_,
|
||||
const vector<Geometry *> &geometry_,
|
||||
const vector<Object *> &objects_)
|
||||
const vector<Object *> &objects_,
|
||||
const Device *device)
|
||||
: BVH(params_, geometry_, objects_),
|
||||
scene(NULL),
|
||||
mem_used(0),
|
||||
top_level(NULL),
|
||||
rtc_device((RTCDevice)device->bvh_device()),
|
||||
stats(NULL),
|
||||
curve_subdivisions(params.curve_subdivisions),
|
||||
build_quality(RTC_BUILD_QUALITY_REFIT),
|
||||
@@ -332,47 +330,8 @@ BVHEmbree::BVHEmbree(const BVHParams ¶ms_,
|
||||
{
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
thread_scoped_lock lock(rtc_shared_mutex);
|
||||
if (rtc_shared_users == 0) {
|
||||
rtc_shared_device = rtcNewDevice("verbose=0");
|
||||
/* Check here if Embree was built with the correct flags. */
|
||||
ssize_t ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED);
|
||||
if (ret != 1) {
|
||||
assert(0);
|
||||
VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED flag."
|
||||
"Ray visibility will not work.";
|
||||
}
|
||||
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED);
|
||||
if (ret != 1) {
|
||||
assert(0);
|
||||
VLOG(1)
|
||||
<< "Embree is compiled without the RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED flag."
|
||||
"Renders may not look as expected.";
|
||||
}
|
||||
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED);
|
||||
if (ret != 1) {
|
||||
assert(0);
|
||||
VLOG(1)
|
||||
<< "Embree is compiled without the RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED flag. "
|
||||
"Line primitives will not be rendered.";
|
||||
}
|
||||
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED);
|
||||
if (ret != 1) {
|
||||
assert(0);
|
||||
VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED "
|
||||
"flag. "
|
||||
"Triangle primitives will not be rendered.";
|
||||
}
|
||||
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED);
|
||||
if (ret != 0) {
|
||||
assert(0);
|
||||
VLOG(1) << "Embree is compiled with the RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED flag. "
|
||||
"Renders may not look as expected.";
|
||||
}
|
||||
}
|
||||
++rtc_shared_users;
|
||||
|
||||
rtcSetDeviceErrorFunction(rtc_shared_device, rtc_error_func, NULL);
|
||||
rtcSetDeviceErrorFunction(rtc_device, rtc_error_func, NULL);
|
||||
|
||||
pack.root_index = -1;
|
||||
}
|
||||
@@ -390,12 +349,6 @@ void BVHEmbree::destroy(RTCScene scene)
|
||||
rtcReleaseScene(scene);
|
||||
scene = NULL;
|
||||
}
|
||||
thread_scoped_lock lock(rtc_shared_mutex);
|
||||
--rtc_shared_users;
|
||||
if (rtc_shared_users == 0) {
|
||||
rtcReleaseDevice(rtc_shared_device);
|
||||
rtc_shared_device = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BVHEmbree::delete_rtcScene()
|
||||
@@ -421,9 +374,9 @@ void BVHEmbree::delete_rtcScene()
|
||||
|
||||
void BVHEmbree::build(Progress &progress, Stats *stats_)
|
||||
{
|
||||
assert(rtc_shared_device);
|
||||
assert(rtc_device);
|
||||
stats = stats_;
|
||||
rtcSetDeviceMemoryMonitorFunction(rtc_shared_device, rtc_memory_monitor_func, stats);
|
||||
rtcSetDeviceMemoryMonitorFunction(rtc_device, rtc_memory_monitor_func, stats);
|
||||
|
||||
progress.set_substatus("Building BVH");
|
||||
|
||||
@@ -434,7 +387,7 @@ void BVHEmbree::build(Progress &progress, Stats *stats_)
|
||||
|
||||
const bool dynamic = params.bvh_type == SceneParams::BVH_DYNAMIC;
|
||||
|
||||
scene = rtcNewScene(rtc_shared_device);
|
||||
scene = rtcNewScene(rtc_device);
|
||||
const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
|
||||
RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST;
|
||||
rtcSetSceneFlags(scene, scene_flags);
|
||||
@@ -561,7 +514,7 @@ void BVHEmbree::add_instance(Object *ob, int i)
|
||||
const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT);
|
||||
assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
|
||||
|
||||
RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_INSTANCE);
|
||||
RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_INSTANCE);
|
||||
rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene);
|
||||
rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
|
||||
|
||||
@@ -615,7 +568,7 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
|
||||
assert(num_geometry_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
|
||||
|
||||
const size_t num_triangles = mesh->num_triangles();
|
||||
RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_TRIANGLE);
|
||||
RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_TRIANGLE);
|
||||
rtcSetGeometryBuildQuality(geom_id, build_quality);
|
||||
rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
|
||||
|
||||
@@ -804,7 +757,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
|
||||
RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE :
|
||||
RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE);
|
||||
|
||||
RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, type);
|
||||
RTCGeometry geom_id = rtcNewGeometry(rtc_device, type);
|
||||
rtcSetGeometryTessellationRate(geom_id, curve_subdivisions + 1);
|
||||
unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
|
||||
geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments);
|
||||
|
@@ -50,7 +50,8 @@ class BVHEmbree : public BVH {
|
||||
friend class BVH;
|
||||
BVHEmbree(const BVHParams ¶ms,
|
||||
const vector<Geometry *> &geometry,
|
||||
const vector<Object *> &objects);
|
||||
const vector<Object *> &objects,
|
||||
const Device *device);
|
||||
|
||||
virtual void pack_nodes(const BVHNode *) override;
|
||||
virtual void refit_nodes() override;
|
||||
@@ -73,9 +74,7 @@ class BVHEmbree : public BVH {
|
||||
void update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh);
|
||||
void update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair);
|
||||
|
||||
static RTCDevice rtc_shared_device;
|
||||
static int rtc_shared_users;
|
||||
static thread_mutex rtc_shared_mutex;
|
||||
RTCDevice rtc_device;
|
||||
|
||||
Stats *stats;
|
||||
vector<RTCScene> delayed_delete_scenes;
|
||||
|
@@ -373,6 +373,12 @@ class Device {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Device specific pointer for BVH creation. Currently only used by Embree. */
|
||||
virtual void *bvh_device() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* load/compile kernels, must be called before adding tasks */
|
||||
virtual bool load_kernels(const DeviceRequestedFeatures & /*requested_features*/)
|
||||
{
|
||||
|
@@ -24,6 +24,10 @@
|
||||
# include <OSL/oslexec.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_EMBREE
|
||||
# include <embree3/rtcore.h>
|
||||
#endif
|
||||
|
||||
#include "device/device.h"
|
||||
#include "device/device_denoising.h"
|
||||
#include "device/device_intern.h"
|
||||
@@ -183,6 +187,9 @@ class CPUDevice : public Device {
|
||||
oidn::FilterRef oidn_filter;
|
||||
#endif
|
||||
thread_spin_lock oidn_task_lock;
|
||||
#ifdef WITH_EMBREE
|
||||
RTCDevice embree_device;
|
||||
#endif
|
||||
|
||||
bool use_split_kernel;
|
||||
|
||||
@@ -301,6 +308,9 @@ class CPUDevice : public Device {
|
||||
|
||||
#ifdef WITH_OSL
|
||||
kernel_globals.osl = &osl_globals;
|
||||
#endif
|
||||
#ifdef WITH_EMBREE
|
||||
embree_device = rtcNewDevice("verbose=0");
|
||||
#endif
|
||||
use_split_kernel = DebugFlags().cpu.split_kernel;
|
||||
if (use_split_kernel) {
|
||||
@@ -339,6 +349,9 @@ class CPUDevice : public Device {
|
||||
|
||||
~CPUDevice()
|
||||
{
|
||||
#ifdef WITH_EMBREE
|
||||
rtcReleaseDevice(embree_device);
|
||||
#endif
|
||||
task_pool.cancel();
|
||||
texture_info.free();
|
||||
}
|
||||
@@ -523,6 +536,15 @@ class CPUDevice : public Device {
|
||||
#endif
|
||||
}
|
||||
|
||||
void *bvh_device() const override
|
||||
{
|
||||
#ifdef WITH_EMBREE
|
||||
return embree_device;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void thread_run(DeviceTask &task)
|
||||
{
|
||||
if (task.type == DeviceTask::RENDER)
|
||||
|
@@ -65,7 +65,7 @@ void MemoryManager::DeviceBuffer::update_device_memory(OpenCLDevice *device)
|
||||
}
|
||||
|
||||
/* Always allocate non-empty buffer, NULL pointers cause problems with some drivers. */
|
||||
total_size = max(total_size, 16);
|
||||
total_size = std::max(total_size, (size_t)16);
|
||||
|
||||
if (need_realloc) {
|
||||
cl_ulong max_buffer_size;
|
||||
|
@@ -214,7 +214,7 @@ void Geometry::compute_bvh(
|
||||
bparams.curve_subdivisions = params->curve_subdivisions();
|
||||
|
||||
delete bvh;
|
||||
bvh = BVH::create(bparams, geometry, objects);
|
||||
bvh = BVH::create(bparams, geometry, objects, device);
|
||||
MEM_GUARDED_CALL(progress, bvh->build, *progress);
|
||||
}
|
||||
}
|
||||
@@ -1029,7 +1029,7 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
|
||||
VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
|
||||
|
||||
BVH *bvh = BVH::create(bparams, scene->geometry, scene->objects);
|
||||
BVH *bvh = BVH::create(bparams, scene->geometry, scene->objects, device);
|
||||
bvh->build(progress, &device->stats);
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
|
@@ -415,7 +415,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
|
||||
[parentWindow->getCocoaWindow() addChildWindow:m_window ordered:NSWindowAbove];
|
||||
[m_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
|
||||
}
|
||||
else if (state != GHOST_kWindowStateFullScreen) {
|
||||
else {
|
||||
[m_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 721 KiB After Width: | Height: | Size: 968 KiB |
@@ -40,6 +40,31 @@
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="2.90" date="2020-08-31">
|
||||
<description>
|
||||
<p>New features:</p>
|
||||
<ul>
|
||||
<li>Nishita sky texture for Cycles</li>
|
||||
<li>EEVEE motion blur</li>
|
||||
<li>Cloth filter</li>
|
||||
<li>Ocean modifier spray</li>
|
||||
<li>Correct face attributes modeling</li>
|
||||
<li>OpenVDB fluid integration with mantaflow</li>
|
||||
<li>Nuke lens distortion model for motion tracking</li>
|
||||
</ul>
|
||||
<p>Enhancements:</p>
|
||||
<ul>
|
||||
<li>Intel Embree for faster motion blur in Cycles</li>
|
||||
<li>Viewport Intel OpenImageDenoise</li>
|
||||
<li>Shadow terminator offset setting</li>
|
||||
<li>NVLink support for CUDA and Optix</li>
|
||||
<li>Multires unsubdivide, rebuild and modes</li>
|
||||
<li>Pose brush transformations</li>
|
||||
<li>Correct face attributes modeling</li>
|
||||
<li>User interface improvements: new search, modifiers, headings, stats</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="2.83" date="2020-06-03">
|
||||
<description>
|
||||
<p>New features:</p>
|
||||
|
@@ -456,9 +456,11 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
|
||||
Recursively get strings, needed in case we have "Blah" + "Blah", passed as an argument in that case it won't
|
||||
evaluate to a string. However, break on some kind of stopper nodes, like e.g. Subscript.
|
||||
"""
|
||||
if type(node) == ast.Str:
|
||||
# New in py 3.8: all constants are of type 'ast.Constant'.
|
||||
# 'ast.Str' will have to be removed when we officially switch to this version.
|
||||
if type(node) in {ast.Str, getattr(ast, "Constant", None)}:
|
||||
eval_str = ast.literal_eval(node)
|
||||
if eval_str:
|
||||
if eval_str and type(eval_str) == str:
|
||||
yield (is_split, eval_str, (node,))
|
||||
else:
|
||||
is_split = (type(node) in separate_nodes)
|
||||
@@ -624,6 +626,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
|
||||
}
|
||||
|
||||
for fp in files:
|
||||
# ~ print("Checking File ", fp)
|
||||
with open(fp, 'r', encoding="utf8") as filedata:
|
||||
root_node = ast.parse(filedata.read(), fp, 'exec')
|
||||
|
||||
@@ -631,8 +634,8 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
|
||||
|
||||
for node in ast.walk(root_node):
|
||||
if type(node) == ast.Call:
|
||||
# print("found function at")
|
||||
# print("%s:%d" % (fp, node.lineno))
|
||||
# ~ print("found function at")
|
||||
# ~ print("%s:%d" % (fp, node.lineno))
|
||||
|
||||
# We can't skip such situations! from blah import foo\nfoo("bar") would also be an ast.Name func!
|
||||
if type(node.func) == ast.Name:
|
||||
@@ -657,31 +660,31 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
|
||||
if kw.arg == arg_kw:
|
||||
context_elements[arg_kw] = kw.value
|
||||
break
|
||||
# print(context_elements)
|
||||
# ~ print(context_elements)
|
||||
for kws, proc in translate_kw[msgid]:
|
||||
if set(kws) <= context_elements.keys():
|
||||
args = tuple(context_elements[k] for k in kws)
|
||||
#print("running ", proc, " with ", args)
|
||||
# ~ print("running ", proc, " with ", args)
|
||||
ctxt = proc(*args)
|
||||
if ctxt:
|
||||
msgctxts[msgid] = ctxt
|
||||
break
|
||||
|
||||
# print(translate_args)
|
||||
# ~ print(func_args)
|
||||
# do nothing if not found
|
||||
for arg_kw, (arg_pos, _) in func_args.items():
|
||||
msgctxt = msgctxts[arg_kw]
|
||||
estr_lst = [(None, ())]
|
||||
if arg_pos < len(node.args):
|
||||
estr_lst = extract_strings_split(node.args[arg_pos])
|
||||
#print(estr, nds)
|
||||
else:
|
||||
for kw in node.keywords:
|
||||
if kw.arg == arg_kw:
|
||||
# ~ print(kw.arg, kw.value)
|
||||
estr_lst = extract_strings_split(kw.value)
|
||||
break
|
||||
#print(estr, nds)
|
||||
for estr, nds in estr_lst:
|
||||
# ~ print(estr, nds)
|
||||
if estr:
|
||||
if nds:
|
||||
msgsrc = "{}:{}".format(fp_rel, sorted({nd.lineno for nd in nds})[0])
|
||||
|
@@ -283,6 +283,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
|
||||
del _initialize
|
||||
|
||||
if reload_scripts:
|
||||
_bpy.context.window_manager.tag_script_reload()
|
||||
|
||||
import gc
|
||||
print("gc.collect() -> %d" % gc.collect())
|
||||
|
||||
|
@@ -260,7 +260,13 @@ class NLA_OT_bake(Operator):
|
||||
|
||||
def execute(self, context):
|
||||
from bpy_extras import anim_utils
|
||||
do_pose = 'POSE' in self.bake_types
|
||||
do_object = 'OBJECT' in self.bake_types
|
||||
|
||||
objects = context.selected_editable_objects
|
||||
if do_pose and not do_object:
|
||||
objects = [obj for obj in objects if obj.pose is not None]
|
||||
|
||||
object_action_pairs = (
|
||||
[(obj, getattr(obj.animation_data, "action", None)) for obj in objects]
|
||||
if self.use_current_action else
|
||||
@@ -271,8 +277,8 @@ class NLA_OT_bake(Operator):
|
||||
object_action_pairs,
|
||||
frames=range(self.frame_start, self.frame_end + 1, self.step),
|
||||
only_selected=self.only_selected,
|
||||
do_pose='POSE' in self.bake_types,
|
||||
do_object='OBJECT' in self.bake_types,
|
||||
do_pose=do_pose,
|
||||
do_object=do_object,
|
||||
do_visual_keying=self.visual_keying,
|
||||
do_constraint_clear=self.clear_constraints,
|
||||
do_parents_clear=self.clear_parents,
|
||||
|
@@ -731,11 +731,18 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
|
||||
|
||||
# Deactivate bake operator if data has not been baked yet.
|
||||
note_flag = True
|
||||
if domain.use_noise and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
|
||||
note = layout.split()
|
||||
note_flag = False
|
||||
note.enabled = note_flag
|
||||
note.label(icon='INFO', text="Unbaked Data: Bake Data first")
|
||||
if domain.use_noise and domain.cache_type == 'MODULAR':
|
||||
label = ""
|
||||
if not domain.has_cache_baked_data:
|
||||
label = "Unbaked Data: Bake Data first"
|
||||
if not domain.cache_resumable:
|
||||
label = "Non Resumable Cache: Enable resumable option first"
|
||||
|
||||
if label:
|
||||
note = layout.split()
|
||||
note_flag = False
|
||||
note.enabled = note_flag
|
||||
note.label(icon='INFO', text=label)
|
||||
|
||||
split = layout.split()
|
||||
split.enabled = domain.has_cache_baked_data and note_flag and ob.mode == 'OBJECT'
|
||||
@@ -817,11 +824,18 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
|
||||
|
||||
# Deactivate bake operator if data has not been baked yet.
|
||||
note_flag = True
|
||||
if domain.use_mesh and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
|
||||
note = layout.split()
|
||||
note_flag = False
|
||||
note.enabled = note_flag
|
||||
note.label(icon='INFO', text="Unbaked Data: Bake Data first")
|
||||
if domain.use_mesh and domain.cache_type == 'MODULAR':
|
||||
label = ""
|
||||
if not domain.has_cache_baked_data:
|
||||
label = "Unbaked Data: Bake Data first"
|
||||
if not domain.cache_resumable:
|
||||
label = "Non Resumable Cache: Enable resumable option first"
|
||||
|
||||
if label:
|
||||
note = layout.split()
|
||||
note_flag = False
|
||||
note.enabled = note_flag
|
||||
note.label(icon='INFO', text=label)
|
||||
|
||||
split = layout.split()
|
||||
split.enabled = domain.has_cache_baked_data and note_flag and ob.mode == 'OBJECT'
|
||||
@@ -931,11 +945,18 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
|
||||
|
||||
# Deactivate bake operator if data has not been baked yet.
|
||||
note_flag = True
|
||||
if using_particles and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
|
||||
note = layout.split()
|
||||
note_flag = False
|
||||
note.enabled = note_flag
|
||||
note.label(icon='INFO', text="Unbaked Data: Bake Data first")
|
||||
if using_particles and domain.cache_type == 'MODULAR':
|
||||
label = ""
|
||||
if not domain.has_cache_baked_data:
|
||||
label = "Unbaked Data: Bake Data first"
|
||||
if not domain.cache_resumable:
|
||||
label = "Non Resumable Cache: Enable resumable option first"
|
||||
|
||||
if label:
|
||||
note = layout.split()
|
||||
note_flag = False
|
||||
note.enabled = note_flag
|
||||
note.label(icon='INFO', text=label)
|
||||
|
||||
split = layout.split()
|
||||
split.enabled = (
|
||||
|
@@ -33,13 +33,13 @@ extern "C" {
|
||||
/* Blender major and minor version. */
|
||||
#define BLENDER_VERSION 290
|
||||
/* Blender patch version for bugfix releases. */
|
||||
#define BLENDER_VERSION_PATCH 0
|
||||
#define BLENDER_VERSION_PATCH 1
|
||||
/** Blender release cycle stage: alpha/beta/rc/release. */
|
||||
#define BLENDER_VERSION_CYCLE beta
|
||||
#define BLENDER_VERSION_CYCLE release
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 7
|
||||
#define BLENDER_FILE_SUBVERSION 8
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
@@ -181,7 +181,6 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds,
|
||||
float *n_b = manta_smoke_get_color_b(fds->fluid);
|
||||
|
||||
/* Noise smoke fields. */
|
||||
int wt_res_old[3];
|
||||
float *o_wt_dens = manta_noise_get_density(fluid_old);
|
||||
float *o_wt_react = manta_noise_get_react(fluid_old);
|
||||
float *o_wt_flame = manta_noise_get_flame(fluid_old);
|
||||
@@ -210,6 +209,7 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds,
|
||||
float *n_wt_tcv2 = manta_noise_get_texture_v2(fds->fluid);
|
||||
float *n_wt_tcw2 = manta_noise_get_texture_w2(fds->fluid);
|
||||
|
||||
int wt_res_old[3];
|
||||
manta_noise_get_res(fluid_old, wt_res_old);
|
||||
|
||||
for (int z = o_min[2]; z < o_max[2]; z++) {
|
||||
@@ -3790,6 +3790,13 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd,
|
||||
}
|
||||
}
|
||||
|
||||
/* Adaptive domain needs to know about current state, so save it here. */
|
||||
int o_res[3], o_min[3], o_max[3], o_shift[3];
|
||||
copy_v3_v3_int(o_res, fds->res);
|
||||
copy_v3_v3_int(o_min, fds->res_min);
|
||||
copy_v3_v3_int(o_max, fds->res_max);
|
||||
copy_v3_v3_int(o_shift, fds->shift);
|
||||
|
||||
/* Ensure that time parameters are initialized correctly before every step. */
|
||||
float fps = scene->r.frs_sec / scene->r.frs_sec_base;
|
||||
fds->frame_length = DT_DEFAULT * (25.0f / fps) * fds->time_scale;
|
||||
@@ -3870,8 +3877,6 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd,
|
||||
bool with_gdomain;
|
||||
with_gdomain = (fds->guide_source == FLUID_DOMAIN_GUIDE_SRC_DOMAIN);
|
||||
|
||||
int o_res[3], o_min[3], o_max[3], o_shift[3];
|
||||
|
||||
/* Cache mode specific settings. */
|
||||
switch (mode) {
|
||||
case FLUID_DOMAIN_CACHE_ALL:
|
||||
@@ -3935,12 +3940,6 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Adaptive domain needs to know about current state, so save it here. */
|
||||
copy_v3_v3_int(o_res, fds->res);
|
||||
copy_v3_v3_int(o_min, fds->res_min);
|
||||
copy_v3_v3_int(o_max, fds->res_max);
|
||||
copy_v3_v3_int(o_shift, fds->shift);
|
||||
|
||||
bool read_partial = false, read_all = false;
|
||||
/* Try to read from cache and keep track of read success. */
|
||||
if (read_cache) {
|
||||
|
@@ -56,10 +56,12 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user)
|
||||
if (id->properties) {
|
||||
IDP_FreePropertyContent_ex(id->properties, do_id_user);
|
||||
MEM_freeN(id->properties);
|
||||
id->properties = NULL;
|
||||
}
|
||||
|
||||
if (id->override_library) {
|
||||
BKE_lib_override_library_free(&id->override_library, do_id_user);
|
||||
id->override_library = NULL;
|
||||
}
|
||||
|
||||
BKE_animdata_free(id, do_id_user);
|
||||
|
@@ -1832,18 +1832,31 @@ static void sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh)
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
mesh->mvert[i].flag |= ME_HIDE;
|
||||
}
|
||||
/* Enabled if the vertex should be visible according to the Face Sets. */
|
||||
BLI_bitmap *visibile_vertex = BLI_BITMAP_NEW(mesh->totvert, "visible vertices");
|
||||
/* Enabled if the visibility of this vertex can be affected by the Face Sets to avoid modifying
|
||||
* disconnected geometry. */
|
||||
BLI_bitmap *modified_vertex = BLI_BITMAP_NEW(mesh->totvert, "modified vertices");
|
||||
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
if (face_sets[i] >= 0) {
|
||||
for (int l = 0; l < mesh->mpoly[i].totloop; l++) {
|
||||
MLoop *loop = &mesh->mloop[mesh->mpoly[i].loopstart + l];
|
||||
mesh->mvert[loop->v].flag &= ~ME_HIDE;
|
||||
const bool is_face_set_visible = face_sets[i] >= 0;
|
||||
for (int l = 0; l < mesh->mpoly[i].totloop; l++) {
|
||||
MLoop *loop = &mesh->mloop[mesh->mpoly[i].loopstart + l];
|
||||
if (is_face_set_visible) {
|
||||
BLI_BITMAP_ENABLE(visibile_vertex, loop->v);
|
||||
}
|
||||
BLI_BITMAP_ENABLE(modified_vertex, loop->v);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
if (BLI_BITMAP_TEST(modified_vertex, i) && !BLI_BITMAP_TEST(visibile_vertex, i)) {
|
||||
mesh->mvert[i].flag |= ME_HIDE;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(visibile_vertex);
|
||||
MEM_SAFE_FREE(modified_vertex);
|
||||
}
|
||||
|
||||
static void sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
|
||||
|
@@ -2402,6 +2402,10 @@ void BKE_scene_transform_orientation_remove(Scene *scene, TransformOrientation *
|
||||
orient_slot->type = V3D_ORIENT_GLOBAL;
|
||||
orient_slot->index_custom = -1;
|
||||
}
|
||||
else if (orient_slot->index_custom > orientation_index) {
|
||||
BLI_assert(orient_slot->type == V3D_ORIENT_CUSTOM);
|
||||
orient_slot->index_custom--;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_freelinkN(&scene->transform_spaces, orientation);
|
||||
|
@@ -3335,10 +3335,16 @@ float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3],
|
||||
|
||||
float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2])
|
||||
{
|
||||
float h[2], u[2], lambda;
|
||||
float h[2], u[2], lambda, denom;
|
||||
sub_v2_v2v2(u, l2, l1);
|
||||
sub_v2_v2v2(h, p, l1);
|
||||
lambda = dot_v2v2(u, h) / dot_v2v2(u, u);
|
||||
denom = dot_v2v2(u, u);
|
||||
if (denom == 0.0f) {
|
||||
r_close[0] = l1[0];
|
||||
r_close[1] = l1[1];
|
||||
return 0.0f;
|
||||
}
|
||||
lambda = dot_v2v2(u, h) / denom;
|
||||
r_close[0] = l1[0] + u[0] * lambda;
|
||||
r_close[1] = l1[1] + u[1] * lambda;
|
||||
return lambda;
|
||||
@@ -3353,12 +3359,12 @@ double closest_to_line_v2_db(double r_close[2],
|
||||
sub_v2_v2v2_db(u, l2, l1);
|
||||
sub_v2_v2v2_db(h, p, l1);
|
||||
denom = dot_v2v2_db(u, u);
|
||||
if (denom < DBL_EPSILON) {
|
||||
if (denom == 0.0) {
|
||||
r_close[0] = l1[0];
|
||||
r_close[1] = l1[1];
|
||||
return 0.0;
|
||||
}
|
||||
lambda = dot_v2v2_db(u, h) / dot_v2v2_db(u, u);
|
||||
lambda = dot_v2v2_db(u, h) / denom;
|
||||
r_close[0] = l1[0] + u[0] * lambda;
|
||||
r_close[1] = l1[1] + u[1] * lambda;
|
||||
return lambda;
|
||||
|
@@ -909,6 +909,19 @@ void BLI_polyfill_calc(const float (*coords)[2],
|
||||
const int coords_sign,
|
||||
uint (*r_tris)[3])
|
||||
{
|
||||
/* Fallback to heap memory for large allocations.
|
||||
* Avoid running out of stack memory on systems with 512kb stack (macOS).
|
||||
* This happens at around 13,000 points, use a much lower value to be safe. */
|
||||
if (UNLIKELY(coords_tot > 8192)) {
|
||||
/* The buffer size only accounts for the index allocation,
|
||||
* worst case we do two allocations when concave, while we should try to be efficient,
|
||||
* any caller that relies on this frequently should use #BLI_polyfill_calc_arena directly. */
|
||||
MemArena *arena = BLI_memarena_new(sizeof(PolyIndex) * coords_tot, __func__);
|
||||
BLI_polyfill_calc_arena(coords, coords_tot, coords_sign, r_tris, arena);
|
||||
BLI_memarena_free(arena);
|
||||
return;
|
||||
}
|
||||
|
||||
PolyFill pf;
|
||||
PolyIndex *indices = BLI_array_alloca(indices, coords_tot);
|
||||
|
||||
|
@@ -9153,6 +9153,9 @@ static void read_libblock_undo_restore_identical(
|
||||
if (ob->proxy != NULL) {
|
||||
ob->proxy->proxy_from = ob;
|
||||
}
|
||||
/* For undo we stay in object mode during undo presses, so keep editmode disabled for re-used
|
||||
* data-blocks too. */
|
||||
ob->mode &= ~OB_MODE_EDIT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1749,24 +1749,6 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
/* Paint Brush. This ensure that the brush paints by default. Used during the development and
|
||||
* patch review of the initial Sculpt Vertex Colors implementation (D5975) */
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
if (brush->ob_mode & OB_MODE_SCULPT && brush->sculpt_tool == SCULPT_TOOL_PAINT) {
|
||||
brush->tip_roundness = 1.0f;
|
||||
brush->flow = 1.0f;
|
||||
brush->density = 1.0f;
|
||||
brush->tip_scale_x = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pose Brush with support for loose parts. */
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_POSE && brush->disconnected_distance_max == 0.0f) {
|
||||
brush->flag2 |= BRUSH_USE_CONNECTED_ONLY;
|
||||
brush->disconnected_distance_max = 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5091,29 +5073,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
* \note Keep this message at the bottom of the function.
|
||||
*/
|
||||
{
|
||||
/* Set the cloth wind factor to 1 for old forces. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "PartDeflect", "float", "f_wind_factor")) {
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->pd) {
|
||||
ob->pd->f_wind_factor = 1.0f;
|
||||
}
|
||||
}
|
||||
LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
|
||||
if (part->pd) {
|
||||
part->pd->f_wind_factor = 1.0f;
|
||||
}
|
||||
if (part->pd2) {
|
||||
part->pd2->f_wind_factor = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
|
||||
/* Don't rotate light with the viewer by default, make it fixed. Shading settings can't be
|
||||
* edited and this flag should always be set. So we can always execute this. */
|
||||
wm->xr.session_settings.shading.flag |= V3D_SHADING_WORLD_ORIENTATION;
|
||||
}
|
||||
|
||||
/* Keep this block, even when empty. */
|
||||
}
|
||||
}
|
||||
|
@@ -29,8 +29,12 @@
|
||||
#include "DNA_genfile.h"
|
||||
#include "DNA_gpencil_modifier_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_force_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_shader_fx_types.h"
|
||||
|
||||
@@ -39,6 +43,7 @@
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
@@ -206,6 +211,36 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 290, 8)) {
|
||||
/* Paint Brush. This ensure that the brush paints by default. Used during the development and
|
||||
* patch review of the initial Sculpt Vertex Colors implementation (D5975) */
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
if (brush->ob_mode & OB_MODE_SCULPT && brush->sculpt_tool == SCULPT_TOOL_PAINT) {
|
||||
brush->tip_roundness = 1.0f;
|
||||
brush->flow = 1.0f;
|
||||
brush->density = 1.0f;
|
||||
brush->tip_scale_x = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pose Brush with support for loose parts. */
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_POSE && brush->disconnected_distance_max == 0.0f) {
|
||||
brush->flag2 |= BRUSH_USE_CONNECTED_ONLY;
|
||||
brush->disconnected_distance_max = 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
|
||||
if (BKE_collection_cycles_fix(bmain, collection)) {
|
||||
printf(
|
||||
"WARNING: Cycle detected in collection '%s', fixed as best as possible.\n"
|
||||
"You may have to reconstruct your View Layers...\n",
|
||||
collection->id.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
@@ -217,14 +252,6 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
|
||||
* \note Keep this message at the bottom of the function.
|
||||
*/
|
||||
{
|
||||
LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
|
||||
if (BKE_collection_cycles_fix(bmain, collection)) {
|
||||
printf(
|
||||
"WARNING: Cycle detected in collection '%s', fixed as best as possible.\n"
|
||||
"You may have to reconstruct your View Layers...\n",
|
||||
collection->id.name);
|
||||
}
|
||||
}
|
||||
/* Keep this block, even when empty. */
|
||||
}
|
||||
}
|
||||
@@ -233,6 +260,33 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
{
|
||||
UNUSED_VARS(fd);
|
||||
|
||||
if (MAIN_VERSION_ATLEAST(bmain, 290, 2) && MAIN_VERSION_OLDER(bmain, 291, 1)) {
|
||||
/* In this range, the extrude manifold could generate meshes with degenerated face. */
|
||||
LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) {
|
||||
for (MPoly *mp = me->mpoly, *mp_end = mp + me->totpoly; mp < mp_end; mp++) {
|
||||
if (mp->totloop == 2) {
|
||||
bool changed;
|
||||
BKE_mesh_validate_arrays(me,
|
||||
me->mvert,
|
||||
me->totvert,
|
||||
me->medge,
|
||||
me->totedge,
|
||||
me->mface,
|
||||
me->totface,
|
||||
me->mloop,
|
||||
me->totloop,
|
||||
me->mpoly,
|
||||
me->totpoly,
|
||||
me->dvert,
|
||||
false,
|
||||
true,
|
||||
&changed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Repair files from duplicate brushes added to blend files, see: T76738. */
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 290, 2)) {
|
||||
{
|
||||
@@ -407,17 +461,29 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
* \note Be sure to check when bumping the version:
|
||||
* - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
|
||||
* - "versioning_userdef.c", #do_versions_theme
|
||||
*
|
||||
* \note Keep this message at the bottom of the function.
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 290, 8)) {
|
||||
/* Set the cloth wind factor to 1 for old forces. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "PartDeflect", "float", "f_wind_factor")) {
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->pd) {
|
||||
ob->pd->f_wind_factor = 1.0f;
|
||||
}
|
||||
}
|
||||
LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
|
||||
if (part->pd) {
|
||||
part->pd->f_wind_factor = 1.0f;
|
||||
}
|
||||
if (part->pd2) {
|
||||
part->pd2->f_wind_factor = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
|
||||
/* Don't rotate light with the viewer by default, make it fixed. Shading settings can't be
|
||||
* edited and this flag should always be set. So we can always execute this. */
|
||||
wm->xr.session_settings.shading.flag |= V3D_SHADING_WORLD_ORIENTATION;
|
||||
}
|
||||
|
||||
/* Initialize additional parameter of the Nishita sky model and change altitude unit. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "NodeTexSky", "float", "sun_intensity")) {
|
||||
@@ -449,4 +515,17 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
* \note Be sure to check when bumping the version:
|
||||
* - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
|
||||
* - "versioning_userdef.c", #do_versions_theme
|
||||
*
|
||||
* \note Keep this message at the bottom of the function.
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
}
|
||||
}
|
||||
|
@@ -758,6 +758,12 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef)
|
||||
userdef->statusbar_flag = STATUSBAR_SHOW_VERSION;
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(290, 8)) {
|
||||
if (userdef->collection_instance_empty_size == 0) {
|
||||
userdef->collection_instance_empty_size = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
@@ -769,10 +775,6 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef)
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
if (userdef->collection_instance_empty_size == 0) {
|
||||
userdef->collection_instance_empty_size = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (userdef->pixelsize == 0.0f) {
|
||||
|
@@ -1844,10 +1844,17 @@ static void write_shaderfxs(BlendWriter *writer, ListBase *fxbase)
|
||||
|
||||
static void write_object(BlendWriter *writer, Object *ob, const void *id_address)
|
||||
{
|
||||
if (ob->id.us > 0 || BLO_write_is_undo(writer)) {
|
||||
const bool is_undo = BLO_write_is_undo(writer);
|
||||
if (ob->id.us > 0 || is_undo) {
|
||||
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
|
||||
BKE_object_runtime_reset(ob);
|
||||
|
||||
if (is_undo) {
|
||||
/* For undo we stay in object mode during undo presses, so keep editmode disabled on save as
|
||||
* well, can help reducing false detection of changed datablocks. */
|
||||
ob->mode &= ~OB_MODE_EDIT;
|
||||
}
|
||||
|
||||
/* write LibData */
|
||||
BLO_write_id_struct(writer, Object, id_address, &ob->id);
|
||||
write_iddata(writer, &ob->id);
|
||||
|
@@ -884,19 +884,14 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
|
||||
}
|
||||
|
||||
for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
|
||||
const bool apply_offset = (ofs && (currkey != actkey) &&
|
||||
(bm->shapenr - 1 == currkey->relative));
|
||||
int cd_shape_offset;
|
||||
int keyi;
|
||||
const float(*ofs_pt)[3] = ofs;
|
||||
float *newkey, (*oldkey)[3], *fp;
|
||||
|
||||
j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey);
|
||||
cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j);
|
||||
if (cd_shape_offset < 0) {
|
||||
/* The target Mesh has more shapekeys than the BMesh. */
|
||||
continue;
|
||||
}
|
||||
const int cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j);
|
||||
const bool apply_offset = (cd_shape_offset != -1) && (ofs != NULL) && (currkey != actkey) &&
|
||||
(bm->shapenr - 1 == currkey->relative);
|
||||
|
||||
fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data");
|
||||
oldkey = currkey->data;
|
||||
@@ -918,7 +913,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (j != -1) {
|
||||
else if (cd_shape_offset != -1) {
|
||||
/* In most cases this runs. */
|
||||
copy_v3_v3(fp, BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset));
|
||||
}
|
||||
|
@@ -614,7 +614,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
|
||||
BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
|
||||
if ((e_other == e) || (BM_DISK_EDGE_NEXT(e_other, v) == e)) {
|
||||
/* Lose edge or BMVert is edge pair. */
|
||||
BM_edge_collapse(bm, BMO_elem_flag_test(bm, e, EXT_TAG) ? e : e_other, v, true, false);
|
||||
BM_edge_collapse(bm, BMO_elem_flag_test(bm, e, EXT_TAG) ? e : e_other, v, true, true);
|
||||
}
|
||||
else {
|
||||
BLI_assert(!BM_vert_is_edge_pair(v));
|
||||
|
@@ -166,7 +166,7 @@ static bool bm_edge_delimit_cdata(CustomData *ldata,
|
||||
r_delim_cd->cd_type = type;
|
||||
r_delim_cd->cd_size = CustomData_sizeof(r_delim_cd->cd_type);
|
||||
r_delim_cd->cd_offset = CustomData_get_n_offset(ldata, type, 0);
|
||||
r_delim_cd->cd_offset_end = r_delim_cd->cd_size * layer_len;
|
||||
r_delim_cd->cd_offset_end = r_delim_cd->cd_offset + (r_delim_cd->cd_size * layer_len);
|
||||
return (r_delim_cd->cd_offset != -1);
|
||||
}
|
||||
|
||||
|
@@ -63,10 +63,9 @@ static struct {
|
||||
|
||||
GPUTexture *depth_src;
|
||||
|
||||
GPUTexture *dummy_density;
|
||||
GPUTexture *dummy_color;
|
||||
GPUTexture *dummy_zero;
|
||||
GPUTexture *dummy_one;
|
||||
GPUTexture *dummy_flame;
|
||||
GPUTexture *dummy_missing;
|
||||
|
||||
GPUTexture *dummy_scatter;
|
||||
GPUTexture *dummy_transmit;
|
||||
@@ -150,14 +149,26 @@ static void eevee_create_shader_volumes(void)
|
||||
e_data.volumetric_accum_sh = DRW_shader_create_fullscreen(datatoc_volumetric_accum_frag_glsl,
|
||||
NULL);
|
||||
|
||||
const float density[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
e_data.dummy_density = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, density);
|
||||
const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
e_data.dummy_zero = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, zero);
|
||||
|
||||
const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
e_data.dummy_one = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, one);
|
||||
|
||||
const float flame = 0.0f;
|
||||
e_data.dummy_flame = DRW_texture_create_3d(1, 1, 1, GPU_R8, DRW_TEX_WRAP, &flame);
|
||||
}
|
||||
|
||||
const float missing[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
e_data.dummy_missing = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, missing);
|
||||
static GPUTexture *eevee_volume_default_texture(eGPUVolumeDefaultValue default_value)
|
||||
{
|
||||
switch (default_value) {
|
||||
case GPU_VOLUME_DEFAULT_0:
|
||||
return e_data.dummy_zero;
|
||||
case GPU_VOLUME_DEFAULT_1:
|
||||
return e_data.dummy_one;
|
||||
}
|
||||
|
||||
return e_data.dummy_zero;
|
||||
}
|
||||
|
||||
void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
|
||||
@@ -378,7 +389,8 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
|
||||
/* Fix principle volumetric not working with world materials. */
|
||||
ListBase gpu_grids = GPU_material_volume_grids(mat);
|
||||
LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, &gpu_grids) {
|
||||
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_missing);
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
|
||||
}
|
||||
|
||||
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
|
||||
@@ -465,8 +477,16 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS
|
||||
DRW_volume_batch_cache_get_grid(volume, volume_grid) :
|
||||
NULL;
|
||||
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, gpu_grid->sampler_name, (drw_grid) ? drw_grid->texture : e_data.dummy_missing);
|
||||
/* Handle 3 cases here:
|
||||
* - Grid exists and texture was loaded -> use texture.
|
||||
* - Grid exists but has zero size or failed to load -> use zero.
|
||||
* - Grid does not exist -> use default value. */
|
||||
GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture :
|
||||
(volume_grid) ?
|
||||
e_data.dummy_zero :
|
||||
eevee_volume_default_texture(gpu_grid->default_value);
|
||||
|
||||
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, grid_tex);
|
||||
|
||||
if (drw_grid && multiple_transforms) {
|
||||
/* Specify per-volume transform matrix that is applied after the
|
||||
@@ -519,21 +539,20 @@ static bool eevee_volume_object_mesh_init(Scene *scene,
|
||||
|
||||
LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
|
||||
if (STREQ(gpu_grid->name, "density")) {
|
||||
DRW_shgroup_uniform_texture_ref(grp,
|
||||
gpu_grid->sampler_name,
|
||||
fds->tex_density ? &fds->tex_density :
|
||||
&e_data.dummy_density);
|
||||
DRW_shgroup_uniform_texture_ref(
|
||||
grp, gpu_grid->sampler_name, fds->tex_density ? &fds->tex_density : &e_data.dummy_one);
|
||||
}
|
||||
else if (STREQ(gpu_grid->name, "color")) {
|
||||
DRW_shgroup_uniform_texture_ref(
|
||||
grp, gpu_grid->sampler_name, fds->tex_color ? &fds->tex_color : &e_data.dummy_density);
|
||||
grp, gpu_grid->sampler_name, fds->tex_color ? &fds->tex_color : &e_data.dummy_one);
|
||||
}
|
||||
else if (STREQ(gpu_grid->name, "flame") || STREQ(gpu_grid->name, "temperature")) {
|
||||
DRW_shgroup_uniform_texture_ref(
|
||||
grp, gpu_grid->sampler_name, fds->tex_flame ? &fds->tex_flame : &e_data.dummy_flame);
|
||||
}
|
||||
else {
|
||||
DRW_shgroup_uniform_texture_ref(grp, gpu_grid->sampler_name, &e_data.dummy_density);
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,7 +568,8 @@ static bool eevee_volume_object_mesh_init(Scene *scene,
|
||||
}
|
||||
else {
|
||||
LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
|
||||
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -858,10 +878,9 @@ void EEVEE_volumes_free(void)
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_transmit);
|
||||
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_zero);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_one);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_color);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_missing);
|
||||
|
||||
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.scatter_sh);
|
||||
|
@@ -169,7 +169,7 @@ static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_us
|
||||
static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
|
||||
{
|
||||
const Mesh *me_final = editmesh_final_or_this(me);
|
||||
const CustomData *cd_ldata = &me_final->ldata;
|
||||
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
|
||||
|
||||
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
|
||||
if (layer != -1) {
|
||||
|
@@ -59,6 +59,7 @@ void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em,
|
||||
const int axis,
|
||||
const bool use_self,
|
||||
const bool use_select,
|
||||
const bool respecthide,
|
||||
const bool use_topology,
|
||||
float maxdist,
|
||||
int *r_index);
|
||||
@@ -66,6 +67,7 @@ void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em,
|
||||
const int axis,
|
||||
const bool use_self,
|
||||
const bool use_select,
|
||||
const bool respecthide,
|
||||
const bool use_toplogy);
|
||||
void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to);
|
||||
struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v);
|
||||
|
@@ -310,7 +310,8 @@ void ED_objects_recalculate_paths(struct bContext *C,
|
||||
eObjectPathCalcRange range);
|
||||
|
||||
/* constraints */
|
||||
struct ListBase *ED_object_constraint_list_from_context(struct Object *ob);
|
||||
struct ListBase *ED_object_constraint_active_list(struct Object *ob);
|
||||
struct ListBase *ED_object_pose_constraint_list(const struct bContext *C);
|
||||
struct ListBase *ED_object_constraint_list_from_constraint(struct Object *ob,
|
||||
struct bConstraint *con,
|
||||
struct bPoseChannel **r_pchan);
|
||||
|
@@ -1950,18 +1950,13 @@ static bool constraint_panel_is_bone(Panel *panel)
|
||||
*/
|
||||
static ListBase *get_constraints(const bContext *C, bool use_bone_constraints)
|
||||
{
|
||||
ListBase *constraints = {NULL};
|
||||
ListBase *constraints = NULL;
|
||||
if (use_bone_constraints) {
|
||||
bPoseChannel *pose_bone = CTX_data_pointer_get(C, "pose_bone").data;
|
||||
if (pose_bone != NULL) {
|
||||
constraints = &pose_bone->constraints;
|
||||
}
|
||||
constraints = ED_object_pose_constraint_list(C);
|
||||
}
|
||||
else {
|
||||
Object *ob = ED_object_active_context(C);
|
||||
if (ob != NULL) {
|
||||
constraints = &ob->constraints;
|
||||
}
|
||||
constraints = ED_object_constraint_active_list(ob);
|
||||
}
|
||||
return constraints;
|
||||
}
|
||||
@@ -2043,7 +2038,13 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
Object *ob = ED_object_active_context(C);
|
||||
ListBase *constraints = get_constraints(C, use_bone_constraints);
|
||||
ListBase *constraints = {NULL};
|
||||
if (use_bone_constraints) {
|
||||
constraints = ED_object_pose_constraint_list(C);
|
||||
}
|
||||
else {
|
||||
constraints = ED_object_constraint_active_list(ob);
|
||||
}
|
||||
|
||||
/* Switch between the bone panel ID function and the object panel ID function. */
|
||||
uiListPanelIDFromDataFunc panel_id_func = use_bone_constraints ? bone_constraint_panel_id :
|
||||
|
@@ -489,7 +489,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
|
||||
/* If no item has an own icon to display, libraries can use the library icons rather than the
|
||||
* name prefix for showing the library status. */
|
||||
int name_prefix_offset = cis->name_prefix_offset;
|
||||
if (!has_id_icon && cis->is_id) {
|
||||
if (!has_id_icon && cis->is_id && !requires_exact_data_name) {
|
||||
cis->iconid = UI_library_icon_get(cis->data);
|
||||
/* No need to re-allocate, string should be shorter than before (lib status prefix is
|
||||
* removed). */
|
||||
|
@@ -110,7 +110,7 @@ void EDBM_select_mirrored(BMEditMesh *em,
|
||||
}
|
||||
}
|
||||
|
||||
EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology);
|
||||
EDBM_verts_mirror_cache_begin(em, axis, true, true, false, use_topology);
|
||||
|
||||
if (!extend) {
|
||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||
|
@@ -2513,7 +2513,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* mirror before smooth */
|
||||
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
|
||||
EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
|
||||
EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology);
|
||||
}
|
||||
|
||||
/* if there is a mirror modifier with clipping, flag the verts that
|
||||
@@ -2658,7 +2658,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* Mirror before smooth. */
|
||||
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
|
||||
EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
|
||||
EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology);
|
||||
}
|
||||
|
||||
bool failed_repeat_loop = false;
|
||||
@@ -7600,7 +7600,7 @@ static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
|
||||
BMVert *v;
|
||||
int i;
|
||||
|
||||
EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, use_topology, thresh, index);
|
||||
EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, false, use_topology, thresh, index);
|
||||
|
||||
BM_mesh_elem_table_ensure(bm, BM_VERT);
|
||||
|
||||
|
@@ -1059,6 +1059,7 @@ static BMVert *cache_mirr_intptr_as_bmvert(const intptr_t *index_lookup, int ind
|
||||
* \param em: Editmesh.
|
||||
* \param use_self: Allow a vertex to point to its self (middle verts).
|
||||
* \param use_select: Restrict to selected verts.
|
||||
* \param respecthide: Skip hidden vertices.
|
||||
* \param use_topology: Use topology mirror.
|
||||
* \param maxdist: Distance for close point test.
|
||||
* \param r_index: Optional array to write into, as an alternative to a customdata layer
|
||||
@@ -1068,6 +1069,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
|
||||
const int axis,
|
||||
const bool use_self,
|
||||
const bool use_select,
|
||||
const bool respecthide,
|
||||
/* extra args */
|
||||
const bool use_topology,
|
||||
float maxdist,
|
||||
@@ -1110,6 +1112,10 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
|
||||
else {
|
||||
tree = BLI_kdtree_3d_new(bm->totvert);
|
||||
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_kdtree_3d_insert(tree, i, v->co);
|
||||
}
|
||||
BLI_kdtree_3d_balance(tree);
|
||||
@@ -1118,44 +1124,45 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
|
||||
#define VERT_INTPTR(_v, _i) (r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset))
|
||||
|
||||
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
BLI_assert(BM_elem_index_get(v) == i);
|
||||
if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* temporary for testing, check for selection */
|
||||
if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) {
|
||||
/* do nothing */
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_assert(BM_elem_index_get(v) == i);
|
||||
BMVert *v_mirr;
|
||||
int *idx = VERT_INTPTR(v, i);
|
||||
|
||||
if (use_topology) {
|
||||
v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
|
||||
}
|
||||
else {
|
||||
BMVert *v_mirr;
|
||||
int *idx = VERT_INTPTR(v, i);
|
||||
int i_mirr;
|
||||
float co[3];
|
||||
copy_v3_v3(co, v->co);
|
||||
co[axis] *= -1.0f;
|
||||
|
||||
if (use_topology) {
|
||||
v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
|
||||
}
|
||||
else {
|
||||
int i_mirr;
|
||||
float co[3];
|
||||
copy_v3_v3(co, v->co);
|
||||
co[axis] *= -1.0f;
|
||||
|
||||
v_mirr = NULL;
|
||||
i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL);
|
||||
if (i_mirr != -1) {
|
||||
BMVert *v_test = BM_vert_at_index(bm, i_mirr);
|
||||
if (len_squared_v3v3(co, v_test->co) < maxdist_sq) {
|
||||
v_mirr = v_test;
|
||||
}
|
||||
v_mirr = NULL;
|
||||
i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL);
|
||||
if (i_mirr != -1) {
|
||||
BMVert *v_test = BM_vert_at_index(bm, i_mirr);
|
||||
if (len_squared_v3v3(co, v_test->co) < maxdist_sq) {
|
||||
v_mirr = v_test;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v_mirr && (use_self || (v_mirr != v))) {
|
||||
const int i_mirr = BM_elem_index_get(v_mirr);
|
||||
*idx = i_mirr;
|
||||
idx = VERT_INTPTR(v_mirr, i_mirr);
|
||||
*idx = i;
|
||||
}
|
||||
else {
|
||||
*idx = -1;
|
||||
}
|
||||
if (v_mirr && (use_self || (v_mirr != v))) {
|
||||
const int i_mirr = BM_elem_index_get(v_mirr);
|
||||
*idx = i_mirr;
|
||||
idx = VERT_INTPTR(v_mirr, i_mirr);
|
||||
*idx = i;
|
||||
}
|
||||
else {
|
||||
*idx = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1173,12 +1180,14 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em,
|
||||
const int axis,
|
||||
const bool use_self,
|
||||
const bool use_select,
|
||||
const bool respecthide,
|
||||
const bool use_topology)
|
||||
{
|
||||
EDBM_verts_mirror_cache_begin_ex(em,
|
||||
axis,
|
||||
use_self,
|
||||
use_select,
|
||||
respecthide,
|
||||
/* extra args */
|
||||
use_topology,
|
||||
BM_SEARCH_MAXDIST_MIRR,
|
||||
|
@@ -80,8 +80,9 @@
|
||||
/** \name Constraint Data Accessors
|
||||
* \{ */
|
||||
|
||||
/* if object in posemode, active bone constraints, else object constraints */
|
||||
ListBase *ED_object_constraint_list_from_context(Object *ob)
|
||||
/* If object is in posemode, return active bone constraints, else object constraints. No
|
||||
* constraints are returned for a bone on an inactive bonelayer. */
|
||||
ListBase *ED_object_constraint_active_list(Object *ob)
|
||||
{
|
||||
if (ob == NULL) {
|
||||
return NULL;
|
||||
@@ -102,6 +103,21 @@ ListBase *ED_object_constraint_list_from_context(Object *ob)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the constraints for the active pose bone. Bone may be on an inactive bonelayer (unlike
|
||||
* ED_object_constraint_active_list, such constraints are not excluded here). */
|
||||
ListBase *ED_object_pose_constraint_list(const bContext *C)
|
||||
{
|
||||
bPoseChannel *pose_bone = CTX_data_pointer_get(C, "active_pose_bone").data;
|
||||
if (pose_bone == NULL) {
|
||||
pose_bone = CTX_data_pointer_get(C, "pose_bone").data;
|
||||
if (pose_bone == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return &pose_bone->constraints;
|
||||
}
|
||||
|
||||
/* Find the list that a given constraint belongs to,
|
||||
* and/or also get the posechannel this is from (if applicable) */
|
||||
ListBase *ED_object_constraint_list_from_constraint(Object *ob,
|
||||
@@ -147,7 +163,7 @@ ListBase *ED_object_constraint_list_from_constraint(Object *ob,
|
||||
/* single constraint */
|
||||
bConstraint *ED_object_constraint_active_get(Object *ob)
|
||||
{
|
||||
return BKE_constraints_active_get(ED_object_constraint_list_from_context(ob));
|
||||
return BKE_constraints_active_get(ED_object_constraint_active_list(ob));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -780,7 +796,7 @@ static bool edit_constraint_invoke_properties(bContext *C,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int type)
|
||||
static bConstraint *edit_constraint_property_get(bContext *C, wmOperator *op, Object *ob, int type)
|
||||
{
|
||||
char constraint_name[MAX_NAME];
|
||||
int owner = RNA_enum_get(op->ptr, "owner");
|
||||
@@ -789,31 +805,11 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
|
||||
|
||||
RNA_string_get(op->ptr, "constraint", constraint_name);
|
||||
|
||||
if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
|
||||
list = &ob->constraints;
|
||||
}
|
||||
else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
|
||||
bPoseChannel *pchan = BKE_pose_channel_active(ob);
|
||||
if (pchan) {
|
||||
list = &pchan->constraints;
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
if (G.debug & G_DEBUG) {
|
||||
printf("edit_constraint_property_get: No active bone for object '%s'\n",
|
||||
(ob) ? ob->id.name + 2 : "<None>");
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
|
||||
list = ED_object_pose_constraint_list(C);
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
if (G.debug & G_DEBUG) {
|
||||
printf("edit_constraint_property_get: defaulting to getting list in the standard way\n");
|
||||
}
|
||||
#endif
|
||||
list = ED_object_constraint_list_from_context(ob);
|
||||
list = ED_object_constraint_active_list(ob);
|
||||
}
|
||||
|
||||
con = BKE_constraints_find_name(list, constraint_name);
|
||||
@@ -842,7 +838,7 @@ static int stretchto_reset_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_STRETCHTO);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_STRETCHTO);
|
||||
bStretchToConstraint *data = (con) ? (bStretchToConstraint *)con->data : NULL;
|
||||
|
||||
/* despite 3 layers of checks, we may still not be able to find a constraint */
|
||||
@@ -897,7 +893,7 @@ static int limitdistance_reset_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_DISTLIMIT);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_DISTLIMIT);
|
||||
bDistLimitConstraint *data = (con) ? (bDistLimitConstraint *)con->data : NULL;
|
||||
|
||||
/* despite 3 layers of checks, we may still not be able to find a constraint */
|
||||
@@ -969,7 +965,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_CHILDOF);
|
||||
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
|
||||
|
||||
/* despite 3 layers of checks, we may still not be able to find a constraint */
|
||||
@@ -1023,7 +1019,7 @@ static int childof_clear_inverse_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_CHILDOF);
|
||||
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
|
||||
|
||||
if (data == NULL) {
|
||||
@@ -1077,7 +1073,7 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
|
||||
bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL;
|
||||
|
||||
bAction *act = NULL;
|
||||
@@ -1221,7 +1217,7 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
|
||||
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
|
||||
|
||||
/* despite 3 layers of checks, we may still not be able to find a constraint */
|
||||
@@ -1283,7 +1279,7 @@ static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
|
||||
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
|
||||
|
||||
if (data == NULL) {
|
||||
@@ -1431,7 +1427,7 @@ static int constraint_delete_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, 0);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
|
||||
ListBase *lb = ED_object_constraint_list_from_constraint(ob, con, NULL);
|
||||
|
||||
/* Store name temporarily for report. */
|
||||
@@ -1497,7 +1493,7 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot)
|
||||
static int constraint_move_down_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, 0);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
|
||||
|
||||
if (con && con->next) {
|
||||
ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL);
|
||||
@@ -1552,7 +1548,7 @@ void CONSTRAINT_OT_move_down(wmOperatorType *ot)
|
||||
static int constraint_move_up_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, 0);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
|
||||
|
||||
if (con && con->prev) {
|
||||
ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL);
|
||||
@@ -1605,7 +1601,7 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot)
|
||||
static int constraint_move_to_index_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, 0);
|
||||
bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
|
||||
|
||||
int new_index = RNA_int_get(op->ptr, "index");
|
||||
if (new_index < 0) {
|
||||
@@ -2162,8 +2158,7 @@ static int pose_constraint_add_exec(bContext *C, wmOperator *op)
|
||||
with_targets = 1;
|
||||
}
|
||||
|
||||
return constraint_add_exec(
|
||||
C, op, ob, ED_object_constraint_list_from_context(ob), type, with_targets);
|
||||
return constraint_add_exec(C, op, ob, ED_object_constraint_active_list(ob), type, with_targets);
|
||||
}
|
||||
|
||||
/* ------------------ */
|
||||
@@ -2364,12 +2359,8 @@ static int pose_ik_add_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* add the constraint - all necessary checks should have
|
||||
* been done by the invoke() callback already... */
|
||||
return constraint_add_exec(C,
|
||||
op,
|
||||
ob,
|
||||
ED_object_constraint_list_from_context(ob),
|
||||
CONSTRAINT_TYPE_KINEMATIC,
|
||||
with_targets);
|
||||
return constraint_add_exec(
|
||||
C, op, ob, ED_object_constraint_active_list(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets);
|
||||
}
|
||||
|
||||
void POSE_OT_ik_add(wmOperatorType *ot)
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
@@ -99,71 +100,61 @@ void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
|
||||
}
|
||||
}
|
||||
|
||||
static void object_fmap_swap_edit_mode(Object *ob, int num1, int num2)
|
||||
static void object_fmap_remap_edit_mode(Object *ob, const int *remap)
|
||||
{
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *me = ob->data;
|
||||
if (ob->type != OB_MESH) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->edit_mesh) {
|
||||
BMEditMesh *em = me->edit_mesh;
|
||||
const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
|
||||
Mesh *me = ob->data;
|
||||
if (me->edit_mesh) {
|
||||
BMEditMesh *em = me->edit_mesh;
|
||||
const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
|
||||
|
||||
if (cd_fmap_offset != -1) {
|
||||
BMFace *efa;
|
||||
BMIter iter;
|
||||
int *map;
|
||||
if (cd_fmap_offset != -1) {
|
||||
BMFace *efa;
|
||||
BMIter iter;
|
||||
int *map;
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
|
||||
|
||||
if (map) {
|
||||
if (num1 != -1) {
|
||||
if (*map == num1) {
|
||||
*map = num2;
|
||||
}
|
||||
else if (*map == num2) {
|
||||
*map = num1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (map && *map != -1) {
|
||||
*map = remap[*map];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void object_fmap_swap_object_mode(Object *ob, int num1, int num2)
|
||||
static void object_fmap_remap_object_mode(Object *ob, const int *remap)
|
||||
{
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *me = ob->data;
|
||||
if (ob->type != OB_MESH) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
|
||||
int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
|
||||
int i;
|
||||
Mesh *me = ob->data;
|
||||
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
|
||||
int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
|
||||
int i;
|
||||
|
||||
if (map) {
|
||||
for (i = 0; i < me->totpoly; i++) {
|
||||
if (num1 != -1) {
|
||||
if (map[i] == num1) {
|
||||
map[i] = num2;
|
||||
}
|
||||
else if (map[i] == num2) {
|
||||
map[i] = num1;
|
||||
}
|
||||
}
|
||||
if (map) {
|
||||
for (i = 0; i < me->totpoly; i++) {
|
||||
if (map[i] != -1) {
|
||||
map[i] = remap[map[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void object_facemap_swap(Object *ob, int num1, int num2)
|
||||
static void object_facemap_remap(Object *ob, const int *remap)
|
||||
{
|
||||
if (BKE_object_is_in_editmode(ob)) {
|
||||
object_fmap_swap_edit_mode(ob, num1, num2);
|
||||
object_fmap_remap_edit_mode(ob, remap);
|
||||
}
|
||||
else {
|
||||
object_fmap_swap_object_mode(ob, num1, num2);
|
||||
object_fmap_remap_object_mode(ob, remap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,45 +423,46 @@ static int face_map_move_exec(bContext *C, wmOperator *op)
|
||||
Object *ob = ED_object_context(C);
|
||||
bFaceMap *fmap;
|
||||
int dir = RNA_enum_get(op->ptr, "direction");
|
||||
int pos1, pos2 = -1, count;
|
||||
|
||||
fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
|
||||
if (!fmap) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
count = BLI_listbase_count(&ob->fmaps);
|
||||
pos1 = BLI_findindex(&ob->fmaps, fmap);
|
||||
if (!fmap->prev && !fmap->next) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
int pos1 = BLI_findindex(&ob->fmaps, fmap);
|
||||
int pos2 = pos1 - dir;
|
||||
int len = BLI_listbase_count(&ob->fmaps);
|
||||
int *map = MEM_mallocN(len * sizeof(*map), __func__);
|
||||
|
||||
if (!IN_RANGE(pos2, -1, len)) {
|
||||
const int offset = len - dir;
|
||||
for (int i = 0; i < len; i++) {
|
||||
map[i] = (i + offset) % len;
|
||||
}
|
||||
pos2 = map[pos1];
|
||||
}
|
||||
else {
|
||||
range_vn_i(map, len, 0);
|
||||
SWAP(int, map[pos1], map[pos2]);
|
||||
}
|
||||
|
||||
void *prev = fmap->prev;
|
||||
void *next = fmap->next;
|
||||
BLI_remlink(&ob->fmaps, fmap);
|
||||
if (dir == 1) { /*up*/
|
||||
void *prev = fmap->prev;
|
||||
|
||||
if (prev) {
|
||||
pos2 = pos1 - 1;
|
||||
}
|
||||
else {
|
||||
pos2 = count - 1;
|
||||
}
|
||||
|
||||
BLI_remlink(&ob->fmaps, fmap);
|
||||
BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
|
||||
}
|
||||
else { /*down*/
|
||||
void *next = fmap->next;
|
||||
|
||||
if (next) {
|
||||
pos2 = pos1 + 1;
|
||||
}
|
||||
else {
|
||||
pos2 = 0;
|
||||
}
|
||||
|
||||
BLI_remlink(&ob->fmaps, fmap);
|
||||
BLI_insertlinkafter(&ob->fmaps, next, fmap);
|
||||
}
|
||||
|
||||
/* iterate through mesh and substitute the indices as necessary */
|
||||
object_facemap_swap(ob, pos2, pos1);
|
||||
/* Iterate through mesh and substitute the indices as necessary. */
|
||||
object_facemap_remap(ob, map);
|
||||
MEM_freeN(map);
|
||||
|
||||
ob->actfmap = pos2 + 1;
|
||||
|
||||
|
@@ -2407,7 +2407,7 @@ void ED_vgroup_mirror(Object *ob,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology);
|
||||
EDBM_verts_mirror_cache_begin(em, 0, true, false, false, use_topology);
|
||||
|
||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
|
||||
|
||||
|
@@ -6114,8 +6114,6 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
|
||||
|
||||
scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
|
||||
|
||||
ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_3D);
|
||||
|
||||
/* allocate and initialize spatial data structures */
|
||||
project_paint_begin(C, &ps, false, 0);
|
||||
|
||||
@@ -6125,8 +6123,10 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
float pos[2] = {0.0, 0.0};
|
||||
float lastpos[2] = {0.0, 0.0};
|
||||
ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_3D);
|
||||
|
||||
const float pos[2] = {0.0, 0.0};
|
||||
const float lastpos[2] = {0.0, 0.0};
|
||||
int a;
|
||||
|
||||
project_paint_op(&ps, lastpos, pos);
|
||||
@@ -6140,6 +6140,8 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
|
||||
|
||||
project_paint_end(&ps);
|
||||
|
||||
ED_image_undo_push_end();
|
||||
|
||||
scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
|
||||
BKE_brush_size_set(scene, ps.brush, orig_brush_size);
|
||||
|
||||
|
@@ -1005,6 +1005,14 @@ void ED_image_undosys_type(UndoType *ut)
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utilities
|
||||
*
|
||||
* \note image undo exposes #ED_image_undo_push_begin, #ED_image_undo_push_end
|
||||
* which must be called by the operator directly.
|
||||
*
|
||||
* Unlike most other undo stacks this is needed:
|
||||
* - So we can always access the state before the image was painted onto,
|
||||
* which is needed if previous undo states aren't image-type.
|
||||
* - So operators can access the pixel-data before the stroke was applied, at run-time.
|
||||
* \{ */
|
||||
|
||||
ListBase *ED_image_paint_tile_list_get(void)
|
||||
@@ -1042,6 +1050,10 @@ static ImageUndoStep *image_undo_push_begin(const char *name, int paint_mode)
|
||||
return us;
|
||||
}
|
||||
|
||||
/**
|
||||
* The caller is responsible for running #ED_image_undo_push_end,
|
||||
* failure to do so causes an invalid state for the undo system.
|
||||
*/
|
||||
void ED_image_undo_push_begin(const char *name, int paint_mode)
|
||||
{
|
||||
image_undo_push_begin(name, paint_mode);
|
||||
|
@@ -115,15 +115,32 @@ static int script_reload_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
WM_script_tag_reload();
|
||||
/* TODO(campbell): this crashes on netrender and keying sets, need to look into why
|
||||
* disable for now unless running in debug mode. */
|
||||
|
||||
/* It would be nice if we could detect when this is called from the Python
|
||||
* only postponing in that case, for now always do it. */
|
||||
if (true) {
|
||||
/* Postpone when called from Python so this can be called from an operator
|
||||
* that might be re-registered, crashing Blender when we try to read from the
|
||||
* freed operator type which, see T80694. */
|
||||
BPY_execute_string(C,
|
||||
(const char *[]){"bpy", NULL},
|
||||
"def fn():\n"
|
||||
" bpy.utils.load_scripts(reload_scripts=True)\n"
|
||||
" return None\n"
|
||||
"bpy.app.timers.register(fn)");
|
||||
}
|
||||
else {
|
||||
WM_cursor_wait(true);
|
||||
BPY_execute_string(
|
||||
C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)");
|
||||
WM_cursor_wait(false);
|
||||
}
|
||||
|
||||
/* Note that #WM_script_tag_reload is called from `bpy.utils.load_scripts`,
|
||||
* any additional updates required by this operator should go there. */
|
||||
|
||||
/* TODO, this crashes on netrender and keying sets, need to look into why
|
||||
* disable for now unless running in debug mode */
|
||||
WM_cursor_wait(1);
|
||||
BPY_execute_string(
|
||||
C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)");
|
||||
WM_cursor_wait(0);
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
#else
|
||||
UNUSED_VARS(C, op);
|
||||
|
@@ -349,6 +349,10 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return early (as in: don't actually create a temporary constraint here), since adding
|
||||
* will take place later in add_pose_transdata() for targetless constraints. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,10 +706,14 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
|
||||
|
||||
/* Add a temporary auto IK constraint here, as we will only temporarily active this
|
||||
* targetless bone during transform. (Targetless IK constraints are treated as if they are
|
||||
* disabled unless they are transformed). */
|
||||
add_temporary_ik_constraint(pchan, data);
|
||||
Main *bmain = CTX_data_main(t->context);
|
||||
update_deg_with_temporary_ik(bmain, ob);
|
||||
* disabled unless they are transformed).
|
||||
* Only do this for targetless IK though, AutoIK already added a constraint in
|
||||
* pose_grab_with_ik_add() beforehand. */
|
||||
if ((data->flag & CONSTRAINT_IK_TEMP) == 0) {
|
||||
add_temporary_ik_constraint(pchan, data);
|
||||
Main *bmain = CTX_data_main(t->context);
|
||||
update_deg_with_temporary_ik(bmain, ob);
|
||||
}
|
||||
|
||||
/* only object matrix correction */
|
||||
copy_m3_m3(td->mtx, omat);
|
||||
@@ -1350,10 +1358,14 @@ static void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, O
|
||||
data->flag |= CONSTRAINT_IK_AUTO;
|
||||
/* Add a temporary auto IK constraint here, as we will only temporarily active this
|
||||
* target-less bone during transform. (Target-less IK constraints are treated as if they are
|
||||
* disabled unless they are transformed) */
|
||||
add_temporary_ik_constraint(pchan, data);
|
||||
Main *bmain = CTX_data_main(t->context);
|
||||
update_deg_with_temporary_ik(bmain, ob);
|
||||
* disabled unless they are transformed).
|
||||
* Only do this for targetless IK though, AutoIK already added a constraint in
|
||||
* pose_grab_with_ik_add() beforehand. */
|
||||
if ((data->flag & CONSTRAINT_IK_TEMP) == 0) {
|
||||
add_temporary_ik_constraint(pchan, data);
|
||||
Main *bmain = CTX_data_main(t->context);
|
||||
update_deg_with_temporary_ik(bmain, ob);
|
||||
}
|
||||
}
|
||||
|
||||
if (pid) {
|
||||
|
@@ -507,7 +507,7 @@ static void editmesh_mirror_data_calc(BMEditMesh *em,
|
||||
|
||||
index[a] = MEM_mallocN(totvert * sizeof(*index[a]), __func__);
|
||||
EDBM_verts_mirror_cache_begin_ex(
|
||||
em, a, false, test_selected_only, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]);
|
||||
em, a, false, test_selected_only, true, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]);
|
||||
|
||||
flag = TD_MIRROR_X << a;
|
||||
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
@@ -1293,6 +1293,9 @@ void mesh_customdatacorrect_init(TransInfo *t)
|
||||
use_merge_group = (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_KEEP_CONNECTED) != 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
mesh_customdatacorrect_init_container(tc, use_merge_group);
|
||||
|
@@ -301,6 +301,9 @@ void createTransUVs(bContext *C, TransInfo *t)
|
||||
|
||||
BM_elem_flag_enable(efa, BM_ELEM_TAG);
|
||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||
/* Make sure that the loop element flag is cleared for when we use it in
|
||||
* uv_set_connectivity_distance later. */
|
||||
BM_elem_flag_disable(l, BM_ELEM_TAG);
|
||||
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
|
||||
countsel++;
|
||||
|
||||
@@ -322,6 +325,8 @@ void createTransUVs(bContext *C, TransInfo *t)
|
||||
}
|
||||
}
|
||||
|
||||
float *prop_dists = NULL;
|
||||
|
||||
/* Support other objects using PET to adjust these, unless connected is enabled. */
|
||||
if (((is_prop_edit && !is_prop_connected) ? count : countsel) == 0) {
|
||||
goto finally;
|
||||
@@ -349,8 +354,6 @@ void createTransUVs(bContext *C, TransInfo *t)
|
||||
td = tc->data;
|
||||
td2d = tc->data_2d;
|
||||
|
||||
float *prop_dists = NULL;
|
||||
|
||||
if (is_prop_connected) {
|
||||
prop_dists = MEM_callocN(em->bm->totloop * sizeof(float), "TransObPropDists(UV Editing)");
|
||||
|
||||
@@ -397,7 +400,7 @@ void createTransUVs(bContext *C, TransInfo *t)
|
||||
|
||||
finally:
|
||||
if (is_prop_connected) {
|
||||
MEM_freeN(prop_dists);
|
||||
MEM_SAFE_FREE(prop_dists);
|
||||
}
|
||||
if (is_island_center) {
|
||||
BM_uv_element_map_free(elementmap);
|
||||
|
@@ -2855,9 +2855,6 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
else if (use_edge && !pinned) {
|
||||
changed = true;
|
||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, efa)) {
|
||||
continue;
|
||||
@@ -2865,29 +2862,18 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
|
||||
|
||||
BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
|
||||
MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
|
||||
bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
|
||||
|
||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||
const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
|
||||
if ((select != luv_select) || (select != luv_select_prev)) {
|
||||
if (BLI_rctf_isect_pt_v(&rectf, luv->uv) &&
|
||||
BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) {
|
||||
uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
|
||||
uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
|
||||
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
|
||||
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
|
||||
}
|
||||
if (BLI_rctf_isect_pt_v(&rectf, luv->uv) && BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) {
|
||||
uvedit_edge_select_set_with_sticky(
|
||||
sima, scene, em, l_prev, select, false, cd_loop_uv_offset);
|
||||
changed = true;
|
||||
}
|
||||
l_prev = l;
|
||||
luv_prev = luv;
|
||||
luv_select_prev = luv_select;
|
||||
}
|
||||
}
|
||||
|
||||
if (sima->sticky == SI_STICKY_VERTEX) {
|
||||
uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* other selection modes */
|
||||
@@ -3086,8 +3072,6 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
else if (use_edge) {
|
||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, efa)) {
|
||||
continue;
|
||||
@@ -3095,29 +3079,18 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
|
||||
|
||||
BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
|
||||
MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
|
||||
bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
|
||||
|
||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||
const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
|
||||
if ((select != luv_select) || (select != luv_select_prev)) {
|
||||
if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) {
|
||||
changed = true;
|
||||
uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
|
||||
uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
|
||||
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
|
||||
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
|
||||
}
|
||||
if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) {
|
||||
uvedit_edge_select_set_with_sticky(
|
||||
sima, scene, em, l_prev, select, false, cd_loop_uv_offset);
|
||||
changed = true;
|
||||
}
|
||||
l_prev = l;
|
||||
luv_prev = luv;
|
||||
luv_select_prev = luv_select;
|
||||
}
|
||||
}
|
||||
|
||||
if (sima->sticky == SI_STICKY_VERTEX) {
|
||||
uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
|
||||
@@ -3277,8 +3250,6 @@ static bool do_lasso_select_mesh_uv(bContext *C,
|
||||
}
|
||||
}
|
||||
else if (use_edge) {
|
||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, efa)) {
|
||||
continue;
|
||||
@@ -3286,32 +3257,21 @@ static bool do_lasso_select_mesh_uv(bContext *C,
|
||||
|
||||
BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
|
||||
MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
|
||||
bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
|
||||
|
||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||
const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
|
||||
if ((select != luv_select) || (select != luv_select_prev)) {
|
||||
if (do_lasso_select_mesh_uv_is_point_inside(
|
||||
region, &rect, mcoords, mcoords_len, luv->uv) &&
|
||||
do_lasso_select_mesh_uv_is_point_inside(
|
||||
region, &rect, mcoords, mcoords_len, luv_prev->uv)) {
|
||||
uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
|
||||
uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
|
||||
changed = true;
|
||||
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
|
||||
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
|
||||
}
|
||||
if (do_lasso_select_mesh_uv_is_point_inside(
|
||||
region, &rect, mcoords, mcoords_len, luv->uv) &&
|
||||
do_lasso_select_mesh_uv_is_point_inside(
|
||||
region, &rect, mcoords, mcoords_len, luv_prev->uv)) {
|
||||
uvedit_edge_select_set_with_sticky(
|
||||
sima, scene, em, l_prev, select, false, cd_loop_uv_offset);
|
||||
changed = true;
|
||||
}
|
||||
l_prev = l;
|
||||
luv_prev = luv;
|
||||
luv_select_prev = luv_select;
|
||||
}
|
||||
}
|
||||
|
||||
if (sima->sticky == SI_STICKY_VERTEX) {
|
||||
uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
|
||||
}
|
||||
}
|
||||
else { /* Vert Sel */
|
||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
|
||||
|
@@ -227,8 +227,8 @@ static void panel_draw(const bContext *C, Panel *panel)
|
||||
else {
|
||||
uiItemR(layout, &ptr, "normalize_opacity", 0, NULL, ICON_NONE);
|
||||
const char *text = (RNA_boolean_get(&ptr, "normalize_opacity")) ? IFACE_("Strength") :
|
||||
IFACE_("Opacity Factor");
|
||||
uiItemR(layout, &ptr, "hardness", 0, text, ICON_NONE);
|
||||
IFACE_("Opacity Factor");
|
||||
uiItemR(layout, &ptr, "factor", 0, text, ICON_NONE);
|
||||
}
|
||||
|
||||
gpencil_modifier_panel_end(layout, &ptr);
|
||||
|
@@ -136,6 +136,11 @@ typedef enum eGPUMaterialStatus {
|
||||
GPU_MAT_SUCCESS,
|
||||
} eGPUMaterialStatus;
|
||||
|
||||
typedef enum eGPUVolumeDefaultValue {
|
||||
GPU_VOLUME_DEFAULT_0,
|
||||
GPU_VOLUME_DEFAULT_1,
|
||||
} eGPUVolumeDefaultValue;
|
||||
|
||||
GPUNodeLink *GPU_constant(const float *num);
|
||||
GPUNodeLink *GPU_uniform(const float *num);
|
||||
GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name);
|
||||
@@ -149,7 +154,9 @@ GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
|
||||
eGPUSamplerState sampler_state);
|
||||
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
|
||||
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
|
||||
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name);
|
||||
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat,
|
||||
const char *name,
|
||||
eGPUVolumeDefaultValue default_value);
|
||||
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
|
||||
|
||||
bool GPU_link(GPUMaterial *mat, const char *name, ...);
|
||||
@@ -242,6 +249,7 @@ typedef struct GPUMaterialTexture {
|
||||
typedef struct GPUMaterialVolumeGrid {
|
||||
struct GPUMaterialVolumeGrid *next, *prev;
|
||||
char *name;
|
||||
eGPUVolumeDefaultValue default_value;
|
||||
char sampler_name[32]; /* Name of sampler in GLSL. */
|
||||
char transform_name[32]; /* Name of 4x4 matrix in GLSL. */
|
||||
int users;
|
||||
|
@@ -333,13 +333,15 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
|
||||
return tex;
|
||||
}
|
||||
|
||||
static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph, const char *name)
|
||||
static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph,
|
||||
const char *name,
|
||||
eGPUVolumeDefaultValue default_value)
|
||||
{
|
||||
/* Find existing volume grid. */
|
||||
int num_grids = 0;
|
||||
GPUMaterialVolumeGrid *grid = graph->volume_grids.first;
|
||||
for (; grid; grid = grid->next) {
|
||||
if (STREQ(grid->name, name)) {
|
||||
if (STREQ(grid->name, name) && grid->default_value == default_value) {
|
||||
break;
|
||||
}
|
||||
num_grids++;
|
||||
@@ -349,6 +351,7 @@ static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph
|
||||
if (grid == NULL) {
|
||||
grid = MEM_callocN(sizeof(*grid), __func__);
|
||||
grid->name = BLI_strdup(name);
|
||||
grid->default_value = default_value;
|
||||
BLI_snprintf(grid->sampler_name, sizeof(grid->sampler_name), "vsamp%d", num_grids);
|
||||
BLI_snprintf(grid->transform_name, sizeof(grid->transform_name), "vtfm%d", num_grids);
|
||||
BLI_addtail(&graph->volume_grids, grid);
|
||||
@@ -442,18 +445,21 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
|
||||
return link;
|
||||
}
|
||||
|
||||
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name)
|
||||
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat,
|
||||
const char *name,
|
||||
eGPUVolumeDefaultValue default_value)
|
||||
{
|
||||
/* NOTE: this could be optimized by automatically merging duplicate
|
||||
* lookups of the same attribute. */
|
||||
GPUNodeGraph *graph = gpu_material_node_graph(mat);
|
||||
GPUNodeLink *link = gpu_node_link_create();
|
||||
link->link_type = GPU_NODE_LINK_VOLUME_GRID;
|
||||
link->volume_grid = gpu_node_graph_add_volume_grid(graph, name);
|
||||
link->volume_grid = gpu_node_graph_add_volume_grid(graph, name, default_value);
|
||||
|
||||
GPUNodeLink *transform_link = gpu_node_link_create();
|
||||
transform_link->link_type = GPU_NODE_LINK_VOLUME_GRID_TRANSFORM;
|
||||
transform_link->volume_grid = link->volume_grid;
|
||||
transform_link->volume_grid->users++;
|
||||
|
||||
/* Two special cases, where we adjust the output values of smoke grids to
|
||||
* bring the into standard range without having to modify the grid values. */
|
||||
|
@@ -271,7 +271,7 @@ void BCAnimationSampler::find_depending_animated(std::set<Object *> &animated_ob
|
||||
std::set<Object *>::iterator it;
|
||||
for (it = candidates.begin(); it != candidates.end(); ++it) {
|
||||
Object *cob = *it;
|
||||
ListBase *conlist = ED_object_constraint_list_from_context(cob);
|
||||
ListBase *conlist = ED_object_constraint_active_list(cob);
|
||||
if (is_animated_by_constraint(cob, conlist, animated_objects)) {
|
||||
animated_objects.insert(cob);
|
||||
candidates.erase(cob);
|
||||
|
@@ -43,6 +43,8 @@
|
||||
# include "BLI_iterator.h"
|
||||
# include "BLI_math.h"
|
||||
|
||||
# include "RNA_access.h"
|
||||
|
||||
# include "BKE_duplilist.h"
|
||||
# include "BKE_object.h"
|
||||
# include "BKE_scene.h"
|
||||
@@ -461,14 +463,19 @@ static PointerRNA rna_Depsgraph_scene_get(PointerRNA *ptr)
|
||||
{
|
||||
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
|
||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_Scene, scene);
|
||||
PointerRNA newptr;
|
||||
RNA_pointer_create(&scene->id, &RNA_Scene, scene, &newptr);
|
||||
return newptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_Depsgraph_view_layer_get(PointerRNA *ptr)
|
||||
{
|
||||
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
|
||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer);
|
||||
PointerRNA newptr;
|
||||
RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer, &newptr);
|
||||
return newptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_Depsgraph_scene_eval_get(PointerRNA *ptr)
|
||||
@@ -476,13 +483,19 @@ static PointerRNA rna_Depsgraph_scene_eval_get(PointerRNA *ptr)
|
||||
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
|
||||
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_Scene, scene_eval);
|
||||
PointerRNA newptr;
|
||||
RNA_pointer_create(&scene_eval->id, &RNA_Scene, scene_eval, &newptr);
|
||||
return newptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_Depsgraph_view_layer_eval_get(PointerRNA *ptr)
|
||||
{
|
||||
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
|
||||
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
|
||||
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer_eval);
|
||||
PointerRNA newptr;
|
||||
RNA_pointer_create(&scene_eval->id, &RNA_ViewLayer, view_layer_eval, &newptr);
|
||||
return newptr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
@@ -1187,9 +1187,12 @@ static bool rna_property_override_diff_propptr_validate_diffing(PointerRNA *prop
|
||||
* This helps a lot in library override case, especially to detect inserted items in collections.
|
||||
*/
|
||||
if (!no_prop_name && (is_valid_for_diffing || do_force_name)) {
|
||||
PropertyRNA *nameprop_a = RNA_struct_name_property(propptr_a->type);
|
||||
PropertyRNA *nameprop_b = (propptr_b != NULL) ? RNA_struct_name_property(propptr_b->type) :
|
||||
NULL;
|
||||
PropertyRNA *nameprop_a = (propptr_a->type != NULL) ?
|
||||
RNA_struct_name_property(propptr_a->type) :
|
||||
NULL;
|
||||
PropertyRNA *nameprop_b = (propptr_b != NULL && propptr_b->type != NULL) ?
|
||||
RNA_struct_name_property(propptr_b->type) :
|
||||
NULL;
|
||||
|
||||
int propname_a_len = 0, propname_b_len = 0;
|
||||
char *propname_a = NULL;
|
||||
|
@@ -558,6 +558,12 @@ static void rna_WindowManager_print_undo_steps(wmWindowManager *wm)
|
||||
BKE_undosys_print(wm->undo_stack);
|
||||
}
|
||||
|
||||
static void rna_WindowManager_tag_script_reload(void)
|
||||
{
|
||||
WM_script_tag_reload();
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
}
|
||||
|
||||
static PointerRNA rna_WindoManager_operator_properties_last(const char *idname)
|
||||
{
|
||||
wmOperatorType *ot = WM_operatortype_find(idname, true);
|
||||
@@ -913,6 +919,12 @@ void RNA_api_wm(StructRNA *srna)
|
||||
|
||||
RNA_def_function(srna, "print_undo_steps", "rna_WindowManager_print_undo_steps");
|
||||
|
||||
/* Used by (#SCRIPT_OT_reload). */
|
||||
func = RNA_def_function(srna, "tag_script_reload", "rna_WindowManager_tag_script_reload");
|
||||
RNA_def_function_ui_description(
|
||||
func, "Tag for refreshing the interface after scripts have been reloaded");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
|
||||
parm = RNA_def_property(srna, "is_interface_locked", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_ui_text(
|
||||
parm,
|
||||
|
@@ -258,6 +258,10 @@ static void panel_draw(const bContext *C, Panel *panel)
|
||||
uiItemR(layout, &ptr, "use_collapse_triangulate", 0, NULL, ICON_NONE);
|
||||
|
||||
modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
|
||||
sub = uiLayoutRow(layout, true);
|
||||
bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
|
||||
uiLayoutSetActive(sub, has_vertex_group);
|
||||
uiItemR(sub, &ptr, "vertex_group_factor", 0, NULL, ICON_NONE);
|
||||
}
|
||||
else if (decimate_type == MOD_DECIM_MODE_UNSUBDIV) {
|
||||
uiItemR(layout, &ptr, "iterations", 0, NULL, ICON_NONE);
|
||||
|
@@ -313,10 +313,19 @@ static void deformVerts_do(HookModifierData *hmd,
|
||||
MOD_get_vgroup(ob, mesh, hmd->name, &dvert, &hd.defgrp_index);
|
||||
int cd_dvert_offset = -1;
|
||||
|
||||
if ((em != NULL) && (hd.defgrp_index != -1)) {
|
||||
cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
if (cd_dvert_offset == -1) {
|
||||
hd.defgrp_index = -1;
|
||||
if (hd.defgrp_index != -1) {
|
||||
/* Edit-mesh. */
|
||||
if (em != NULL) {
|
||||
cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
if (cd_dvert_offset == -1) {
|
||||
hd.defgrp_index = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Regular mesh. */
|
||||
if (dvert == NULL) {
|
||||
hd.defgrp_index = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -280,8 +280,9 @@ static void warpModifier_do(WarpModifierData *wmd,
|
||||
/* skip if no vert group found */
|
||||
if (defgrp_index != -1) {
|
||||
dv = &dvert[i];
|
||||
weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) * strength :
|
||||
BKE_defvert_find_weight(dv, defgrp_index) * strength;
|
||||
weight = (invert_vgroup ? (1.0f - BKE_defvert_find_weight(dv, defgrp_index)) :
|
||||
BKE_defvert_find_weight(dv, defgrp_index)) *
|
||||
strength;
|
||||
if (weight <= 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
@@ -249,9 +249,10 @@ void weightvg_do_mask(const ModifierEvalContext *ctx,
|
||||
/* For each weight (vertex), make the mix between org and new weights. */
|
||||
for (i = 0; i < num; i++) {
|
||||
int idx = indices ? indices[i] : i;
|
||||
const float f = invert_vgroup_mask ?
|
||||
1.0f - BKE_defvert_find_weight(&dvert[idx], ref_didx) * fact :
|
||||
BKE_defvert_find_weight(&dvert[idx], ref_didx) * fact;
|
||||
const float f = (invert_vgroup_mask ?
|
||||
(1.0f - BKE_defvert_find_weight(&dvert[idx], ref_didx)) :
|
||||
BKE_defvert_find_weight(&dvert[idx], ref_didx)) *
|
||||
fact;
|
||||
org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f - f));
|
||||
/* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */
|
||||
}
|
||||
|
@@ -44,13 +44,13 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
|
||||
|
||||
if (GPU_material_is_volume_shader(mat)) {
|
||||
if (out[0].hasoutput) {
|
||||
out[0].link = GPU_volume_grid(mat, attr->name);
|
||||
out[0].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
if (out[1].hasoutput) {
|
||||
out[1].link = GPU_volume_grid(mat, attr->name);
|
||||
out[1].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
if (out[2].hasoutput) {
|
||||
out[2].link = GPU_volume_grid(mat, attr->name);
|
||||
out[2].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@@ -34,16 +34,16 @@ static int node_shader_gpu_volume_info(GPUMaterial *mat,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
if (out[0].hasoutput) {
|
||||
out[0].link = GPU_volume_grid(mat, "color");
|
||||
out[0].link = GPU_volume_grid(mat, "color", GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
if (out[1].hasoutput) {
|
||||
out[1].link = GPU_volume_grid(mat, "density");
|
||||
out[1].link = GPU_volume_grid(mat, "density", GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
if (out[2].hasoutput) {
|
||||
out[2].link = GPU_volume_grid(mat, "flame");
|
||||
out[2].link = GPU_volume_grid(mat, "flame", GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
if (out[3].hasoutput) {
|
||||
out[3].link = GPU_volume_grid(mat, "temperature");
|
||||
out[3].link = GPU_volume_grid(mat, "temperature", GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@@ -78,13 +78,13 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat,
|
||||
}
|
||||
|
||||
if (STREQ(sock->name, "Density Attribute")) {
|
||||
density = GPU_volume_grid(mat, attribute_name);
|
||||
density = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_1);
|
||||
}
|
||||
else if (STREQ(sock->name, "Color Attribute")) {
|
||||
color = GPU_volume_grid(mat, attribute_name);
|
||||
color = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_1);
|
||||
}
|
||||
else if (use_blackbody && STREQ(sock->name, "Temperature Attribute")) {
|
||||
temperature = GPU_volume_grid(mat, attribute_name);
|
||||
temperature = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -93,13 +93,13 @@ static const EnumPropertyItem property_flag_override_items[] = {
|
||||
"LIBRARY_OVERRIDABLE",
|
||||
0,
|
||||
"Library Overridable",
|
||||
"Allow that property to be overridable from library linked data-blocks"},
|
||||
"Make that property editable in library overrides of linked data-blocks"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
#define BPY_PROPDEF_OPTIONS_OVERRIDE_DOC \
|
||||
" :arg options: Enumerator in ['LIBRARY_OVERRIDE'].\n" \
|
||||
" :type options: set\n"
|
||||
" :arg override: Enumerator in ['LIBRARY_OVERRIDABLE'].\n" \
|
||||
" :type override: set\n"
|
||||
|
||||
static const EnumPropertyItem property_flag_override_collection_items[] = {
|
||||
{PROPOVERRIDE_OVERRIDABLE_LIBRARY,
|
||||
@@ -116,8 +116,8 @@ static const EnumPropertyItem property_flag_override_collection_items[] = {
|
||||
};
|
||||
|
||||
#define BPY_PROPDEF_OPTIONS_OVERRIDE_COLLECTION_DOC \
|
||||
" :arg options: Enumerator in ['LIBRARY_OVERRIDE', 'NO_PROPERTY_NAME'].\n" \
|
||||
" :type options: set\n"
|
||||
" :arg override: Enumerator in ['LIBRARY_OVERRIDABLE', 'NO_PROPERTY_NAME'].\n" \
|
||||
" :type override: set\n"
|
||||
|
||||
/* subtypes */
|
||||
/* XXX Keep in sync with rna_rna.c's rna_enum_property_subtype_items ???
|
||||
|
Reference in New Issue
Block a user