Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
a2df63e996
|
@ -10,8 +10,9 @@
|
|||
# Changes that belong here:
|
||||
# - Massive comment, doxy-sections, or spelling corrections.
|
||||
# - Clang-format, PEP8 or other automated changes which are *strictly* "no functional change".
|
||||
# - Several smaller commits should be added to this list at once, because adding
|
||||
# one extra commit (to edit this file) after every small cleanup is noisy.
|
||||
# - Several commits should be added to this list at once, because adding
|
||||
# one extra commit (to edit this file) after every cleanup is noisy.
|
||||
# - No clang-tidy changes.
|
||||
#
|
||||
# Note:
|
||||
# - The comment above the SHA should be the first line of the commit.
|
||||
|
@ -92,78 +93,12 @@ c42a6b77b52560d257279de2cb624b4ef2c0d24c
|
|||
# Cleanup: use doxy sections for imbuf
|
||||
c207f7c22e1439e0b285fba5d2c072bdae23f981
|
||||
|
||||
# Cleanup: Clang-Tidy, modernize-use-bool-literals
|
||||
af35ada2f3fa8da4d46b3a71de724d353d716820
|
||||
|
||||
# Cleanup: Use nullptr everywhere in fluid code
|
||||
311031ecd03dbfbf43e1df672a395f24b2e7d4d3
|
||||
|
||||
# Cleanup: Clang-Tidy, modernize-redundant-void-arg
|
||||
a331d5c99299c4514ca33c843b1c79b872f2728d
|
||||
|
||||
# Cleanup: Clang-Tidy modernize-use-nullptr
|
||||
16732def37c5a66f3ea28dbe247b09cc6bca6677
|
||||
|
||||
# Cleanup: Clang-tidy, modernize-concat-nested-namespaces
|
||||
4525049aa0cf818f6483dce589ac9791eb562338
|
||||
|
||||
# Cleanup: Clang-tidy else-after-return
|
||||
ae342ed4511cf2e144dcd27ce2c635d3d536f9ad
|
||||
|
||||
# Cleanup: Clang-Tidy, readability-redundant-member-init
|
||||
190170d4cc92ff34abe1744a10474ac4f1074086
|
||||
|
||||
# Cleanup: use 'filepath' instead of 'name' for ImBuf utilities
|
||||
99f56b4c16323f96c0cbf54e392fb509fcac5bda
|
||||
|
||||
# Cleanup: clang-format
|
||||
c4d8f6a4a8ddc29ed27311ed7578b3c8c31399d2
|
||||
b5d310b569e07a937798a2d38539cfd290149f1c
|
||||
8c846cccd6bdfd3e90a695fabbf05f53e5466a57
|
||||
40d4a4cb1a6b4c3c2a486e8f2868f547530e0811
|
||||
4eac03d821fa17546f562485f7d073813a5e5943
|
||||
1166110a9d66af9c5a47cee2be591f50fdc445e8
|
||||
|
||||
# Cleanup: use preprocessor version check for PyTypeObject declaration
|
||||
cd9acfed4f7674b84be965d469a367aef96f8af3
|
||||
|
||||
# Cycles: fix compilation of OSL shaders following API change
|
||||
b980cd163a9d5d77eeffc2e353333e739fa9e719
|
||||
|
||||
# Cleanup: clang-tidy suppress warnings for PyTypeObject.tp_print
|
||||
efd71aad4f22ec0073d80b8dd296015d3f395aa8
|
||||
|
||||
# Cleanup: fix wrong merge, remove extra unique_ptr.
|
||||
6507449e54a167c63a72229e4d0119dd2af68ae5
|
||||
|
||||
# Cleanup: fix some clang tidy issues
|
||||
525a042c5c7513c41240b118acca002f6c60cc12
|
||||
|
||||
# Fix T82520: error building freestyle with Python3.8
|
||||
e118426e4695a97d67e65d69677f3c4e2db50a56
|
||||
|
||||
# Cleanup: Clang-tidy, readability-else-after-return
|
||||
7be47dadea5066ae095c644e0b4f1f10d75f5ab3
|
||||
|
||||
# Cleanup: Add `r_` to return parameter
|
||||
45dca05b1cd2a5ead59144c93d790fdfe7c35ee6
|
||||
|
||||
# Cleanup: Typo in `print_default_info` function name.
|
||||
41a73909dec716642f044e60b40a28335c9fdb10
|
||||
|
||||
# Cleanup: Reduce indentation
|
||||
1cc3a0e2cf73a5ff4f9e0a7f5338eda77266b300
|
||||
|
||||
# Build-system: Force C linkage for all DNA type headers
|
||||
ad4b7741dba45a2be210942c18af6b6e4438f129
|
||||
|
||||
# Cleanup: Move function to proper section
|
||||
c126e27cdc8b28365a9d5f9fafc4d521d1eb83df
|
||||
|
||||
# Cleanup: remove break after return statements
|
||||
bbdfeb751e16d939482d2e4b95c4d470f53f18a5
|
||||
|
||||
# Cleanup: clang-tidy
|
||||
af013ff76feef7e8b8ba642279c62a5dc275d59f
|
||||
|
||||
# Cleanup: Make panel type flag names more clear
|
||||
9d28353b525ecfbcca1501be72e4276dfb2bbc2a
|
||||
# Cleanup: clang-format.
|
||||
40d4a4cb1a6b4c3c2a486e8f2868f547530e0811
|
||||
|
|
|
@ -520,7 +520,7 @@ format: .FORCE
|
|||
|
||||
# Simple version of ./doc/python_api/sphinx_doc_gen.sh with no PDF generation.
|
||||
doc_py: .FORCE
|
||||
ASAN_OPTIONS=halt_on_error=0 \
|
||||
ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \
|
||||
$(BLENDER_BIN) --background -noaudio --factory-startup \
|
||||
--python doc/python_api/sphinx_doc_gen.py
|
||||
sphinx-build -b html -j $(NPROCS) doc/python_api/sphinx-in doc/python_api/sphinx-out
|
||||
|
|
|
@ -99,7 +99,9 @@ macro(BLENDER_SRC_GTEST_EX)
|
|||
|
||||
# Don't fail tests on leaks since these often happen in external libraries
|
||||
# that we can't fix.
|
||||
set_tests_properties(${TARGET_NAME} PROPERTIES ENVIRONMENT LSAN_OPTIONS=exitcode=0)
|
||||
set_tests_properties(${TARGET_NAME} PROPERTIES
|
||||
ENVIRONMENT LSAN_OPTIONS=exitcode=0:$ENV{LSAN_OPTIONS}
|
||||
)
|
||||
endif()
|
||||
if(WIN32)
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES VS_GLOBAL_VcpkgEnabled "false")
|
||||
|
|
|
@ -52,10 +52,11 @@ outfilename = sys.argv[2]
|
|||
|
||||
cmd = [blender_bin, "--help"]
|
||||
print(" executing:", " ".join(cmd))
|
||||
ASAN_OPTIONS = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "")
|
||||
blender_help = subprocess.run(
|
||||
cmd, env={"ASAN_OPTIONS": "exitcode=0"}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8")
|
||||
cmd, env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8")
|
||||
blender_version = subprocess.run(
|
||||
[blender_bin, "--version"], env={"ASAN_OPTIONS": "exitcode=0"}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8").strip()
|
||||
[blender_bin, "--version"], env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8").strip()
|
||||
blender_version, blender_date = (blender_version.split("build") + [None, None])[0:2]
|
||||
blender_version = blender_version.rstrip().partition(" ")[2] # remove 'Blender' prefix.
|
||||
if blender_date is None:
|
||||
|
|
|
@ -55,7 +55,7 @@ if $DO_EXE_BLENDER ; then
|
|||
# Don't delete existing docs, now partial updates are used for quick builds.
|
||||
#
|
||||
# Disable ASAN error halt since it results in nonzero exit code on any minor issue.
|
||||
ASAN_OPTIONS=halt_on_error=0 \
|
||||
ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \
|
||||
$BLENDER_BIN \
|
||||
--background \
|
||||
-noaudio \
|
||||
|
|
|
@ -100,7 +100,9 @@ class DenoiseParams {
|
|||
neighbor_frames = 2;
|
||||
clamp_input = true;
|
||||
|
||||
input_passes = DENOISER_INPUT_RGB_ALBEDO_NORMAL;
|
||||
/* Default to color + albedo only, since normal input does not always have the desired effect
|
||||
* when denoising with OptiX. */
|
||||
input_passes = DENOISER_INPUT_RGB_ALBEDO;
|
||||
|
||||
start_sample = 0;
|
||||
}
|
||||
|
|
|
@ -115,7 +115,15 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
|
|||
}
|
||||
});
|
||||
|
||||
if (sampling_pattern_is_modified()) {
|
||||
const bool need_update_lut = ao_samples_is_modified() || diffuse_samples_is_modified() ||
|
||||
glossy_samples_is_modified() || max_bounce_is_modified() ||
|
||||
max_transmission_bounce_is_modified() ||
|
||||
mesh_light_samples_is_modified() || method_is_modified() ||
|
||||
sampling_pattern_is_modified() ||
|
||||
subsurface_samples_is_modified() ||
|
||||
transmission_samples_is_modified() || volume_samples_is_modified();
|
||||
|
||||
if (need_update_lut) {
|
||||
dscene->sample_pattern_lut.tag_realloc();
|
||||
}
|
||||
|
||||
|
@ -248,7 +256,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
|
|||
int dimensions = PRNG_BASE_NUM + max_samples * PRNG_BOUNCE_NUM;
|
||||
dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
|
||||
|
||||
if (sampling_pattern_is_modified()) {
|
||||
if (need_update_lut) {
|
||||
if (sampling_pattern == SAMPLING_PATTERN_SOBOL) {
|
||||
uint *directions = dscene->sample_pattern_lut.alloc(SOBOL_BITS * dimensions);
|
||||
|
||||
|
@ -272,6 +280,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
|
|||
}
|
||||
}
|
||||
|
||||
dscene->sample_pattern_lut.clear_modified();
|
||||
clear_modified();
|
||||
}
|
||||
|
||||
|
@ -292,6 +301,11 @@ void Integrator::tag_update(Scene *scene, uint32_t flag)
|
|||
tag_ao_bounces_modified();
|
||||
}
|
||||
|
||||
if ((flag & LIGHT_SAMPLES_MODIFIED) && (method == BRANCHED_PATH)) {
|
||||
/* the number of light samples may affect the size of the sample_pattern_lut */
|
||||
tag_sampling_pattern_modified();
|
||||
}
|
||||
|
||||
if (filter_glossy_is_modified()) {
|
||||
foreach (Shader *shader, scene->shaders) {
|
||||
if (shader->has_integrator_dependency) {
|
||||
|
|
|
@ -92,6 +92,7 @@ class Integrator : public Node {
|
|||
enum : uint32_t {
|
||||
AO_PASS_MODIFIED = (1 << 0),
|
||||
BACKGROUND_AO_MODIFIED = (1 << 1),
|
||||
LIGHT_SAMPLES_MODIFIED = (1 << 2),
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
|
|
@ -164,6 +164,10 @@ void Light::tag_update(Scene *scene)
|
|||
{
|
||||
if (is_modified()) {
|
||||
scene->light_manager->tag_update(scene, LightManager::LIGHT_MODIFIED);
|
||||
|
||||
if (samples_is_modified()) {
|
||||
scene->integrator->tag_update(scene, Integrator::LIGHT_SAMPLES_MODIFIED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,6 +287,7 @@ const bTheme U_theme_default = {
|
|||
.outline_width = 1,
|
||||
.facedot_size = 4,
|
||||
.match = RGBA(0x5680c2ff),
|
||||
.active = RGBA(0x5680c2ff),
|
||||
},
|
||||
.space_view3d = {
|
||||
.back = RGBA(0x393939ff),
|
||||
|
|
|
@ -855,6 +855,7 @@
|
|||
<properties>
|
||||
<ThemeProperties
|
||||
match="#5680c2"
|
||||
active_modifier="#5680c2ff"
|
||||
>
|
||||
<space>
|
||||
<ThemeSpaceGeneric
|
||||
|
|
|
@ -1,3 +1,28 @@
|
|||
#
|
||||
# Notes on this key-map:
|
||||
#
|
||||
# This uses Blender's key-map, running with `legacy=True`.
|
||||
#
|
||||
# The intention of this key-map is to match Blender 2.7x which had many more key-map items available.
|
||||
#
|
||||
# There are some differences with the original Blender 2.7x key-map.
|
||||
# There is no intention to change these are they are not considered significant
|
||||
# enough to make a 1:1 match with the previous Blender version.
|
||||
#
|
||||
# These include:
|
||||
#
|
||||
# 3D View
|
||||
# =======
|
||||
#
|
||||
# - Border Render (`Shift-B` -> `Ctrl-B`)
|
||||
# Both `Shift-B` and `Ctrl-B` were used.
|
||||
#
|
||||
# Time Line/Animation Views
|
||||
# =========================
|
||||
#
|
||||
# - Start Frame/End Frame (`S/E` -> `Ctrl-Home/Ctrl-End`)
|
||||
#
|
||||
|
||||
import os
|
||||
import bpy
|
||||
from bpy.props import (
|
||||
|
|
|
@ -2556,8 +2556,8 @@ def km_sequencer(params):
|
|||
{"properties": [("unselected", False)]}),
|
||||
("sequencer.unmute", {"type": 'H', "value": 'PRESS', "shift": True, "alt": True},
|
||||
{"properties": [("unselected", True)]}),
|
||||
("sequencer.lock", {"type": 'L', "value": 'PRESS', "shift": True}, None),
|
||||
("sequencer.unlock", {"type": 'L', "value": 'PRESS', "shift": True, "alt": True}, None),
|
||||
("sequencer.lock", {"type": 'H', "value": 'PRESS', "ctrl": True}, None),
|
||||
("sequencer.unlock", {"type": 'H', "value": 'PRESS', "ctrl": True, "alt": True}, None),
|
||||
("sequencer.reassign_inputs", {"type": 'R', "value": 'PRESS'}, None),
|
||||
("sequencer.reload", {"type": 'R', "value": 'PRESS', "alt": True}, None),
|
||||
("sequencer.reload", {"type": 'R', "value": 'PRESS', "shift": True, "alt": True},
|
||||
|
|
|
@ -6269,17 +6269,20 @@ class VIEW3D_PT_overlay_edit_mesh(Panel):
|
|||
overlay = view.overlay
|
||||
display_all = overlay.show_overlays
|
||||
|
||||
is_any_solid_shading = not (shading.show_xray or (shading.type == 'WIREFRAME'))
|
||||
|
||||
col = layout.column()
|
||||
col.active = display_all
|
||||
|
||||
split = col.split()
|
||||
|
||||
sub = split.column()
|
||||
sub.active = not ((shading.type == 'WIREFRAME') or shading.show_xray)
|
||||
sub.active = is_any_solid_shading
|
||||
sub.prop(overlay, "show_edges", text="Edges")
|
||||
sub = split.column()
|
||||
sub.prop(overlay, "show_faces", text="Faces")
|
||||
sub = split.column()
|
||||
sub.active = is_any_solid_shading
|
||||
sub.prop(overlay, "show_face_center", text="Center")
|
||||
|
||||
row = col.row(align=True)
|
||||
|
|
|
@ -127,25 +127,25 @@ class MyCustomShapeWidgetGroup(GizmoGroup):
|
|||
def setup(self, context):
|
||||
# Assign the 'offset' target property to the light energy.
|
||||
ob = context.object
|
||||
mpr = self.gizmos.new(MyCustomShapeWidget.bl_idname)
|
||||
mpr.target_set_prop("offset", ob.data, "energy")
|
||||
gz = self.gizmos.new(MyCustomShapeWidget.bl_idname)
|
||||
gz.target_set_prop("offset", ob.data, "energy")
|
||||
|
||||
mpr.color = 1.0, 0.5, 1.0
|
||||
mpr.alpha = 0.5
|
||||
gz.color = 1.0, 0.5, 1.0
|
||||
gz.alpha = 0.5
|
||||
|
||||
mpr.color_highlight = 1.0, 1.0, 1.0
|
||||
mpr.alpha_highlight = 0.5
|
||||
gz.color_highlight = 1.0, 1.0, 1.0
|
||||
gz.alpha_highlight = 0.5
|
||||
|
||||
# units are large, so shrink to something more reasonable.
|
||||
mpr.scale_basis = 0.1
|
||||
mpr.use_draw_modal = True
|
||||
gz.scale_basis = 0.1
|
||||
gz.use_draw_modal = True
|
||||
|
||||
self.energy_widget = mpr
|
||||
self.energy_gizmo = gz
|
||||
|
||||
def refresh(self, context):
|
||||
ob = context.object
|
||||
mpr = self.energy_widget
|
||||
mpr.matrix_basis = ob.matrix_world.normalized()
|
||||
gz = self.energy_gizmo
|
||||
gz.matrix_basis = ob.matrix_world.normalized()
|
||||
|
||||
|
||||
classes = (
|
||||
|
|
|
@ -34,7 +34,7 @@ def main(context, plane_co, plane_no):
|
|||
|
||||
|
||||
class SelectSideOfPlane(Operator):
|
||||
"""UV Operator description"""
|
||||
"""Select all vertices on one side of a plane defined by a location and a direction"""
|
||||
bl_idname = "mesh.select_side_of_plane"
|
||||
bl_label = "Select Side of Plane"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
@ -126,20 +126,20 @@ class SelectSideOfPlaneGizmoGroup(GizmoGroup):
|
|||
# XXX, this may change!
|
||||
op.execute(context)
|
||||
|
||||
mpr = self.gizmos.new("GIZMO_GT_move_3d")
|
||||
mpr.target_set_handler("offset", get=move_get_cb, set=move_set_cb)
|
||||
gz = self.gizmos.new("GIZMO_GT_move_3d")
|
||||
gz.target_set_handler("offset", get=move_get_cb, set=move_set_cb)
|
||||
|
||||
mpr.use_draw_value = True
|
||||
gz.use_draw_value = True
|
||||
|
||||
mpr.color = 0.8, 0.8, 0.8
|
||||
mpr.alpha = 0.5
|
||||
gz.color = 0.8, 0.8, 0.8
|
||||
gz.alpha = 0.5
|
||||
|
||||
mpr.color_highlight = 1.0, 1.0, 1.0
|
||||
mpr.alpha_highlight = 1.0
|
||||
gz.color_highlight = 1.0, 1.0, 1.0
|
||||
gz.alpha_highlight = 1.0
|
||||
|
||||
mpr.scale_basis = 0.2
|
||||
gz.scale_basis = 0.2
|
||||
|
||||
self.widget_move = mpr
|
||||
self.gizmo_move = gz
|
||||
|
||||
# ----
|
||||
# Dial
|
||||
|
@ -147,7 +147,7 @@ class SelectSideOfPlaneGizmoGroup(GizmoGroup):
|
|||
def direction_get_cb():
|
||||
op = SelectSideOfPlaneGizmoGroup.my_target_operator(context)
|
||||
|
||||
no_a = self.widget_dial.matrix_basis.col[1].xyz
|
||||
no_a = self.gizmo_dial.matrix_basis.col[1].xyz
|
||||
no_b = Vector(op.plane_no)
|
||||
|
||||
no_a = (no_a @ self.view_inv).xy.normalized()
|
||||
|
@ -157,23 +157,23 @@ class SelectSideOfPlaneGizmoGroup(GizmoGroup):
|
|||
def direction_set_cb(value):
|
||||
op = SelectSideOfPlaneGizmoGroup.my_target_operator(context)
|
||||
matrix_rotate = Matrix.Rotation(-value, 3, self.rotate_axis)
|
||||
no = matrix_rotate @ self.widget_dial.matrix_basis.col[1].xyz
|
||||
no = matrix_rotate @ self.gizmo_dial.matrix_basis.col[1].xyz
|
||||
op.plane_no = no
|
||||
op.execute(context)
|
||||
|
||||
mpr = self.gizmos.new("GIZMO_GT_dial_3d")
|
||||
mpr.target_set_handler("offset", get=direction_get_cb, set=direction_set_cb)
|
||||
mpr.draw_options = {'ANGLE_START_Y'}
|
||||
gz = self.gizmos.new("GIZMO_GT_dial_3d")
|
||||
gz.target_set_handler("offset", get=direction_get_cb, set=direction_set_cb)
|
||||
gz.draw_options = {'ANGLE_START_Y'}
|
||||
|
||||
mpr.use_draw_value = True
|
||||
gz.use_draw_value = True
|
||||
|
||||
mpr.color = 0.8, 0.8, 0.8
|
||||
mpr.alpha = 0.5
|
||||
gz.color = 0.8, 0.8, 0.8
|
||||
gz.alpha = 0.5
|
||||
|
||||
mpr.color_highlight = 1.0, 1.0, 1.0
|
||||
mpr.alpha_highlight = 1.0
|
||||
gz.color_highlight = 1.0, 1.0, 1.0
|
||||
gz.alpha_highlight = 1.0
|
||||
|
||||
self.widget_dial = mpr
|
||||
self.gizmo_dial = gz
|
||||
|
||||
def draw_prepare(self, context):
|
||||
from mathutils import Vector
|
||||
|
@ -194,7 +194,7 @@ class SelectSideOfPlaneGizmoGroup(GizmoGroup):
|
|||
no_y = no_z.orthogonal()
|
||||
no_x = no_z.cross(no_y)
|
||||
|
||||
matrix = self.widget_move.matrix_basis
|
||||
matrix = self.gizmo_move.matrix_basis
|
||||
matrix.identity()
|
||||
matrix.col[0].xyz = no_x
|
||||
matrix.col[1].xyz = no_y
|
||||
|
@ -206,7 +206,7 @@ class SelectSideOfPlaneGizmoGroup(GizmoGroup):
|
|||
no_y = (no - (no.project(no_z))).normalized()
|
||||
no_x = self.rotate_axis.cross(no_y)
|
||||
|
||||
matrix = self.widget_dial.matrix_basis
|
||||
matrix = self.gizmo_dial.matrix_basis
|
||||
matrix.identity()
|
||||
matrix.col[0].xyz = no_x
|
||||
matrix.col[1].xyz = no_y
|
||||
|
|
|
@ -24,27 +24,27 @@ class MyCameraWidgetGroup(GizmoGroup):
|
|||
def setup(self, context):
|
||||
# Run an operator using the dial gizmo
|
||||
ob = context.object
|
||||
mpr = self.gizmos.new("GIZMO_GT_dial_3d")
|
||||
props = mpr.target_set_operator("transform.rotate")
|
||||
gz = self.gizmos.new("GIZMO_GT_dial_3d")
|
||||
props = gz.target_set_operator("transform.rotate")
|
||||
props.constraint_axis = False, False, True
|
||||
props.orient_type = 'LOCAL'
|
||||
props.release_confirm = True
|
||||
|
||||
mpr.matrix_basis = ob.matrix_world.normalized()
|
||||
mpr.line_width = 3
|
||||
gz.matrix_basis = ob.matrix_world.normalized()
|
||||
gz.line_width = 3
|
||||
|
||||
mpr.color = 0.8, 0.8, 0.8
|
||||
mpr.alpha = 0.5
|
||||
gz.color = 0.8, 0.8, 0.8
|
||||
gz.alpha = 0.5
|
||||
|
||||
mpr.color_highlight = 1.0, 1.0, 1.0
|
||||
mpr.alpha_highlight = 1.0
|
||||
gz.color_highlight = 1.0, 1.0, 1.0
|
||||
gz.alpha_highlight = 1.0
|
||||
|
||||
self.roll_widget = mpr
|
||||
self.roll_gizmo = gz
|
||||
|
||||
def refresh(self, context):
|
||||
ob = context.object
|
||||
mpr = self.roll_widget
|
||||
mpr.matrix_basis = ob.matrix_world.normalized()
|
||||
gz = self.roll_gizmo
|
||||
gz.matrix_basis = ob.matrix_world.normalized()
|
||||
|
||||
|
||||
bpy.utils.register_class(MyCameraWidgetGroup)
|
||||
|
|
|
@ -25,23 +25,23 @@ class MyLightWidgetGroup(GizmoGroup):
|
|||
def setup(self, context):
|
||||
# Arrow gizmo has one 'offset' property we can assign to the light energy.
|
||||
ob = context.object
|
||||
mpr = self.gizmos.new("GIZMO_GT_arrow_3d")
|
||||
mpr.target_set_prop("offset", ob.data, "energy")
|
||||
mpr.matrix_basis = ob.matrix_world.normalized()
|
||||
mpr.draw_style = 'BOX'
|
||||
gz = self.gizmos.new("GIZMO_GT_arrow_3d")
|
||||
gz.target_set_prop("offset", ob.data, "energy")
|
||||
gz.matrix_basis = ob.matrix_world.normalized()
|
||||
gz.draw_style = 'BOX'
|
||||
|
||||
mpr.color = 1.0, 0.5, 0.0
|
||||
mpr.alpha = 0.5
|
||||
gz.color = 1.0, 0.5, 0.0
|
||||
gz.alpha = 0.5
|
||||
|
||||
mpr.color_highlight = 1.0, 0.5, 1.0
|
||||
mpr.alpha_highlight = 0.5
|
||||
gz.color_highlight = 1.0, 0.5, 1.0
|
||||
gz.alpha_highlight = 0.5
|
||||
|
||||
self.energy_widget = mpr
|
||||
self.energy_gizmo = gz
|
||||
|
||||
def refresh(self, context):
|
||||
ob = context.object
|
||||
mpr = self.energy_widget
|
||||
mpr.matrix_basis = ob.matrix_world.normalized()
|
||||
gz = self.energy_gizmo
|
||||
gz.matrix_basis = ob.matrix_world.normalized()
|
||||
|
||||
|
||||
bpy.utils.register_class(MyLightWidgetGroup)
|
||||
|
|
|
@ -147,21 +147,18 @@ enum {
|
|||
G_DEBUG_DEPSGRAPH = (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_EVAL | G_DEBUG_DEPSGRAPH_TAG |
|
||||
G_DEBUG_DEPSGRAPH_TIME | G_DEBUG_DEPSGRAPH_UUID),
|
||||
G_DEBUG_SIMDATA = (1 << 15), /* sim debug data display */
|
||||
G_DEBUG_GPU_MEM = (1 << 16), /* gpu memory in status bar */
|
||||
G_DEBUG_GPU = (1 << 17), /* gpu debug */
|
||||
G_DEBUG_IO = (1 << 18), /* IO Debugging (for Collada, ...)*/
|
||||
G_DEBUG_GPU_SHADERS = (1 << 19), /* GLSL shaders */
|
||||
G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 20), /* force gpu workarounds bypassing detections. */
|
||||
G_DEBUG_XR = (1 << 21), /* XR/OpenXR messages */
|
||||
G_DEBUG_XR_TIME = (1 << 22), /* XR/OpenXR timing messages */
|
||||
G_DEBUG_GPU = (1 << 16), /* gpu debug */
|
||||
G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/
|
||||
G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 18), /* force gpu workarounds bypassing detections. */
|
||||
G_DEBUG_XR = (1 << 19), /* XR/OpenXR messages */
|
||||
G_DEBUG_XR_TIME = (1 << 20), /* XR/OpenXR timing messages */
|
||||
|
||||
G_DEBUG_GHOST = (1 << 23), /* Debug GHOST module. */
|
||||
G_DEBUG_GHOST = (1 << 21), /* Debug GHOST module. */
|
||||
};
|
||||
|
||||
#define G_DEBUG_ALL \
|
||||
(G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \
|
||||
G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO | G_DEBUG_GPU_SHADERS | \
|
||||
G_DEBUG_GHOST)
|
||||
G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_IO | G_DEBUG_GHOST)
|
||||
|
||||
/** #Global.fileflags */
|
||||
enum {
|
||||
|
|
|
@ -223,7 +223,8 @@ void BKE_scene_free_depsgraph_hash(struct Scene *scene);
|
|||
void BKE_scene_free_view_layer_depsgraph(struct Scene *scene, struct ViewLayer *view_layer);
|
||||
|
||||
/* Do not allocate new depsgraph. */
|
||||
struct Depsgraph *BKE_scene_get_depsgraph(struct Scene *scene, struct ViewLayer *view_layer);
|
||||
struct Depsgraph *BKE_scene_get_depsgraph(const struct Scene *scene,
|
||||
const struct ViewLayer *view_layer);
|
||||
/* Allocate new depsgraph if necessary. */
|
||||
struct Depsgraph *BKE_scene_ensure_depsgraph(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
|
|
|
@ -139,6 +139,7 @@ typedef struct SpaceType {
|
|||
/* region types are also defined using spacetypes_init, via a callback */
|
||||
|
||||
typedef struct wmRegionListenerParams {
|
||||
struct wmWindow *window;
|
||||
struct ScrArea *area; /* Can be NULL when the region is not part of an area. */
|
||||
struct ARegion *region;
|
||||
struct wmNotifier *notifier;
|
||||
|
|
|
@ -3316,7 +3316,7 @@ int BKE_scene_multiview_num_videos_get(const RenderData *rd)
|
|||
|
||||
/* This is a key which identifies depsgraph. */
|
||||
typedef struct DepsgraphKey {
|
||||
ViewLayer *view_layer;
|
||||
const ViewLayer *view_layer;
|
||||
/* TODO(sergey): Need to include window somehow (same layer might be in a
|
||||
* different states in different windows).
|
||||
*/
|
||||
|
@ -3451,10 +3451,13 @@ static Depsgraph **scene_ensure_depsgraph_p(Main *bmain, Scene *scene, ViewLayer
|
|||
return depsgraph_ptr;
|
||||
}
|
||||
|
||||
Depsgraph *BKE_scene_get_depsgraph(Scene *scene, ViewLayer *view_layer)
|
||||
Depsgraph *BKE_scene_get_depsgraph(const Scene *scene, const ViewLayer *view_layer)
|
||||
{
|
||||
Depsgraph **depsgraph_ptr = scene_get_depsgraph_p(scene, view_layer, false);
|
||||
return (depsgraph_ptr != NULL) ? *depsgraph_ptr : NULL;
|
||||
BLI_assert(BKE_scene_has_view_layer(scene, view_layer));
|
||||
|
||||
DepsgraphKey key;
|
||||
key.view_layer = view_layer;
|
||||
return BLI_ghash_lookup(scene->depsgraph_hash, &key);
|
||||
}
|
||||
|
||||
Depsgraph *BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer)
|
||||
|
|
|
@ -88,7 +88,11 @@ static void sigbus_handler(int sig, siginfo_t *siginfo, void *ptr)
|
|||
file->io_error = true;
|
||||
|
||||
/* Replace the mapped memory with zeroes. */
|
||||
mmap(file->memory, file->length, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
const void *mapped_memory = mmap(
|
||||
file->memory, file->length, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (mapped_memory == MAP_FAILED) {
|
||||
fprintf(stderr, "SIGBUS handler: Error replacing mapped file with zeros\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -272,6 +272,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
FROM_DEFAULT_V4_UCHAR(space_properties.active);
|
||||
}
|
||||
|
||||
#undef FROM_DEFAULT_V4_UCHAR
|
||||
|
|
|
@ -852,6 +852,10 @@ static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data)
|
|||
BM_vert_edge_count_nonwire(e->v1),
|
||||
BM_vert_edge_count_nonwire(e->v2),
|
||||
};
|
||||
const int vert_face_count[2] = {
|
||||
BM_vert_face_count(e->v1),
|
||||
BM_vert_face_count(e->v2),
|
||||
};
|
||||
|
||||
v = e->v1;
|
||||
|
||||
|
@ -863,8 +867,75 @@ static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data)
|
|||
lwalk->is_boundary = BM_edge_is_boundary(e);
|
||||
lwalk->is_single = (lwalk->is_boundary && bm_edge_is_single(e));
|
||||
|
||||
/* could also check that vertex*/
|
||||
if ((lwalk->is_boundary == false) && (vert_edge_count[0] == 3 || vert_edge_count[1] == 3)) {
|
||||
/**
|
||||
* Detect an NGon (face-hub)
|
||||
* =========================
|
||||
*
|
||||
* The face-hub - #BMwEdgeLoopWalker.f_hub - is set when there is an ngon
|
||||
* on one side of the edge and a series of faces on the other,
|
||||
* loop around the ngon for as long as it's connected to faces which would form an edge loop
|
||||
* in the absence of the ngon (used as the hub).
|
||||
*
|
||||
* This isn't simply ignoring the ngon though, as the edges looped over must all be
|
||||
* connected to the hub.
|
||||
*
|
||||
* NGon in Grid Example
|
||||
* --------------------
|
||||
* \code{.txt}
|
||||
* +-----+-----+-----+-----+-----+
|
||||
* | | | | | |
|
||||
* +-----va=ea=+==eb=+==ec=vb----+
|
||||
* | | | |
|
||||
* +-----+ +-----+
|
||||
* | | f_hub | |
|
||||
* +-----+ +-----+
|
||||
* | | | |
|
||||
* +-----+-----+-----+-----+-----+
|
||||
* | | | | | |
|
||||
* +-----+-----+-----+-----+-----+
|
||||
* \endcode
|
||||
*
|
||||
* In the example above, starting from edges marked `ea/eb/ec`,
|
||||
* the will detect `f_hub` and walk along the edge loop between `va -> vb`.
|
||||
* The same is true for any of the un-marked sides of the ngon,
|
||||
* walking stops for vertices with >= 3 connected faces (in this case they look like corners).
|
||||
*
|
||||
* Mixed Triangle-Fan & Quad Example
|
||||
* ---------------------------------
|
||||
* \code{.txt}
|
||||
* +-----------------------------------------------+
|
||||
* | f_hub |
|
||||
* va-ea-vb=eb=+==ec=+=ed==+=ee=vc=ef=vd----------ve
|
||||
* | |\ | | | / / \ |
|
||||
* | | \ \ | / / / \ |
|
||||
* | | \ | | | / / \ |
|
||||
* | | \ \ | / / / \ |
|
||||
* | | \ | | | / / \ |
|
||||
* | | \ \ | / / / \ |
|
||||
* | | \ | | | / / \ |
|
||||
* | | \ \ | / / / \ |
|
||||
* | | \| | |/ / \ |
|
||||
* | | \\|// / \ |
|
||||
* | | \|/ / \|
|
||||
* +-----+-----------+-----+-----------------------+
|
||||
* \endcode
|
||||
*
|
||||
* In the example above, starting from edges marked `eb/eb/ed/ed/ef`,
|
||||
* the will detect `f_hub` and walk along the edge loop between `vb -> vd`.
|
||||
*
|
||||
* Notice `vb` and `vd` delimit the loop, since the faces connected to `vb`
|
||||
* excluding `f_hub` don't share an edge, which isn't walked over in the case
|
||||
* of boundaries either.
|
||||
*
|
||||
* Notice `vc` doesn't delimit stepping from `ee` onto `ef` as the stepping method used
|
||||
* doesn't differentiate between the number of sides of faces opposite `f_hub`,
|
||||
* only that each of the connected faces share an edge.
|
||||
*/
|
||||
if ((lwalk->is_boundary == false) &&
|
||||
/* Without checking the face count, the 3 edges could be this edge
|
||||
* plus two boundary edges (which would not be stepped over), see T84906. */
|
||||
((vert_edge_count[0] == 3 && vert_face_count[0] == 3) ||
|
||||
(vert_edge_count[1] == 3 && vert_face_count[1] == 3))) {
|
||||
BMIter iter;
|
||||
BMFace *f_iter;
|
||||
BMFace *f_best = NULL;
|
||||
|
|
|
@ -68,6 +68,7 @@ void GaussianAlphaXBlurOperation::updateGauss()
|
|||
if (this->m_distbuf_inv == nullptr) {
|
||||
updateSize();
|
||||
float rad = max_ff(m_size * m_data.sizex, 0.0f);
|
||||
rad = min_ff(rad, MAX_GAUSSTAB_RADIUS);
|
||||
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
|
||||
|
||||
m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff);
|
||||
|
|
|
@ -60,6 +60,7 @@ void GaussianAlphaYBlurOperation::updateGauss()
|
|||
if (this->m_gausstab == nullptr) {
|
||||
updateSize();
|
||||
float rad = max_ff(m_size * m_data.sizey, 0.0f);
|
||||
rad = min_ff(rad, MAX_GAUSSTAB_RADIUS);
|
||||
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
|
||||
|
||||
m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize);
|
||||
|
|
|
@ -66,6 +66,7 @@ void GaussianXBlurOperation::updateGauss()
|
|||
if (this->m_gausstab == nullptr) {
|
||||
updateSize();
|
||||
float rad = max_ff(m_size * m_data.sizex, 0.0f);
|
||||
rad = min_ff(rad, MAX_GAUSSTAB_RADIUS);
|
||||
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
|
||||
|
||||
this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize);
|
||||
|
|
|
@ -65,6 +65,7 @@ void GaussianYBlurOperation::updateGauss()
|
|||
if (this->m_gausstab == nullptr) {
|
||||
updateSize();
|
||||
float rad = max_ff(m_size * m_data.sizey, 0.0f);
|
||||
rad = min_ff(rad, MAX_GAUSSTAB_RADIUS);
|
||||
m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS);
|
||||
|
||||
this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize);
|
||||
|
|
|
@ -175,7 +175,8 @@ typedef struct DEGEditorUpdateContext {
|
|||
} DEGEditorUpdateContext;
|
||||
|
||||
typedef void (*DEG_EditorUpdateIDCb)(const DEGEditorUpdateContext *update_ctx, struct ID *id);
|
||||
typedef void (*DEG_EditorUpdateSceneCb)(const DEGEditorUpdateContext *update_ctx, int updated);
|
||||
typedef void (*DEG_EditorUpdateSceneCb)(const DEGEditorUpdateContext *update_ctx,
|
||||
const bool updated);
|
||||
|
||||
/* Set callbacks which are being called when depsgraph changes. */
|
||||
void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, DEG_EditorUpdateSceneCb scene_func);
|
||||
|
|
|
@ -387,7 +387,9 @@ void DepsgraphNodeBuilder::build_id(ID *id)
|
|||
if (id == nullptr) {
|
||||
return;
|
||||
}
|
||||
switch (GS(id->name)) {
|
||||
|
||||
const ID_Type id_type = GS(id->name);
|
||||
switch (id_type) {
|
||||
case ID_AC:
|
||||
build_action((bAction *)id);
|
||||
break;
|
||||
|
@ -477,13 +479,39 @@ void DepsgraphNodeBuilder::build_id(ID *id)
|
|||
case ID_SIM:
|
||||
build_simulation((Simulation *)id);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unhandled ID %s\n", id->name);
|
||||
BLI_assert(!"Should never happen");
|
||||
case ID_PA:
|
||||
build_particle_settings((ParticleSettings *)id);
|
||||
break;
|
||||
case ID_GD:
|
||||
build_gpencil((bGPdata *)id);
|
||||
break;
|
||||
|
||||
case ID_LI:
|
||||
case ID_IP:
|
||||
case ID_SCR:
|
||||
case ID_VF:
|
||||
case ID_BR:
|
||||
case ID_WM:
|
||||
case ID_PAL:
|
||||
case ID_PC:
|
||||
case ID_WS:
|
||||
BLI_assert(!deg_copy_on_write_is_needed(id_type));
|
||||
build_generic_id(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DepsgraphNodeBuilder::build_generic_id(ID *id)
|
||||
{
|
||||
if (built_map_.checkIsBuiltAndTag(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
build_idproperties(id->properties);
|
||||
build_animdata(id);
|
||||
build_parameters(id);
|
||||
}
|
||||
|
||||
static void build_idproperties_callback(IDProperty *id_property, void *user_data)
|
||||
{
|
||||
DepsgraphNodeBuilder *builder = reinterpret_cast<DepsgraphNodeBuilder *>(user_data);
|
||||
|
@ -649,6 +677,11 @@ void DepsgraphNodeBuilder::build_object(int base_index,
|
|||
if (object->particlesystem.first != nullptr) {
|
||||
build_particle_systems(object, is_visible);
|
||||
}
|
||||
/* Force field Texture. */
|
||||
if ((object->pd != nullptr) && (object->pd->forcefield == PFIELD_TEXTURE) &&
|
||||
(object->pd->tex != nullptr)) {
|
||||
build_texture(object->pd->tex);
|
||||
}
|
||||
/* Proxy object to copy from. */
|
||||
build_object_proxy_from(object, is_visible);
|
||||
build_object_proxy_group(object, is_visible);
|
||||
|
|
|
@ -152,6 +152,9 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
|
|||
|
||||
virtual void build_id(ID *id);
|
||||
|
||||
/* Build function for ID types that do not need their own build_xxx() function. */
|
||||
virtual void build_generic_id(ID *id);
|
||||
|
||||
virtual void build_idproperties(IDProperty *id_property);
|
||||
|
||||
virtual void build_scene_render(Scene *scene, ViewLayer *view_layer);
|
||||
|
|
|
@ -434,6 +434,13 @@ void DepsgraphRelationBuilder::add_particle_forcefield_relations(const Operation
|
|||
add_relation(mod_key, key, name);
|
||||
}
|
||||
|
||||
/* Force field Texture. */
|
||||
if ((relation->pd != nullptr) && (relation->pd->forcefield == PFIELD_TEXTURE) &&
|
||||
(relation->pd->tex != nullptr)) {
|
||||
ComponentKey tex_key(&relation->pd->tex->id, NodeType::GENERIC_DATABLOCK);
|
||||
add_relation(tex_key, key, "Force field Texture");
|
||||
}
|
||||
|
||||
/* Smoke flow relations. */
|
||||
if (relation->pd->forcefield == PFIELD_FLUIDFLOW && relation->pd->f_source) {
|
||||
ComponentKey trf_key(&relation->pd->f_source->id, NodeType::TRANSFORM);
|
||||
|
@ -484,7 +491,9 @@ void DepsgraphRelationBuilder::build_id(ID *id)
|
|||
if (id == nullptr) {
|
||||
return;
|
||||
}
|
||||
switch (GS(id->name)) {
|
||||
|
||||
const ID_Type id_type = GS(id->name);
|
||||
switch (id_type) {
|
||||
case ID_AC:
|
||||
build_action((bAction *)id);
|
||||
break;
|
||||
|
@ -560,13 +569,40 @@ void DepsgraphRelationBuilder::build_id(ID *id)
|
|||
case ID_SIM:
|
||||
build_simulation((Simulation *)id);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unhandled ID %s\n", id->name);
|
||||
BLI_assert(!"Should never happen");
|
||||
case ID_PA:
|
||||
build_particle_settings((ParticleSettings *)id);
|
||||
break;
|
||||
case ID_GD:
|
||||
build_gpencil((bGPdata *)id);
|
||||
break;
|
||||
|
||||
case ID_LI:
|
||||
case ID_IP:
|
||||
case ID_SCR:
|
||||
case ID_VF:
|
||||
case ID_BR:
|
||||
case ID_WM:
|
||||
case ID_PAL:
|
||||
case ID_PC:
|
||||
case ID_WS:
|
||||
BLI_assert(!deg_copy_on_write_is_needed(id_type));
|
||||
build_generic_id(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DepsgraphRelationBuilder::build_generic_id(ID *id)
|
||||
{
|
||||
|
||||
if (built_map_.checkIsBuiltAndTag(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
build_idproperties(id->properties);
|
||||
build_animdata(id);
|
||||
build_parameters(id);
|
||||
}
|
||||
|
||||
static void build_idproperties_callback(IDProperty *id_property, void *user_data)
|
||||
{
|
||||
DepsgraphRelationBuilder *builder = reinterpret_cast<DepsgraphRelationBuilder *>(user_data);
|
||||
|
@ -712,6 +748,11 @@ void DepsgraphRelationBuilder::build_object(Object *object)
|
|||
if (object->particlesystem.first != nullptr) {
|
||||
build_particle_systems(object);
|
||||
}
|
||||
/* Force field Texture. */
|
||||
if ((object->pd != nullptr) && (object->pd->forcefield == PFIELD_TEXTURE) &&
|
||||
(object->pd->tex != nullptr)) {
|
||||
build_texture(object->pd->tex);
|
||||
}
|
||||
/* Proxy object to copy from. */
|
||||
build_object_proxy_from(object);
|
||||
build_object_proxy_group(object);
|
||||
|
@ -1725,6 +1766,11 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
|
|||
ComponentKey effector_geometry_key(&effector_relation->ob->id, NodeType::GEOMETRY);
|
||||
add_relation(effector_geometry_key, rb_init_key, "RigidBody Field");
|
||||
}
|
||||
if ((effector_relation->pd->forcefield == PFIELD_TEXTURE) &&
|
||||
(effector_relation->pd->tex != nullptr)) {
|
||||
ComponentKey tex_key(&effector_relation->pd->tex->id, NodeType::GENERIC_DATABLOCK);
|
||||
add_relation(tex_key, rb_init_key, "Force field Texture");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Objects. */
|
||||
|
|
|
@ -198,6 +198,9 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
|
|||
|
||||
virtual void build_id(ID *id);
|
||||
|
||||
/* Build function for ID types that do not need their own build_xxx() function. */
|
||||
virtual void build_generic_id(ID *id);
|
||||
|
||||
virtual void build_idproperties(IDProperty *id_property);
|
||||
|
||||
virtual void build_scene_render(Scene *scene, ViewLayer *view_layer);
|
||||
|
|
|
@ -142,6 +142,14 @@ static void clear_id_nodes_conditional(Depsgraph::IDDepsNodes *id_nodes, const F
|
|||
* datablock for her own dirty needs. */
|
||||
continue;
|
||||
}
|
||||
if (id_node->id_cow == id_node->id_orig) {
|
||||
/* Copy-on-write version is not needed for this ID type.
|
||||
*
|
||||
* NOTE: Is important to not de-reference the original datablock here because it might be
|
||||
* freed already (happens during main database free when some IDs are freed prior to a
|
||||
* scene). */
|
||||
continue;
|
||||
}
|
||||
if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -207,13 +207,15 @@ bool deg_iterator_components_step(BLI_Iterator *iter)
|
|||
if (component != nullptr) {
|
||||
const Volume *volume = component->get_for_read();
|
||||
|
||||
Object *temp_object = &data->temp_geometry_component_object;
|
||||
*temp_object = *data->geometry_component_owner;
|
||||
temp_object->type = OB_VOLUME;
|
||||
temp_object->data = (void *)volume;
|
||||
temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id;
|
||||
iter->current = temp_object;
|
||||
return true;
|
||||
if (volume != nullptr) {
|
||||
Object *temp_object = &data->temp_geometry_component_object;
|
||||
*temp_object = *data->geometry_component_owner;
|
||||
temp_object->type = OB_VOLUME;
|
||||
temp_object->data = (void *)volume;
|
||||
temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id;
|
||||
iter->current = temp_object;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -265,6 +265,10 @@ void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id)
|
|||
void depsgraph_id_tag_copy_on_write(Depsgraph *graph, IDNode *id_node, eUpdateSource update_source)
|
||||
{
|
||||
ComponentNode *cow_comp = id_node->find_component(NodeType::COPY_ON_WRITE);
|
||||
if (cow_comp == nullptr) {
|
||||
BLI_assert(!deg_copy_on_write_is_needed(GS(id_node->id_orig->name)));
|
||||
return;
|
||||
}
|
||||
cow_comp->tag_update(graph, update_source);
|
||||
}
|
||||
|
||||
|
|
|
@ -620,6 +620,15 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
|
|||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS);
|
||||
gpd->runtime.playing = (short)pd->playing;
|
||||
|
||||
/* When render in background the active frame could not be properly set due thread priority
|
||||
* better set again. This is not required in viewport. */
|
||||
if (txl->render_depth_tx) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
gpl->actframe = BKE_gpencil_layer_frame_get(gpl, pd->cfra, GP_GETFRAME_USE_PREV);
|
||||
}
|
||||
}
|
||||
|
||||
BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL,
|
||||
ob,
|
||||
gpencil_layer_cache_populate,
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
|
||||
uniform sampler2D depthBuf;
|
||||
uniform float strokeDepth2d;
|
||||
uniform bool strokeOrder3d;
|
||||
|
||||
noperspective in vec4 uvcoordsvar;
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = textureLod(depthBuf, uvcoordsvar.xy, 0).r;
|
||||
float depth = textureLod(depthBuf, gl_FragCoord.xy / vec2(textureSize(depthBuf, 0)), 0).r;
|
||||
if (strokeOrder3d) {
|
||||
gl_FragDepth = depth;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
uniform vec4 gpModelMatrix[4];
|
||||
|
||||
noperspective out vec4 uvcoordsvar;
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 model_matrix = mat4(gpModelMatrix[0], gpModelMatrix[1], gpModelMatrix[2], gpModelMatrix[3]);
|
||||
|
@ -10,5 +8,4 @@ void main()
|
|||
float x = -1.0 + float((v & 1) << 2);
|
||||
float y = -1.0 + float((v & 2) << 1);
|
||||
gl_Position = ViewProjectionMatrix * (model_matrix * vec4(x, y, 0.0, 1.0));
|
||||
uvcoordsvar = vec4((gl_Position.xy / gl_Position.w + 1.0) * 0.5, 0.0, 0.0);
|
||||
}
|
||||
|
|
|
@ -110,12 +110,6 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
|
|||
float face_alpha = (do_occlude_wire || !pd->edit_mesh.do_faces) ? 0.0f : 1.0f;
|
||||
GPUTexture **depth_tex = (pd->edit_mesh.do_zbufclip) ? &dtxl->depth : &txl->dummy_depth_tx;
|
||||
|
||||
if (select_face && !pd->edit_mesh.do_faces && pd->edit_mesh.do_edges) {
|
||||
/* Force display of face centers in this case because that's
|
||||
* the only way to see if a face is selected. */
|
||||
show_face_dots = true;
|
||||
}
|
||||
|
||||
/* Run Twice for in-front passes. */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
/* Complementary Depth Pass */
|
||||
|
|
|
@ -29,15 +29,17 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct bContext;
|
||||
struct bScreen;
|
||||
struct DEGEditorUpdateContext;
|
||||
struct Depsgraph;
|
||||
struct ID;
|
||||
struct MTex;
|
||||
struct Main;
|
||||
struct MTex;
|
||||
struct Render;
|
||||
struct Scene;
|
||||
struct ScrArea;
|
||||
struct bContext;
|
||||
struct bScreen;
|
||||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
|
||||
/* render_ops.c */
|
||||
|
@ -53,7 +55,11 @@ void ED_render_view_layer_changed(struct Main *bmain, struct bScreen *screen);
|
|||
/* Callbacks handling data update events coming from depsgraph. */
|
||||
|
||||
void ED_render_id_flush_update(const struct DEGEditorUpdateContext *update_ctx, struct ID *id);
|
||||
void ED_render_scene_update(const struct DEGEditorUpdateContext *update_ctx, int updated);
|
||||
void ED_render_scene_update(const struct DEGEditorUpdateContext *update_ctx, const bool updated);
|
||||
void ED_render_view3d_update(struct Depsgraph *depsgraph,
|
||||
struct wmWindow *window,
|
||||
struct ScrArea *area,
|
||||
const bool updated);
|
||||
|
||||
struct Scene *ED_render_job_get_scene(const struct bContext *C);
|
||||
struct Scene *ED_render_job_get_current_scene(const struct bContext *C);
|
||||
|
|
|
@ -789,7 +789,7 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but)
|
|||
BLI_assert(oldbut->active);
|
||||
|
||||
/* flags from the buttons we want to refresh, may want to add more here... */
|
||||
const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON;
|
||||
const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON | UI_SELECT_DRAW;
|
||||
const int drawflag_copy = 0; /* None currently. */
|
||||
|
||||
/* still stuff needs to be copied */
|
||||
|
@ -988,6 +988,11 @@ bool UI_but_active_only(const bContext *C, ARegion *region, uiBlock *block, uiBu
|
|||
*/
|
||||
bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *region, uiBlock *block)
|
||||
{
|
||||
|
||||
/* Running this command before end-block has run, means buttons that open menus
|
||||
* wont have those menus correctly positioned, see T83539. */
|
||||
BLI_assert(block->endblock != 0);
|
||||
|
||||
bool done = false;
|
||||
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
|
||||
if (but->flag & UI_BUT_ACTIVATE_ON_INIT) {
|
||||
|
@ -3194,6 +3199,7 @@ void ui_but_range_set_soft(uiBut *but)
|
|||
|
||||
if (but->rnaprop) {
|
||||
const PropertyType type = RNA_property_type(but->rnaprop);
|
||||
const PropertySubType subtype = RNA_property_subtype(but->rnaprop);
|
||||
double softmin, softmax /*, step, precision*/;
|
||||
double value_min;
|
||||
double value_max;
|
||||
|
@ -3217,7 +3223,7 @@ void ui_but_range_set_soft(uiBut *but)
|
|||
value_max = (double)value_range[1];
|
||||
}
|
||||
else {
|
||||
value_min = value_max = (double)RNA_property_int_get(&but->rnapoin, but->rnaprop);
|
||||
value_min = value_max = ui_but_value_get(but);
|
||||
}
|
||||
}
|
||||
else if (type == PROP_FLOAT) {
|
||||
|
@ -3230,14 +3236,15 @@ void ui_but_range_set_soft(uiBut *but)
|
|||
/*step = fstep;*/ /*UNUSED*/
|
||||
/*precision = fprecision;*/ /*UNUSED*/
|
||||
|
||||
if (is_array) {
|
||||
/* Use shared min/max for array values, except for color alpha. */
|
||||
if (is_array && !(subtype == PROP_COLOR && but->rnaindex == 3)) {
|
||||
float value_range[2];
|
||||
RNA_property_float_get_array_range(&but->rnapoin, but->rnaprop, value_range);
|
||||
value_min = (double)value_range[0];
|
||||
value_max = (double)value_range[1];
|
||||
}
|
||||
else {
|
||||
value_min = value_max = (double)RNA_property_float_get(&but->rnapoin, but->rnaprop);
|
||||
value_min = value_max = ui_but_value_get(but);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -4193,9 +4193,17 @@ static uiButExtraOpIcon *ui_but_extra_operator_icon_mouse_over_get(uiBut *but,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Same as in 'widget_draw_extra_icons', icon padding from the right edge. */
|
||||
xmax -= 0.2 * icon_size;
|
||||
|
||||
/* Handle the padding space from the right edge as the last button. */
|
||||
if (x > xmax) {
|
||||
return but->extra_op_icons.last;
|
||||
}
|
||||
|
||||
/* Inverse order, from right to left. */
|
||||
LISTBASE_FOREACH_BACKWARD (uiButExtraOpIcon *, op_icon, &but->extra_op_icons) {
|
||||
if ((x > (xmax - icon_size)) && x < xmax) {
|
||||
if ((x > (xmax - icon_size)) && x <= xmax) {
|
||||
return op_icon;
|
||||
}
|
||||
xmax -= icon_size;
|
||||
|
@ -9914,6 +9922,12 @@ static int ui_handle_menu_event(bContext *C,
|
|||
break;
|
||||
}
|
||||
|
||||
/* Only respond to explicit press to avoid the event that opened the menu
|
||||
* activating an item when the key is held. */
|
||||
if (event->is_repeat) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (event->alt) {
|
||||
act += 10;
|
||||
}
|
||||
|
@ -9993,8 +10007,11 @@ static int ui_handle_menu_event(bContext *C,
|
|||
case EVT_XKEY:
|
||||
case EVT_YKEY:
|
||||
case EVT_ZKEY: {
|
||||
if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
|
||||
!IS_EVENT_MOD(event, shift, ctrl, oskey)) {
|
||||
if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK) &&
|
||||
!IS_EVENT_MOD(event, shift, ctrl, oskey) &&
|
||||
/* Only respond to explicit press to avoid the event that opened the menu
|
||||
* activating an item when the key is held. */
|
||||
!event->is_repeat) {
|
||||
if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval)) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1119,10 +1119,9 @@ static void panel_draw_highlight_border(const Panel *panel,
|
|||
radius = 0.0f;
|
||||
}
|
||||
|
||||
/* Abuse the property search theme color for now. */
|
||||
float color[4];
|
||||
UI_GetThemeColor4fv(TH_MATCH, color);
|
||||
UI_draw_roundbox_aa(
|
||||
UI_GetThemeColor4fv(TH_SELECT_ACTIVE, color);
|
||||
UI_draw_roundbox_4fv(
|
||||
&(const rctf){
|
||||
.xmin = rect->xmin,
|
||||
.xmax = rect->xmax,
|
||||
|
|
|
@ -2254,20 +2254,33 @@ static void widget_draw_extra_icons(const uiWidgetColors *wcol,
|
|||
rcti *rect,
|
||||
float alpha)
|
||||
{
|
||||
/* inverse order, from right to left. */
|
||||
const float icon_size = ICON_SIZE_FROM_BUTRECT(rect);
|
||||
|
||||
/* Offset of icons from the right edge. Keep in sync
|
||||
with 'ui_but_extra_operator_icon_mouse_over_get'. */
|
||||
if (!BLI_listbase_is_empty(&but->extra_op_icons)) {
|
||||
/* Eyeballed. */
|
||||
rect->xmax -= 0.2 * icon_size;
|
||||
}
|
||||
|
||||
/* Inverse order, from right to left. */
|
||||
LISTBASE_FOREACH_BACKWARD (uiButExtraOpIcon *, op_icon, &but->extra_op_icons) {
|
||||
rcti temp = *rect;
|
||||
float alpha_this = alpha;
|
||||
|
||||
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
|
||||
temp.xmin = temp.xmax - icon_size;
|
||||
|
||||
if (!op_icon->highlighted) {
|
||||
alpha_this *= 0.75f;
|
||||
}
|
||||
|
||||
/* Draw the icon at the center, and restore the flags after. */
|
||||
const int old_drawflags = but->drawflag;
|
||||
UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT);
|
||||
widget_draw_icon(but, op_icon->icon, alpha_this, &temp, wcol->text);
|
||||
but->drawflag = old_drawflags;
|
||||
|
||||
rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
|
||||
rect->xmax -= icon_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ typedef struct SlidePointData {
|
|||
|
||||
bool is_sliding_new_point;
|
||||
|
||||
/* Data needed to restre the state. */
|
||||
/* Data needed to restore the state. */
|
||||
float vec[3][3];
|
||||
char old_h1, old_h2;
|
||||
|
||||
|
@ -863,7 +863,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
if (event->type == data->event_invoke_type && event->val == KM_RELEASE) {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* dont key sliding feather uw's */
|
||||
/* Don't key sliding feather UW's. */
|
||||
if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == false) {
|
||||
if (IS_AUTOKEY_ON(scene)) {
|
||||
ED_mask_layer_shape_auto_key(data->mask_layer, CFRA);
|
||||
|
@ -1053,7 +1053,7 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C,
|
|||
slide_data->bezt_backup = *slide_data->adjust_bezt;
|
||||
slide_data->other_bezt_backup = *slide_data->other_bezt;
|
||||
|
||||
/* Let's dont touch other side of the point for now, so set handle to FREE. */
|
||||
/* Let's don't touch other side of the point for now, so set handle to FREE. */
|
||||
if (u < 0.5f) {
|
||||
if (slide_data->adjust_bezt->h2 <= HD_VECT) {
|
||||
slide_data->adjust_bezt->h2 = HD_FREE;
|
||||
|
@ -1270,7 +1270,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
|
|||
case LEFTMOUSE:
|
||||
case RIGHTMOUSE:
|
||||
if (event->type == slide_data->event_invoke_type && event->val == KM_RELEASE) {
|
||||
/* dont key sliding feather uw's */
|
||||
/* Don't key sliding feather UW's. */
|
||||
if (IS_AUTOKEY_ON(scene)) {
|
||||
ED_mask_layer_shape_auto_key(slide_data->mask_layer, CFRA);
|
||||
}
|
||||
|
|
|
@ -200,6 +200,11 @@ static bool check_engine_supports_preview(Scene *scene)
|
|||
return (type->flag & RE_USE_PREVIEW) != 0;
|
||||
}
|
||||
|
||||
static bool preview_method_is_render(int pr_method)
|
||||
{
|
||||
return ELEM(pr_method, PR_ICON_RENDER, PR_BUTS_RENDER, PR_NODE_RENDER);
|
||||
}
|
||||
|
||||
void ED_preview_free_dbase(void)
|
||||
{
|
||||
if (G_pr_main) {
|
||||
|
@ -1352,13 +1357,12 @@ static void common_preview_startjob(void *customdata,
|
|||
*/
|
||||
static void other_id_types_preview_render(IconPreview *ip,
|
||||
IconPreviewSize *cur_size,
|
||||
const bool is_deferred,
|
||||
const int pr_method,
|
||||
short *stop,
|
||||
short *do_update,
|
||||
float *progress)
|
||||
{
|
||||
ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
|
||||
const bool is_render = !is_deferred;
|
||||
|
||||
/* These types don't use the ShaderPreview mess, they have their own types and functions. */
|
||||
BLI_assert(!ip->id || !ELEM(GS(ip->id->name), ID_OB));
|
||||
|
@ -1368,7 +1372,7 @@ static void other_id_types_preview_render(IconPreview *ip,
|
|||
sp->owner = ip->owner;
|
||||
sp->sizex = cur_size->sizex;
|
||||
sp->sizey = cur_size->sizey;
|
||||
sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
|
||||
sp->pr_method = pr_method;
|
||||
sp->pr_rect = cur_size->rect;
|
||||
sp->id = ip->id;
|
||||
sp->id_copy = ip->id_copy;
|
||||
|
@ -1376,7 +1380,7 @@ static void other_id_types_preview_render(IconPreview *ip,
|
|||
sp->own_id_copy = false;
|
||||
Material *ma = NULL;
|
||||
|
||||
if (is_render) {
|
||||
if (sp->pr_method == PR_ICON_RENDER) {
|
||||
BLI_assert(ip->id);
|
||||
|
||||
/* grease pencil use its own preview file */
|
||||
|
@ -1424,6 +1428,8 @@ static void icon_preview_startjob_all_sizes(void *customdata,
|
|||
|
||||
for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
|
||||
PreviewImage *prv = ip->owner;
|
||||
/* Is this a render job or a deferred loading job? */
|
||||
const int pr_method = (prv->tag & PRV_TAG_DEFFERED) ? PR_ICON_DEFERRED : PR_ICON_RENDER;
|
||||
|
||||
if (*stop) {
|
||||
break;
|
||||
|
@ -1434,7 +1440,7 @@ static void icon_preview_startjob_all_sizes(void *customdata,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!check_engine_supports_preview(ip->scene)) {
|
||||
if (preview_method_is_render(pr_method) && !check_engine_supports_preview(ip->scene)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1450,8 +1456,7 @@ static void icon_preview_startjob_all_sizes(void *customdata,
|
|||
object_preview_render(ip, cur_size);
|
||||
}
|
||||
else {
|
||||
other_id_types_preview_render(
|
||||
ip, cur_size, (prv->tag & PRV_TAG_DEFFERED), stop, do_update, progress);
|
||||
other_id_types_preview_render(ip, cur_size, pr_method, stop, do_update, progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1634,7 +1639,7 @@ void ED_preview_shader_job(const bContext *C,
|
|||
/* Use workspace render only for buttons Window,
|
||||
* since the other previews are related to the datablock. */
|
||||
|
||||
if (!check_engine_supports_preview(scene)) {
|
||||
if (preview_method_is_render(method) && !check_engine_supports_preview(scene)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,23 +61,79 @@
|
|||
#include "ED_view3d.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "render_intern.h" /* own include */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/***************************** Render Engines ********************************/
|
||||
|
||||
void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int updated)
|
||||
/* Update 3D viewport render or draw engine on changes to the scene or view settings . */
|
||||
void ED_render_view3d_update(Depsgraph *depsgraph,
|
||||
wmWindow *window,
|
||||
ScrArea *area,
|
||||
const bool updated)
|
||||
{
|
||||
Main *bmain = DEG_get_bmain(depsgraph);
|
||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
|
||||
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
if (region->regiontype != RGN_TYPE_WINDOW) {
|
||||
continue;
|
||||
}
|
||||
|
||||
View3D *v3d = area->spacedata.first;
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
RenderEngine *engine = rv3d->render_engine;
|
||||
|
||||
/* call update if the scene changed, or if the render engine
|
||||
* tagged itself for update (e.g. because it was busy at the
|
||||
* time of the last update) */
|
||||
if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) {
|
||||
/* Create temporary context to execute callback in. */
|
||||
bContext *C = CTX_create();
|
||||
CTX_data_main_set(C, bmain);
|
||||
CTX_data_scene_set(C, scene);
|
||||
CTX_wm_manager_set(C, bmain->wm.first);
|
||||
CTX_wm_window_set(C, window);
|
||||
CTX_wm_screen_set(C, WM_window_get_active_screen(window));
|
||||
CTX_wm_area_set(C, area);
|
||||
CTX_wm_region_set(C, region);
|
||||
|
||||
engine->flag &= ~RE_ENGINE_DO_UPDATE;
|
||||
/* NOTE: Important to pass non-updated depsgraph, This is because this function is called
|
||||
* from inside dependency graph evaluation. Additionally, if we pass fully evaluated one
|
||||
* we will lose updates stored in the graph. */
|
||||
engine->type->view_update(engine, C, CTX_data_depsgraph_pointer(C));
|
||||
|
||||
CTX_free(C);
|
||||
}
|
||||
else {
|
||||
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
|
||||
if (updated) {
|
||||
DRW_notify_view_update((&(DRWUpdateContext){
|
||||
.bmain = bmain,
|
||||
.depsgraph = depsgraph,
|
||||
.scene = scene,
|
||||
.view_layer = view_layer,
|
||||
.region = region,
|
||||
.v3d = v3d,
|
||||
.engine_type = engine_type,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update all 3D viewport render and draw engines on changes to the scene.
|
||||
* This is called by the dependency graph when it detects changes. */
|
||||
void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, const bool updated)
|
||||
{
|
||||
/* viewport rendering update on data changes, happens after depsgraph
|
||||
* updates if there was any change. context is set to the 3d view */
|
||||
Main *bmain = update_ctx->bmain;
|
||||
Scene *scene = update_ctx->scene;
|
||||
ViewLayer *view_layer = update_ctx->view_layer;
|
||||
bContext *C;
|
||||
wmWindowManager *wm;
|
||||
wmWindow *win;
|
||||
static bool recursive_check = false;
|
||||
|
||||
/* don't do this render engine update if we're updating the scene from
|
||||
|
@ -98,66 +154,17 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int update
|
|||
|
||||
recursive_check = true;
|
||||
|
||||
C = CTX_create();
|
||||
CTX_data_main_set(C, bmain);
|
||||
CTX_data_scene_set(C, scene);
|
||||
wmWindowManager *wm = bmain->wm.first;
|
||||
LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
|
||||
bScreen *screen = WM_window_get_active_screen(window);
|
||||
|
||||
CTX_wm_manager_set(C, bmain->wm.first);
|
||||
wm = bmain->wm.first;
|
||||
|
||||
for (win = wm->windows.first; win; win = win->next) {
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
ScrArea *area;
|
||||
ARegion *region;
|
||||
|
||||
CTX_wm_window_set(C, win);
|
||||
|
||||
for (area = screen->areabase.first; area; area = area->next) {
|
||||
if (area->spacetype != SPACE_VIEW3D) {
|
||||
continue;
|
||||
}
|
||||
View3D *v3d = area->spacedata.first;
|
||||
for (region = area->regionbase.first; region; region = region->next) {
|
||||
if (region->regiontype != RGN_TYPE_WINDOW) {
|
||||
continue;
|
||||
}
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
RenderEngine *engine = rv3d->render_engine;
|
||||
/* call update if the scene changed, or if the render engine
|
||||
* tagged itself for update (e.g. because it was busy at the
|
||||
* time of the last update) */
|
||||
if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) {
|
||||
|
||||
CTX_wm_screen_set(C, screen);
|
||||
CTX_wm_area_set(C, area);
|
||||
CTX_wm_region_set(C, region);
|
||||
|
||||
engine->flag &= ~RE_ENGINE_DO_UPDATE;
|
||||
/* NOTE: Important to pass non-updated depsgraph, This is because this function is called
|
||||
* from inside dependency graph evaluation. Additionally, if we pass fully evaluated one
|
||||
* we will lose updates stored in the graph. */
|
||||
engine->type->view_update(engine, C, CTX_data_depsgraph_pointer(C));
|
||||
}
|
||||
else {
|
||||
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
|
||||
if (updated) {
|
||||
DRW_notify_view_update((&(DRWUpdateContext){
|
||||
.bmain = bmain,
|
||||
.depsgraph = update_ctx->depsgraph,
|
||||
.scene = scene,
|
||||
.view_layer = view_layer,
|
||||
.region = region,
|
||||
.v3d = (View3D *)area->spacedata.first,
|
||||
.engine_type = engine_type,
|
||||
}));
|
||||
}
|
||||
}
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
if (area->spacetype == SPACE_VIEW3D) {
|
||||
ED_render_view3d_update(update_ctx->depsgraph, window, area, updated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTX_free(C);
|
||||
|
||||
recursive_check = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,8 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y);
|
|||
bool clip_view_calculate_view_selection(
|
||||
const struct bContext *C, bool fit, float *r_offset_x, float *r_offset_y, float *r_zoom);
|
||||
|
||||
bool clip_view_has_locked_selection(const struct bContext *C);
|
||||
|
||||
void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene);
|
||||
|
||||
/* tracking_ops.c */
|
||||
|
|
|
@ -125,7 +125,7 @@ static void sclip_zoom_set(const bContext *C,
|
|||
dx = ((location[0] - 0.5f) * w - sc->xof) * (sc->zoom - oldzoom) / sc->zoom;
|
||||
dy = ((location[1] - 0.5f) * h - sc->yof) * (sc->zoom - oldzoom) / sc->zoom;
|
||||
|
||||
if (sc->flag & SC_LOCK_SELECTION) {
|
||||
if (clip_view_has_locked_selection(C)) {
|
||||
sc->xlockof += dx;
|
||||
sc->ylockof += dy;
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
vpd->x = event->x;
|
||||
vpd->y = event->y;
|
||||
|
||||
if (sc->flag & SC_LOCK_SELECTION) {
|
||||
if (clip_view_has_locked_selection(C)) {
|
||||
vpd->vec = &sc->xlockof;
|
||||
}
|
||||
else {
|
||||
|
@ -434,7 +434,7 @@ static int view_pan_exec(bContext *C, wmOperator *op)
|
|||
|
||||
RNA_float_get_array(op->ptr, "offset", offset);
|
||||
|
||||
if (sc->flag & SC_LOCK_SELECTION) {
|
||||
if (clip_view_has_locked_selection(C)) {
|
||||
sc->xlockof += offset[0];
|
||||
sc->ylockof += offset[1];
|
||||
}
|
||||
|
|
|
@ -465,6 +465,68 @@ static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2]
|
|||
return ok;
|
||||
}
|
||||
|
||||
static bool tracking_has_selection(SpaceClip *space_clip)
|
||||
{
|
||||
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
||||
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
|
||||
const int framenr = ED_space_clip_get_clip_frame_number(space_clip);
|
||||
|
||||
LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
|
||||
if (!TRACK_VIEW_SELECTED(space_clip, track)) {
|
||||
continue;
|
||||
}
|
||||
const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
|
||||
if (marker != NULL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool mask_has_selection(const bContext *C, bool include_handles)
|
||||
{
|
||||
Mask *mask = CTX_data_edit_mask(C);
|
||||
if (mask == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
|
||||
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
|
||||
for (int i = 0; i < spline->tot_point; i++) {
|
||||
const MaskSplinePoint *point = &spline->points[i];
|
||||
const BezTriple *bezt = &point->bezt;
|
||||
if (!MASKPOINT_ISSEL_ANY(point)) {
|
||||
continue;
|
||||
}
|
||||
if (bezt->f2 & SELECT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!include_handles) {
|
||||
/* Ignore handles. */
|
||||
}
|
||||
else if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) {
|
||||
return true;
|
||||
}
|
||||
if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool selected_boundbox(const bContext *C, float min[2], float max[2], bool include_handles)
|
||||
{
|
||||
SpaceClip *sc = CTX_wm_space_clip(C);
|
||||
|
@ -546,6 +608,23 @@ bool clip_view_calculate_view_selection(
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Returns truth if lock-to-selection is enabled and possible.
|
||||
* Locking to selection is not possible if there is no selection. */
|
||||
bool clip_view_has_locked_selection(const bContext *C)
|
||||
{
|
||||
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
||||
|
||||
if ((space_clip->flag & SC_LOCK_SELECTION) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (space_clip->mode == SC_MODE_TRACKING) {
|
||||
return tracking_has_selection(space_clip);
|
||||
}
|
||||
|
||||
return mask_has_selection(C, false);
|
||||
}
|
||||
|
||||
void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
|
||||
{
|
||||
UI_view2d_view_ortho(v2d);
|
||||
|
|
|
@ -243,8 +243,6 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
changed = true;
|
||||
}
|
||||
}
|
||||
/* Nothing selected now, unlock view so it can be scrolled nice again. */
|
||||
sc->flag &= ~SC_LOCK_SELECTION;
|
||||
if (changed) {
|
||||
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
||||
}
|
||||
|
@ -313,11 +311,6 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
}
|
||||
}
|
||||
|
||||
if (!has_selection) {
|
||||
/* Nothing selected now, unlock view so it can be scrolled nice again. */
|
||||
sc->flag &= ~SC_LOCK_SELECTION;
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@ -1224,13 +1217,6 @@ static int hide_tracks_exec(bContext *C, wmOperator *op)
|
|||
clip->tracking.act_plane_track = NULL;
|
||||
}
|
||||
|
||||
if (unselected == 0) {
|
||||
/* No selection on screen now, unlock view so it can be
|
||||
* scrolled nice again.
|
||||
*/
|
||||
sc->flag &= ~SC_LOCK_SELECTION;
|
||||
}
|
||||
|
||||
BKE_tracking_dopesheet_tag_update(tracking);
|
||||
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
|
||||
|
||||
|
|
|
@ -875,10 +875,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
|
|||
bool has_selection = false;
|
||||
ED_clip_select_all(sc, action, &has_selection);
|
||||
|
||||
if (!has_selection) {
|
||||
sc->flag &= ~SC_LOCK_SELECTION;
|
||||
}
|
||||
else {
|
||||
if (has_selection) {
|
||||
ED_clip_view_lock_state_restore_no_jump(C, &lock_state);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,8 +167,6 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner)
|
|||
static void check_persistent(
|
||||
SpaceOutliner *space_outliner, TreeElement *te, ID *id, short type, short nr)
|
||||
{
|
||||
TreeStoreElem *tselem;
|
||||
|
||||
if (space_outliner->treestore == NULL) {
|
||||
/* if treestore was not created in readfile.c, create it here */
|
||||
space_outliner->treestore = BLI_mempool_create(
|
||||
|
@ -181,7 +179,8 @@ static void check_persistent(
|
|||
|
||||
/* find any unused tree element in treestore and mark it as used
|
||||
* (note that there may be multiple unused elements in case of linked objects) */
|
||||
tselem = BKE_outliner_treehash_lookup_unused(space_outliner->runtime->treehash, type, nr, id);
|
||||
TreeStoreElem *tselem = BKE_outliner_treehash_lookup_unused(
|
||||
space_outliner->runtime->treehash, type, nr, id);
|
||||
if (tselem) {
|
||||
te->store_elem = tselem;
|
||||
tselem->used = 1;
|
||||
|
@ -204,8 +203,7 @@ static void check_persistent(
|
|||
|
||||
void outliner_free_tree(ListBase *tree)
|
||||
{
|
||||
for (TreeElement *element = tree->first, *element_next; element; element = element_next) {
|
||||
element_next = element->next;
|
||||
LISTBASE_FOREACH_MUTABLE (TreeElement *, element, tree) {
|
||||
outliner_free_tree_element(element, tree);
|
||||
}
|
||||
}
|
||||
|
@ -271,8 +269,8 @@ static void outliner_add_bone(SpaceOutliner *space_outliner,
|
|||
te->name = curBone->name;
|
||||
te->directdata = curBone;
|
||||
|
||||
for (curBone = curBone->childbase.first; curBone; curBone = curBone->next) {
|
||||
outliner_add_bone(space_outliner, &te->subtree, id, curBone, te, a);
|
||||
LISTBASE_FOREACH (Bone *, child_bone, &curBone->childbase) {
|
||||
outliner_add_bone(space_outliner, &te->subtree, id, child_bone, te, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,35 +379,30 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
|
|||
|
||||
if (ob->pose) {
|
||||
bArmature *arm = ob->data;
|
||||
bPoseChannel *pchan;
|
||||
TreeElement *tenla = outliner_add_element(
|
||||
space_outliner, &te->subtree, ob, te, TSE_POSE_BASE, 0);
|
||||
|
||||
tenla->name = IFACE_("Pose");
|
||||
|
||||
/* channels undefined in editmode, but we want the 'tenla' pose icon itself */
|
||||
if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) {
|
||||
TreeElement *ten;
|
||||
int a = 0, const_index = 1000; /* ensure unique id for bone constraints */
|
||||
|
||||
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next, a++) {
|
||||
ten = outliner_add_element(
|
||||
int const_index = 1000; /* ensure unique id for bone constraints */
|
||||
int a;
|
||||
LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, a) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
space_outliner, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a);
|
||||
ten->name = pchan->name;
|
||||
ten->directdata = pchan;
|
||||
pchan->temp = (void *)ten;
|
||||
|
||||
if (pchan->constraints.first) {
|
||||
if (!BLI_listbase_is_empty(&pchan->constraints)) {
|
||||
/* Object *target; */
|
||||
bConstraint *con;
|
||||
TreeElement *ten1;
|
||||
TreeElement *tenla1 = outliner_add_element(
|
||||
space_outliner, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0);
|
||||
tenla1->name = IFACE_("Constraints");
|
||||
/* char *str; */
|
||||
|
||||
tenla1->name = IFACE_("Constraints");
|
||||
for (con = pchan->constraints.first; con; con = con->next, const_index++) {
|
||||
ten1 = outliner_add_element(
|
||||
LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
|
||||
TreeElement *ten1 = outliner_add_element(
|
||||
space_outliner, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index);
|
||||
#if 0 /* disabled as it needs to be reworked for recoded constraints system */
|
||||
target = get_constraint_target(con, &str);
|
||||
|
@ -427,15 +420,16 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
|
|||
ten1->directdata = con;
|
||||
/* possible add all other types links? */
|
||||
}
|
||||
const_index++;
|
||||
}
|
||||
}
|
||||
/* make hierarchy */
|
||||
ten = tenla->subtree.first;
|
||||
TreeElement *ten = tenla->subtree.first;
|
||||
while (ten) {
|
||||
TreeElement *nten = ten->next, *par;
|
||||
tselem = TREESTORE(ten);
|
||||
if (tselem->type == TSE_POSE_CHANNEL) {
|
||||
pchan = (bPoseChannel *)ten->directdata;
|
||||
bPoseChannel *pchan = (bPoseChannel *)ten->directdata;
|
||||
if (pchan->parent) {
|
||||
BLI_remlink(&tenla->subtree, ten);
|
||||
par = (TreeElement *)pchan->parent->temp;
|
||||
|
@ -448,17 +442,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
|
||||
/* Pose Groups */
|
||||
if (ob->pose->agroups.first) {
|
||||
bActionGroup *agrp;
|
||||
if (!BLI_listbase_is_empty(&ob->pose->agroups)) {
|
||||
TreeElement *ten_bonegrp = outliner_add_element(
|
||||
space_outliner, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0);
|
||||
int a = 0;
|
||||
|
||||
ten_bonegrp->name = IFACE_("Bone Groups");
|
||||
for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) {
|
||||
TreeElement *ten;
|
||||
ten = outliner_add_element(
|
||||
space_outliner, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, a);
|
||||
|
||||
int index;
|
||||
LISTBASE_FOREACH_INDEX (bActionGroup *, agrp, &ob->pose->agroups, index) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
space_outliner, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, index);
|
||||
ten->name = agrp->name;
|
||||
ten->directdata = agrp;
|
||||
}
|
||||
|
@ -469,18 +461,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
|
|||
outliner_add_element(space_outliner, &te->subtree, ob->mat[a], te, 0, a);
|
||||
}
|
||||
|
||||
if (ob->constraints.first) {
|
||||
/* Object *target; */
|
||||
bConstraint *con;
|
||||
TreeElement *ten;
|
||||
if (!BLI_listbase_is_empty(&ob->constraints)) {
|
||||
TreeElement *tenla = outliner_add_element(
|
||||
space_outliner, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0);
|
||||
/* char *str; */
|
||||
int a;
|
||||
|
||||
tenla->name = IFACE_("Constraints");
|
||||
for (con = ob->constraints.first, a = 0; con; con = con->next, a++) {
|
||||
ten = outliner_add_element(space_outliner, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a);
|
||||
|
||||
int index;
|
||||
LISTBASE_FOREACH_INDEX (bConstraint *, con, &ob->constraints, index) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
space_outliner, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, index);
|
||||
#if 0 /* disabled due to constraints system targets recode... code here needs review */
|
||||
target = get_constraint_target(con, &str);
|
||||
if (str && str[0]) {
|
||||
|
@ -499,14 +488,13 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
}
|
||||
|
||||
if (ob->modifiers.first) {
|
||||
ModifierData *md;
|
||||
if (!BLI_listbase_is_empty(&ob->modifiers)) {
|
||||
TreeElement *ten_mod = outliner_add_element(
|
||||
space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0);
|
||||
int index;
|
||||
|
||||
ten_mod->name = IFACE_("Modifiers");
|
||||
for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) {
|
||||
|
||||
int index;
|
||||
LISTBASE_FOREACH_INDEX (ModifierData *, md, &ob->modifiers, index) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
space_outliner, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index);
|
||||
ten->name = md->name;
|
||||
|
@ -559,8 +547,8 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
|
|||
if (!BLI_listbase_is_empty(&ob->greasepencil_modifiers)) {
|
||||
TreeElement *ten_mod = outliner_add_element(
|
||||
space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0);
|
||||
|
||||
ten_mod->name = IFACE_("Modifiers");
|
||||
|
||||
int index;
|
||||
LISTBASE_FOREACH_INDEX (GpencilModifierData *, md, &ob->greasepencil_modifiers, index) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
|
@ -599,8 +587,8 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
|
|||
if (!BLI_listbase_is_empty(&ob->shader_fx)) {
|
||||
TreeElement *ten_fx = outliner_add_element(
|
||||
space_outliner, &te->subtree, ob, te, TSE_GPENCIL_EFFECT_BASE, 0);
|
||||
|
||||
ten_fx->name = IFACE_("Effects");
|
||||
|
||||
int index;
|
||||
LISTBASE_FOREACH_INDEX (ShaderFxData *, fx, &ob->shader_fx, index) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
|
@ -620,16 +608,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
|
||||
/* vertex groups */
|
||||
if (ob->defbase.first) {
|
||||
bDeformGroup *defgroup;
|
||||
TreeElement *ten;
|
||||
if (!BLI_listbase_is_empty(&ob->defbase)) {
|
||||
TreeElement *tenla = outliner_add_element(
|
||||
space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
|
||||
int a;
|
||||
|
||||
tenla->name = IFACE_("Vertex Groups");
|
||||
for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) {
|
||||
ten = outliner_add_element(space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a);
|
||||
|
||||
int index;
|
||||
LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, &ob->defbase, index) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index);
|
||||
ten->name = defgroup->name;
|
||||
ten->directdata = defgroup;
|
||||
}
|
||||
|
@ -694,14 +681,13 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_ME: {
|
||||
Mesh *me = (Mesh *)id;
|
||||
int a;
|
||||
|
||||
if (outliner_animdata_test(me->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, me, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
||||
outliner_add_element(space_outliner, &te->subtree, me->key, te, 0, 0);
|
||||
for (a = 0; a < me->totcol; a++) {
|
||||
for (int a = 0; a < me->totcol; a++) {
|
||||
outliner_add_element(space_outliner, &te->subtree, me->mat[a], te, 0, a);
|
||||
}
|
||||
/* could do tfaces with image links, but the images are not grouped nicely.
|
||||
|
@ -710,33 +696,30 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_CU: {
|
||||
Curve *cu = (Curve *)id;
|
||||
int a;
|
||||
|
||||
if (outliner_animdata_test(cu->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, cu, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
||||
for (a = 0; a < cu->totcol; a++) {
|
||||
for (int a = 0; a < cu->totcol; a++) {
|
||||
outliner_add_element(space_outliner, &te->subtree, cu->mat[a], te, 0, a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ID_MB: {
|
||||
MetaBall *mb = (MetaBall *)id;
|
||||
int a;
|
||||
|
||||
if (outliner_animdata_test(mb->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, mb, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
||||
for (a = 0; a < mb->totcol; a++) {
|
||||
for (int a = 0; a < mb->totcol; a++) {
|
||||
outliner_add_element(space_outliner, &te->subtree, mb->mat[a], te, 0, a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ID_MA: {
|
||||
Material *ma = (Material *)id;
|
||||
|
||||
if (outliner_animdata_test(ma->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, ma, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -744,7 +727,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_TE: {
|
||||
Tex *tex = (Tex *)id;
|
||||
|
||||
if (outliner_animdata_test(tex->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, tex, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -753,7 +735,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_CA: {
|
||||
Camera *ca = (Camera *)id;
|
||||
|
||||
if (outliner_animdata_test(ca->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, ca, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -761,7 +742,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_CF: {
|
||||
CacheFile *cache_file = (CacheFile *)id;
|
||||
|
||||
if (outliner_animdata_test(cache_file->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -770,7 +750,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_LA: {
|
||||
Light *la = (Light *)id;
|
||||
|
||||
if (outliner_animdata_test(la->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, la, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -778,7 +757,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_SPK: {
|
||||
Speaker *spk = (Speaker *)id;
|
||||
|
||||
if (outliner_animdata_test(spk->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, spk, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -786,7 +764,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_LP: {
|
||||
LightProbe *prb = (LightProbe *)id;
|
||||
|
||||
if (outliner_animdata_test(prb->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, prb, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -794,7 +771,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_WO: {
|
||||
World *wrld = (World *)id;
|
||||
|
||||
if (outliner_animdata_test(wrld->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, wrld, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -802,7 +778,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_KE: {
|
||||
Key *key = (Key *)id;
|
||||
|
||||
if (outliner_animdata_test(key->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, key, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
@ -815,27 +790,25 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_AR: {
|
||||
bArmature *arm = (bArmature *)id;
|
||||
int a = 0;
|
||||
|
||||
if (outliner_animdata_test(arm->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, arm, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
||||
if (arm->edbo) {
|
||||
EditBone *ebone;
|
||||
TreeElement *ten;
|
||||
|
||||
for (ebone = arm->edbo->first; ebone; ebone = ebone->next, a++) {
|
||||
ten = outliner_add_element(space_outliner, &te->subtree, id, te, TSE_EBONE, a);
|
||||
int a = 0;
|
||||
LISTBASE_FOREACH_INDEX (EditBone *, ebone, arm->edbo, a) {
|
||||
TreeElement *ten = outliner_add_element(
|
||||
space_outliner, &te->subtree, id, te, TSE_EBONE, a);
|
||||
ten->directdata = ebone;
|
||||
ten->name = ebone->name;
|
||||
ebone->temp.p = ten;
|
||||
}
|
||||
/* make hierarchy */
|
||||
ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL;
|
||||
TreeElement *ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL;
|
||||
while (ten) {
|
||||
TreeElement *nten = ten->next, *par;
|
||||
ebone = (EditBone *)ten->directdata;
|
||||
EditBone *ebone = (EditBone *)ten->directdata;
|
||||
if (ebone->parent) {
|
||||
BLI_remlink(&te->subtree, ten);
|
||||
par = ebone->parent->temp.p;
|
||||
|
@ -852,9 +825,9 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
/* pass */
|
||||
}
|
||||
else {
|
||||
Bone *curBone;
|
||||
for (curBone = arm->bonebase.first; curBone; curBone = curBone->next) {
|
||||
outliner_add_bone(space_outliner, &te->subtree, id, curBone, te, &a);
|
||||
int a = 0;
|
||||
LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
|
||||
outliner_add_bone(space_outliner, &te->subtree, id, bone, te, &a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -862,13 +835,12 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_LS: {
|
||||
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id;
|
||||
int a;
|
||||
|
||||
if (outliner_animdata_test(linestyle->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
||||
for (a = 0; a < MAX_MTEX; a++) {
|
||||
for (int a = 0; a < MAX_MTEX; a++) {
|
||||
if (linestyle->mtex[a]) {
|
||||
outliner_add_element(space_outliner, &te->subtree, linestyle->mtex[a]->tex, te, 0, a);
|
||||
}
|
||||
|
@ -877,17 +849,16 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
}
|
||||
case ID_GD: {
|
||||
bGPdata *gpd = (bGPdata *)id;
|
||||
bGPDlayer *gpl;
|
||||
int a = 0;
|
||||
|
||||
if (outliner_animdata_test(gpd->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, gpd, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
||||
/* TODO: base element for layers? */
|
||||
for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
|
||||
outliner_add_element(space_outliner, &te->subtree, gpl, te, TSE_GP_LAYER, a);
|
||||
a++;
|
||||
int index = 0;
|
||||
LISTBASE_FOREACH_BACKWARD (bGPDlayer *, gpl, &gpd->layers) {
|
||||
outliner_add_element(space_outliner, &te->subtree, gpl, te, TSE_GP_LAYER, index);
|
||||
index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -957,8 +928,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
short type,
|
||||
short index)
|
||||
{
|
||||
TreeElement *te;
|
||||
TreeStoreElem *tselem;
|
||||
ID *id = idv;
|
||||
|
||||
if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
|
||||
|
@ -985,12 +954,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
BLI_assert(TREESTORE_ID_TYPE(id));
|
||||
}
|
||||
|
||||
te = MEM_callocN(sizeof(TreeElement), "tree elem");
|
||||
TreeElement *te = MEM_callocN(sizeof(TreeElement), __func__);
|
||||
/* add to the visual tree */
|
||||
BLI_addtail(lb, te);
|
||||
/* add to the storage */
|
||||
check_persistent(space_outliner, te, id, type, index);
|
||||
tselem = TREESTORE(te);
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
/* if we are searching for something expand to see child elements */
|
||||
if (SEARCHING_OUTLINER(space_outliner)) {
|
||||
|
@ -1062,7 +1031,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
}
|
||||
else if (type == TSE_SEQUENCE) {
|
||||
Sequence *seq = (Sequence *)idv;
|
||||
Sequence *p;
|
||||
|
||||
/*
|
||||
* The idcode is a little hack, but the outliner
|
||||
|
@ -1081,10 +1049,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
*/
|
||||
|
||||
if (seq->type == SEQ_TYPE_META) {
|
||||
p = seq->seqbase.first;
|
||||
while (p) {
|
||||
LISTBASE_FOREACH (Sequence *, p, &seq->seqbase) {
|
||||
outliner_add_element(space_outliner, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1112,17 +1078,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
te->name = seq->strip->stripdata->name;
|
||||
}
|
||||
else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
|
||||
PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv;
|
||||
PropertyRNA *prop, *iterprop;
|
||||
PropertyType proptype;
|
||||
PointerRNA *ptr = (PointerRNA *)idv;
|
||||
|
||||
/* Don't display arrays larger, weak but index is stored as a short,
|
||||
* also the outliner isn't intended for editing such large data-sets. */
|
||||
BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!")
|
||||
const int tot_limit = SHRT_MAX;
|
||||
|
||||
int a, tot;
|
||||
|
||||
/* we do lazy build, for speed and to avoid infinite recursion */
|
||||
|
||||
if (ptr->data == NULL) {
|
||||
|
@ -1144,8 +1106,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
tselem->flag &= ~TSE_CHILDSEARCH;
|
||||
}
|
||||
|
||||
iterprop = RNA_struct_iterator_property(ptr->type);
|
||||
tot = RNA_property_collection_length(ptr, iterprop);
|
||||
PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type);
|
||||
int tot = RNA_property_collection_length(ptr, iterprop);
|
||||
CLAMP_MAX(tot, tot_limit);
|
||||
|
||||
/* auto open these cases */
|
||||
|
@ -1156,7 +1118,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
}
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
for (a = 0; a < tot; a++) {
|
||||
for (int a = 0; a < tot; a++) {
|
||||
PointerRNA propptr;
|
||||
RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr);
|
||||
if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) {
|
||||
outliner_add_element(
|
||||
|
@ -1172,11 +1135,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
}
|
||||
else if (type == TSE_RNA_PROPERTY) {
|
||||
/* property */
|
||||
iterprop = RNA_struct_iterator_property(ptr->type);
|
||||
PointerRNA propptr;
|
||||
PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type);
|
||||
RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr);
|
||||
|
||||
prop = propptr.data;
|
||||
proptype = RNA_property_type(prop);
|
||||
PropertyRNA *prop = propptr.data;
|
||||
PropertyType proptype = RNA_property_type(prop);
|
||||
|
||||
te->name = RNA_property_ui_name(prop);
|
||||
te->directdata = prop;
|
||||
|
@ -1188,7 +1152,7 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
}
|
||||
|
||||
if (proptype == PROP_POINTER) {
|
||||
pptr = RNA_property_pointer_get(ptr, prop);
|
||||
PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
|
||||
|
||||
if (pptr.data) {
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
|
@ -1201,11 +1165,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
}
|
||||
}
|
||||
else if (proptype == PROP_COLLECTION) {
|
||||
tot = RNA_property_collection_length(ptr, prop);
|
||||
int tot = RNA_property_collection_length(ptr, prop);
|
||||
CLAMP_MAX(tot, tot_limit);
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
for (a = 0; a < tot; a++) {
|
||||
for (int a = 0; a < tot; a++) {
|
||||
PointerRNA pptr;
|
||||
RNA_property_collection_lookup_int(ptr, prop, a, &pptr);
|
||||
outliner_add_element(
|
||||
space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, a);
|
||||
|
@ -1216,11 +1181,11 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
}
|
||||
}
|
||||
else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
|
||||
tot = RNA_property_array_length(ptr, prop);
|
||||
int tot = RNA_property_array_length(ptr, prop);
|
||||
CLAMP_MAX(tot, tot_limit);
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
for (a = 0; a < tot; a++) {
|
||||
for (int a = 0; a < tot; a++) {
|
||||
outliner_add_element(
|
||||
space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_ARRAY_ELEM, a);
|
||||
}
|
||||
|
@ -1231,15 +1196,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
}
|
||||
}
|
||||
else if (type == TSE_RNA_ARRAY_ELEM) {
|
||||
char c;
|
||||
|
||||
prop = parent->directdata;
|
||||
PropertyRNA *prop = parent->directdata;
|
||||
|
||||
te->directdata = prop;
|
||||
te->rnaptr = *ptr;
|
||||
te->index = index;
|
||||
|
||||
c = RNA_property_array_item_char(prop, index);
|
||||
char c = RNA_property_array_item_char(prop, index);
|
||||
|
||||
te->name = MEM_callocN(sizeof(char[20]), "OutlinerRNAArrayName");
|
||||
if (c) {
|
||||
|
@ -1253,16 +1216,14 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
|
|||
}
|
||||
else if (type == TSE_KEYMAP) {
|
||||
wmKeyMap *km = (wmKeyMap *)idv;
|
||||
wmKeyMapItem *kmi;
|
||||
char opname[OP_MAX_TYPENAME];
|
||||
|
||||
te->directdata = idv;
|
||||
te->name = km->idname;
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
int a = 0;
|
||||
|
||||
for (kmi = km->items.first; kmi; kmi = kmi->next, a++) {
|
||||
int a;
|
||||
LISTBASE_FOREACH_INDEX (wmKeyMapItem *, kmi, &km->items, a) {
|
||||
const char *key = WM_key_event_string(kmi->type, false);
|
||||
|
||||
if (key[0]) {
|
||||
|
@ -1344,21 +1305,18 @@ static TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outli
|
|||
/* make sure elements are correctly nested */
|
||||
void outliner_make_object_parent_hierarchy(ListBase *lb)
|
||||
{
|
||||
TreeElement *te, *ten, *tep;
|
||||
TreeStoreElem *tselem;
|
||||
|
||||
/* build hierarchy */
|
||||
/* XXX also, set extents here... */
|
||||
te = lb->first;
|
||||
TreeElement *te = lb->first;
|
||||
while (te) {
|
||||
ten = te->next;
|
||||
tselem = TREESTORE(te);
|
||||
TreeElement *ten = te->next;
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
if (tselem->type == 0 && te->idcode == ID_OB) {
|
||||
Object *ob = (Object *)tselem->id;
|
||||
if (ob->parent && ob->parent->id.newid) {
|
||||
BLI_remlink(lb, te);
|
||||
tep = (TreeElement *)ob->parent->id.newid;
|
||||
TreeElement *tep = (TreeElement *)ob->parent->id.newid;
|
||||
BLI_addtail(&tep->subtree, te);
|
||||
te->parent = tep;
|
||||
}
|
||||
|
@ -1380,10 +1338,9 @@ typedef struct tTreeSort {
|
|||
static int treesort_alpha_ob(const void *v1, const void *v2)
|
||||
{
|
||||
const tTreeSort *x1 = v1, *x2 = v2;
|
||||
int comp;
|
||||
|
||||
/* first put objects last (hierarchy) */
|
||||
comp = (x1->idcode == ID_OB);
|
||||
int comp = (x1->idcode == ID_OB);
|
||||
if (x2->idcode == ID_OB) {
|
||||
comp += 2;
|
||||
}
|
||||
|
@ -1432,9 +1389,8 @@ static int treesort_child_not_in_collection(const void *v1, const void *v2)
|
|||
static int treesort_alpha(const void *v1, const void *v2)
|
||||
{
|
||||
const tTreeSort *x1 = v1, *x2 = v2;
|
||||
int comp;
|
||||
|
||||
comp = BLI_strcasecmp_natural(x1->name, x2->name);
|
||||
int comp = BLI_strcasecmp_natural(x1->name, x2->name);
|
||||
|
||||
if (comp > 0) {
|
||||
return 1;
|
||||
|
@ -1489,14 +1445,11 @@ static int treesort_obtype_alpha(const void *v1, const void *v2)
|
|||
/* sort happens on each subtree individual */
|
||||
static void outliner_sort(ListBase *lb)
|
||||
{
|
||||
TreeElement *te;
|
||||
TreeStoreElem *tselem;
|
||||
|
||||
te = lb->last;
|
||||
TreeElement *te = lb->last;
|
||||
if (te == NULL) {
|
||||
return;
|
||||
}
|
||||
tselem = TREESTORE(te);
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
/* sorting rules; only object lists, ID lists, or deformgroups */
|
||||
if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) ||
|
||||
|
@ -1558,14 +1511,11 @@ static void outliner_sort(ListBase *lb)
|
|||
|
||||
static void outliner_collections_children_sort(ListBase *lb)
|
||||
{
|
||||
TreeElement *te;
|
||||
TreeStoreElem *tselem;
|
||||
|
||||
te = lb->last;
|
||||
TreeElement *te = lb->last;
|
||||
if (te == NULL) {
|
||||
return;
|
||||
}
|
||||
tselem = TREESTORE(te);
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
/* Sorting rules: only object lists. */
|
||||
if (tselem->type == 0 && te->idcode == ID_OB) {
|
||||
|
@ -1687,8 +1637,7 @@ static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner
|
|||
const float view_co,
|
||||
const float view_co_limit)
|
||||
{
|
||||
TreeElement *te, *te_sub;
|
||||
te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_co);
|
||||
TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_co);
|
||||
|
||||
bool (*callback_test)(TreeElement *);
|
||||
if ((space_outliner->outlinevis == SO_VIEW_LAYER) &&
|
||||
|
@ -1700,7 +1649,7 @@ static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner
|
|||
}
|
||||
|
||||
while (te != NULL) {
|
||||
te_sub = outliner_find_first_desired_element_at_y_recursive(
|
||||
TreeElement *te_sub = outliner_find_first_desired_element_at_y_recursive(
|
||||
space_outliner, te, view_co_limit, callback_test);
|
||||
if (te_sub != NULL) {
|
||||
/* Skip the element if it was not visible to start with. */
|
||||
|
@ -1742,12 +1691,12 @@ static void outliner_store_scrolling_position(SpaceOutliner *space_outliner,
|
|||
ARegion *region,
|
||||
OutlinerTreeElementFocus *focus)
|
||||
{
|
||||
TreeElement *te;
|
||||
float limit = region->v2d.cur.ymin;
|
||||
|
||||
outliner_set_coordinates(region, space_outliner);
|
||||
|
||||
te = outliner_find_first_desired_element_at_y(space_outliner, region->v2d.cur.ymax, limit);
|
||||
TreeElement *te = outliner_find_first_desired_element_at_y(
|
||||
space_outliner, region->v2d.cur.ymax, limit);
|
||||
|
||||
if (te != NULL) {
|
||||
focus->tselem = TREESTORE(te);
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "BKE_screen.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "ED_render.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_transform.h"
|
||||
|
@ -799,6 +800,7 @@ static void *view3d_main_region_duplicate(void *poin)
|
|||
|
||||
static void view3d_main_region_listener(const wmRegionListenerParams *params)
|
||||
{
|
||||
wmWindow *window = params->window;
|
||||
ScrArea *area = params->area;
|
||||
ARegion *region = params->region;
|
||||
wmNotifier *wmn = params->notifier;
|
||||
|
@ -1018,11 +1020,17 @@ static void view3d_main_region_listener(const wmRegionListenerParams *params)
|
|||
if (wmn->subtype == NS_VIEW3D_GPU) {
|
||||
rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
|
||||
}
|
||||
#ifdef WITH_XR_OPENXR
|
||||
else if (wmn->subtype == NS_VIEW3D_SHADING) {
|
||||
#ifdef WITH_XR_OPENXR
|
||||
ED_view3d_xr_shading_update(G_MAIN->wm.first, v3d, scene);
|
||||
}
|
||||
#endif
|
||||
|
||||
ViewLayer *view_layer = WM_window_get_active_view_layer(window);
|
||||
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer);
|
||||
if (depsgraph) {
|
||||
ED_render_view3d_update(depsgraph, window, area, true);
|
||||
}
|
||||
}
|
||||
ED_region_tag_redraw(region);
|
||||
WM_gizmomap_tag_refresh(gzmap);
|
||||
}
|
||||
|
|
|
@ -1962,13 +1962,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
|
|||
/* XXX(jbakker): `do_color_management` should be controlled by the caller. Currently when doing a
|
||||
* viewport render animation and saving to an 8bit file format, color management would be applied
|
||||
* twice. Once here, and once when saving the saving to disk. In this case the Save As Render
|
||||
* option cannot be controlled either. But when doing an offscreen render you want to do the
|
||||
* option cannot be controlled either. But when doing an off-screen render you want to do the
|
||||
* color management here.
|
||||
*
|
||||
* This option was added here to increase the performance when rendering for a playblast. When
|
||||
* using workbench the color differences haven't been reported as a bug. But users also use the
|
||||
* viewport rendering to render Eevee scenes. In the later situation the saved colors
|
||||
* are totally wrong. */
|
||||
* This option was added here to increase the performance for quick view-port preview renders.
|
||||
* When using workbench the color differences haven't been reported as a bug. But users also use
|
||||
* the viewport rendering to render Eevee scenes. In the later situation the saved colors are
|
||||
* totally wrong. */
|
||||
const bool do_color_management = (ibuf->rect_float == NULL);
|
||||
ED_view3d_draw_offscreen(depsgraph,
|
||||
scene,
|
||||
|
|
|
@ -618,7 +618,7 @@ static void gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgrou
|
|||
/* set up widget data */
|
||||
RNA_float_set(gz->ptr, "length", 1.0f);
|
||||
float axis[3] = {0.0f};
|
||||
axis[(i + 1) % 2] = 1.0f;
|
||||
axis[i] = 1.0f;
|
||||
WM_gizmo_set_matrix_rotation_from_z_axis(gz, axis);
|
||||
|
||||
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
|
||||
|
@ -651,8 +651,8 @@ static void gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgrou
|
|||
/* Assign operator. */
|
||||
PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_resize, NULL);
|
||||
if (i < 2) {
|
||||
bool constraint[3] = {0};
|
||||
constraint[(i + 1) % 2] = 1;
|
||||
bool constraint[3] = {false};
|
||||
constraint[i] = true;
|
||||
if (RNA_struct_find_property(ptr, "constraint_axis")) {
|
||||
RNA_boolean_set_array(ptr, "constraint_axis", constraint);
|
||||
}
|
||||
|
|
|
@ -320,8 +320,9 @@ static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList *
|
|||
/* Pointers match on redo. */
|
||||
const int target_step_index = BLI_findindex(&wm->undo_stack->steps, undo_step_from_name);
|
||||
const int active_step_index = BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active);
|
||||
const enum eUndoStepDir undo_dir = (target_step_index < active_step_index) ? STEP_UNDO :
|
||||
STEP_REDO;
|
||||
/* NOTE: when current and target active steps are the same, we are in undo case. */
|
||||
const enum eUndoStepDir undo_dir = (target_step_index <= active_step_index) ? STEP_UNDO :
|
||||
STEP_REDO;
|
||||
|
||||
CLOG_INFO(&LOG,
|
||||
1,
|
||||
|
|
|
@ -344,6 +344,20 @@ void GPU_bgl_start()
|
|||
/* Expected by many addons (see T80169, T81289).
|
||||
* This will reset the blend function. */
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
|
||||
/* Equivalent of setting the depth func `glDepthFunc(GL_LEQUAL)`
|
||||
* Needed since Python scripts may enable depth test.
|
||||
* Without this block the depth test function is undefined. */
|
||||
{
|
||||
eGPUDepthTest depth_test_real = GPU_depth_test_get();
|
||||
eGPUDepthTest depth_test_temp = GPU_DEPTH_LESS_EQUAL;
|
||||
if (depth_test_real != depth_test_temp) {
|
||||
GPU_depth_test(depth_test_temp);
|
||||
state_manager.apply_state();
|
||||
GPU_depth_test(depth_test_real);
|
||||
}
|
||||
}
|
||||
|
||||
state_manager.apply_state();
|
||||
state_manager.use_bgl = true;
|
||||
}
|
||||
|
|
|
@ -53,11 +53,6 @@ typedef struct img_folder {
|
|||
float *rates;
|
||||
} img_fol_t;
|
||||
|
||||
enum {
|
||||
DCP_CINEMA2K = 3,
|
||||
DCP_CINEMA4K = 4,
|
||||
};
|
||||
|
||||
static bool check_jp2(const unsigned char *mem, const size_t size) /* J2K_CFMT */
|
||||
{
|
||||
if (size < sizeof(JP2_HEAD)) {
|
||||
|
@ -733,7 +728,7 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters,
|
|||
parameters->cp_rsiz = OPJ_STD_RSIZ;
|
||||
}
|
||||
else {
|
||||
parameters->cp_rsiz = DCP_CINEMA2K;
|
||||
parameters->cp_rsiz = OPJ_CINEMA2K;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -754,7 +749,7 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters,
|
|||
parameters->cp_rsiz = OPJ_STD_RSIZ;
|
||||
}
|
||||
else {
|
||||
parameters->cp_rsiz = DCP_CINEMA2K;
|
||||
parameters->cp_rsiz = OPJ_CINEMA4K;
|
||||
}
|
||||
parameters->numpocs = init_4K_poc(parameters->POC, parameters->numresolution);
|
||||
break;
|
||||
|
|
|
@ -413,11 +413,22 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
|
|||
jpeg_finish_decompress(cinfo);
|
||||
}
|
||||
|
||||
jpeg_destroy((j_common_ptr)cinfo);
|
||||
if (ibuf) {
|
||||
/* Density_unit may be 0 for unknown, 1 for dots/inch, or 2 for dots/cm. */
|
||||
if (cinfo->density_unit == 1) {
|
||||
/* Convert inches to meters. */
|
||||
ibuf->ppm[0] = cinfo->X_density / 0.0254f;
|
||||
ibuf->ppm[1] = cinfo->Y_density / 0.0254f;
|
||||
}
|
||||
else if (cinfo->density_unit == 2) {
|
||||
ibuf->ppm[0] = cinfo->X_density * 100.0f;
|
||||
ibuf->ppm[1] = cinfo->Y_density * 100.0f;
|
||||
}
|
||||
|
||||
ibuf->ftype = IMB_FTYPE_JPG;
|
||||
ibuf->foptions.quality = MIN2(ibuf_quality, 100);
|
||||
}
|
||||
jpeg_destroy((j_common_ptr)cinfo);
|
||||
}
|
||||
|
||||
return ibuf;
|
||||
|
|
|
@ -530,7 +530,8 @@ typedef enum ID_Type {
|
|||
#define ID_IS_ASSET(_id) (((const ID *)(_id))->asset_data != NULL)
|
||||
|
||||
/* Check whether datablock type is covered by copy-on-write. */
|
||||
#define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_PAL, ID_IM))
|
||||
#define ID_TYPE_IS_COW(_id_type) \
|
||||
(!ELEM(_id_type, ID_LI, ID_IP, ID_SCR, ID_VF, ID_BR, ID_WM, ID_PAL, ID_PC, ID_WS, ID_IM))
|
||||
|
||||
#ifdef GS
|
||||
# undef GS
|
||||
|
|
|
@ -128,6 +128,17 @@ static void rna_Image_colormanage_update(Main *bmain, Scene *UNUSED(scene), Poin
|
|||
WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
|
||||
}
|
||||
|
||||
static void rna_Image_alpha_mode_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
Image *ima = (Image *)ptr->owner_id;
|
||||
/* When operating on a generated image, avoid re-generating when changing the alpha-mode
|
||||
* as it doesn't impact generated images, causing them to reload pixel data, see T82785. */
|
||||
if (ima->source == IMA_SRC_GENERATED) {
|
||||
return;
|
||||
}
|
||||
rna_Image_colormanage_update(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
static void rna_Image_views_format_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
Image *ima = (Image *)ptr->owner_id;
|
||||
|
@ -1133,7 +1144,7 @@ static void rna_def_image(BlenderRNA *brna)
|
|||
"Alpha Mode",
|
||||
"Representation of alpha in the image file, to convert to and from "
|
||||
"when saving and loading the image");
|
||||
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
|
||||
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_alpha_mode_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_half_precision", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_HIGH_BITDEPTH);
|
||||
|
|
|
@ -494,22 +494,6 @@ static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_no_bo
|
|||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem rna_node_geometry_object_info_transform_space_items[] = {
|
||||
{GEO_NODE_TRANSFORM_SPACE_ORIGINAL,
|
||||
"ORIGINAL",
|
||||
0,
|
||||
"Original",
|
||||
"Output the geometry relative to the input object transform, and the location, rotation and "
|
||||
"scale relative to the world origin"},
|
||||
{GEO_NODE_TRANSFORM_SPACE_RELATIVE,
|
||||
"RELATIVE",
|
||||
0,
|
||||
"Relative",
|
||||
"Bring the input object geometry, location, rotation and scale into the modified object, "
|
||||
"maintaining the relative position between the two objects in the scene"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#undef ITEM_ATTRIBUTE
|
||||
|
@ -8870,6 +8854,23 @@ static void def_geo_object_info(StructRNA *srna)
|
|||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem rna_node_geometry_object_info_transform_space_items[] = {
|
||||
{GEO_NODE_TRANSFORM_SPACE_ORIGINAL,
|
||||
"ORIGINAL",
|
||||
0,
|
||||
"Original",
|
||||
"Output the geometry relative to the input object transform, and the location, rotation "
|
||||
"and "
|
||||
"scale relative to the world origin"},
|
||||
{GEO_NODE_TRANSFORM_SPACE_RELATIVE,
|
||||
"RELATIVE",
|
||||
0,
|
||||
"Relative",
|
||||
"Bring the input object geometry, location, rotation and scale into the modified object, "
|
||||
"maintaining the relative position between the two objects in the scene"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeGeometryObjectInfo", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE);
|
||||
|
|
|
@ -4016,7 +4016,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
|
|||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
parm = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
|
||||
parm = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
|
||||
RNA_def_int(func, "uv_no", 0, INT_MIN, INT_MAX, "UV no", "", INT_MIN, INT_MAX);
|
||||
|
|
|
@ -4038,7 +4038,10 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
|
|||
|
||||
prop = RNA_def_property(srna, "show_face_center", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_FACE_DOT);
|
||||
RNA_def_property_ui_text(prop, "Draw Face Center", "Display face center");
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Draw Face Center",
|
||||
"Display face center when face selection is enabled in solid shading modes");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_edge_crease", PROP_BOOLEAN, PROP_NONE);
|
||||
|
|
|
@ -3005,6 +3005,12 @@ static void rna_def_userdef_theme_space_buts(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Search Match", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
prop = RNA_def_property(srna, "active_modifier", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_float_sdna(prop, NULL, "active");
|
||||
RNA_def_property_array(prop, 4);
|
||||
RNA_def_property_ui_text(prop, "Active Modifier Outline", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
rna_def_userdef_theme_spaces_main(srna);
|
||||
}
|
||||
|
||||
|
|
|
@ -600,6 +600,18 @@ static wmGizmo *rna_GizmoGroup_gizmo_new(wmGizmoGroup *gzgroup,
|
|||
BKE_reportf(reports, RPT_ERROR, "GizmoType '%s' not known", idname);
|
||||
return NULL;
|
||||
}
|
||||
if ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0) {
|
||||
/* Allow for neither callbacks to be set, while this doesn't seem like a valid use case,
|
||||
* there may be rare situations where a developer wants a gizmo to be draw-only. */
|
||||
if ((gzt->test_select == NULL) && (gzt->draw_select != NULL)) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"GizmoType '%s' is for a 3D gizmo-group. "
|
||||
"The 'draw_select' callback is set where only 'test_select' will be used.",
|
||||
idname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
wmGizmo *gz = WM_gizmo_new_ptr(gzt, gzgroup, NULL);
|
||||
return gz;
|
||||
}
|
||||
|
|
|
@ -114,7 +114,12 @@ typedef struct SDefBindPoly {
|
|||
float weight_dist_proj;
|
||||
float weight_dist;
|
||||
float weight;
|
||||
/** Distances from the centroid to edges flanking the corner vertex, used to penalize
|
||||
* small or long and narrow faces in favor of bigger and more square ones. */
|
||||
float scales[2];
|
||||
/** Distance weight from the corner vertex to the chord line, used to penalize
|
||||
* cases with the three consecutive vertices being nearly in line. */
|
||||
float scale_mid;
|
||||
/** Center of `coords` */
|
||||
float centroid[3];
|
||||
/** Center of `coords_v2` */
|
||||
|
@ -123,15 +128,18 @@ typedef struct SDefBindPoly {
|
|||
* The calculated normal of coords (could be shared between faces).
|
||||
*/
|
||||
float normal[3];
|
||||
/** Vectors pointing from the centroid to the midpoints of the two edges
|
||||
* flanking the corner vertex. */
|
||||
float cent_edgemid_vecs_v2[2][2];
|
||||
/**
|
||||
* The unsigned angle of this face-corner in `[0.0 .. PI]` range,
|
||||
* where a small value is a thin corner. PI is a straight line.
|
||||
* Take care dividing by this value as it can approach zero.
|
||||
*/
|
||||
/** Angle between the cent_edgemid_vecs_v2 vectors. */
|
||||
float edgemid_angle;
|
||||
/** Angles between the centroid-to-point and cent_edgemid_vecs_v2 vectors.
|
||||
* Positive values measured towards the corner; clamped non-negative. */
|
||||
float point_edgemid_angles[2];
|
||||
/** Angles between the centroid-to-corner and cent_edgemid_vecs_v2 vectors. */
|
||||
float corner_edgemid_angles[2];
|
||||
/** Weight of the bind mode based on the corner and two adjacent vertices,
|
||||
* versus the one based on the centroid and the dominant edge. */
|
||||
float dominant_angle_weight;
|
||||
/** Index of the input polygon. */
|
||||
uint index;
|
||||
|
@ -414,13 +422,14 @@ BLI_INLINE uint nearestVert(SDefBindCalcData *const data, const float point_co[3
|
|||
|
||||
BLI_INLINE int isPolyValid(const float coords[][2], const uint nr)
|
||||
{
|
||||
float prev_co[2];
|
||||
float prev_co[2], prev_prev_co[2];
|
||||
float curr_vec[2], prev_vec[2];
|
||||
|
||||
if (!is_poly_convex_v2(coords, nr)) {
|
||||
return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
|
||||
}
|
||||
|
||||
copy_v2_v2(prev_prev_co, coords[nr - 2]);
|
||||
copy_v2_v2(prev_co, coords[nr - 1]);
|
||||
sub_v2_v2v2(prev_vec, prev_co, coords[nr - 2]);
|
||||
normalize_v2(prev_vec);
|
||||
|
@ -428,15 +437,23 @@ BLI_INLINE int isPolyValid(const float coords[][2], const uint nr)
|
|||
for (int i = 0; i < nr; i++) {
|
||||
sub_v2_v2v2(curr_vec, coords[i], prev_co);
|
||||
|
||||
/* Check ovelap between directly adjacent vertices. */
|
||||
const float curr_len = normalize_v2(curr_vec);
|
||||
if (curr_len < FLT_EPSILON) {
|
||||
return MOD_SDEF_BIND_RESULT_OVERLAP_ERR;
|
||||
}
|
||||
|
||||
/* Check ovelap between vertices skipping one. */
|
||||
if (len_squared_v2v2(prev_prev_co, coords[i]) < FLT_EPSILON * FLT_EPSILON) {
|
||||
return MOD_SDEF_BIND_RESULT_OVERLAP_ERR;
|
||||
}
|
||||
|
||||
/* Check for adjacent parallel edges. */
|
||||
if (1.0f - dot_v2v2(prev_vec, curr_vec) < FLT_EPSILON) {
|
||||
return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
|
||||
}
|
||||
|
||||
copy_v2_v2(prev_prev_co, prev_co);
|
||||
copy_v2_v2(prev_co, coords[i]);
|
||||
copy_v2_v2(prev_vec, curr_vec);
|
||||
}
|
||||
|
@ -460,9 +477,9 @@ static void freeBindData(SDefBindWeightData *const bwdata)
|
|||
MEM_freeN(bwdata);
|
||||
}
|
||||
|
||||
BLI_INLINE float computeAngularWeight(const float point_angle)
|
||||
BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle)
|
||||
{
|
||||
return sinf(point_angle * M_PI_2);
|
||||
return sinf(min_ff(point_angle / edgemid_angle, 1) * M_PI_2);
|
||||
}
|
||||
|
||||
BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
|
||||
|
@ -603,33 +620,51 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
|
|||
|
||||
avg_point_dist += bpoly->weight_dist;
|
||||
|
||||
/* Compute centroid to mid-edge vectors */
|
||||
mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0],
|
||||
bpoly->coords_v2[bpoly->edge_vert_inds[0]],
|
||||
bpoly->coords_v2[bpoly->corner_ind]);
|
||||
/* Common vertex coordinates. */
|
||||
const float *const vert0_v2 = bpoly->coords_v2[bpoly->edge_vert_inds[0]];
|
||||
const float *const vert1_v2 = bpoly->coords_v2[bpoly->edge_vert_inds[1]];
|
||||
const float *const corner_v2 = bpoly->coords_v2[bpoly->corner_ind];
|
||||
|
||||
mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1],
|
||||
bpoly->coords_v2[bpoly->edge_vert_inds[1]],
|
||||
bpoly->coords_v2[bpoly->corner_ind]);
|
||||
/* Compute centroid to mid-edge vectors */
|
||||
mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0], vert0_v2, corner_v2);
|
||||
mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1], vert1_v2, corner_v2);
|
||||
|
||||
sub_v2_v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->centroid_v2);
|
||||
sub_v2_v2(bpoly->cent_edgemid_vecs_v2[1], bpoly->centroid_v2);
|
||||
|
||||
/* Compute poly scales with respect to mid-edges, and normalize the vectors */
|
||||
bpoly->scales[0] = normalize_v2(bpoly->cent_edgemid_vecs_v2[0]);
|
||||
bpoly->scales[1] = normalize_v2(bpoly->cent_edgemid_vecs_v2[1]);
|
||||
normalize_v2(bpoly->cent_edgemid_vecs_v2[0]);
|
||||
normalize_v2(bpoly->cent_edgemid_vecs_v2[1]);
|
||||
|
||||
/* Compute the required polygon angles */
|
||||
/* Compute poly scales with respect to the two edges. */
|
||||
bpoly->scales[0] = dist_to_line_v2(bpoly->centroid_v2, vert0_v2, corner_v2);
|
||||
bpoly->scales[1] = dist_to_line_v2(bpoly->centroid_v2, vert1_v2, corner_v2);
|
||||
|
||||
/* Compute the angle between the edge mid vectors. */
|
||||
bpoly->edgemid_angle = angle_normalized_v2v2(bpoly->cent_edgemid_vecs_v2[0],
|
||||
bpoly->cent_edgemid_vecs_v2[1]);
|
||||
|
||||
sub_v2_v2v2(tmp_vec_v2, bpoly->coords_v2[bpoly->corner_ind], bpoly->centroid_v2);
|
||||
/* Compute the angles between the corner and the edge mid vectors. The angles
|
||||
* are computed signed in order to correctly clamp point_edgemid_angles later. */
|
||||
float corner_angles[2];
|
||||
|
||||
sub_v2_v2v2(tmp_vec_v2, corner_v2, bpoly->centroid_v2);
|
||||
normalize_v2(tmp_vec_v2);
|
||||
|
||||
bpoly->corner_edgemid_angles[0] = angle_normalized_v2v2(tmp_vec_v2,
|
||||
bpoly->cent_edgemid_vecs_v2[0]);
|
||||
bpoly->corner_edgemid_angles[1] = angle_normalized_v2v2(tmp_vec_v2,
|
||||
bpoly->cent_edgemid_vecs_v2[1]);
|
||||
corner_angles[0] = angle_signed_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[0]);
|
||||
corner_angles[1] = angle_signed_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[1]);
|
||||
|
||||
bpoly->corner_edgemid_angles[0] = fabsf(corner_angles[0]);
|
||||
bpoly->corner_edgemid_angles[1] = fabsf(corner_angles[1]);
|
||||
|
||||
/* Verify that the computed values are valid (the polygon isn't somehow
|
||||
* degenerate despite having passed isPolyValid). */
|
||||
if (bpoly->scales[0] < FLT_EPSILON || bpoly->scales[1] < FLT_EPSILON ||
|
||||
bpoly->edgemid_angle < FLT_EPSILON || bpoly->corner_edgemid_angles[0] < FLT_EPSILON ||
|
||||
bpoly->corner_edgemid_angles[1] < FLT_EPSILON) {
|
||||
freeBindData(bwdata);
|
||||
data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check for infinite weights, and compute angular data otherwise. */
|
||||
if (bpoly->weight_dist < FLT_EPSILON) {
|
||||
|
@ -640,15 +675,54 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
|
|||
inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
|
||||
}
|
||||
else {
|
||||
float cent_point_vec[2];
|
||||
/* Compute angles between the point and the edge mid vectors. */
|
||||
float cent_point_vec[2], point_angles[2];
|
||||
|
||||
sub_v2_v2v2(cent_point_vec, bpoly->point_v2, bpoly->centroid_v2);
|
||||
normalize_v2(cent_point_vec);
|
||||
|
||||
bpoly->point_edgemid_angles[0] = angle_normalized_v2v2(cent_point_vec,
|
||||
bpoly->cent_edgemid_vecs_v2[0]);
|
||||
bpoly->point_edgemid_angles[1] = angle_normalized_v2v2(cent_point_vec,
|
||||
bpoly->cent_edgemid_vecs_v2[1]);
|
||||
point_angles[0] = angle_signed_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[0]) *
|
||||
signf(corner_angles[0]);
|
||||
point_angles[1] = angle_signed_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[1]) *
|
||||
signf(corner_angles[1]);
|
||||
|
||||
if (point_angles[0] <= 0 && point_angles[1] <= 0) {
|
||||
/* If the point is outside the corner formed by the edge mid vectors,
|
||||
* choose to clamp the closest side and flip the other. */
|
||||
if (point_angles[0] < point_angles[1]) {
|
||||
point_angles[0] = bpoly->edgemid_angle - point_angles[1];
|
||||
}
|
||||
else {
|
||||
point_angles[1] = bpoly->edgemid_angle - point_angles[0];
|
||||
}
|
||||
}
|
||||
|
||||
bpoly->point_edgemid_angles[0] = max_ff(0, point_angles[0]);
|
||||
bpoly->point_edgemid_angles[1] = max_ff(0, point_angles[1]);
|
||||
|
||||
/* Compute the distance scale for the corner. The base value is the orthogonal
|
||||
* distance from the corner to the chord, scaled by sqrt(2) to preserve the old
|
||||
* values in case of a square grid. This doesn't use the centroid because the
|
||||
* LOOPTRI method only uses these three vertices. */
|
||||
bpoly->scale_mid = area_tri_v2(vert0_v2, corner_v2, vert1_v2) /
|
||||
len_v2v2(vert0_v2, vert1_v2) * sqrtf(2);
|
||||
|
||||
if (bpoly->inside) {
|
||||
/* When inside, interpolate to centroid-based scale close to the center. */
|
||||
float min_dist = min_ff(bpoly->scales[0], bpoly->scales[1]);
|
||||
|
||||
bpoly->scale_mid = interpf(bpoly->scale_mid,
|
||||
(bpoly->scales[0] + bpoly->scales[1]) / 2,
|
||||
min_ff(bpoly->weight_dist_proj / min_dist, 1));
|
||||
}
|
||||
|
||||
/* Verify that the additional computed values are valid. */
|
||||
if (bpoly->scale_mid < FLT_EPSILON ||
|
||||
bpoly->point_edgemid_angles[0] + bpoly->point_edgemid_angles[1] < FLT_EPSILON) {
|
||||
freeBindData(bwdata);
|
||||
data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -688,12 +762,15 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
|
|||
|
||||
/* Compute angular weight component */
|
||||
if (epolys->num == 1) {
|
||||
ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]]);
|
||||
ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]],
|
||||
bpolys[0]->edgemid_angle);
|
||||
bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0];
|
||||
}
|
||||
else if (epolys->num == 2) {
|
||||
ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]]);
|
||||
ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]]);
|
||||
ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]],
|
||||
bpolys[0]->edgemid_angle);
|
||||
ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]],
|
||||
bpolys[1]->edgemid_angle);
|
||||
|
||||
bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1];
|
||||
bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1];
|
||||
|
@ -731,6 +808,13 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
|
|||
bpoly->dominant_angle_weight = corner_angle_weights[1];
|
||||
}
|
||||
|
||||
/* Check for invalid weights just in case computations fail. */
|
||||
if (bpoly->dominant_angle_weight < 0 || bpoly->dominant_angle_weight > 1) {
|
||||
freeBindData(bwdata);
|
||||
data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bpoly->dominant_angle_weight = sinf(bpoly->dominant_angle_weight * M_PI_2);
|
||||
|
||||
/* Compute quadratic angular scale interpolation weight */
|
||||
|
@ -748,10 +832,15 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
|
|||
inv_sqr *= inv_sqr;
|
||||
scale_weight = sqr / (sqr + inv_sqr);
|
||||
|
||||
BLI_assert(scale_weight >= 0 && scale_weight <= 1);
|
||||
|
||||
/* Compute interpolated scale (no longer need the individual scales,
|
||||
* so simply storing the result over the scale in index zero) */
|
||||
bpoly->scales[0] = bpoly->scales[bpoly->dominant_edge] * (1.0f - scale_weight) +
|
||||
bpoly->scales[!bpoly->dominant_edge] * scale_weight;
|
||||
bpoly->scales[0] = interpf(bpoly->scale_mid,
|
||||
interpf(bpoly->scales[!bpoly->dominant_edge],
|
||||
bpoly->scales[bpoly->dominant_edge],
|
||||
scale_weight),
|
||||
bpoly->dominant_angle_weight);
|
||||
|
||||
/* Scale the point distance weights, and introduce falloff */
|
||||
bpoly->weight_dist_proj /= bpoly->scales[0];
|
||||
|
|
|
@ -163,6 +163,9 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components,
|
|||
int offset = 0;
|
||||
for (const GeometryComponent *component : src_components) {
|
||||
const int domain_size = component->attribute_domain_size(domain);
|
||||
if (domain_size == 0) {
|
||||
continue;
|
||||
}
|
||||
ReadAttributePtr read_attribute = component->attribute_get_for_read(
|
||||
attribute_name, domain, data_type, nullptr);
|
||||
|
||||
|
|
|
@ -65,8 +65,7 @@ static int gpu_shader_displacement(GPUMaterial *mat,
|
|||
mat, node, "node_displacement_object", in, out, GPU_builtin(GPU_OBJECT_MATRIX));
|
||||
}
|
||||
|
||||
return GPU_stack_link(
|
||||
mat, node, "node_displacement_world", in, out, GPU_builtin(GPU_OBJECT_MATRIX));
|
||||
return GPU_stack_link(mat, node, "node_displacement_world", in, out);
|
||||
}
|
||||
|
||||
/* node type definition */
|
||||
|
|
|
@ -424,11 +424,6 @@ static PyGetSetDef bpy_app_getsets[] = {
|
|||
bpy_app_debug_set,
|
||||
bpy_app_debug_doc,
|
||||
(void *)G_DEBUG_SIMDATA},
|
||||
{"debug_gpumem",
|
||||
bpy_app_debug_get,
|
||||
bpy_app_debug_set,
|
||||
bpy_app_debug_doc,
|
||||
(void *)G_DEBUG_GPU_MEM},
|
||||
{"debug_io", bpy_app_debug_get, bpy_app_debug_set, bpy_app_debug_doc, (void *)G_DEBUG_IO},
|
||||
|
||||
{"use_event_simulate",
|
||||
|
|
|
@ -450,6 +450,13 @@ void BPY_python_start(bContext *C, int argc, const char **argv)
|
|||
py_tstate = PyGILState_GetThisThreadState();
|
||||
PyEval_ReleaseThread(py_tstate);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PYTHON_MODULE
|
||||
/* Disable all add-ons at exit, not essential, it just avoids resource leaks, see T71362. */
|
||||
BPY_run_string_eval(C,
|
||||
(const char *[]){"atexit", "addon_utils", NULL},
|
||||
"atexit.register(addon_utils.disable_all)");
|
||||
#endif
|
||||
}
|
||||
|
||||
void BPY_python_end(void)
|
||||
|
|
|
@ -168,6 +168,9 @@ if(WITH_PYTHON)
|
|||
../python
|
||||
)
|
||||
add_definitions(-DWITH_PYTHON)
|
||||
if(WITH_PYTHON_MODULE)
|
||||
add_definitions(-DWITH_PYTHON_MODULE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_BUILDINFO)
|
||||
|
|
|
@ -544,6 +544,7 @@ void wm_event_do_notifiers(bContext *C)
|
|||
|
||||
LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
|
||||
wmRegionListenerParams region_params = {
|
||||
.window = win,
|
||||
.area = NULL,
|
||||
.region = region,
|
||||
.scene = scene,
|
||||
|
@ -562,6 +563,7 @@ void wm_event_do_notifiers(bContext *C)
|
|||
ED_area_do_listen(&area_params);
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
wmRegionListenerParams region_params = {
|
||||
.window = win,
|
||||
.area = area,
|
||||
.region = region,
|
||||
.scene = scene,
|
||||
|
|
|
@ -523,11 +523,15 @@ void WM_exit_ex(bContext *C, const bool do_python)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
#if defined(WITH_PYTHON) && !defined(WITH_PYTHON_MODULE)
|
||||
/* Without this, we there isn't a good way to manage false-positive resource leaks
|
||||
* where a #PyObject references memory allocated with guarded-alloc, T71362.
|
||||
*
|
||||
* This allows add-ons to free resources when unregistered (which is good practice anyway). */
|
||||
* This allows add-ons to free resources when unregistered (which is good practice anyway).
|
||||
*
|
||||
* Don't run this code when built as a Python module as this runs when Python is in the
|
||||
* process of shutting down, where running a snippet like this will crash, see T82675.
|
||||
* Instead use the `atexit` module, installed by #BPY_python_start */
|
||||
BPY_run_string_eval(C, (const char *[]){"addon_utils", NULL}, "addon_utils.disable_all()");
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1403,8 +1403,6 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *userD
|
|||
UI_block_bounds_set_popup(
|
||||
block, 6 * U.dpi_fac, (const int[2]){data->width / -2, data->height / 2});
|
||||
|
||||
UI_block_active_only_flagged_buttons(C, region, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
|
|
@ -587,7 +587,6 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
|
|||
BLI_args_print_arg_doc(ba, "--debug-depsgraph-time");
|
||||
BLI_args_print_arg_doc(ba, "--debug-depsgraph-pretty");
|
||||
BLI_args_print_arg_doc(ba, "--debug-gpu");
|
||||
BLI_args_print_arg_doc(ba, "--debug-gpumem");
|
||||
BLI_args_print_arg_doc(ba, "--debug-gpu-shaders");
|
||||
BLI_args_print_arg_doc(ba, "--debug-gpu-force-workarounds");
|
||||
BLI_args_print_arg_doc(ba, "--debug-wm");
|
||||
|
@ -977,9 +976,9 @@ static const char arg_handle_debug_mode_generic_set_doc_depsgraph_no_threads[] =
|
|||
static const char arg_handle_debug_mode_generic_set_doc_depsgraph_pretty[] =
|
||||
"\n\t"
|
||||
"Enable colors for dependency graph debug messages.";
|
||||
static const char arg_handle_debug_mode_generic_set_doc_gpumem[] =
|
||||
static const char arg_handle_debug_mode_generic_set_doc_gpu_force_workarounds[] =
|
||||
"\n\t"
|
||||
"Enable GPU memory stats in status bar.";
|
||||
"Enable workarounds for typical GPU issues and disable all GPU extensions.";
|
||||
|
||||
static int arg_handle_debug_mode_generic_set(int UNUSED(argc),
|
||||
const char **UNUSED(argv),
|
||||
|
@ -2157,20 +2156,10 @@ void main_args_setup(bContext *C, bArgs *ba)
|
|||
"--debug-depsgraph-uuid",
|
||||
CB_EX(arg_handle_debug_mode_generic_set, depsgraph_build),
|
||||
(void *)G_DEBUG_DEPSGRAPH_UUID);
|
||||
BLI_args_add(ba,
|
||||
NULL,
|
||||
"--debug-gpumem",
|
||||
CB_EX(arg_handle_debug_mode_generic_set, gpumem),
|
||||
(void *)G_DEBUG_GPU_MEM);
|
||||
BLI_args_add(ba,
|
||||
NULL,
|
||||
"--debug-gpu-shaders",
|
||||
CB_EX(arg_handle_debug_mode_generic_set, gpumem),
|
||||
(void *)G_DEBUG_GPU_SHADERS);
|
||||
BLI_args_add(ba,
|
||||
NULL,
|
||||
"--debug-gpu-force-workarounds",
|
||||
CB_EX(arg_handle_debug_mode_generic_set, gpumem),
|
||||
CB_EX(arg_handle_debug_mode_generic_set, gpu_force_workarounds),
|
||||
(void *)G_DEBUG_GPU_FORCE_WORKAROUNDS);
|
||||
BLI_args_add(ba, NULL, "--debug-exit-on-error", CB(arg_handle_debug_exit_on_error), NULL);
|
||||
|
||||
|
|
Loading…
Reference in New Issue