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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2020-03-16 20:14:24 +0300
committerJulian Eisel <julian@blender.org>2020-03-16 20:14:24 +0300
commitddbbd9928ec443f813ee4d46011288e360278e9f (patch)
tree91f50fc6e8e8b68be5686903aca191d43cdafae5
parentb86be9b2145458037fd0b17433b7af0efa7b6472 (diff)
parentd2ef342b2a50a7eac725889708fd689ffa126e25 (diff)
Merge branch 'temp-openxr-ghostxr' into temp-openxr-blenderside
-rw-r--r--extern/mantaflow/helper/util/vectorbase.h2
-rw-r--r--extern/mantaflow/preprocessed/gitinfo.h2
-rw-r--r--intern/cycles/blender/addon/engine.py2
-rw-r--r--intern/cycles/blender/addon/ui.py2
-rw-r--r--intern/cycles/device/cuda/device_cuda.h8
-rw-r--r--intern/cycles/device/cuda/device_cuda_impl.cpp84
-rw-r--r--intern/cycles/device/device_cpu.cpp86
-rw-r--r--intern/cycles/device/device_memory.cpp96
-rw-r--r--intern/cycles/device/device_memory.h42
-rw-r--r--intern/cycles/device/opencl/device_opencl.h6
-rw-r--r--intern/cycles/device/opencl/device_opencl_impl.cpp76
-rw-r--r--intern/cycles/kernel/kernel.h2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel.cpp2
-rw-r--r--intern/cycles/render/image.cpp135
-rw-r--r--intern/cycles/render/image.h8
-rw-r--r--intern/cycles/render/scene.cpp76
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm2
-rw-r--r--intern/ghost/test/multitest/stubs.c2
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp5
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_factory.cc62
-rw-r--r--release/datafiles/alert_icons.pngbin0 -> 38642 bytes
-rw-r--r--release/datafiles/alert_icons.svg185
-rw-r--r--release/datafiles/alert_icons_update.py25
-rwxr-xr-xrelease/datafiles/blender_icons_geom_update.py2
-rw-r--r--release/datafiles/icons/brush.gpencil_draw.tint.datbin0 -> 3158 bytes
-rw-r--r--release/datafiles/icons/brush.paint_vertex.replace.datbin0 -> 4130 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.blob.datbin1466 -> 2852 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.clay_thumb.datbin0 -> 1790 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.cloth.datbin0 -> 20258 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.draw_face_sets.datbin0 -> 4256 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.draw_sharp.datbin2492 -> 2474 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.inflate.datbin1862 -> 1466 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.multiplane_scrape.datbin7640 -> 1916 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.pinch.datbin2456 -> 2744 bytes
-rw-r--r--release/datafiles/icons/brush.sculpt.rotate.datbin5966 -> 55448 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.transform_fill.datbin0 -> 2132 bytes
m---------release/datafiles/locale0
-rw-r--r--release/datafiles/preview.blendbin1494238 -> 1453009 bytes
-rw-r--r--release/datafiles/userdef/userdef_default_theme.c2
m---------release/scripts/addons0
m---------release/scripts/addons_contrib0
-rw-r--r--release/scripts/presets/interface_theme/deep_grey.xml1481
-rw-r--r--release/scripts/presets/interface_theme/maya.xml1481
-rw-r--r--release/scripts/presets/interface_theme/minimal_dark.xml1481
-rw-r--r--release/scripts/presets/interface_theme/modo.xml1481
-rw-r--r--release/scripts/presets/interface_theme/print_friendly.xml1481
-rw-r--r--release/scripts/presets/interface_theme/white.xml1470
-rw-r--r--release/scripts/presets/interface_theme/xsi.xml1481
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py51
-rw-r--r--release/scripts/startup/bl_ui/properties_data_shaderfx.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py10
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py6
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_camera.h19
-rw-r--r--source/blender/blenkernel/BKE_cloth.h2
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h5
-rw-r--r--source/blender/blenkernel/BKE_idtype.h2
-rw-r--r--source/blender/blenkernel/BKE_image.h2
-rw-r--r--source/blender/blenkernel/BKE_multires.h41
-rw-r--r--source/blender/blenkernel/BKE_object.h4
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/BKE_scene.h6
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h2
-rw-r--r--source/blender/blenkernel/BKE_sound.h5
-rw-r--r--source/blender/blenkernel/BKE_writeavi.h12
-rw-r--r--source/blender/blenkernel/BKE_writeffmpeg.h6
-rw-r--r--source/blender/blenkernel/CMakeLists.txt8
-rw-r--r--source/blender/blenkernel/intern/camera.c25
-rw-r--r--source/blender/blenkernel/intern/constraint.c2
-rw-r--r--source/blender/blenkernel/intern/fluid.c22
-rw-r--r--source/blender/blenkernel/intern/gpencil.c29
-rw-r--r--source/blender/blenkernel/intern/image.c46
-rw-r--r--source/blender/blenkernel/intern/lib_id.c3
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c1
-rw-r--r--source/blender/blenkernel/intern/multires.c219
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.c236
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.h327
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_apply_base.c158
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_ccg.c72
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_legacy.c1056
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_smooth.c1064
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_util.c739
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_vertcos.c212
-rw-r--r--source/blender/blenkernel/intern/object.c4
-rw-r--r--source/blender/blenkernel/intern/scene.c12
-rw-r--r--source/blender/blenkernel/intern/seqcache.c1
-rw-r--r--source/blender/blenkernel/intern/sequencer.c6
-rw-r--r--source/blender/blenkernel/intern/sound.c4
-rw-r--r--source/blender/blenkernel/intern/subdiv_displacement_multires.c6
-rw-r--r--source/blender/blenkernel/intern/subdiv_foreach.c24
-rw-r--r--source/blender/blenkernel/intern/writeavi.c12
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c17
-rw-r--r--source/blender/blenlib/intern/math_geom.c2
-rw-r--r--source/blender/blenlib/intern/voronoi_2d.c13
-rw-r--r--source/blender/blenloader/intern/readfile.c44
-rw-r--r--source/blender/blenloader/intern/versioning_280.c33
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c7
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c4
-rw-r--r--source/blender/blenloader/intern/writefile.c10
-rw-r--r--source/blender/blentranslation/BLT_translation.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h2
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c2
-rw-r--r--source/blender/draw/engines/external/external_engine.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h10
-rw-r--r--source/blender/draw/engines/overlay/overlay_image.c7
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c8
-rw-r--r--source/blender/draw/intern/DRW_render.h2
-rw-r--r--source/blender/draw/intern/draw_manager.c2
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c3
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c111
-rw-r--r--source/blender/editors/animation/anim_deps.c4
-rw-r--r--source/blender/editors/animation/anim_filter.c41
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/animation/keyingsets.c4
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt7
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt2
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c12
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h4
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c120
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_paint.c18
-rw-r--r--source/blender/editors/include/ED_datafiles.h3
-rw-r--r--source/blender/editors/include/ED_fileselect.h9
-rw-r--r--source/blender/editors/include/ED_gpencil.h4
-rw-r--r--source/blender/editors/include/ED_keyframing.h6
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/ED_view3d.h16
-rw-r--r--source/blender/editors/include/ED_view3d_offscreen.h8
-rw-r--r--source/blender/editors/include/UI_interface.h10
-rw-r--r--source/blender/editors/include/UI_interface_icons.h11
-rw-r--r--source/blender/editors/include/UI_view2d.h10
-rw-r--r--source/blender/editors/interface/interface.c44
-rw-r--r--source/blender/editors/interface/interface_context_menu.c4
-rw-r--r--source/blender/editors/interface/interface_draw.c24
-rw-r--r--source/blender/editors/interface/interface_handlers.c30
-rw-r--r--source/blender/editors/interface/interface_icons.c24
-rw-r--r--source/blender/editors/interface/interface_intern.h2
-rw-r--r--source/blender/editors/interface/interface_layout.c27
-rw-r--r--source/blender/editors/interface/interface_panel.c4
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c3
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c4
-rw-r--r--source/blender/editors/interface/interface_region_popover.c2
-rw-r--r--source/blender/editors/interface/interface_region_search.c2
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c2
-rw-r--r--source/blender/editors/interface/interface_style.c6
-rw-r--r--source/blender/editors/interface/interface_templates.c14
-rw-r--r--source/blender/editors/interface/interface_widgets.c43
-rw-r--r--source/blender/editors/interface/view2d.c6
-rw-r--r--source/blender/editors/interface/view2d_ops.c2
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c8
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c8
-rw-r--r--source/blender/editors/object/object_modes.c4
-rw-r--r--source/blender/editors/object/object_modifier.c31
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/object/object_remesh.c16
-rw-r--r--source/blender/editors/screen/area.c11
-rw-r--r--source/blender/editors/screen/area_query.c12
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c78
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h3
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c14
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c2
-rw-r--r--source/blender/editors/space_file/file_draw.c6
-rw-r--r--source/blender/editors/space_file/file_ops.c14
-rw-r--r--source/blender/editors/space_file/filelist.c42
-rw-r--r--source/blender/editors/space_file/filelist.h4
-rw-r--r--source/blender/editors/space_file/filesel.c17
-rw-r--r--source/blender/editors/space_file/space_file.c4
-rw-r--r--source/blender/editors/space_image/image_ops.c13
-rw-r--r--source/blender/editors/space_image/space_image.c12
-rw-r--r--source/blender/editors/space_info/info_draw.c34
-rw-r--r--source/blender/editors/space_info/textview.h8
-rw-r--r--source/blender/editors/space_nla/nla_draw.c4
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c4
-rw-r--r--source/blender/editors/space_script/script_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c4
-rw-r--r--source/blender/editors/space_text/text_format_py.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c37
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c23
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h2
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c2
-rw-r--r--source/blender/editors/transform/CMakeLists.txt4
-rw-r--r--source/blender/editors/transform/transform_convert.c21
-rw-r--r--source/blender/editors/transform/transform_mode.h4
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c107
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h2
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt1
-rw-r--r--source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c3
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c233
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c314
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c10
-rw-r--r--source/blender/gpu/intern/gpu_draw.c71
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c2
-rw-r--r--source/blender/io/avi/intern/avi_rgb.c5
-rw-r--r--source/blender/io/usd/intern/abstract_hierarchy_iterator.cc28
-rw-r--r--source/blender/io/usd/intern/abstract_hierarchy_iterator.h2
-rw-r--r--source/blender/io/usd/intern/usd_capi.cc18
-rw-r--r--source/blender/io/usd/intern/usd_writer_abstract.cc32
-rw-r--r--source/blender/io/usd/intern/usd_writer_abstract.h1
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h75
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h3
-rw-r--r--source/blender/makesdna/DNA_image_types.h4
-rw-r--r--source/blender/makesrna/intern/makesrna.c4
-rw-r--r--source/blender/makesrna/intern/rna_ID.c9
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c232
-rw-r--r--source/blender/makesrna/intern/rna_image.c2
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c2
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c22
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keying.c1
-rw-r--r--source/blender/python/intern/bpy_rna.c177
-rw-r--r--source/blender/render/extern/include/RE_engine.h2
-rw-r--r--source/blender/render/intern/include/render_result.h4
-rw-r--r--source/blender/render/intern/source/external_engine.c2
-rw-r--r--source/blender/render/intern/source/render_result.c4
-rw-r--r--source/blender/windowmanager/intern/wm_files.c127
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c27
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c10
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c4
-rw-r--r--source/blender/windowmanager/intern/wm_splash_screen.c26
m---------source/tools0
-rw-r--r--tests/gtests/blenlib/BLI_delaunay_2d_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc20
-rw-r--r--tests/gtests/blenlib/BLI_polyfill_2d_test.cc2
-rw-r--r--tests/python/CMakeLists.txt5
-rw-r--r--tests/python/bl_pyapi_prop_array.py85
-rwxr-xr-xtests/python/eevee_render_tests.py10
246 files changed, 15769 insertions, 3003 deletions
diff --git a/extern/mantaflow/helper/util/vectorbase.h b/extern/mantaflow/helper/util/vectorbase.h
index a3135431eb3..41584663a0f 100644
--- a/extern/mantaflow/helper/util/vectorbase.h
+++ b/extern/mantaflow/helper/util/vectorbase.h
@@ -15,7 +15,7 @@
#define _VECTORBASE_H
// get rid of windos min/max defines
-#if defined(WIN32) || defined(_WIN32)
+#if (defined(WIN32) || defined(_WIN32)) && !defined(NOMINMAX)
# define NOMINMAX
#endif
diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h
index 48bb85c8479..574b655d6ce 100644
--- a/extern/mantaflow/preprocessed/gitinfo.h
+++ b/extern/mantaflow/preprocessed/gitinfo.h
@@ -1,3 +1,3 @@
-#define MANTA_GIT_VERSION "commit 1d55979473c25318f39c4a6bf48a5ab77b3bf39b"
+#define MANTA_GIT_VERSION "commit caae2ddea6ea895677aca88df00a130a67eeb6c7"
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index afa573c8dc5..2b872bb5c39 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -33,7 +33,7 @@ def _is_using_buggy_driver():
# in the version string, but those cards do not quite work and
# causing crashes.
return True
- regex = re.compile(".*Compatibility Profile Context ([0-9]+(\.[0-9]+)+)$")
+ regex = re.compile(".*Compatibility Profile Context ([0-9]+(\\.[0-9]+)+)$")
if not regex.match(version):
# Skip cards like FireGL
return False
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 3e0d40bc5fd..e545d436c85 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1415,8 +1415,6 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
light = context.light
clamp = light.cycles
- layout.use_property_decorate = False
-
if self.bl_space_type == 'PROPERTIES':
layout.row().prop(light, "type", expand=True)
layout.use_property_split = True
diff --git a/intern/cycles/device/cuda/device_cuda.h b/intern/cycles/device/cuda/device_cuda.h
index 6a0b39434aa..3e397da895b 100644
--- a/intern/cycles/device/cuda/device_cuda.h
+++ b/intern/cycles/device/cuda/device_cuda.h
@@ -155,9 +155,13 @@ class CUDADevice : public Device {
virtual void const_copy_to(const char *name, void *host, size_t size);
- void tex_alloc(device_memory &mem);
+ void global_alloc(device_memory &mem);
- void tex_free(device_memory &mem);
+ void global_free(device_memory &mem);
+
+ void tex_alloc(device_texture &mem);
+
+ void tex_free(device_texture &mem);
bool denoising_non_local_means(device_ptr image_ptr,
device_ptr guide_ptr,
diff --git a/intern/cycles/device/cuda/device_cuda_impl.cpp b/intern/cycles/device/cuda/device_cuda_impl.cpp
index 4df1ca2097a..a4e7bc2f64a 100644
--- a/intern/cycles/device/cuda/device_cuda_impl.cpp
+++ b/intern/cycles/device/cuda/device_cuda_impl.cpp
@@ -185,7 +185,7 @@ void CUDADevice::cuda_error_message(const string &message)
}
CUDADevice::CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
- : Device(info, stats, profiler, background_), texture_info(this, "__texture_info", MEM_TEXTURE)
+ : Device(info, stats, profiler, background_), texture_info(this, "__texture_info", MEM_GLOBAL)
{
first_error = true;
background = background_;
@@ -684,7 +684,8 @@ void CUDADevice::move_textures_to_host(size_t size, bool for_texture)
device_memory &mem = *pair.first;
CUDAMem *cmem = &pair.second;
- bool is_texture = (mem.type == MEM_TEXTURE) && (&mem != &texture_info);
+ bool is_texture = (mem.type == MEM_TEXTURE || mem.type == MEM_GLOBAL) &&
+ (&mem != &texture_info);
bool is_image = is_texture && (mem.data_height > 1);
/* Can't move this type of memory. */
@@ -724,8 +725,7 @@ void CUDADevice::move_textures_to_host(size_t size, bool for_texture)
device_ptr prev_pointer = max_mem->device_pointer;
size_t prev_size = max_mem->device_size;
- tex_free(*max_mem);
- tex_alloc(*max_mem);
+ mem_copy_to(*max_mem);
size = (max_size >= size) ? 0 : size - max_size;
max_mem->device_pointer = prev_pointer;
@@ -759,7 +759,7 @@ CUDADevice::CUDAMem *CUDADevice::generic_alloc(device_memory &mem, size_t pitch_
* If there is not enough room for working memory, we will try to move
* textures to host memory, assuming the performance impact would have
* been worse for working memory. */
- bool is_texture = (mem.type == MEM_TEXTURE) && (&mem != &texture_info);
+ bool is_texture = (mem.type == MEM_TEXTURE || mem.type == MEM_GLOBAL) && (&mem != &texture_info);
bool is_image = is_texture && (mem.data_height > 1);
size_t headroom = (is_texture) ? device_texture_headroom : device_working_headroom;
@@ -922,6 +922,9 @@ void CUDADevice::mem_alloc(device_memory &mem)
else if (mem.type == MEM_TEXTURE) {
assert(!"mem_alloc not supported for textures.");
}
+ else if (mem.type == MEM_GLOBAL) {
+ assert(!"mem_alloc not supported for global memory.");
+ }
else {
generic_alloc(mem);
}
@@ -932,9 +935,13 @@ void CUDADevice::mem_copy_to(device_memory &mem)
if (mem.type == MEM_PIXELS) {
assert(!"mem_copy_to not supported for pixels.");
}
+ else if (mem.type == MEM_GLOBAL) {
+ global_free(mem);
+ global_alloc(mem);
+ }
else if (mem.type == MEM_TEXTURE) {
- tex_free(mem);
- tex_alloc(mem);
+ tex_free((device_texture &)mem);
+ tex_alloc((device_texture &)mem);
}
else {
if (!mem.device_pointer) {
@@ -950,7 +957,7 @@ void CUDADevice::mem_copy_from(device_memory &mem, int y, int w, int h, int elem
if (mem.type == MEM_PIXELS && !background) {
pixels_copy_from(mem, y, w, h);
}
- else if (mem.type == MEM_TEXTURE) {
+ else if (mem.type == MEM_TEXTURE || mem.type == MEM_GLOBAL) {
assert(!"mem_copy_from not supported for textures.");
}
else if (mem.host_pointer) {
@@ -993,8 +1000,11 @@ void CUDADevice::mem_free(device_memory &mem)
if (mem.type == MEM_PIXELS && !background) {
pixels_free(mem);
}
+ else if (mem.type == MEM_GLOBAL) {
+ global_free(mem);
+ }
else if (mem.type == MEM_TEXTURE) {
- tex_free(mem);
+ tex_free((device_texture &)mem);
}
else {
generic_free(mem);
@@ -1017,7 +1027,25 @@ void CUDADevice::const_copy_to(const char *name, void *host, size_t size)
cuda_assert(cuMemcpyHtoD(mem, host, size));
}
-void CUDADevice::tex_alloc(device_memory &mem)
+void CUDADevice::global_alloc(device_memory &mem)
+{
+ CUDAContextScope scope(this);
+
+ generic_alloc(mem);
+ generic_copy_to(mem);
+
+ const_copy_to(mem.name, &mem.device_pointer, sizeof(mem.device_pointer));
+}
+
+void CUDADevice::global_free(device_memory &mem)
+{
+ if (mem.device_pointer) {
+ CUDAContextScope scope(this);
+ generic_free(mem);
+ }
+}
+
+void CUDADevice::tex_alloc(device_texture &mem)
{
CUDAContextScope scope(this);
@@ -1027,7 +1055,7 @@ void CUDADevice::tex_alloc(device_memory &mem)
size_t size = mem.memory_size();
CUaddress_mode address_mode = CU_TR_ADDRESS_MODE_WRAP;
- switch (mem.extension) {
+ switch (mem.info.extension) {
case EXTENSION_REPEAT:
address_mode = CU_TR_ADDRESS_MODE_WRAP;
break;
@@ -1043,22 +1071,13 @@ void CUDADevice::tex_alloc(device_memory &mem)
}
CUfilter_mode filter_mode;
- if (mem.interpolation == INTERPOLATION_CLOSEST) {
+ if (mem.info.interpolation == INTERPOLATION_CLOSEST) {
filter_mode = CU_TR_FILTER_MODE_POINT;
}
else {
filter_mode = CU_TR_FILTER_MODE_LINEAR;
}
- /* Data Storage */
- if (mem.interpolation == INTERPOLATION_NONE) {
- generic_alloc(mem);
- generic_copy_to(mem);
-
- const_copy_to(bind_name.c_str(), &mem.device_pointer, sizeof(mem.device_pointer));
- return;
- }
-
/* Image Texture Storage */
CUarray_format_enum format;
switch (mem.data_type) {
@@ -1169,15 +1188,6 @@ void CUDADevice::tex_alloc(device_memory &mem)
}
/* Kepler+, bindless textures. */
- int slot = 0;
- if (string_startswith(mem.name, "__tex_image")) {
- int pos = string(mem.name).rfind("_");
- slot = atoi(mem.name + pos + 1);
- }
- else {
- assert(0);
- }
-
CUDA_RESOURCE_DESC resDesc;
memset(&resDesc, 0, sizeof(resDesc));
@@ -1214,6 +1224,7 @@ void CUDADevice::tex_alloc(device_memory &mem)
cuda_assert(cuTexObjectCreate(&cmem->texobject, &resDesc, &texDesc, NULL));
/* Resize once */
+ const uint slot = mem.slot;
if (slot >= texture_info.size()) {
/* Allocate some slots in advance, to reduce amount
* of re-allocations. */
@@ -1221,19 +1232,12 @@ void CUDADevice::tex_alloc(device_memory &mem)
}
/* Set Mapping and tag that we need to (re-)upload to device */
- TextureInfo &info = texture_info[slot];
- info.data = (uint64_t)cmem->texobject;
- info.data_type = mem.image_data_type;
- info.cl_buffer = 0;
- info.interpolation = mem.interpolation;
- info.extension = mem.extension;
- info.width = mem.data_width;
- info.height = mem.data_height;
- info.depth = mem.data_depth;
+ texture_info[slot] = mem.info;
+ texture_info[slot].data = (uint64_t)cmem->texobject;
need_texture_info = true;
}
-void CUDADevice::tex_free(device_memory &mem)
+void CUDADevice::tex_free(device_texture &mem)
{
if (mem.device_pointer) {
CUDAContextScope scope(this);
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 56569a5ee3d..57e8523e02a 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -264,7 +264,7 @@ class CPUDevice : public Device {
CPUDevice(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background_)
: Device(info_, stats_, profiler_, background_),
- texture_info(this, "__texture_info", MEM_TEXTURE),
+ texture_info(this, "__texture_info", MEM_GLOBAL),
#define REGISTER_KERNEL(name) name##_kernel(KERNEL_FUNCTIONS(name))
REGISTER_KERNEL(path_trace),
REGISTER_KERNEL(convert_to_half_float),
@@ -372,6 +372,9 @@ class CPUDevice : public Device {
if (mem.type == MEM_TEXTURE) {
assert(!"mem_alloc not supported for textures.");
}
+ else if (mem.type == MEM_GLOBAL) {
+ assert(!"mem_alloc not supported for global memory.");
+ }
else {
if (mem.name) {
VLOG(1) << "Buffer allocate: " << mem.name << ", "
@@ -396,9 +399,13 @@ class CPUDevice : public Device {
void mem_copy_to(device_memory &mem)
{
- if (mem.type == MEM_TEXTURE) {
- tex_free(mem);
- tex_alloc(mem);
+ if (mem.type == MEM_GLOBAL) {
+ global_free(mem);
+ global_alloc(mem);
+ }
+ else if (mem.type == MEM_TEXTURE) {
+ tex_free((device_texture &)mem);
+ tex_alloc((device_texture &)mem);
}
else if (mem.type == MEM_PIXELS) {
assert(!"mem_copy_to not supported for pixels.");
@@ -430,8 +437,11 @@ class CPUDevice : public Device {
void mem_free(device_memory &mem)
{
- if (mem.type == MEM_TEXTURE) {
- tex_free(mem);
+ if (mem.type == MEM_GLOBAL) {
+ global_free(mem);
+ }
+ else if (mem.type == MEM_TEXTURE) {
+ tex_free((device_texture &)mem);
}
else if (mem.device_pointer) {
if (mem.type == MEM_DEVICE_ONLY) {
@@ -453,52 +463,50 @@ class CPUDevice : public Device {
kernel_const_copy(&kernel_globals, name, host, size);
}
- void tex_alloc(device_memory &mem)
+ void global_alloc(device_memory &mem)
{
- VLOG(1) << "Texture allocate: " << mem.name << ", "
+ VLOG(1) << "Global memory allocate: " << mem.name << ", "
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
<< string_human_readable_size(mem.memory_size()) << ")";
- if (mem.interpolation == INTERPOLATION_NONE) {
- /* Data texture. */
- kernel_tex_copy(&kernel_globals, mem.name, mem.host_pointer, mem.data_size);
- }
- else {
- /* Image Texture. */
- int slot = 0;
- if (string_startswith(mem.name, "__tex_image")) {
- int pos = string(mem.name).rfind("_");
- slot = atoi(mem.name + pos + 1);
- }
- else {
- assert(0);
- }
-
- if (slot >= texture_info.size()) {
- /* Allocate some slots in advance, to reduce amount
- * of re-allocations. */
- texture_info.resize(slot + 128);
- }
+ kernel_global_memory_copy(&kernel_globals, mem.name, mem.host_pointer, mem.data_size);
- TextureInfo &info = texture_info[slot];
- info.data = (uint64_t)mem.host_pointer;
- info.data_type = mem.image_data_type;
- info.cl_buffer = 0;
- info.interpolation = mem.interpolation;
- info.extension = mem.extension;
- info.width = mem.data_width;
- info.height = mem.data_height;
- info.depth = mem.data_depth;
+ mem.device_pointer = (device_ptr)mem.host_pointer;
+ mem.device_size = mem.memory_size();
+ stats.mem_alloc(mem.device_size);
+ }
- need_texture_info = true;
+ void global_free(device_memory &mem)
+ {
+ if (mem.device_pointer) {
+ mem.device_pointer = 0;
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
}
+ }
+
+ void tex_alloc(device_texture &mem)
+ {
+ VLOG(1) << "Texture allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
mem.device_pointer = (device_ptr)mem.host_pointer;
mem.device_size = mem.memory_size();
stats.mem_alloc(mem.device_size);
+
+ const uint slot = mem.slot;
+ if (slot >= texture_info.size()) {
+ /* Allocate some slots in advance, to reduce amount of re-allocations. */
+ texture_info.resize(slot + 128);
+ }
+
+ texture_info[slot] = mem.info;
+ texture_info[slot].data = (uint64_t)mem.host_pointer;
+ need_texture_info = true;
}
- void tex_free(device_memory &mem)
+ void tex_free(device_texture &mem)
{
if (mem.device_pointer) {
mem.device_pointer = 0;
diff --git a/intern/cycles/device/device_memory.cpp b/intern/cycles/device/device_memory.cpp
index f22b91f3fa1..3c4f68cfc77 100644
--- a/intern/cycles/device/device_memory.cpp
+++ b/intern/cycles/device/device_memory.cpp
@@ -31,9 +31,6 @@ device_memory::device_memory(Device *device, const char *name, MemoryType type)
data_depth(0),
type(type),
name(name),
- image_data_type(IMAGE_DATA_NUM_TYPES),
- interpolation(INTERPOLATION_NONE),
- extension(EXTENSION_REPEAT),
device(device),
device_pointer(0),
host_pointer(0),
@@ -77,7 +74,7 @@ void device_memory::host_free()
void device_memory::device_alloc()
{
- assert(!device_pointer && type != MEM_TEXTURE);
+ assert(!device_pointer && type != MEM_TEXTURE && type != MEM_GLOBAL);
device->mem_alloc(*this);
}
@@ -97,7 +94,7 @@ void device_memory::device_copy_to()
void device_memory::device_copy_from(int y, int w, int h, int elem)
{
- assert(type != MEM_TEXTURE && type != MEM_READ_ONLY);
+ assert(type != MEM_TEXTURE && type != MEM_READ_ONLY && type != MEM_GLOBAL);
device->mem_copy_from(*this, y, w, h, elem);
}
@@ -140,4 +137,93 @@ device_sub_ptr::~device_sub_ptr()
device->mem_free_sub_ptr(ptr);
}
+/* Device Texture */
+
+device_texture::device_texture(Device *device,
+ const char *name,
+ const uint slot,
+ ImageDataType image_data_type,
+ InterpolationType interpolation,
+ ExtensionType extension)
+ : device_memory(device, name, MEM_TEXTURE), slot(slot)
+{
+ switch (image_data_type) {
+ case IMAGE_DATA_TYPE_FLOAT4:
+ data_type = TYPE_FLOAT;
+ data_elements = 4;
+ break;
+ case IMAGE_DATA_TYPE_FLOAT:
+ data_type = TYPE_FLOAT;
+ data_elements = 1;
+ break;
+ case IMAGE_DATA_TYPE_BYTE4:
+ data_type = TYPE_UCHAR;
+ data_elements = 4;
+ break;
+ case IMAGE_DATA_TYPE_BYTE:
+ data_type = TYPE_UCHAR;
+ data_elements = 1;
+ break;
+ case IMAGE_DATA_TYPE_HALF4:
+ data_type = TYPE_HALF;
+ data_elements = 4;
+ break;
+ case IMAGE_DATA_TYPE_HALF:
+ data_type = TYPE_HALF;
+ data_elements = 1;
+ break;
+ case IMAGE_DATA_TYPE_USHORT4:
+ data_type = TYPE_UINT16;
+ data_elements = 4;
+ break;
+ case IMAGE_DATA_TYPE_USHORT:
+ data_type = TYPE_UINT16;
+ data_elements = 1;
+ break;
+ case IMAGE_DATA_NUM_TYPES:
+ assert(0);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.data_type = image_data_type;
+ info.interpolation = interpolation;
+ info.extension = extension;
+}
+
+device_texture::~device_texture()
+{
+ device_free();
+ host_free();
+}
+
+/* Host memory allocation. */
+void *device_texture::alloc(const size_t width, const size_t height, const size_t depth)
+{
+ const size_t new_size = size(width, height, depth);
+
+ if (new_size != data_size) {
+ device_free();
+ host_free();
+ host_pointer = host_alloc(data_elements * datatype_size(data_type) * new_size);
+ assert(device_pointer == 0);
+ }
+
+ data_size = new_size;
+ data_width = width;
+ data_height = height;
+ data_depth = depth;
+
+ info.width = width;
+ info.height = height;
+ info.depth = depth;
+
+ return host_pointer;
+}
+
+void device_texture::copy_to_device()
+{
+ device_copy_to();
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 617cc0c4342..1c20db900bc 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -23,6 +23,7 @@
#include "util/util_array.h"
#include "util/util_half.h"
+#include "util/util_string.h"
#include "util/util_texture.h"
#include "util/util_types.h"
#include "util/util_vector.h"
@@ -31,7 +32,14 @@ CCL_NAMESPACE_BEGIN
class Device;
-enum MemoryType { MEM_READ_ONLY, MEM_READ_WRITE, MEM_DEVICE_ONLY, MEM_TEXTURE, MEM_PIXELS };
+enum MemoryType {
+ MEM_READ_ONLY,
+ MEM_READ_WRITE,
+ MEM_DEVICE_ONLY,
+ MEM_GLOBAL,
+ MEM_TEXTURE,
+ MEM_PIXELS
+};
/* Supported Data Types */
@@ -208,9 +216,6 @@ class device_memory {
size_t data_depth;
MemoryType type;
const char *name;
- ImageDataType image_data_type;
- InterpolationType interpolation;
- ExtensionType extension;
/* Pointers. */
Device *device;
@@ -311,7 +316,7 @@ template<typename T> class device_only_memory : public device_memory {
* in and copied to the device with copy_to_device(). Or alternatively
* allocated and set to zero on the device with zero_to_device().
*
- * When using memory type MEM_TEXTURE, a pointer to this memory will be
+ * When using memory type MEM_GLOBAL, a pointer to this memory will be
* automatically attached to kernel globals, using the provided name
* matching an entry in kernel_textures.h. */
@@ -504,6 +509,33 @@ class device_sub_ptr {
device_ptr ptr;
};
+/* Device Texture
+ *
+ * 2D or 3D image texture memory. */
+
+class device_texture : public device_memory {
+ public:
+ device_texture(Device *device,
+ const char *name,
+ const uint slot,
+ ImageDataType image_data_type,
+ InterpolationType interpolation,
+ ExtensionType extension);
+ ~device_texture();
+
+ void *alloc(const size_t width, const size_t height, const size_t depth = 0);
+ void copy_to_device();
+
+ uint slot;
+ TextureInfo info;
+
+ protected:
+ size_t size(const size_t width, const size_t height, const size_t depth)
+ {
+ return width * ((height == 0) ? 1 : height) * ((depth == 0) ? 1 : depth);
+ }
+};
+
CCL_NAMESPACE_END
#endif /* __DEVICE_MEMORY_H__ */
diff --git a/intern/cycles/device/opencl/device_opencl.h b/intern/cycles/device/opencl/device_opencl.h
index b761726b1ad..53017c34b2b 100644
--- a/intern/cycles/device/opencl/device_opencl.h
+++ b/intern/cycles/device/opencl/device_opencl.h
@@ -428,8 +428,10 @@ class OpenCLDevice : public Device {
int mem_sub_ptr_alignment();
void const_copy_to(const char *name, void *host, size_t size);
- void tex_alloc(device_memory &mem);
- void tex_free(device_memory &mem);
+ void global_alloc(device_memory &mem);
+ void global_free(device_memory &mem);
+ void tex_alloc(device_texture &mem);
+ void tex_free(device_texture &mem);
size_t global_size_round_up(int group_size, int global_size);
void enqueue_kernel(cl_kernel kernel,
diff --git a/intern/cycles/device/opencl/device_opencl_impl.cpp b/intern/cycles/device/opencl/device_opencl_impl.cpp
index 09d3b78dd28..6b1b0e4c369 100644
--- a/intern/cycles/device/opencl/device_opencl_impl.cpp
+++ b/intern/cycles/device/opencl/device_opencl_impl.cpp
@@ -613,7 +613,7 @@ OpenCLDevice::OpenCLDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, b
kernel_programs(this),
preview_programs(this),
memory_manager(this),
- texture_info(this, "__texture_info", MEM_TEXTURE)
+ texture_info(this, "__texture_info", MEM_GLOBAL)
{
cpPlatform = NULL;
cdDevice = NULL;
@@ -945,7 +945,7 @@ void OpenCLDevice::mem_alloc(device_memory &mem)
cl_mem_flags mem_flag;
void *mem_ptr = NULL;
- if (mem.type == MEM_READ_ONLY || mem.type == MEM_TEXTURE)
+ if (mem.type == MEM_READ_ONLY || mem.type == MEM_TEXTURE || mem.type == MEM_GLOBAL)
mem_flag = CL_MEM_READ_ONLY;
else
mem_flag = CL_MEM_READ_WRITE;
@@ -969,9 +969,13 @@ void OpenCLDevice::mem_alloc(device_memory &mem)
void OpenCLDevice::mem_copy_to(device_memory &mem)
{
- if (mem.type == MEM_TEXTURE) {
- tex_free(mem);
- tex_alloc(mem);
+ if (mem.type == MEM_GLOBAL) {
+ global_free(mem);
+ global_alloc(mem);
+ }
+ else if (mem.type == MEM_TEXTURE) {
+ tex_free((device_texture &)mem);
+ tex_alloc((device_texture &)mem);
}
else {
if (!mem.device_pointer) {
@@ -1077,8 +1081,11 @@ void OpenCLDevice::mem_zero(device_memory &mem)
void OpenCLDevice::mem_free(device_memory &mem)
{
- if (mem.type == MEM_TEXTURE) {
- tex_free(mem);
+ if (mem.type == MEM_GLOBAL) {
+ global_free(mem);
+ }
+ else if (mem.type == MEM_TEXTURE) {
+ tex_free((device_texture &)mem);
}
else {
if (mem.device_pointer) {
@@ -1101,7 +1108,7 @@ int OpenCLDevice::mem_sub_ptr_alignment()
device_ptr OpenCLDevice::mem_alloc_sub_ptr(device_memory &mem, int offset, int size)
{
cl_mem_flags mem_flag;
- if (mem.type == MEM_READ_ONLY || mem.type == MEM_TEXTURE)
+ if (mem.type == MEM_READ_ONLY || mem.type == MEM_TEXTURE || mem.type == MEM_GLOBAL)
mem_flag = CL_MEM_READ_ONLY;
else
mem_flag = CL_MEM_READ_WRITE;
@@ -1141,9 +1148,9 @@ void OpenCLDevice::const_copy_to(const char *name, void *host, size_t size)
data->copy_to_device();
}
-void OpenCLDevice::tex_alloc(device_memory &mem)
+void OpenCLDevice::global_alloc(device_memory &mem)
{
- VLOG(1) << "Texture allocate: " << mem.name << ", "
+ VLOG(1) << "Global memory allocate: " << mem.name << ", "
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
<< string_human_readable_size(mem.memory_size()) << ")";
@@ -1155,7 +1162,7 @@ void OpenCLDevice::tex_alloc(device_memory &mem)
textures_need_update = true;
}
-void OpenCLDevice::tex_free(device_memory &mem)
+void OpenCLDevice::global_free(device_memory &mem)
{
if (mem.device_pointer) {
mem.device_pointer = 0;
@@ -1173,6 +1180,25 @@ void OpenCLDevice::tex_free(device_memory &mem)
}
}
+void OpenCLDevice::tex_alloc(device_texture &mem)
+{
+ VLOG(1) << "Texture allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+
+ memory_manager.alloc(mem.name, mem);
+ /* Set the pointer to non-null to keep code that inspects its value from thinking its
+ * unallocated. */
+ mem.device_pointer = 1;
+ textures[mem.name] = &mem;
+ textures_need_update = true;
+}
+
+void OpenCLDevice::tex_free(device_texture &mem)
+{
+ global_free(mem);
+}
+
size_t OpenCLDevice::global_size_round_up(int group_size, int global_size)
{
int r = global_size % group_size;
@@ -1273,10 +1299,10 @@ void OpenCLDevice::flush_texture_buffers()
foreach (TexturesMap::value_type &tex, textures) {
string name = tex.first;
+ device_memory *mem = tex.second;
- if (string_startswith(name, "__tex_image")) {
- int pos = name.rfind("_");
- int id = atoi(name.data() + pos + 1);
+ if (mem->type == MEM_TEXTURE) {
+ const uint id = ((device_texture *)mem)->slot;
texture_slots.push_back(texture_slot_t(name, num_data_slots + id));
num_slots = max(num_slots, num_data_slots + id + 1);
}
@@ -1289,24 +1315,20 @@ void OpenCLDevice::flush_texture_buffers()
/* Fill in descriptors */
foreach (texture_slot_t &slot, texture_slots) {
+ device_memory *mem = textures[slot.name];
TextureInfo &info = texture_info[slot.slot];
MemoryManager::BufferDescriptor desc = memory_manager.get_descriptor(slot.name);
- info.data = desc.offset;
- info.cl_buffer = desc.device_buffer;
-
- if (string_startswith(slot.name, "__tex_image")) {
- device_memory *mem = textures[slot.name];
- info.data_type = mem->image_data_type;
-
- info.width = mem->data_width;
- info.height = mem->data_height;
- info.depth = mem->data_depth;
-
- info.interpolation = mem->interpolation;
- info.extension = mem->extension;
+ if (mem->type == MEM_TEXTURE) {
+ info = ((device_texture *)mem)->info;
+ }
+ else {
+ memset(&info, 0, sizeof(TextureInfo));
}
+
+ info.data = desc.offset;
+ info.cl_buffer = desc.device_buffer;
}
/* Force write of descriptors. */
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index dfdd8843f29..3debfc76fbb 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -38,7 +38,7 @@ void *kernel_osl_memory(KernelGlobals *kg);
bool kernel_osl_use(KernelGlobals *kg);
void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size);
-void kernel_tex_copy(KernelGlobals *kg, const char *name, void *mem, size_t size);
+void kernel_global_memory_copy(KernelGlobals *kg, const char *name, void *mem, size_t size);
#define KERNEL_ARCH cpu
#include "kernel/kernels/cpu/kernel_cpu.h"
diff --git a/intern/cycles/kernel/kernels/cpu/kernel.cpp b/intern/cycles/kernel/kernels/cpu/kernel.cpp
index f2146302a27..8829a14ead5 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel.cpp
@@ -72,7 +72,7 @@ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t s
assert(0);
}
-void kernel_tex_copy(KernelGlobals *kg, const char *name, void *mem, size_t size)
+void kernel_global_memory_copy(KernelGlobals *kg, const char *name, void *mem, size_t size)
{
if (0) {
}
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index b4539b5ce3c..8868811b5e7 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -150,7 +150,7 @@ int ImageHandle::svm_slot(const int tile_index) const
if (manager->osl_texture_system) {
ImageManager::Image *img = manager->images[tile_slots[tile_index]];
- if (img->loader->osl_filepath()) {
+ if (!img->loader->osl_filepath().empty()) {
return -1;
}
}
@@ -158,7 +158,7 @@ int ImageHandle::svm_slot(const int tile_index) const
return tile_slots[tile_index];
}
-device_memory *ImageHandle::image_memory(const int tile_index) const
+device_texture *ImageHandle::image_memory(const int tile_index) const
{
if (tile_index >= tile_slots.size()) {
return NULL;
@@ -304,7 +304,12 @@ void ImageManager::load_image_metadata(Image *img)
metadata = ImageMetaData();
metadata.colorspace = img->params.colorspace;
- img->loader->load_metadata(metadata);
+ if (img->loader->load_metadata(metadata)) {
+ assert(metadata.type != IMAGE_DATA_NUM_TYPES);
+ }
+ else {
+ metadata.type = IMAGE_DATA_TYPE_BYTE4;
+ }
metadata.detect_colorspace();
@@ -394,7 +399,7 @@ int ImageManager::add_image_slot(ImageLoader *loader,
img->params = params;
img->loader = loader;
img->need_metadata = true;
- img->need_load = !(osl_texture_system && img->loader->osl_filepath());
+ img->need_load = !(osl_texture_system && !img->loader->osl_filepath().empty());
img->builtin = builtin;
img->users = 1;
img->mem = NULL;
@@ -438,10 +443,8 @@ static bool image_associate_alpha(ImageManager::Image *img)
img->params.alpha_type == IMAGE_ALPHA_CHANNEL_PACKED);
}
-template<TypeDesc::BASETYPE FileFormat, typename StorageType, typename DeviceType>
-bool ImageManager::file_load_image(Image *img,
- int texture_limit,
- device_vector<DeviceType> &tex_img)
+template<TypeDesc::BASETYPE FileFormat, typename StorageType>
+bool ImageManager::file_load_image(Image *img, int texture_limit)
{
/* we only handle certain number of components */
if (!(img->metadata.channels >= 1 && img->metadata.channels <= 4)) {
@@ -470,7 +473,7 @@ bool ImageManager::file_load_image(Image *img,
}
else {
thread_scoped_lock device_lock(device_mutex);
- pixels = (StorageType *)tex_img.alloc(width, height, depth);
+ pixels = (StorageType *)img->mem->alloc(width, height, depth);
}
if (pixels == NULL) {
@@ -587,7 +590,7 @@ bool ImageManager::file_load_image(Image *img,
{
thread_scoped_lock device_lock(device_mutex);
- texture_pixels = (StorageType *)tex_img.alloc(scaled_width, scaled_height, scaled_depth);
+ texture_pixels = (StorageType *)img->mem->alloc(scaled_width, scaled_height, scaled_depth);
}
memcpy(texture_pixels, &scaled_pixels[0], scaled_pixels.size() * sizeof(StorageType));
@@ -596,14 +599,6 @@ bool ImageManager::file_load_image(Image *img,
return true;
}
-static void image_set_device_memory(ImageManager::Image *img, device_memory *mem)
-{
- img->mem = mem;
- mem->image_data_type = img->metadata.type;
- mem->interpolation = img->params.interpolation;
- mem->extension = img->params.extension;
-}
-
void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Progress *progress)
{
if (progress->get_cancel()) {
@@ -619,7 +614,7 @@ void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Pro
load_image_metadata(img);
ImageDataType type = img->metadata.type;
- /* Slot assignment */
+ /* Name for debugging. */
img->mem_name = string_printf("__tex_image_%s_%03d", name_from_type(type), slot);
/* Free previous texture in slot. */
@@ -629,154 +624,98 @@ void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Pro
img->mem = NULL;
}
+ img->mem = new device_texture(
+ device, img->mem_name.c_str(), slot, type, img->params.interpolation, img->params.extension);
+
/* Create new texture. */
if (type == IMAGE_DATA_TYPE_FLOAT4) {
- device_vector<float4> *tex_img = new device_vector<float4>(
- device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if (!file_load_image<TypeDesc::FLOAT, float>(img, texture_limit, *tex_img)) {
+ if (!file_load_image<TypeDesc::FLOAT, float>(img, texture_limit)) {
/* on failure to load, we set a 1x1 pixels pink image */
thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float *)tex_img->alloc(1, 1);
+ float *pixels = (float *)img->mem->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R;
pixels[1] = TEX_IMAGE_MISSING_G;
pixels[2] = TEX_IMAGE_MISSING_B;
pixels[3] = TEX_IMAGE_MISSING_A;
}
-
- image_set_device_memory(img, tex_img);
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
}
else if (type == IMAGE_DATA_TYPE_FLOAT) {
- device_vector<float> *tex_img = new device_vector<float>(
- device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if (!file_load_image<TypeDesc::FLOAT, float>(img, texture_limit, *tex_img)) {
+ if (!file_load_image<TypeDesc::FLOAT, float>(img, texture_limit)) {
/* on failure to load, we set a 1x1 pixels pink image */
thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float *)tex_img->alloc(1, 1);
+ float *pixels = (float *)img->mem->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R;
}
-
- image_set_device_memory(img, tex_img);
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
}
else if (type == IMAGE_DATA_TYPE_BYTE4) {
- device_vector<uchar4> *tex_img = new device_vector<uchar4>(
- device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if (!file_load_image<TypeDesc::UINT8, uchar>(img, texture_limit, *tex_img)) {
+ if (!file_load_image<TypeDesc::UINT8, uchar>(img, texture_limit)) {
/* on failure to load, we set a 1x1 pixels pink image */
thread_scoped_lock device_lock(device_mutex);
- uchar *pixels = (uchar *)tex_img->alloc(1, 1);
+ uchar *pixels = (uchar *)img->mem->alloc(1, 1);
pixels[0] = (TEX_IMAGE_MISSING_R * 255);
pixels[1] = (TEX_IMAGE_MISSING_G * 255);
pixels[2] = (TEX_IMAGE_MISSING_B * 255);
pixels[3] = (TEX_IMAGE_MISSING_A * 255);
}
-
- image_set_device_memory(img, tex_img);
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
}
else if (type == IMAGE_DATA_TYPE_BYTE) {
- device_vector<uchar> *tex_img = new device_vector<uchar>(
- device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if (!file_load_image<TypeDesc::UINT8, uchar>(img, texture_limit, *tex_img)) {
+ if (!file_load_image<TypeDesc::UINT8, uchar>(img, texture_limit)) {
/* on failure to load, we set a 1x1 pixels pink image */
thread_scoped_lock device_lock(device_mutex);
- uchar *pixels = (uchar *)tex_img->alloc(1, 1);
+ uchar *pixels = (uchar *)img->mem->alloc(1, 1);
pixels[0] = (TEX_IMAGE_MISSING_R * 255);
}
-
- image_set_device_memory(img, tex_img);
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
}
else if (type == IMAGE_DATA_TYPE_HALF4) {
- device_vector<half4> *tex_img = new device_vector<half4>(
- device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if (!file_load_image<TypeDesc::HALF, half>(img, texture_limit, *tex_img)) {
+ if (!file_load_image<TypeDesc::HALF, half>(img, texture_limit)) {
/* on failure to load, we set a 1x1 pixels pink image */
thread_scoped_lock device_lock(device_mutex);
- half *pixels = (half *)tex_img->alloc(1, 1);
+ half *pixels = (half *)img->mem->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R;
pixels[1] = TEX_IMAGE_MISSING_G;
pixels[2] = TEX_IMAGE_MISSING_B;
pixels[3] = TEX_IMAGE_MISSING_A;
}
-
- image_set_device_memory(img, tex_img);
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
}
else if (type == IMAGE_DATA_TYPE_USHORT) {
- device_vector<uint16_t> *tex_img = new device_vector<uint16_t>(
- device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, texture_limit, *tex_img)) {
+ if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, texture_limit)) {
/* on failure to load, we set a 1x1 pixels pink image */
thread_scoped_lock device_lock(device_mutex);
- uint16_t *pixels = (uint16_t *)tex_img->alloc(1, 1);
+ uint16_t *pixels = (uint16_t *)img->mem->alloc(1, 1);
pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
}
-
- image_set_device_memory(img, tex_img);
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
}
else if (type == IMAGE_DATA_TYPE_USHORT4) {
- device_vector<ushort4> *tex_img = new device_vector<ushort4>(
- device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, texture_limit, *tex_img)) {
+ if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, texture_limit)) {
/* on failure to load, we set a 1x1 pixels pink image */
thread_scoped_lock device_lock(device_mutex);
- uint16_t *pixels = (uint16_t *)tex_img->alloc(1, 1);
+ uint16_t *pixels = (uint16_t *)img->mem->alloc(1, 1);
pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
pixels[1] = (TEX_IMAGE_MISSING_G * 65535);
pixels[2] = (TEX_IMAGE_MISSING_B * 65535);
pixels[3] = (TEX_IMAGE_MISSING_A * 65535);
}
-
- image_set_device_memory(img, tex_img);
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
}
else if (type == IMAGE_DATA_TYPE_HALF) {
- device_vector<half> *tex_img = new device_vector<half>(
- device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if (!file_load_image<TypeDesc::HALF, half>(img, texture_limit, *tex_img)) {
+ if (!file_load_image<TypeDesc::HALF, half>(img, texture_limit)) {
/* on failure to load, we set a 1x1 pixels pink image */
thread_scoped_lock device_lock(device_mutex);
- half *pixels = (half *)tex_img->alloc(1, 1);
+ half *pixels = (half *)img->mem->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R;
}
+ }
- image_set_device_memory(img, tex_img);
-
+ {
thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
+ img->mem->copy_to_device();
}
/* Cleanup memory in image loader. */
@@ -794,7 +733,7 @@ void ImageManager::device_free_image(Device *, int slot)
if (osl_texture_system) {
#ifdef WITH_OSL
ustring filepath = img->loader->osl_filepath();
- if (filepath) {
+ if (!filepath.empty()) {
((OSL::TextureSystem *)osl_texture_system)->invalidate(filepath);
}
#endif
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 82f3e2759c6..734bb83f774 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -142,7 +142,7 @@ class ImageHandle {
ImageMetaData metadata();
int svm_slot(const int tile_index = 0) const;
- device_memory *image_memory(const int tile_index = 0) const;
+ device_texture *image_memory(const int tile_index = 0) const;
protected:
vector<int> tile_slots;
@@ -191,7 +191,7 @@ class ImageManager {
bool builtin;
string mem_name;
- device_memory *mem;
+ device_texture *mem;
int users;
thread_mutex mutex;
@@ -212,8 +212,8 @@ class ImageManager {
void load_image_metadata(Image *img);
- template<TypeDesc::BASETYPE FileFormat, typename StorageType, typename DeviceType>
- bool file_load_image(Image *img, int texture_limit, device_vector<DeviceType> &tex_img);
+ template<TypeDesc::BASETYPE FileFormat, typename StorageType>
+ bool file_load_image(Image *img, int texture_limit);
void device_load_image(Device *device, Scene *scene, int slot, Progress *progress);
void device_free_image(Device *device, int slot);
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 1e20513e88a..76f62fd6690 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -41,44 +41,44 @@
CCL_NAMESPACE_BEGIN
DeviceScene::DeviceScene(Device *device)
- : bvh_nodes(device, "__bvh_nodes", MEM_TEXTURE),
- bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_TEXTURE),
- object_node(device, "__object_node", MEM_TEXTURE),
- prim_tri_index(device, "__prim_tri_index", MEM_TEXTURE),
- prim_tri_verts(device, "__prim_tri_verts", MEM_TEXTURE),
- prim_type(device, "__prim_type", MEM_TEXTURE),
- prim_visibility(device, "__prim_visibility", MEM_TEXTURE),
- prim_index(device, "__prim_index", MEM_TEXTURE),
- prim_object(device, "__prim_object", MEM_TEXTURE),
- prim_time(device, "__prim_time", MEM_TEXTURE),
- tri_shader(device, "__tri_shader", MEM_TEXTURE),
- tri_vnormal(device, "__tri_vnormal", MEM_TEXTURE),
- tri_vindex(device, "__tri_vindex", MEM_TEXTURE),
- tri_patch(device, "__tri_patch", MEM_TEXTURE),
- tri_patch_uv(device, "__tri_patch_uv", MEM_TEXTURE),
- curves(device, "__curves", MEM_TEXTURE),
- curve_keys(device, "__curve_keys", MEM_TEXTURE),
- patches(device, "__patches", MEM_TEXTURE),
- objects(device, "__objects", MEM_TEXTURE),
- object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE),
- object_motion(device, "__object_motion", MEM_TEXTURE),
- object_flag(device, "__object_flag", MEM_TEXTURE),
- camera_motion(device, "__camera_motion", MEM_TEXTURE),
- attributes_map(device, "__attributes_map", MEM_TEXTURE),
- attributes_float(device, "__attributes_float", MEM_TEXTURE),
- attributes_float2(device, "__attributes_float2", MEM_TEXTURE),
- attributes_float3(device, "__attributes_float3", MEM_TEXTURE),
- attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE),
- light_distribution(device, "__light_distribution", MEM_TEXTURE),
- lights(device, "__lights", MEM_TEXTURE),
- light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_TEXTURE),
- light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_TEXTURE),
- particles(device, "__particles", MEM_TEXTURE),
- svm_nodes(device, "__svm_nodes", MEM_TEXTURE),
- shaders(device, "__shaders", MEM_TEXTURE),
- lookup_table(device, "__lookup_table", MEM_TEXTURE),
- sample_pattern_lut(device, "__sample_pattern_lut", MEM_TEXTURE),
- ies_lights(device, "__ies", MEM_TEXTURE)
+ : bvh_nodes(device, "__bvh_nodes", MEM_GLOBAL),
+ bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_GLOBAL),
+ object_node(device, "__object_node", MEM_GLOBAL),
+ prim_tri_index(device, "__prim_tri_index", MEM_GLOBAL),
+ prim_tri_verts(device, "__prim_tri_verts", MEM_GLOBAL),
+ prim_type(device, "__prim_type", MEM_GLOBAL),
+ prim_visibility(device, "__prim_visibility", MEM_GLOBAL),
+ prim_index(device, "__prim_index", MEM_GLOBAL),
+ prim_object(device, "__prim_object", MEM_GLOBAL),
+ prim_time(device, "__prim_time", MEM_GLOBAL),
+ tri_shader(device, "__tri_shader", MEM_GLOBAL),
+ tri_vnormal(device, "__tri_vnormal", MEM_GLOBAL),
+ tri_vindex(device, "__tri_vindex", MEM_GLOBAL),
+ tri_patch(device, "__tri_patch", MEM_GLOBAL),
+ tri_patch_uv(device, "__tri_patch_uv", MEM_GLOBAL),
+ curves(device, "__curves", MEM_GLOBAL),
+ curve_keys(device, "__curve_keys", MEM_GLOBAL),
+ patches(device, "__patches", MEM_GLOBAL),
+ objects(device, "__objects", MEM_GLOBAL),
+ object_motion_pass(device, "__object_motion_pass", MEM_GLOBAL),
+ object_motion(device, "__object_motion", MEM_GLOBAL),
+ object_flag(device, "__object_flag", MEM_GLOBAL),
+ camera_motion(device, "__camera_motion", MEM_GLOBAL),
+ attributes_map(device, "__attributes_map", MEM_GLOBAL),
+ attributes_float(device, "__attributes_float", MEM_GLOBAL),
+ attributes_float2(device, "__attributes_float2", MEM_GLOBAL),
+ attributes_float3(device, "__attributes_float3", MEM_GLOBAL),
+ attributes_uchar4(device, "__attributes_uchar4", MEM_GLOBAL),
+ light_distribution(device, "__light_distribution", MEM_GLOBAL),
+ lights(device, "__lights", MEM_GLOBAL),
+ light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_GLOBAL),
+ light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_GLOBAL),
+ particles(device, "__particles", MEM_GLOBAL),
+ svm_nodes(device, "__svm_nodes", MEM_GLOBAL),
+ shaders(device, "__shaders", MEM_GLOBAL),
+ lookup_table(device, "__lookup_table", MEM_GLOBAL),
+ sample_pattern_lut(device, "__sample_pattern_lut", MEM_GLOBAL),
+ ies_lights(device, "__ies", MEM_GLOBAL)
{
memset((void *)&data, 0, sizeof(data));
}
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index a7ec137a0a4..9d899a4fc2f 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -580,7 +580,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
keyEquivalent:@"h"];
[menuItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
- menuItem = [appMenu addItemWithTitle:@"Hide others"
+ menuItem = [appMenu addItemWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"];
[menuItem
diff --git a/intern/ghost/test/multitest/stubs.c b/intern/ghost/test/multitest/stubs.c
index 151cdc71777..611c98cd004 100644
--- a/intern/ghost/test/multitest/stubs.c
+++ b/intern/ghost/test/multitest/stubs.c
@@ -22,8 +22,8 @@
#include "BLI_utildefines.h"
#include "IMB_imbuf.h"
-struct ImBuf;
struct ColorSpace;
+struct ImBuf;
void IMB_freeImBuf(struct ImBuf *UNUSED(ibuf))
{
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index 9d24f880983..5d35de7898f 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -171,9 +171,8 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
mMeshFromFile = false;
mParticlesFromFile = false;
- // Only start Mantaflow once. No need to start whenever new FLUID objected is allocated
- if (!mantaInitialized)
- initializeMantaflow();
+ // Setup Mantaflow in Python
+ initializeMantaflow();
// Initialize Mantaflow variables in Python
// Liquid
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
index a42adf72c49..d5902918663 100644
--- a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
+++ b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
@@ -140,30 +140,26 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
using OpenSubdiv::Sdc::Crease;
const OpenSubdiv_Converter *converter = cb_data.converter;
const bool full_topology_specified = converter->specifiesFullTopology(converter);
- if (!full_topology_specified && converter->getNumEdges == NULL) {
- assert(converter->getEdgeSharpness == NULL);
- assert(converter->getVertexSharpness == NULL);
- assert(converter->isInfiniteSharpVertex == NULL);
- return true;
- }
- const int num_edges = converter->getNumEdges(converter);
- for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
- const float sharpness = converter->getEdgeSharpness(converter, edge_index);
- if (sharpness < 1e-6f) {
- continue;
- }
- if (full_topology_specified) {
- setBaseEdgeSharpness(refiner, edge_index, sharpness);
- }
- else {
- int edge_vertices[2];
- converter->getEdgeVertices(converter, edge_index, edge_vertices);
- const int base_edge_index = findBaseEdge(refiner, edge_vertices[0], edge_vertices[1]);
- if (base_edge_index == OpenSubdiv::Far::INDEX_INVALID) {
- printf("OpenSubdiv Error: failed to find reconstructed edge\n");
- return false;
+ if (full_topology_specified || converter->getEdgeVertices != NULL) {
+ const int num_edges = converter->getNumEdges(converter);
+ for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
+ const float sharpness = converter->getEdgeSharpness(converter, edge_index);
+ if (sharpness < 1e-6f) {
+ continue;
+ }
+ if (full_topology_specified) {
+ setBaseEdgeSharpness(refiner, edge_index, sharpness);
+ }
+ else {
+ int edge_vertices[2];
+ converter->getEdgeVertices(converter, edge_index, edge_vertices);
+ const int base_edge_index = findBaseEdge(refiner, edge_vertices[0], edge_vertices[1]);
+ if (base_edge_index == OpenSubdiv::Far::INDEX_INVALID) {
+ printf("OpenSubdiv Error: failed to find reconstructed edge\n");
+ return false;
+ }
+ setBaseEdgeSharpness(refiner, base_edge_index, sharpness);
}
- setBaseEdgeSharpness(refiner, base_edge_index, sharpness);
}
}
// OpenSubdiv expects non-manifold vertices to be sharp but at the time it
@@ -177,16 +173,18 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
setBaseVertexSharpness(refiner, vertex_index, Crease::SHARPNESS_INFINITE);
continue;
}
- float sharpness = converter->getVertexSharpness(converter, vertex_index);
- if (vertex_edges.size() == 2) {
- const int edge0 = vertex_edges[0], edge1 = vertex_edges[1];
- const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0);
- const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1);
- // TODO(sergey): Find a better mixing between edge and vertex sharpness.
- sharpness += min(sharpness0, sharpness1);
- sharpness = min(sharpness, 10.0f);
+ if (converter->getVertexSharpness != NULL) {
+ float sharpness = converter->getVertexSharpness(converter, vertex_index);
+ if (vertex_edges.size() == 2) {
+ const int edge0 = vertex_edges[0], edge1 = vertex_edges[1];
+ const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0);
+ const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1);
+ // TODO(sergey): Find a better mixing between edge and vertex sharpness.
+ sharpness += min(sharpness0, sharpness1);
+ sharpness = min(sharpness, 10.0f);
+ }
+ setBaseVertexSharpness(refiner, vertex_index, sharpness);
}
- setBaseVertexSharpness(refiner, vertex_index, sharpness);
}
return true;
}
diff --git a/release/datafiles/alert_icons.png b/release/datafiles/alert_icons.png
new file mode 100644
index 00000000000..5b6385b2325
--- /dev/null
+++ b/release/datafiles/alert_icons.png
Binary files differ
diff --git a/release/datafiles/alert_icons.svg b/release/datafiles/alert_icons.svg
new file mode 100644
index 00000000000..0f30b4ad47b
--- /dev/null
+++ b/release/datafiles/alert_icons.svg
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1280"
+ height="256"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
+ version="1.0"
+ sodipodi:docname="alert_icons.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ style="display:inline;enable-background:new"
+ inkscape:export-filename="alert_icons.png"
+ inkscape:export-xdpi="96.000008"
+ inkscape:export-ydpi="96.000008">
+ <metadata
+ id="metadata5323">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ id="namedview5321"
+ showgrid="true"
+ inkscape:zoom="1"
+ inkscape:cx="935.85776"
+ inkscape:cy="91.379624"
+ inkscape:window-x="1912"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:document-rotation="0"
+ inkscape:snap-global="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid9048"
+ spacingx="256"
+ spacingy="256"
+ empcolor="#818181"
+ empopacity="0.25098039"
+ visible="true"
+ enabled="true" />
+ <inkscape:grid
+ type="xygrid"
+ id="grid5904"
+ spacingx="8"
+ spacingy="8"
+ color="#0effa8"
+ opacity="0.1254902"
+ dotted="true"
+ empspacing="1"
+ enabled="true" />
+ <inkscape:grid
+ type="xygrid"
+ id="grid5914"
+ spacingx="2"
+ spacingy="2"
+ enabled="false" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="ICONS"
+ style="display:inline">
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:16.6870575;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
+ d="m 127.63711,28.7478 c -5.87683,0.194787 -11.21722,3.472426 -14.05563,8.62676 L 23.520017,200.96344 c -6.122262,11.1248 1.916754,24.74614 14.606389,24.74895 H 218.24917 c 12.68963,-0.003 20.72865,-13.62415 14.6064,-24.74895 L 142.79409,37.37456 c -3.02886,-5.500109 -8.88551,-8.833516 -15.15698,-8.62676 z m 0.22154,6.670573 v 0 c 3.73286,-0.124026 7.22725,1.867665 9.02982,5.141498 l 90.14625,163.738859 c 3.60722,6.55818 -1.22393,14.73515 -8.70414,14.73655 H 38.0383 c -7.480045,-0.002 -12.311115,-8.17837 -8.703973,-14.73655 L 119.48372,40.559871 c 1.68886,-3.067777 4.87047,-5.025451 8.36825,-5.141498 z m 0.11013,3.341816 c -2.32339,0.07946 -4.43144,1.37183 -5.55381,3.410278 L 32.268804,205.90932 c -2.456157,4.46565 0.682153,9.78322 5.775511,9.78416 H 218.33641 c 5.09337,-8.3e-4 8.23175,-5.31851 5.77562,-9.78416 L 133.96261,42.170467 c -1.19843,-2.176546 -3.50581,-3.490246 -5.98737,-3.410278 v 0 z M 120,88 h 16 c 2.04554,5e-4 4.12156,2.199338 4,4 l -6,74 c -0.11183,1.65503 -0.59661,2.75123 -2.47659,2.75165 l -7.04624,-0.0312 C 122.59719,168.71998 122.11192,167.65503 122,166 l -6,-74 c -0.12175,-1.800662 1.95448,-3.9995 4,-4 z m 8,90 c 5.52669,-2e-5 10,4.4685 10,10 0,5.53149 -4.47331,10.00002 -10,10 -5.52677,2e-5 -10.00016,-4.46851 -10,-10 -1.6e-4,-5.5315 4.47323,-10.00002 10,-10 z"
+ id="path6144"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccc" />
+ <path
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:99.71450043px;line-height:0;font-family:Balloons;-inkscape-font-specification:Balloons;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:17.32685852;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal;enable-background:new"
+ d="m 383.95942,24 c -57.41261,0 -103.95477,46.547438 -103.95477,103.96662 0,57.41919 46.54216,103.96662 103.95477,103.96662 57.4126,0 103.95484,-46.54743 103.95484,-103.96662 C 487.91426,70.547438 441.37202,24 383.95942,24 Z m 0,6.601049 c 53.74795,0 97.35455,43.611594 97.35455,97.365571 0,53.75398 -43.6066,97.36556 -97.35455,97.36556 -53.74796,0 -97.35448,-43.61158 -97.35448,-97.36556 0,-53.753977 43.60652,-97.365571 97.35448,-97.365571 z m 0,3.300528 c -51.9643,0 -94.05432,42.094804 -94.05432,94.065043 0,51.97024 42.09002,94.06504 94.05432,94.06504 51.96438,0 94.05439,-42.09482 94.05439,-94.06504 0,-51.970239 -42.09001,-94.065043 -94.05439,-94.065043 z m 0.0908,32.982721 c 9.84154,-0.01154 19.616,3.163309 27.0651,9.337525 7.44926,6.174231 12.46912,15.484523 12.46912,26.990837 0,30.52988 -31.3515,32.18014 -31.3515,51.15818 v 6.62361 c -1.7e-4,1.82277 -1.47764,3.30035 -3.30015,3.30053 h -9.94566 c -1.82251,-1.8e-4 -3.29998,-1.47776 -3.30014,-3.30053 v -6.62361 c 0,-29.70475 31.37409,-29.70475 31.35149,-51.15818 0,-6.446126 -2.72956,-11.141868 -7.00639,-14.520388 -4.27665,-3.378519 -10.19753,-5.260217 -16.09787,-5.260217 -5.62494,0 -11.59672,2.555319 -16.01727,6.236842 -4.42104,3.681525 -7.05852,8.409614 -7.05852,11.893503 -1.7e-4,1.82275 -1.47765,3.30035 -3.30015,3.30053 h -9.90045 c -1.82251,-1.8e-4 -3.29998,-1.47778 -3.30015,-3.30053 0,-9.471145 5.13288,-18.135164 12.52374,-24.39618 7.39102,-6.26102 17.1535,-10.269545 27.1683,-10.281922 z m -0.19653,105.739362 c 5.46786,-1e-5 9.90045,4.43309 9.90045,9.90159 0,5.4685 -4.43259,9.9016 -9.90045,9.90159 -5.46785,1e-5 -9.90043,-4.43309 -9.90043,-9.90159 0,-5.4685 4.43258,-9.9016 9.90043,-9.90159 z"
+ id="circle6315"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ssssssssssssssscccccccccccsccccccccccccc" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path6333"
+ d="m 599.84744,24 c -1.80933,3.07e-4 -3.54432,0.719021 -4.82371,1.998072 l -57.09842,57.077994 c -1.27955,1.278828 -1.99844,3.013304 -1.99878,4.821983 v 80.215561 c 3.4e-4,1.80869 0.71921,3.54317 1.99878,4.822 l 57.09842,57.078 c 1.27939,1.27906 3.01438,1.99776 4.82371,1.99807 h 80.24427 c 1.80933,-3.1e-4 3.54432,-0.71901 4.82372,-1.99807 l 57.09841,-57.078 c 1.27955,-1.27883 1.99845,-3.01331 1.99878,-4.822 V 87.898049 c 5.1e-4,-1.806564 -0.71597,-3.539557 -1.99211,-4.818658 L 685.03536,26.001397 C 683.75491,24.719499 682.01719,23.999438 680.20496,24 Z m 0.7029,6.820055 h 78.9484 c 0.4535,-8.02e-4 0.88863,0.17894 1.20926,0.499517 l 55.98244,56.075635 c 0.31986,0.319706 0.4996,0.753326 0.49969,1.205495 v 78.810278 c -9e-5,0.45216 -0.17983,0.88577 -0.49969,1.20549 l -56.0957,56.07563 c -0.31982,0.31975 -0.75359,0.49943 -1.20592,0.49951 h -78.83848 c -0.45233,-8e-5 -0.88611,-0.17976 -1.20592,-0.49951 l -56.0957,-56.07563 c -0.31987,-0.31972 -0.49961,-0.75333 -0.4997,-1.20549 V 88.600702 c 9e-5,-0.452169 0.17983,-0.885789 0.4997,-1.205495 l 56.0957,-56.075635 c 0.31981,-0.319758 0.75359,-0.499433 1.20592,-0.499517 z m 0.70624,3.410027 -55.09631,55.076599 v 77.398309 l 55.09631,55.07659 h 77.42599 l 55.09631,-55.07659 V 89.306681 L 678.79251,34.230082 Z m 0.28649,43.477851 c 0.92189,-0.01364 1.80993,0.34714 2.46182,0.999035 l 35.96469,36.511252 35.96468,-36.511252 c 1.33226,-1.331257 3.49144,-1.331257 4.8237,0 l 8.52812,8.525069 c 1.33158,1.331718 1.33158,3.490265 0,4.821983 l -36.52432,35.95182 36.52432,35.95182 c 1.33158,1.33172 1.33158,3.49026 0,4.82197 l -8.52812,8.52507 c -1.33226,1.33127 -3.49144,1.33127 -4.8237,0 l -35.96468,-36.51126 -35.96469,36.51126 c -1.33226,1.33127 -3.49143,1.33127 -4.8237,0 l -8.52812,-8.52507 c -1.33158,-1.33171 -1.33158,-3.49025 0,-4.82197 L 627.1774,128.00584 590.65307,92.05402 c -1.33158,-1.331718 -1.33158,-3.490265 0,-4.821983 l 8.52812,-8.525069 c 0.62733,-0.627427 1.47461,-0.985395 2.36188,-0.999035 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.82127094;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ <path
+ style="display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.4464879;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal;enable-background:new"
+ d="m 824.87953,24.018442 c -19.10949,0 -34.49375,15.358505 -34.49375,34.436102 v 99.864706 c 0,17.91493 13.56662,32.54727 31.04439,34.26458 v -6.90406 C 807.68893,184.01188 797.2408,172.53207 797.2408,158.31925 V 58.454544 c 0,-15.383034 12.23007,-27.592598 27.63873,-27.592598 h 144.8736 c 15.40867,0 27.63877,12.209564 27.63877,27.592598 v 99.864706 c 0,15.38302 -12.2301,27.59259 -27.63877,27.59259 h -95.80091 l -5.63213,6.84349 h 101.43304 c 19.1095,0 34.49377,-15.3585 34.49377,-34.43608 V 58.454544 c 0,-19.077597 -15.38427,-34.436102 -34.49377,-34.436102 z m 0,10.287115 c -13.59981,0 -24.18938,10.571906 -24.18938,24.148987 v 99.864706 c 0,13.57706 10.58957,24.14898 24.18938,24.14898 v 3.44361 6.84349 3.44361 34.43612 c 7e-4,3.22387 4.06509,4.65054 6.10375,2.19934 l 0.91288,-1.09632 32.39946,-38.98275 h 0.0303 l 8.58971,-10.32409 c 0.0742,-0.0121 0.15004,-0.0207 0.22575,-0.0235 0.1673,-0.003 0.33391,0.0172 0.49516,0.0606 h 96.11747 c 13.59983,0 24.18941,-10.57191 24.18941,-24.14899 V 58.454579 c 0,-13.577083 -10.58958,-24.148987 -24.18941,-24.148987 z m 70.60096,20.809631 c 5.71509,-1.6e-5 10.3481,4.625269 10.3481,10.330833 0,5.705565 -4.63301,10.330849 -10.3481,10.33083 -5.71525,1.9e-5 -10.34827,-4.625265 -10.3481,-10.33083 -1.7e-4,-5.705564 4.63285,-10.330849 10.3481,-10.330833 z m 5.28521,32.610044 c 0.21939,4.99e-4 0.43816,0.02186 0.65348,0.06387 2.54598,0.323665 4.52032,2.47196 4.52057,5.10152 v 55.097748 h 8.62342 c 1.905,2e-4 3.4492,1.54185 3.44937,3.44361 v 3.44363 c -1.7e-4,1.90176 -1.54437,3.44343 -3.44937,3.44362 H 880.0695 c -1.905,-1.9e-4 -3.4492,-1.54186 -3.44936,-3.44362 v -3.44363 c 1.6e-4,-1.90176 1.54436,-3.44341 3.44936,-3.44361 h 8.62341 V 98.056045 h -8.62341 c -1.905,-1.9e-4 -3.4492,-1.541842 -3.44936,-3.443611 v -3.443609 c 1.6e-4,-1.901769 1.54436,-3.443422 3.44936,-3.443611 z"
+ id="rect6452"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssccsssssssccssssssssccccccccccccssssscscccccccccccccccccccccc" />
+ <g
+ id="g888">
+ <path
+ inkscape:transform-center-y="-16.504573"
+ inkscape:transform-center-x="7.7978312"
+ d="m 1234.3776,142.72031 a 49.979294,47.518188 0 0 1 -49.8548,47.51804 49.979294,47.518188 0 0 1 -50.1032,-47.28143 49.979294,47.518188 0 0 1 49.6054,-47.753477 49.979294,47.518188 0 0 1 50.3501,47.043637"
+ sodipodi:open="true"
+ sodipodi:end="6.2732263"
+ sodipodi:start="0"
+ sodipodi:ry="47.518188"
+ sodipodi:rx="49.979294"
+ sodipodi:cy="142.72031"
+ sodipodi:cx="1184.3983"
+ sodipodi:type="arc"
+ id="path869"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke-width:4.34395075;stroke-miterlimit:4;stroke-dasharray:none" />
+ <g
+ transform="matrix(4.318758,0,0,4.4238041,-165.58547,-1034.3978)"
+ id="g15769">
+ <path
+ inkscape:connector-curvature="0"
+ id="path14548"
+ style="clip-rule:evenodd;display:inline;fill:#265787;fill-rule:nonzero;stroke-width:0.88226169;stroke-linejoin:round;stroke-miterlimit:1.41420996"
+ d="m 306.07569,265.40069 c 0.0928,-1.6816 0.90332,-3.16312 2.12613,-4.21334 1.19918,-1.03156 2.81325,-1.66205 4.57438,-1.66205 1.75937,0 3.37345,0.63049 4.5735,1.66205 1.22194,1.05022 2.03248,2.53174 2.12613,4.21157 0.0928,1.72784 -0.59083,3.33297 -1.79001,4.52281 -1.22281,1.21029 -2.96205,1.96973 -4.90962,1.96973 -1.94757,0 -3.69031,-0.75944 -4.91225,-1.96973 -1.20005,-1.18984 -1.88192,-2.79497 -1.78826,-4.52104 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path14552"
+ style="clip-rule:evenodd;display:inline;fill:#e87d0d;fill-rule:nonzero;stroke-width:0.88226169;stroke-linejoin:round;stroke-miterlimit:1.41420996"
+ d="m 295.40565,268.79858 c 0.0114,0.65806 0.21795,1.93683 0.52781,2.93547 0.65123,2.11379 1.75587,4.06929 3.29292,5.79269 1.57731,1.77142 3.51963,3.19425 5.76305,4.20446 2.35809,1.06089 4.91312,1.60157 7.56707,1.59712 2.64956,-0.004 5.2046,-0.5549 7.56269,-1.6238 2.24342,-1.01999 4.18398,-2.44904 5.75867,-4.22135 1.53617,-1.73052 2.63906,-3.68957 3.29205,-5.80336 0.32824,-1.06801 0.53569,-2.15203 0.61884,-3.2396 0.0814,-1.07157 0.0473,-2.14491 -0.10241,-3.21737 -0.29235,-2.08978 -1.00398,-4.05061 -2.09987,-5.83804 -1.00223,-1.64248 -2.29419,-3.08042 -3.83036,-4.29072 l 0.004,-0.003 -15.50264,-12.09315 c -0.014,-0.0107 -0.0254,-0.0222 -0.0403,-0.032 -1.01711,-0.79323 -2.72747,-0.79056 -3.84612,0.004 -1.1309,0.8039 -1.26045,2.13336 -0.25384,2.97193 l -0.004,0.004 6.46593,5.34183 -19.70764,0.0213 c -0.01,0 -0.0192,0 -0.0262,0 -1.62896,0.002 -3.19489,1.08757 -3.50475,2.45971 -0.31861,1.39793 0.78778,2.55753 2.48151,2.56376 l -0.003,0.006 9.98906,-0.0196 -17.82484,13.90014 c -0.0228,0.0169 -0.0473,0.0347 -0.0683,0.0516 -1.68147,1.30812 -2.22504,3.48326 -1.16591,4.85985 1.07488,1.39971 3.36032,1.40238 5.0593,0.008 l 9.72805,-8.08876 c 0,0 -0.1418,1.09202 -0.13042,1.74741 z m 24.99801,3.65667 c -2.00446,2.07466 -4.81071,3.25116 -7.84716,3.25739 -3.04084,0.005 -5.84708,-1.1605 -7.85155,-3.2316 -0.97947,-1.00932 -1.69898,-2.1707 -2.14276,-3.40767 -0.43503,-1.21563 -0.60396,-2.50596 -0.49192,-3.80785 0.10591,-1.27254 0.47879,-2.48639 1.074,-3.58463 0.58471,-1.07957 1.39,-2.0551 2.38435,-2.88034 1.94844,-1.61313 4.42908,-2.48639 7.0235,-2.48995 2.59705,-0.004 5.07593,0.8617 7.02613,2.4695 0.9926,0.82168 1.79701,1.79365 2.38172,2.87144 0.59784,1.09736 0.96809,2.30676 1.07838,3.58286 0.11029,1.30011 -0.0586,2.58866 -0.49368,3.80517 -0.44466,1.24053 -1.16153,2.40192 -2.14101,3.41568 z" />
+ </g>
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="sheet_layout"
+ style="display:none">
+ <g
+ style="opacity:1"
+ id="g3323">
+ <rect
+ y="0"
+ x="768"
+ height="256"
+ width="256"
+ id="rect6450"
+ style="display:inline;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:7.5590601;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:105.70800018;stroke-opacity:1;marker:none;paint-order:fill markers stroke;enable-background:new" />
+ <rect
+ style="display:inline;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:7.5590601;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:105.70800018;stroke-opacity:1;marker:none;paint-order:fill markers stroke;enable-background:new"
+ id="rect6442"
+ width="256"
+ height="256"
+ x="512"
+ y="0" />
+ <rect
+ style="display:inline;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:7.5590601;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:105.70800018;stroke-opacity:1;marker:none;paint-order:fill markers stroke;enable-background:new"
+ id="rect6134"
+ width="256"
+ height="256"
+ x="0"
+ y="0" />
+ <rect
+ y="0"
+ x="256"
+ height="256"
+ width="256"
+ id="rect6161"
+ style="display:inline;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:7.5590601;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:105.70800018;stroke-opacity:1;marker:none;paint-order:fill markers stroke;enable-background:new" />
+ </g>
+ </g>
+</svg>
diff --git a/release/datafiles/alert_icons_update.py b/release/datafiles/alert_icons_update.py
new file mode 100644
index 00000000000..dba96c2126a
--- /dev/null
+++ b/release/datafiles/alert_icons_update.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+# This script updates icons from the SVG file
+import os
+import subprocess
+import sys
+
+BASEDIR = os.path.abspath(os.path.dirname(__file__))
+
+inkscape_path = 'inkscape'
+
+if sys.platform == 'darwin':
+ inkscape_app_path = '/Applications/Inkscape.app/Contents/Resources/script'
+ if os.path.exists(inkscape_app_path):
+ inkscape_path = inkscape_app_path
+
+cmd = (
+ inkscape_path,
+ os.path.join(BASEDIR, "alert_icons.svg"),
+ "--export-width=1280",
+ "--export-height=256",
+ "--without-gui",
+ "--export-png=" + os.path.join(BASEDIR, "alert_icons.png"),
+)
+subprocess.check_call(cmd)
diff --git a/release/datafiles/blender_icons_geom_update.py b/release/datafiles/blender_icons_geom_update.py
index 5e4b0383b9a..3b7724756db 100755
--- a/release/datafiles/blender_icons_geom_update.py
+++ b/release/datafiles/blender_icons_geom_update.py
@@ -86,5 +86,5 @@ edit_text_file(
os.path.join(ROOTDIR, "source", "blender", "editors", "datafiles", "CMakeLists.txt"),
"# BEGIN ICON_GEOM_NAMES",
"# END ICON_GEOM_NAMES",
- "\t" + "\n\t".join(icon_files) + "\n",
+ " " + "\n ".join(icon_files) + "\n",
)
diff --git a/release/datafiles/icons/brush.gpencil_draw.tint.dat b/release/datafiles/icons/brush.gpencil_draw.tint.dat
new file mode 100644
index 00000000000..016e4304498
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil_draw.tint.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.paint_vertex.replace.dat b/release/datafiles/icons/brush.paint_vertex.replace.dat
new file mode 100644
index 00000000000..a37fdf2e1b1
--- /dev/null
+++ b/release/datafiles/icons/brush.paint_vertex.replace.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.blob.dat b/release/datafiles/icons/brush.sculpt.blob.dat
index 7e85ee23fcf..890a73e26a6 100644
--- a/release/datafiles/icons/brush.sculpt.blob.dat
+++ b/release/datafiles/icons/brush.sculpt.blob.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.clay_thumb.dat b/release/datafiles/icons/brush.sculpt.clay_thumb.dat
new file mode 100644
index 00000000000..e543185b5d7
--- /dev/null
+++ b/release/datafiles/icons/brush.sculpt.clay_thumb.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.cloth.dat b/release/datafiles/icons/brush.sculpt.cloth.dat
new file mode 100644
index 00000000000..5e8fad60035
--- /dev/null
+++ b/release/datafiles/icons/brush.sculpt.cloth.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.draw_face_sets.dat b/release/datafiles/icons/brush.sculpt.draw_face_sets.dat
new file mode 100644
index 00000000000..7a05f00ab9d
--- /dev/null
+++ b/release/datafiles/icons/brush.sculpt.draw_face_sets.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.draw_sharp.dat b/release/datafiles/icons/brush.sculpt.draw_sharp.dat
index c3e0c7a7536..ad42f4bf870 100644
--- a/release/datafiles/icons/brush.sculpt.draw_sharp.dat
+++ b/release/datafiles/icons/brush.sculpt.draw_sharp.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.inflate.dat b/release/datafiles/icons/brush.sculpt.inflate.dat
index 1d131599742..7e85ee23fcf 100644
--- a/release/datafiles/icons/brush.sculpt.inflate.dat
+++ b/release/datafiles/icons/brush.sculpt.inflate.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.multiplane_scrape.dat b/release/datafiles/icons/brush.sculpt.multiplane_scrape.dat
index 98a5b3be902..b785bb51431 100644
--- a/release/datafiles/icons/brush.sculpt.multiplane_scrape.dat
+++ b/release/datafiles/icons/brush.sculpt.multiplane_scrape.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.pinch.dat b/release/datafiles/icons/brush.sculpt.pinch.dat
index 4a76c725561..abdb62dcfc8 100644
--- a/release/datafiles/icons/brush.sculpt.pinch.dat
+++ b/release/datafiles/icons/brush.sculpt.pinch.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.sculpt.rotate.dat b/release/datafiles/icons/brush.sculpt.rotate.dat
index 408adde61e1..a0bb63d14db 100644
--- a/release/datafiles/icons/brush.sculpt.rotate.dat
+++ b/release/datafiles/icons/brush.sculpt.rotate.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.transform_fill.dat b/release/datafiles/icons/ops.gpencil.transform_fill.dat
new file mode 100644
index 00000000000..a364882d33f
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.transform_fill.dat
Binary files differ
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject 2a25e004396d3f135a98da132b496923275a3dc
+Subproject 34d98762cef85b9c065f21a051d1dbe3bf2979b
diff --git a/release/datafiles/preview.blend b/release/datafiles/preview.blend
index f8fafb285c6..f92f68ad029 100644
--- a/release/datafiles/preview.blend
+++ b/release/datafiles/preview.blend
Binary files differ
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c
index 2c1e648d33d..f87e6e9d86d 100644
--- a/release/datafiles/userdef/userdef_default_theme.c
+++ b/release/datafiles/userdef/userdef_default_theme.c
@@ -483,7 +483,7 @@ const bTheme U_theme_default = {
.info_selected_text = RGBA(0xffffffff),
.info_error = RGBA(0xff613dff),
.info_error_text = RGBA(0xffffffff),
- .info_warning = RGBA(0xb36a00ff),
+ .info_warning = RGBA(0xf5bc41ff),
.info_warning_text = RGBA(0xffffffff),
.info_info = RGBA(0x1d4383ff),
.info_info_text = RGBA(0xffffffff),
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject 7f50343d1c53ca9a5ca747f47e3b1e5bbcbe847
+Subproject 47a32a5370d36942674621e5a03e57e8dd4986d
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject 9468c406fb554e32ff47b62bfef356b3908ec65
+Subproject 70b649775eeeebedb02c1c7b7aa996a7f629417
diff --git a/release/scripts/presets/interface_theme/deep_grey.xml b/release/scripts/presets/interface_theme/deep_grey.xml
new file mode 100644
index 00000000000..d6a78997eec
--- /dev/null
+++ b/release/scripts/presets/interface_theme/deep_grey.xml
@@ -0,0 +1,1481 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface
+ menu_shadow_fac="0.1"
+ menu_shadow_width="10"
+ icon_alpha="1"
+ icon_saturation="1"
+ widget_emboss="#ffffff00"
+ editor_outline="#303030"
+ widget_text_cursor="#d9d9d9"
+ axis_x="#e54444"
+ axis_y="#2de579"
+ axis_z="#2d89e5"
+ gizmo_hi="#ffffff"
+ gizmo_primary="#f5f14d"
+ gizmo_secondary="#63ffff"
+ gizmo_a="#4da84d"
+ gizmo_b="#a33535"
+ icon_scene="#e6e6e6ff"
+ icon_collection="#ccccccff"
+ icon_object="#ffa864ff"
+ icon_object_data="#98cc98ff"
+ icon_modifier="#8cc0ffff"
+ icon_shading="#ff8b8bff"
+ icon_folder="#bdbdbdff"
+ icon_border_intensity="0"
+ >
+ <wcol_regular>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#595959ff"
+ inner_sel="#c85130ff"
+ item="#333333ff"
+ text="#cccccc"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#595959ff"
+ inner_sel="#c85130ff"
+ item="#b8b8b8ff"
+ text="#cccccc"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#595959ff"
+ inner_sel="#c85130ff"
+ item="#ccccccff"
+ text="#cccccc"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
+ <wcol_radio>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#595959ff"
+ inner_sel="#c85130ff"
+ item="#ffffffff"
+ text="#cccccc"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#333333ff"
+ inner_sel="#505050ff"
+ item="#333333ff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors
+ outline="#e6e6e6"
+ inner="#47474700"
+ inner_sel="#cbcbcbff"
+ item="#000000ff"
+ text="#b8b8b8"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#595959ff"
+ inner_sel="#c85130ff"
+ item="#ffffffff"
+ text="#cccccc"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#333333ff"
+ inner_sel="#505050ff"
+ item="#333333ff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#333333ff"
+ inner_sel="#505050ff"
+ item="#c85130ff"
+ text="#cccccc"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-10"
+ shadedown="0"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#00000019"
+ inner_sel="#c85130ff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-7"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#595959ff"
+ inner_sel="#c85130ff"
+ item="#ccccccff"
+ text="#cccccc"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#474747ff"
+ inner_sel="#c85130ff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#474747ff"
+ inner_sel="#616161ff"
+ item="#333333ff"
+ text="#b8b8b8"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#474747ff"
+ inner_sel="#c85130ff"
+ item="#6b6b6bff"
+ text="#b8b8b8"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#ffffe1ff"
+ inner_sel="#c85130ff"
+ item="#646464ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#3f3f3f00"
+ inner_sel="#c85130ff"
+ item="#b8b8b8ff"
+ text="#b8b8b8"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="20"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#333333ff"
+ inner_sel="#c85130ff"
+ item="#6b6b6bff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#333333ff"
+ inner_sel="#646464b4"
+ item="#c85130ff"
+ text="#b8b8b8"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#3f3f3f00"
+ inner_sel="#c85130ff"
+ item="#ffffffff"
+ text="#b8b8b8"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-10"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors
+ inner_anim="#53992e"
+ inner_anim_sel="#38a600"
+ inner_key="#b3ae36"
+ inner_key_sel="#b29700"
+ inner_driven="#9000cc"
+ inner_driven_sel="#9900e6"
+ inner_overridden="#00c3c3"
+ inner_overridden_sel="#118f8f"
+ inner_changed="#cc7529"
+ inner_changed_sel="#d26400"
+ blend="0.4"
+ >
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors
+ outline="#202020"
+ inner="#333333ff"
+ inner_sel="#6b6b6bff"
+ item="#5a5a5aff"
+ text="#b8b8b8"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_tab>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D
+ grid="#51515180"
+ clipping_border_3d="#313131ff"
+ wire="#000000"
+ wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ text_grease_pencil="#b5e61d"
+ object_selected="#00b5ff"
+ object_active="#ffaa18"
+ text_keyframe="#ddd700"
+ camera="#b3ccbe"
+ empty="#000000"
+ light="#b3ccbe28"
+ speaker="#000000"
+ vertex="#000000"
+ vertex_select="#ffaa18"
+ vertex_size="3"
+ vertex_bevel="#00a5ff"
+ vertex_unreferenced="#000000"
+ edge_select="#ffa000"
+ edge_seam="#db2512"
+ edge_sharp="#00ffff"
+ edge_crease="#cc0099"
+ edge_bevel="#00a5ff"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#7fff7f"
+ face="#80808014"
+ face_select="#ffa5526c"
+ face_dot="#00beb0"
+ facedot_size="3"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#e54444b3"
+ face_front="#2d89e5b3"
+ nurb_uline="#89908a"
+ nurb_vline="#fff8f4"
+ nurb_sel_uline="#2400ff"
+ nurb_sel_vline="#f0deeb"
+ act_spline="#00c6db"
+ handle_free="#000000"
+ handle_auto="#1c00ff"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#7b807e"
+ handle_sel_free="#000000"
+ handle_sel_auto="#9aa3a1"
+ handle_sel_align="#f0e6e9"
+ lastsel_point="#ffffff"
+ extra_edge_len="#fff3fa"
+ extra_edge_angle="#202000"
+ extra_face_angle="#ffff00"
+ extra_face_area="#002000"
+ editmesh_active="#ffffff80"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_pose="#00b5ff"
+ bone_pose_active="#ffaa18"
+ bone_solid="#b2b2b2"
+ bone_locked_weight="#ff000080"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#b44d4d"
+ view_overlay="#000000"
+ transform="#ffffff"
+ frame_current="#4c9933"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1"
+ object_origin_size="6"
+ >
+ <space>
+ <ThemeSpaceGradient
+ title="#000000"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#47474700"
+ header_text="#d9d9d9"
+ header_text_hi="#ffffff"
+ button="#47474700"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#9e9e9e"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <gradients>
+ <ThemeGradientColors
+ background_type="SINGLE_COLOR"
+ high_gradient="#404040"
+ gradient="#383838"
+ >
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor
+ grid="#303030"
+ frame_current="#4c9933"
+ time_scrub_background="#333333e6"
+ time_marker_line="#b8b8b880"
+ time_marker_line_selected="#ffaa18e6"
+ window_sliders="#969696"
+ channels_region="#505050"
+ dopesheet_channel="#c85130"
+ dopesheet_subchannel="#805543"
+ channel_group="#42566d"
+ active_channels_group="#326799"
+ preview_range="#a14d0066"
+ vertex="#000000"
+ vertex_select="#ffc832"
+ vertex_size="6"
+ vertex_bevel="#00a5ff"
+ vertex_unreferenced="#000000"
+ handle_free="#000000"
+ handle_auto="#8d8e90"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#b6b5b6"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#148bce"
+ handle_auto_clamped="#7e7e7e"
+ handle_sel_auto_clamped="#f0af90"
+ lastsel_point="#ffffff"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffc832"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#ffffff"
+ text="#b8b8b8"
+ text_hi="#fcfcfc"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#b7b7b7"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#474747"
+ list_title="#8b8b8b"
+ list_text="#b8b8b8"
+ list_text_hi="#fff500"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser
+ selected_file="#c85130"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#e4e4e4"
+ text="#cacaca"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#ffffff"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#474747ff"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor
+ grid="#303030"
+ view_sliders="#969696"
+ dopesheet_channel="#42566d"
+ nla_track="#424242"
+ active_action="#a65b1566"
+ active_action_unset="#7365494d"
+ preview_range="#a14d0066"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ frame_current="#4c9933"
+ time_scrub_background="#333333e6"
+ time_marker_line="#b8b8b880"
+ time_marker_line_selected="#ffaa18e6"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#ffffff"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#b7b7b7"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#474747"
+ list_title="#000000"
+ list_text="#b8b8b8"
+ list_text_hi="#fff500"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet
+ grid="#303030"
+ frame_current="#4c9933"
+ time_scrub_background="#333333e6"
+ time_marker_line="#b8b8b880"
+ time_marker_line_selected="#ffaa18e6"
+ value_sliders="#000000"
+ view_sliders="#929292"
+ dopesheet_channel="#c8513024"
+ dopesheet_subchannel="#80554324"
+ channels="#505050ff"
+ channels_selected="#60c04044"
+ channel_group="#42566d37"
+ active_channels_group="#32679955"
+ long_key="#1a151580"
+ long_key_selected="#ff8c00cc"
+ keyframe="#e8e8e8"
+ keyframe_selected="#ffbe33"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#94e575"
+ keyframe_jitter_selected="#61c042"
+ keyframe_movehold="#5c5656"
+ keyframe_movehold_selected="#ffaf23"
+ keyframe_border="#2c2c2cff"
+ keyframe_border_selected="#2c2c2cff"
+ keyframe_scale_factor="1"
+ summary="#3b3b3b6d"
+ preview_range="#a14d0066"
+ interpolation_line="#94e575cc"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#ffffff"
+ text="#b8b8b8"
+ text_hi="#fcfcfc"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#b7b7b7"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#474747"
+ list_title="#000000"
+ list_text="#b8b8b8"
+ list_text_hi="#fff500"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor
+ vertex="#000000"
+ vertex_select="#ffaa18"
+ vertex_size="3"
+ vertex_bevel="#00a5ff"
+ vertex_unreferenced="#000000"
+ face="#ffce990a"
+ face_select="#ff85003c"
+ face_dot="#ff8500"
+ facedot_size="2"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#00000000"
+ face_front="#00000000"
+ editmesh_active="#ffffff80"
+ wire_edit="#5c5c5c"
+ edge_select="#ff8500"
+ scope_back="#333333ff"
+ preview_stitch_face="#1242b026"
+ preview_stitch_edge="#ff8500b2"
+ preview_stitch_vert="#ff85007f"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#4c9933"
+ metadatabg="#333333"
+ metadatatext="#b8b8b8"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#ffffff"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#47474700"
+ header_text="#d9d9d9"
+ header_text_hi="#b8b8b8"
+ button="#47474700"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor
+ grid="#404040"
+ window_sliders="#a0a0a0"
+ movie_strip="#516987"
+ movieclip_strip="#8f4c4c"
+ image_strip="#8f744b"
+ scene_strip="#828f50"
+ audio_strip="#2e8f8f"
+ effect_strip="#a9547c"
+ transition_strip="#a25f6f"
+ meta_strip="#6d9183"
+ text_strip="#a29700"
+ frame_current="#4c9933"
+ time_scrub_background="#333333e6"
+ time_marker_line="#b8b8b880"
+ time_marker_line_selected="#ffaa18e6"
+ keyframe="#ff8500"
+ draw_action="#607f9e"
+ preview_back="#474747"
+ metadatabg="#333333"
+ metadatatext="#b8b8b8"
+ preview_range="#a14d0066"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#e4e4e4"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#b7b7b7"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#cccccc"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#b8b8b8"
+ header_text_hi="#ffffff"
+ button="#474747ff"
+ button_title="#c7c7c7"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#474747ff"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor
+ line_numbers="#838383"
+ line_numbers_background="#2e2e2e"
+ selected_text="#575757"
+ cursor="#d9d9d9"
+ syntax_builtin="#009eed"
+ syntax_symbols="#b8b8b8"
+ syntax_special="#009eed"
+ syntax_preprocessor="#409090"
+ syntax_reserved="#c4753b"
+ syntax_comment="#6a9955"
+ syntax_string="#f0ad6d"
+ syntax_numbers="#48c5e6"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#fefefe"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#b8b8b8"
+ header_text_hi="#cccccc"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <node_editor>
+ <ThemeNodeEditor
+ node_selected="#00b5ff"
+ node_active="#ffaa18"
+ wire="#808080"
+ wire_inner="#808080"
+ wire_select="#ffffff"
+ selected_text="#909090"
+ node_backdrop="#585858ff"
+ converter_node="#7f8080"
+ color_node="#4c5975"
+ group_node="#3a582cb9"
+ group_socket_node="#353b47"
+ frame_node="#50505080"
+ matte_node="#0076b6"
+ distor_node="#292929"
+ noodle_curving="2"
+ grid_levels="2"
+ input_node="#3471ae"
+ output_node="#cc6666"
+ filter_node="#0076b6"
+ vector_node="#7191e2"
+ texture_node="#e66d25"
+ shader_node="#32995e"
+ script_node="#141414"
+ pattern_node="#008db6"
+ layout_node="#3c3c3c"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#ffffff"
+ text="#d9d9d9"
+ text_hi="#d9d9d9"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#b7b7b7"
+ button="#47474700"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#a5a5a5"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#fff500"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <outliner>
+ <ThemeOutliner
+ match="#2e732e"
+ selected_highlight="#575757"
+ active="#666666"
+ selected_object="#00b5ff"
+ active_object="#fff500"
+ edited_object="#00806266"
+ row_alternate="#4f4f4fff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#e4e4e4"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#ffffff"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#e4e4e4"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo
+ info_selected="#c85130"
+ info_selected_text="#ffffff"
+ info_error="#801a1aff"
+ info_error_text="#d9d9d9"
+ info_warning="#3b3b3bff"
+ info_warning_text="#ffe100"
+ info_info="#1c4180ff"
+ info_info_text="#d9d9d9"
+ info_debug="#c4c4c4ff"
+ info_debug_text="#000000"
+ info_property="#3ace87ff"
+ info_property_text="#ffffff"
+ info_operator="#3ace87ff"
+ info_operator_text="#ffffff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#e4e4e4"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#000000"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <preferences>
+ <ThemePreferences>
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#cccccc"
+ text="#b8b8b8"
+ text_hi="#d9d9d9"
+ header="#474747ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#474747ff"
+ execution_buts="#474747ff"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#232323ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemePreferences>
+ </preferences>
+ <console>
+ <ThemeConsole
+ line_output="#838383"
+ line_input="#d9d9d9"
+ line_info="#6585a6"
+ line_error="#ff404e"
+ cursor="#d9d9d9"
+ select="#ffffff29"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#e4e4e4"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#ffffff"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ path_keyframe_before="#ffc4c4"
+ path_keyframe_after="#c4c4ff"
+ frame_current="#4c9933"
+ time_scrub_background="#333333e6"
+ time_marker_line="#b8b8b880"
+ time_marker_line_selected="#ffaa18e6"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ metadatabg="#333333"
+ metadatatext="#b8b8b8"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#474747"
+ title="#ffffff"
+ text="#b8b8b8"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#b8b8b8"
+ button="#474747ff"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#6b6b6b"
+ tab_inactive="#333333"
+ tab_back="#474747ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#6b6b6bff"
+ back="#474747ff"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#474747"
+ list_title="#000000"
+ list_text="#b8b8b8"
+ list_text_hi="#fff500"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#6b6b6b"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#d9d9d9"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#393939"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#474747ff"
+ header_text="#b8b8b8"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#cccccc"
+ button_text="#b8b8b8"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#47474700"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#202020"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
+ <bone_color_sets>
+ <ThemeBoneColorSet
+ normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1"
+ >
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1"
+ >
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.25"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/maya.xml b/release/scripts/presets/interface_theme/maya.xml
new file mode 100644
index 00000000000..1e93f3a0993
--- /dev/null
+++ b/release/scripts/presets/interface_theme/maya.xml
@@ -0,0 +1,1481 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface
+ menu_shadow_fac="0.3"
+ menu_shadow_width="4"
+ icon_alpha="1"
+ icon_saturation="0.5"
+ widget_emboss="#00000005"
+ editor_outline="#1f1f1f"
+ widget_text_cursor="#3399e6"
+ axis_x="#ff3352"
+ axis_y="#8bdc00"
+ axis_z="#2890ff"
+ gizmo_hi="#000000"
+ gizmo_primary="#000000"
+ gizmo_secondary="#000000"
+ gizmo_a="#000000"
+ gizmo_b="#000000"
+ icon_scene="#e6e6e6ff"
+ icon_collection="#f4f4f4ff"
+ icon_object="#ee9e5dff"
+ icon_object_data="#00d4a3ff"
+ icon_modifier="#84b8ffff"
+ icon_shading="#ea7581ff"
+ icon_folder="#e3c16eff"
+ icon_border_intensity="0"
+ >
+ <wcol_regular>
+ <ThemeWidgetColors
+ outline="#373737"
+ inner="#585858ff"
+ inner_sel="#000000e6"
+ item="#3e3e3eff"
+ text="#ebebeb"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-5"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors
+ outline="#373737"
+ inner="#585858ff"
+ inner_sel="#5e84a3ff"
+ item="#ffffffff"
+ text="#f2f2f2"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-5"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors
+ outline="#2f2f2f"
+ inner="#444444ff"
+ inner_sel="#5e84a3ff"
+ item="#ffffff8f"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
+ <wcol_radio>
+ <ThemeWidgetColors
+ outline="#373737"
+ inner="#595959ff"
+ inner_sel="#bfbfbfe6"
+ item="#ffffffff"
+ text="#eeeeee"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors
+ outline="#444444"
+ inner="#1f1f1fff"
+ inner_sel="#808080ff"
+ item="#333333ff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-3"
+ shadedown="0"
+ roundness="0.2"
+ >
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors
+ outline="#373737"
+ inner="#666666ff"
+ inner_sel="#000000e6"
+ item="#ffffffff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-15"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors
+ outline="#373737"
+ inner="#595959ff"
+ inner_sel="#1d1d1de6"
+ item="#191919ff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors
+ outline="#444444"
+ inner="#2c2c2cff"
+ inner_sel="#b3b3b366"
+ item="#333333ff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4107"
+ >
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors
+ outline="#444444"
+ inner="#595959ff"
+ inner_sel="#333333ff"
+ item="#c2c2c2e6"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-4"
+ shadedown="0"
+ roundness="0.390947"
+ >
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors
+ outline="#444444"
+ inner="#00000033"
+ inner_sel="#696e76ff"
+ item="#191919ff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors
+ outline="#444444"
+ inner="#5e5e5eff"
+ inner_sel="#696e76ff"
+ item="#e6e6e6ff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#2e2e2e99"
+ inner_sel="#5680c2ff"
+ item="#727272ff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors
+ outline="#19191a"
+ inner="#1f1f1fef"
+ inner_sel="#585858ff"
+ item="#727272ff"
+ text="#b3b3b3"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors
+ outline="#2e2e2e"
+ inner="#212121ff"
+ inner_sel="#585858ff"
+ item="#5680c2ff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors
+ outline="#19191a"
+ inner="#19191aef"
+ inner_sel="#19191aef"
+ item="#19191aef"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.8"
+ >
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#00000000"
+ inner_sel="#5680c2ff"
+ item="#ffffff8f"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="38"
+ shadedown="0"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors
+ outline="#424242"
+ inner="#67676700"
+ inner_sel="#b3b3b3ff"
+ item="#676767ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors
+ outline="#585858"
+ inner="#2c2c2cff"
+ inner_sel="#5680c2ff"
+ item="#5680c2ff"
+ text="#eeeeee"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors
+ outline="#2d2d2d"
+ inner="#2d2d2d00"
+ inner_sel="#696e76ff"
+ item="#b3b3b3ff"
+ text="#e1e1e1"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors
+ inner_anim="#73be4c"
+ inner_anim_sel="#5aa633"
+ inner_key="#f0eb64"
+ inner_key_sel="#d7d34b"
+ inner_driven="#b400ff"
+ inner_driven_sel="#9900e6"
+ inner_overridden="#19c3c3"
+ inner_overridden_sel="#118f8f"
+ inner_changed="#cc7529"
+ inner_changed_sel="#d26400"
+ blend="0.5"
+ >
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors
+ outline="#2d2d2d"
+ inner="#323232ff"
+ inner_sel="#4b4b4bff"
+ item="#2d2d2dff"
+ text="#a4a4a4"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.3"
+ >
+ </ThemeWidgetColors>
+ </wcol_tab>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D
+ grid="#0427084d"
+ clipping_border_3d="#313131ff"
+ wire="#020044"
+ wire_edit="#79fdff"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ text_grease_pencil="#b5e61d"
+ object_selected="#ffffff"
+ object_active="#26ff99"
+ text_keyframe="#ddd700"
+ camera="#000000"
+ empty="#000000"
+ light="#00000028"
+ speaker="#000000"
+ vertex="#ff00fa"
+ vertex_select="#ffea00"
+ vertex_size="2"
+ vertex_bevel="#00a5ff"
+ vertex_unreferenced="#000000"
+ edge_select="#ff904f"
+ edge_seam="#db2512"
+ edge_sharp="#00ffff"
+ edge_crease="#cc0099"
+ edge_bevel="#00a5ff"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#7fff7f"
+ face="#00000012"
+ face_select="#ff904f3d"
+ face_dot="#ff8500"
+ facedot_size="3"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#ff0000b3"
+ face_front="#0000ffb3"
+ nurb_uline="#909000"
+ nurb_vline="#803060"
+ nurb_sel_uline="#f0ff40"
+ nurb_sel_vline="#f090a0"
+ act_spline="#db2512"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ lastsel_point="#ffffff"
+ extra_edge_len="#150806"
+ extra_edge_angle="#4d4d00"
+ extra_face_angle="#0000cc"
+ extra_face_area="#004d00"
+ editmesh_active="#ffffff80"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_pose="#50c8ff"
+ bone_pose_active="#8cffff"
+ bone_solid="#c8c8c8"
+ bone_locked_weight="#ff000080"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#b44d4d"
+ view_overlay="#000000"
+ transform="#ffffff"
+ frame_current="#60c040"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1"
+ object_origin_size="6"
+ >
+ <space>
+ <ThemeSpaceGradient
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#42424200"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#35353500"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <gradients>
+ <ThemeGradientColors
+ background_type="LINEAR"
+ high_gradient="#8895aa"
+ gradient="#0f0f10"
+ >
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor
+ grid="#1a1a1a"
+ frame_current="#308837"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ window_sliders="#969696"
+ channels_region="#2e2e2e"
+ dopesheet_channel="#5a85b2"
+ dopesheet_subchannel="#7d98b3"
+ channel_group="#44992e"
+ active_channels_group="#5ccd3e"
+ preview_range="#a14d0066"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="6"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#994030"
+ handle_sel_auto_clamped="#f0af90"
+ lastsel_point="#ffffff"
+ handle_vertex="#000000"
+ handle_vertex_select="#ff8500"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#353535"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#2e2e2eff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#2e2e2e"
+ list_title="#ffffff"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser
+ selected_file="#5b8199"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#353535"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#2e2e2eff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#444444ff"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor
+ grid="#5e5e5e"
+ view_sliders="#969696"
+ dopesheet_channel="#5a85b2"
+ nla_track="#424242"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
+ preview_range="#a14d0066"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ frame_current="#308837"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#353535"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#212121ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#2e2e2e"
+ list_title="#ffffff"
+ list_text="#cccccc"
+ list_text_hi="#cccccc"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet
+ grid="#272727"
+ frame_current="#308837"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ value_sliders="#000000"
+ view_sliders="#c0c0c0"
+ dopesheet_channel="#5a85b224"
+ dopesheet_subchannel="#7d98b324"
+ channels="#707070ff"
+ channels_selected="#60c04044"
+ channel_group="#44992e37"
+ active_channels_group="#5ccd3e55"
+ long_key="#1a151580"
+ long_key_selected="#ff8c00cc"
+ keyframe="#e8e8e8"
+ keyframe_selected="#ffbe33"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#94e575"
+ keyframe_jitter_selected="#61c042"
+ keyframe_movehold="#5c5656"
+ keyframe_movehold_selected="#ffaf23"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ keyframe_scale_factor="1"
+ summary="#a14d0066"
+ preview_range="#a14d0066"
+ interpolation_line="#94e575cc"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#424242"
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#2e2e2e"
+ list_title="#d8d8d8"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="3"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ face="#ffffff0a"
+ face_select="#ff85003c"
+ face_dot="#ff8500"
+ facedot_size="3"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#00000000"
+ face_front="#00000000"
+ editmesh_active="#ffffff80"
+ wire_edit="#c0c0c0"
+ edge_select="#ff8500"
+ scope_back="#727272ff"
+ preview_stitch_face="#7f7f0033"
+ preview_stitch_edge="#ff00ff33"
+ preview_stitch_vert="#0000ff33"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#444444"
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor
+ grid="#404040"
+ window_sliders="#a0a0a0"
+ movie_strip="#516987"
+ movieclip_strip="#20208f"
+ image_strip="#6d5881"
+ scene_strip="#4e983e"
+ audio_strip="#2e8f8f"
+ effect_strip="#a9547c"
+ transition_strip="#a25f6f"
+ meta_strip="#6d9183"
+ text_strip="#a29700"
+ frame_current="#308837"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ keyframe="#ff8500"
+ draw_action="#50c8ff"
+ preview_back="#000000"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ preview_range="#a14d0066"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#424242"
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric
+ back="#444444"
+ title="#d4d4d4"
+ text="#e5e5e5"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#232323ff"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#5e5e5eff"
+ back="#4a4a4aff"
+ sub_back="#00000024"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor
+ line_numbers="#d0d0d0"
+ line_numbers_background="#313133"
+ selected_text="#19191a"
+ cursor="#ff0000"
+ syntax_builtin="#ff1961"
+ syntax_symbols="#ff734d"
+ syntax_special="#95d600"
+ syntax_preprocessor="#ad80ff"
+ syntax_reserved="#c4753b"
+ syntax_comment="#939393"
+ syntax_string="#f6e162"
+ syntax_numbers="#50dbff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#272727"
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#42424200"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#42424200"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <node_editor>
+ <ThemeNodeEditor
+ node_selected="#ed5700"
+ node_active="#ffffff"
+ wire="#808080"
+ wire_inner="#808080"
+ wire_select="#ffffff"
+ selected_text="#7f7070"
+ node_backdrop="#565656ff"
+ converter_node="#66c4ff"
+ color_node="#ccb83d"
+ group_node="#49b300b9"
+ group_socket_node="#1a1a1a"
+ frame_node="#9b9b9ba0"
+ matte_node="#975b5b"
+ distor_node="#749797"
+ noodle_curving="0"
+ grid_levels="2"
+ input_node="#e64555"
+ output_node="#b33641"
+ filter_node="#584d80"
+ vector_node="#9b80ff"
+ texture_node="#e68745"
+ shader_node="#39bf6d"
+ script_node="#084d4d"
+ pattern_node="#6c696f"
+ layout_node="#6c696f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#232323"
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#2e2e2e"
+ list_title="#ffffff"
+ list_text="#cccccc"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <outliner>
+ <ThemeOutliner
+ match="#337f33"
+ selected_highlight="#456481"
+ active="#5981a6"
+ selected_object="#ffffff"
+ active_object="#ffffff"
+ edited_object="#00806266"
+ row_alternate="#ffffff00"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#353535"
+ title="#ffffff"
+ text="#c3c3c3"
+ text_hi="#ffffff"
+ header="#454545ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo
+ info_selected="#6080ff"
+ info_selected_text="#ffffff"
+ info_error="#990000ff"
+ info_error_text="#ffffff"
+ info_warning="#b36a00ff"
+ info_warning_text="#ffffff"
+ info_info="#668000ff"
+ info_info_text="#ffffff"
+ info_debug="#d3d3d3ff"
+ info_debug_text="#000000"
+ info_property="#3ace87ff"
+ info_property_text="#ffffff"
+ info_operator="#3ace87ff"
+ info_operator_text="#ffffff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#424242"
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <preferences>
+ <ThemePreferences>
+ <space>
+ <ThemeSpaceGeneric
+ back="#424242"
+ title="#eeeeee"
+ text="#e6e6e6"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#4b4b4bff"
+ execution_buts="#4b4b4bff"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#232323ff"
+ tab_outline="#232323"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#42424200"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemePreferences>
+ </preferences>
+ <console>
+ <ThemeConsole
+ line_output="#b3c2ff"
+ line_input="#ffffff"
+ line_info="#47b347"
+ line_error="#de6f6f"
+ cursor="#de5959"
+ select="#ffffff30"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#272727"
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ path_keyframe_before="#ffc4c4"
+ path_keyframe_after="#c4c4ff"
+ frame_current="#308837"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#424242"
+ title="#eeeeee"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#424242ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#4b4b4b"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#232323ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#2e2e2e"
+ title="#ffffff"
+ text="#838383"
+ text_hi="#ffffff"
+ header="#303030ff"
+ header_text="#aaaaaa"
+ header_text_hi="#ffffff"
+ button="#353535ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#5680c2"
+ tab_inactive="#424242"
+ tab_back="#232323ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
+ <bone_color_sets>
+ <ThemeBoneColorSet
+ normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle
+ points="12"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1"
+ >
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1"
+ >
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.25"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/minimal_dark.xml b/release/scripts/presets/interface_theme/minimal_dark.xml
new file mode 100644
index 00000000000..b61589d6e84
--- /dev/null
+++ b/release/scripts/presets/interface_theme/minimal_dark.xml
@@ -0,0 +1,1481 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface
+ menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_alpha="1"
+ icon_saturation="1"
+ widget_emboss="#00000000"
+ editor_outline="#202020"
+ widget_text_cursor="#cccccc"
+ axis_x="#ff4040"
+ axis_y="#00ff00"
+ axis_z="#6666ff"
+ gizmo_hi="#ffffff"
+ gizmo_primary="#f3ef4c"
+ gizmo_secondary="#63ffff"
+ gizmo_a="#4da84d"
+ gizmo_b="#a33535"
+ icon_scene="#f2f2f2ff"
+ icon_collection="#f2f2f2ff"
+ icon_object="#f2f2f2ff"
+ icon_object_data="#f2f2f2ff"
+ icon_modifier="#f2f2f2ff"
+ icon_shading="#f2f2f2ff"
+ icon_folder="#e3c16eff"
+ icon_border_intensity="0"
+ >
+ <wcol_regular>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#262626ff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#ffffffff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors
+ outline="#404040"
+ inner="#404040ff"
+ inner_sel="#337fccff"
+ item="#ffffffff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
+ <wcol_radio>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#ffffffff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#262626ff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors
+ outline="#393939"
+ inner="#262626ff"
+ inner_sel="#337fccff"
+ item="#e6e6e600"
+ text="#d9d9d9"
+ text_sel="#d9d9d9"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#e6e6e600"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#333333ff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#333333ff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-10"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors
+ outline="#333333"
+ inner="#2e2e2eff"
+ inner_sel="#337fccff"
+ item="#ffffffff"
+ text="#f2f2f2"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-7"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors
+ outline="#4d4d4d"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#bfbfbfff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="5"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors
+ outline="#383838"
+ inner="#4d4d4dff"
+ inner_sel="#337fccff"
+ item="#ffffffff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors
+ outline="#333333"
+ inner="#333333ff"
+ inner_sel="#337fccff"
+ item="#262626ff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors
+ outline="#1a1a1a"
+ inner="#1a1a1aff"
+ inner_sel="#337fccff"
+ item="#337fccff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors
+ outline="#0d0d0d"
+ inner="#0d0d0dff"
+ inner_sel="#337fccff"
+ item="#646464ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors
+ outline="#262626"
+ inner="#26262600"
+ inner_sel="#337fccff"
+ item="#ffffffff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="20"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors
+ outline="#383838"
+ inner="#383838ff"
+ inner_sel="#337fccff"
+ item="#262626ff"
+ text="#999999"
+ text_sel="#b0b0b0"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors
+ outline="#262626"
+ inner="#1a1a1aff"
+ inner_sel="#262626ff"
+ item="#337fccff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors
+ outline="#323232"
+ inner="#36363600"
+ inner_sel="#337fccff"
+ item="#323232ff"
+ text="#999999"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-10"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors
+ inner_anim="#4d664d"
+ inner_anim_sel="#4d664d"
+ inner_key="#008000"
+ inner_key_sel="#008000"
+ inner_driven="#f500ff"
+ inner_driven_sel="#f500ff"
+ inner_overridden="#19c3c3"
+ inner_overridden_sel="#19c3c3"
+ inner_changed="#cc7529"
+ inner_changed_sel="#e6852d"
+ blend="0.8"
+ >
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors
+ outline="#262626"
+ inner="#262626ff"
+ inner_sel="#404040ff"
+ item="#404040ff"
+ text="#bfbfbf"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.25"
+ >
+ </ThemeWidgetColors>
+ </wcol_tab>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D
+ grid="#1a1a1a80"
+ clipping_border_3d="#313131ff"
+ wire="#666666"
+ wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ text_grease_pencil="#b5e61d"
+ object_selected="#00d9ff"
+ object_active="#00ff2f"
+ text_keyframe="#ddd700"
+ camera="#0d0d0d"
+ empty="#0d0d0d"
+ light="#0d0d0d00"
+ speaker="#0d0d0d"
+ vertex="#0d0d0d"
+ vertex_select="#00abe6"
+ vertex_size="3"
+ vertex_bevel="#008dff"
+ vertex_unreferenced="#000000"
+ edge_select="#40cfff"
+ edge_seam="#bfaa00"
+ edge_sharp="#0d0d0d"
+ edge_crease="#ff0f00"
+ edge_bevel="#008dff"
+ edge_facesel="#515151"
+ freestyle_edge_mark="#ff7d00"
+ face="#4040404d"
+ face_select="#0094ff80"
+ face_dot="#00b5ff"
+ facedot_size="3"
+ freestyle_face_mark="#ff8a0433"
+ face_back="#ff0000b3"
+ face_front="#0000ffb3"
+ nurb_uline="#7b807e"
+ nurb_vline="#fff8f4"
+ nurb_sel_uline="#00bdff"
+ nurb_sel_vline="#f0deeb"
+ act_spline="#666666"
+ handle_free="#9c003a"
+ handle_auto="#805c00"
+ handle_vect="#b035b1"
+ handle_sel_vect="#00bdff"
+ handle_align="#404080"
+ handle_sel_free="#00bdff"
+ handle_sel_auto="#00bdff"
+ handle_sel_align="#00bdff"
+ lastsel_point="#00ff12"
+ extra_edge_len="#fff3fa"
+ extra_edge_angle="#fff200"
+ extra_face_angle="#009aff"
+ extra_face_area="#000000"
+ editmesh_active="#00ff2fff"
+ normal="#22dddd"
+ vertex_normal="#225dd4"
+ split_normal="#dd23dd"
+ bone_pose="#00b8ff"
+ bone_pose_active="#00ff2f"
+ bone_solid="#bab5bc"
+ bone_locked_weight="#ff000080"
+ bundle_solid="#dadada"
+ camera_path="#4d4d4d"
+ skin_root="#000000"
+ view_overlay="#000000"
+ transform="#ffffff"
+ frame_current="#60c040"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="3"
+ object_origin_size="6"
+ >
+ <space>
+ <ThemeSpaceGradient
+ title="#000000"
+ text="#e4e4e4"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#e4e4e4"
+ header_text_hi="#ffffff"
+ button="#40404000"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#3a3a3a"
+ navigation_bar="#262626ff"
+ execution_buts="#26262600"
+ tab_active="#404040"
+ tab_inactive="#262626"
+ tab_back="#262626ff"
+ tab_outline="#262626"
+ >
+ <gradients>
+ <ThemeGradientColors
+ background_type="RADIAL"
+ high_gradient="#3f3f3f"
+ gradient="#2d2d2d"
+ >
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors
+ header="#404040e6"
+ back="#383838e6"
+ sub_back="#33333380"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor
+ grid="#2b2b2b"
+ frame_current="#337fcc"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ window_sliders="#808080"
+ channels_region="#262626"
+ dopesheet_channel="#404040"
+ dopesheet_subchannel="#393939"
+ channel_group="#333333"
+ active_channels_group="#337fcc"
+ preview_range="#00000080"
+ vertex="#000000"
+ vertex_select="#00bdff"
+ vertex_size="8"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#404040"
+ handle_free="#000000"
+ handle_auto="#8d8e90"
+ handle_vect="#7e7e7e"
+ handle_sel_vect="#19acff"
+ handle_align="#b6b5b6"
+ handle_sel_free="#19acff"
+ handle_sel_auto="#fdfffc"
+ handle_sel_align="#19acff"
+ handle_auto_clamped="#7e7e7e"
+ handle_sel_auto_clamped="#19acff"
+ lastsel_point="#f2f0ff"
+ handle_vertex="#808080"
+ handle_vertex_select="#ffffff"
+ handle_vertex_size="4"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#ffffff"
+ text="#a6a6a6"
+ text_hi="#fcfcfc"
+ header="#575757cc"
+ header_text="#ffffff"
+ header_text_hi="#bababa"
+ button="#404040ff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ navigation_bar="#131313ff"
+ execution_buts="#00000000"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#2b2b2bff"
+ tab_outline="#2b2b2b"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#404040ff"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#404040"
+ list_title="#bfbfbf"
+ list_text="#b3b3b3"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser
+ selected_file="#337fcc"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#e4e4e4"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#cacaca"
+ header_text_hi="#ffffff"
+ button="#404040ff"
+ button_title="#cacaca"
+ button_text="#e4e4e4"
+ button_text_hi="#ffffff"
+ navigation_bar="#262626ff"
+ execution_buts="#444444ff"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#232323ff"
+ tab_outline="#232323"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#404040ff"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor
+ grid="#292929"
+ view_sliders="#000000"
+ dopesheet_channel="#262626"
+ nla_track="#575757"
+ active_action="#00991d80"
+ active_action_unset="#33333380"
+ preview_range="#26262680"
+ strips="#333333"
+ strips_selected="#00bbff"
+ transition_strips="#314553"
+ transition_strips_selected="#00bbff"
+ meta_strips="#503a64"
+ meta_strips_selected="#00bbff"
+ sound_strips="#33442f"
+ sound_strips_selected="#00bbff"
+ tweak="#00991d"
+ tweak_duplicate="#d90000"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#00bbffff"
+ frame_current="#337fcc"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#ffffff"
+ text="#cccccc"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#ffffff"
+ header_text_hi="#ffffff"
+ button="#404040ff"
+ button_title="#bfbfbf"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ navigation_bar="#202020ff"
+ execution_buts="#202020ff"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#2b2b2bff"
+ tab_outline="#2b2b2b"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#40404000"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#404040"
+ list_title="#cecece"
+ list_text="#e6e6e6"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet
+ grid="#2b2b2b"
+ frame_current="#337fcc"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000040"
+ time_marker_line_selected="#ffffff33"
+ value_sliders="#000000"
+ view_sliders="#000000"
+ dopesheet_channel="#404040bf"
+ dopesheet_subchannel="#393939bf"
+ channels="#262626bf"
+ channels_selected="#337fcc80"
+ channel_group="#333333bf"
+ active_channels_group="#337fcc80"
+ long_key="#00000040"
+ long_key_selected="#00bdff40"
+ keyframe="#808080"
+ keyframe_selected="#00bdff"
+ keyframe_extreme="#808080"
+ keyframe_extreme_selected="#00bdff"
+ keyframe_breakdown="#808080"
+ keyframe_breakdown_selected="#00bdff"
+ keyframe_jitter="#808080"
+ keyframe_jitter_selected="#00bdff"
+ keyframe_movehold="#808080"
+ keyframe_movehold_selected="#00bdff"
+ keyframe_border="#00000080"
+ keyframe_border_selected="#00bdffff"
+ keyframe_scale_factor="1"
+ summary="#59595900"
+ preview_range="#26262680"
+ interpolation_line="#bfbfbf40"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#ffffff"
+ text="#a6a6a6"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#ffffff"
+ header_text_hi="#b7b7b7"
+ button="#404040ff"
+ button_title="#c7c7c7"
+ button_text="#cccccc"
+ button_text_hi="#ffffff"
+ navigation_bar="#131313ff"
+ execution_buts="#00000000"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#2b2b2bff"
+ tab_outline="#2b2b2b"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#404040ff"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#404040"
+ list_title="#e6e6e6"
+ list_text="#b3b3b3"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor
+ vertex="#000000"
+ vertex_select="#00c0ff"
+ vertex_size="3"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ face="#80808080"
+ face_select="#00c0ffa9"
+ face_dot="#00c0ff"
+ facedot_size="2"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#00000000"
+ face_front="#00000000"
+ editmesh_active="#00ff90ff"
+ wire_edit="#000000"
+ edge_select="#00c0ff"
+ scope_back="#0000004c"
+ preview_stitch_face="#1242b026"
+ preview_stitch_edge="#ff8500b2"
+ preview_stitch_vert="#ff85007f"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="3"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#1a1a1a"
+ title="#ffffff"
+ text="#8b8b8b"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#000000"
+ header_text_hi="#b8b8b8"
+ button="#40404000"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ navigation_bar="#262626ff"
+ execution_buts="#262626ff"
+ tab_active="#404040"
+ tab_inactive="#262626"
+ tab_back="#262626ff"
+ tab_outline="#262626"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#404040ff"
+ back="#383838e6"
+ sub_back="#333333e6"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor
+ grid="#000000"
+ window_sliders="#999999"
+ movie_strip="#3cbfe6"
+ movieclip_strip="#4d4d99"
+ image_strip="#a3a3a3"
+ scene_strip="#777777"
+ audio_strip="#60bf77"
+ effect_strip="#71fe9b"
+ transition_strip="#80797d"
+ meta_strip="#608073"
+ text_strip="#d1ff80"
+ frame_current="#337fcc"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ keyframe="#00ff00"
+ draw_action="#5d7b99"
+ preview_back="#1a1a1a"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ preview_range="#a14d0066"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#e4e4e4"
+ text="#a6a6a6"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#000000"
+ header_text_hi="#b7b7b7"
+ button="#333333ff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ navigation_bar="#202020ff"
+ execution_buts="#20202000"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#2b2b2bff"
+ tab_outline="#2b2b2b"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#40404000"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric
+ back="#404040"
+ title="#c7c7c7"
+ text="#bfbfbf"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#c7c7c7"
+ header_text_hi="#ffffff"
+ button="#404040ff"
+ button_title="#c7c7c7"
+ button_text="#777777"
+ button_text_hi="#ffffff"
+ navigation_bar="#262626ff"
+ execution_buts="#262626ff"
+ tab_active="#404040"
+ tab_inactive="#404040"
+ tab_back="#404040ff"
+ tab_outline="#131313"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#33333300"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor
+ line_numbers="#999999"
+ line_numbers_background="#262626"
+ selected_text="#262626"
+ cursor="#8b8bff"
+ syntax_builtin="#40bfff"
+ syntax_symbols="#40ff9a"
+ syntax_special="#c366ff"
+ syntax_preprocessor="#398080"
+ syntax_reserved="#a94800"
+ syntax_comment="#999999"
+ syntax_string="#40ff46"
+ syntax_numbers="#fffe40"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#fefefe"
+ text="#e7e7e7"
+ text_hi="#ffffff"
+ header="#575757e6"
+ header_text="#ffffff"
+ header_text_hi="#b7b7b7"
+ button="#40404000"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ navigation_bar="#131313ff"
+ execution_buts="#00000000"
+ tab_active="#262626"
+ tab_inactive="#1a1a1a"
+ tab_back="#1a1a1aff"
+ tab_outline="#1a1a1a"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#404040ff"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <node_editor>
+ <ThemeNodeEditor
+ node_selected="#00bdff"
+ node_active="#00ff2f"
+ wire="#1a1a1a"
+ wire_inner="#0d0d0d"
+ wire_select="#00bdff"
+ selected_text="#cccccc"
+ node_backdrop="#404040ff"
+ converter_node="#404040"
+ color_node="#404040"
+ group_node="#404040e6"
+ group_socket_node="#404040"
+ frame_node="#666666ff"
+ matte_node="#404040"
+ distor_node="#404040"
+ noodle_curving="0"
+ grid_levels="2"
+ input_node="#404040"
+ output_node="#404040"
+ filter_node="#404040"
+ vector_node="#404040"
+ texture_node="#404040"
+ shader_node="#404040"
+ script_node="#404040"
+ pattern_node="#404040"
+ layout_node="#404040"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#262626"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#cdcdcd"
+ header_text_hi="#b7b7b7"
+ button="#40404000"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ navigation_bar="#131313ff"
+ execution_buts="#00000000"
+ tab_active="#404040"
+ tab_inactive="#232323"
+ tab_back="#23232300"
+ tab_outline="#232323"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#404040ff"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#262626"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <outliner>
+ <ThemeOutliner
+ match="#404040"
+ selected_highlight="#337fcc"
+ active="#00991d"
+ selected_object="#ffffff"
+ active_object="#ffffff"
+ edited_object="#00000080"
+ row_alternate="#ffffff06"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#333333"
+ title="#dadada"
+ text="#e6e6e6"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#c7c7c7"
+ header_text_hi="#ffffff"
+ button="#404040ff"
+ button_title="#c7c7c7"
+ button_text="#000000"
+ button_text_hi="#d8d8d8"
+ navigation_bar="#202020ff"
+ execution_buts="#00000000"
+ tab_active="#727272"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#222222"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#26262600"
+ back="#292929ff"
+ sub_back="#242424ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo
+ info_selected="#18669e"
+ info_selected_text="#ffffff"
+ info_error="#131313ff"
+ info_error_text="#ff4040"
+ info_warning="#262626ff"
+ info_warning_text="#ffe100"
+ info_info="#262626ff"
+ info_info_text="#25ff00"
+ info_debug="#c4c4c4ff"
+ info_debug_text="#000000"
+ info_property="#3ace87ff"
+ info_property_text="#ffffff"
+ info_operator="#3ace87ff"
+ info_operator_text="#ffffff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#404040"
+ title="#e4e4e4"
+ text="#cecece"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#ffffff"
+ header_text_hi="#000000"
+ button="#262626ff"
+ button_title="#c7c7c7"
+ button_text="#000000"
+ button_text_hi="#000000"
+ navigation_bar="#131313ff"
+ execution_buts="#00000000"
+ tab_active="#727272"
+ tab_inactive="#222222"
+ tab_back="#222222ff"
+ tab_outline="#222222"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#333333ff"
+ back="#292929ff"
+ sub_back="#242424ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <preferences>
+ <ThemePreferences>
+ <space>
+ <ThemeSpaceGeneric
+ back="#404040"
+ title="#eeeeee"
+ text="#e6e6e6"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#404040ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#262626ff"
+ execution_buts="#262626ff"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#232323ff"
+ tab_outline="#232323"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#40404000"
+ back="#383838ff"
+ sub_back="#333333ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemePreferences>
+ </preferences>
+ <console>
+ <ThemeConsole
+ line_output="#40bfff"
+ line_input="#ffffff"
+ line_info="#607f9e"
+ line_error="#ff0019"
+ cursor="#8b8bff"
+ select="#18181880"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#262626"
+ title="#e4e4e4"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#262626ff"
+ button_title="#c7c7c7"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#131313ff"
+ execution_buts="#00000000"
+ tab_active="#727272"
+ tab_inactive="#4a4a4a"
+ tab_back="#414141ff"
+ tab_outline="#2d2d2d"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#262626ff"
+ back="#1f1f1fff"
+ sub_back="#1a1a1aff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ path_keyframe_before="#ffc4c4"
+ path_keyframe_after="#c4c4ff"
+ frame_current="#01c040"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#1a1a1a"
+ title="#ffffff"
+ text="#a6a6a6"
+ text_hi="#ffffff"
+ header="#575757cc"
+ header_text="#000000"
+ header_text_hi="#b8b8b8"
+ button="#262626ff"
+ button_title="#c7c7c7"
+ button_text="#b4b4b4"
+ button_text_hi="#ffffff"
+ navigation_bar="#131313ff"
+ execution_buts="#00000000"
+ tab_active="#262626"
+ tab_inactive="#1a1a1a"
+ tab_back="#1a1a1aff"
+ tab_outline="#1a1a1a"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#262626ff"
+ back="#1f1f1fff"
+ sub_back="#1a1a1aff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#262626"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#404040"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#262626ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#333333ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#202020ff"
+ execution_buts="#1a1a1a00"
+ tab_active="#262626"
+ tab_inactive="#282828"
+ tab_back="#262626ff"
+ tab_outline="#131313"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#26262600"
+ back="#292929ff"
+ sub_back="#242424ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#262626"
+ title="#ffffff"
+ text="#838383"
+ text_hi="#ffffff"
+ header="#262626ff"
+ header_text="#aaaaaa"
+ header_text_hi="#ffffff"
+ button="#333333ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#202020ff"
+ execution_buts="#1a1a1a00"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#232323ff"
+ tab_outline="#232323"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#31313100"
+ back="#292929ff"
+ sub_back="#242424ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
+ <bone_color_sets>
+ <ThemeBoneColorSet
+ normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#0a3694"
+ select="#3667df"
+ active="#65ceff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#010000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle
+ points="10"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle
+ points="10"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/modo.xml b/release/scripts/presets/interface_theme/modo.xml
new file mode 100644
index 00000000000..b98d00d7152
--- /dev/null
+++ b/release/scripts/presets/interface_theme/modo.xml
@@ -0,0 +1,1481 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface
+ menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_alpha="1"
+ icon_saturation="0.4"
+ widget_emboss="#48484800"
+ editor_outline="#383838"
+ widget_text_cursor="#585858"
+ axis_x="#dc0000"
+ axis_y="#00dc00"
+ axis_z="#0000dc"
+ gizmo_hi="#000000"
+ gizmo_primary="#0000dc"
+ gizmo_secondary="#dc0000"
+ gizmo_a="#4da84d"
+ gizmo_b="#a33535"
+ icon_scene="#acacacff"
+ icon_collection="#282828ff"
+ icon_object="#0083b9ff"
+ icon_object_data="#b46c97ff"
+ icon_modifier="#58a47aff"
+ icon_shading="#a2783fff"
+ icon_folder="#bda670ff"
+ icon_border_intensity="0.297222"
+ >
+ <wcol_regular>
+ <ThemeWidgetColors
+ outline="#686868"
+ inner="#686868ff"
+ inner_sel="#f49c1cff"
+ item="#2f76c3ff"
+ text="#cccccc"
+ text_sel="#181818"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors
+ outline="#484848"
+ inner="#686868ff"
+ inner_sel="#f49c1cff"
+ item="#181818ff"
+ text="#cccccc"
+ text_sel="#181818"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors
+ outline="#383838"
+ inner="#585858ff"
+ inner_sel="#f49c1cff"
+ item="#181818ff"
+ text="#cccccc"
+ text_sel="#181818"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
+ <wcol_radio>
+ <ThemeWidgetColors
+ outline="#484848"
+ inner="#5a5a5aff"
+ inner_sel="#f49c1cff"
+ item="#ccccccff"
+ text="#cccccc"
+ text_sel="#181818"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors
+ outline="#9098a0"
+ inner="#9098a0ff"
+ inner_sel="#757c84ff"
+ item="#0071daff"
+ text="#181818"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="25"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors
+ outline="#181818"
+ inner="#686868ff"
+ inner_sel="#f49c1cff"
+ item="#181818ff"
+ text="#cccccc"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors
+ outline="#302e2e"
+ inner="#606060ff"
+ inner_sel="#f49c1cff"
+ item="#5a5a5aff"
+ text="#e1e1e1"
+ text_sel="#181818"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors
+ outline="#484848"
+ inner="#9098a0ff"
+ inner_sel="#f49c1cff"
+ item="#5a5a5aff"
+ text="#181818"
+ text_sel="#eeeeee"
+ show_shaded="FALSE"
+ shadetop="-20"
+ shadedown="0"
+ roundness="0.6"
+ >
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors
+ outline="#191919"
+ inner="#b4b4b4ff"
+ inner_sel="#f49c1cff"
+ item="#9098a0ff"
+ text="#181818"
+ text_sel="#eeeeee"
+ show_shaded="FALSE"
+ shadetop="-20"
+ shadedown="0"
+ roundness="0.6"
+ >
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors
+ outline="#383838"
+ inner="#444444ff"
+ inner_sel="#646464ff"
+ item="#181818ff"
+ text="#cccccc"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors
+ outline="#484848"
+ inner="#606060ff"
+ inner_sel="#f49c1cff"
+ item="#ccccccff"
+ text="#cccccc"
+ text_sel="#181818"
+ show_shaded="FALSE"
+ shadetop="15"
+ shadedown="-15"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors
+ outline="#181818"
+ inner="#606060ff"
+ inner_sel="#f49c1c00"
+ item="#ccccccff"
+ text="#cccccc"
+ text_sel="#f49c1c"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors
+ outline="#181818"
+ inner="#484848ff"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#bfbfbf"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors
+ outline="#383838"
+ inner="#585858f7"
+ inner_sel="#f49c1cff"
+ item="#f49c1cff"
+ text="#dfdfdf"
+ text_sel="#181818"
+ show_shaded="TRUE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors
+ outline="#181818"
+ inner="#191919e6"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#cccccc"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors
+ outline="#ffffff"
+ inner="#18181800"
+ inner_sel="#505860ff"
+ item="#ccccccff"
+ text="#cccccc"
+ text_sel="#181818"
+ show_shaded="FALSE"
+ shadetop="38"
+ shadedown="0"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors
+ outline="#383838"
+ inner="#383838b4"
+ inner_sel="#646464b4"
+ item="#585858ff"
+ text="#cccccc"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors
+ outline="#181818"
+ inner="#bebebeff"
+ inner_sel="#646464b4"
+ item="#f49c1cff"
+ text="#0b0b0b"
+ text_sel="#cccccc"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="0.5"
+ >
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors
+ outline="#181818"
+ inner="#18181800"
+ inner_sel="#f49c1c00"
+ item="#5a5a5aff"
+ text="#cccccc"
+ text_sel="#f49c1c"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors
+ inner_anim="#53992e"
+ inner_anim_sel="#5aa633"
+ inner_key="#b3ae36"
+ inner_key_sel="#d7d34b"
+ inner_driven="#b400ff"
+ inner_driven_sel="#9900e6"
+ inner_overridden="#19c3c3"
+ inner_overridden_sel="#118f8f"
+ inner_changed="#cc7529"
+ inner_changed_sel="#e6852d"
+ blend="0.5"
+ >
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors
+ outline="#3e3e3e"
+ inner="#3e3e3eff"
+ inner_sel="#484848ff"
+ item="#2f76c3ff"
+ text="#909090"
+ text_sel="#f49c1c"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.3"
+ >
+ </ThemeWidgetColors>
+ </wcol_tab>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D
+ grid="#505050ff"
+ clipping_border_3d="#313131ff"
+ wire="#393939"
+ wire_edit="#282828"
+ gp_vertex="#292929"
+ gp_vertex_select="#ffa829"
+ gp_vertex_size="2"
+ text_grease_pencil="#b5e61d"
+ object_selected="#ffa829"
+ object_active="#ffa829"
+ text_keyframe="#ddd700"
+ camera="#cccccc"
+ empty="#cccccc"
+ light="#cccccc28"
+ speaker="#cccccc"
+ vertex="#292929"
+ vertex_select="#ffa829"
+ vertex_size="3"
+ vertex_bevel="#0ec6ff"
+ vertex_unreferenced="#404040"
+ edge_select="#ffa829"
+ edge_seam="#0077db"
+ edge_sharp="#800055"
+ edge_crease="#ad009d"
+ edge_bevel="#00a449"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#7fff7f"
+ face="#18181812"
+ face_select="#ffa82940"
+ face_dot="#ffa829"
+ facedot_size="1"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#ff0000b3"
+ face_front="#0000ffb3"
+ nurb_uline="#1d8fff"
+ nurb_vline="#803060"
+ nurb_sel_uline="#f0ff40"
+ nurb_sel_vline="#f090a0"
+ act_spline="#1d8fff"
+ handle_free="#181818"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#1d8fff"
+ handle_sel_free="#181818"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#1d8fff"
+ lastsel_point="#1d8fff"
+ extra_edge_len="#181818"
+ extra_edge_angle="#181818"
+ extra_face_angle="#002000"
+ extra_face_area="#000080"
+ editmesh_active="#ffa82940"
+ normal="#22dddd"
+ vertex_normal="#407eff"
+ split_normal="#ff4cff"
+ bone_pose="#50c8ff"
+ bone_pose_active="#cccccc"
+ bone_solid="#c8c8c8"
+ bone_locked_weight="#ff000080"
+ bundle_solid="#c8c8c8"
+ camera_path="#181818"
+ skin_root="#181818"
+ view_overlay="#181818"
+ transform="#cccccc"
+ frame_current="#60c040"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1"
+ object_origin_size="10"
+ >
+ <space>
+ <ThemeSpaceGradient
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#383838"
+ >
+ <gradients>
+ <ThemeGradientColors
+ background_type="SINGLE_COLOR"
+ high_gradient="#5c666b"
+ gradient="#2d2d2e"
+ >
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#48484880"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor
+ grid="#5b6672"
+ frame_current="#c67f14"
+ time_scrub_background="#9296a5cc"
+ time_marker_line="#18181860"
+ time_marker_line_selected="#ffffff60"
+ window_sliders="#969696"
+ channels_region="#424242"
+ dopesheet_channel="#424242"
+ dopesheet_subchannel="#424242"
+ channel_group="#424242"
+ active_channels_group="#86570d"
+ preview_range="#f49c1c00"
+ vertex="#181818"
+ vertex_select="#f49c1c"
+ vertex_size="3"
+ vertex_bevel="#181818"
+ vertex_unreferenced="#181818"
+ handle_free="#181818"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#181818"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#994030"
+ handle_sel_auto_clamped="#f0af90"
+ lastsel_point="#181818"
+ handle_vertex="#181818"
+ handle_vertex_select="#ff8500"
+ handle_vertex_size="3"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#64707c"
+ title="#cccccc"
+ text="#303442"
+ text_hi="#ffffff"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#ffffff"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#48484880"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#484848"
+ list_title="#181818"
+ list_text="#cccccc"
+ list_text_hi="#f49c1c"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser
+ selected_file="#f49c1c"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#484848"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#383838ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#3f3f3fff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#444444ff"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#3f3f3fff"
+ sub_back="#3f3f3fff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor
+ grid="#5e5e5e"
+ view_sliders="#969696"
+ dopesheet_channel="#5a85b2"
+ nla_track="#525252"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
+ preview_range="#cc701a66"
+ strips="#181818"
+ strips_selected="#ff8c00"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
+ keyframe_border="#181818ff"
+ keyframe_border_selected="#181818ff"
+ frame_current="#c69345"
+ time_scrub_background="#292929e6"
+ time_marker_line="#18181860"
+ time_marker_line_selected="#ffffff60"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#64707c"
+ title="#cccccc"
+ text="#a6a6a6"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#484848"
+ list_title="#181818"
+ list_text="#181818"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet
+ grid="#5b6672"
+ frame_current="#c67f14"
+ time_scrub_background="#9296a5cc"
+ time_marker_line="#18181860"
+ time_marker_line_selected="#cccccc60"
+ value_sliders="#181818"
+ view_sliders="#969696"
+ dopesheet_channel="#424242ff"
+ dopesheet_subchannel="#424242ff"
+ channels="#424242ff"
+ channels_selected="#f49c1cff"
+ channel_group="#42424210"
+ active_channels_group="#86570d57"
+ long_key="#18181880"
+ long_key_selected="#f49c1ccc"
+ keyframe="#bddae8"
+ keyframe_selected="#ffb21e"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#ace493"
+ keyframe_jitter_selected="#61c042"
+ keyframe_movehold="#5c5656"
+ keyframe_movehold_selected="#ffaf23"
+ keyframe_border="#18181880"
+ keyframe_border_selected="#181818ff"
+ keyframe_scale_factor="0.9"
+ summary="#9b661057"
+ preview_range="#f49c1c00"
+ interpolation_line="#94e575cc"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#64707c"
+ title="#cccccc"
+ text="#303442"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#484848"
+ list_title="#181818"
+ list_text="#cccccc"
+ list_text_hi="#f49c1c"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor
+ vertex="#eeeeee"
+ vertex_select="#ffa829"
+ vertex_size="5"
+ vertex_bevel="#eeeeee"
+ vertex_unreferenced="#404040"
+ face="#eeeeee0a"
+ face_select="#ffa8293c"
+ face_dot="#ffa829"
+ facedot_size="1"
+ freestyle_face_mark="#18181800"
+ face_back="#18181800"
+ face_front="#18181800"
+ editmesh_active="#ffa829ff"
+ wire_edit="#c0c0c0"
+ edge_select="#ffa829"
+ scope_back="#727272ff"
+ preview_stitch_face="#1242b026"
+ preview_stitch_edge="#ffa829b2"
+ preview_stitch_vert="#ffa8297f"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ metadatabg="#181818"
+ metadatatext="#eeeeee"
+ handle_free="#181818"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#181818"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#181818"
+ handle_sel_auto_clamped="#181818"
+ handle_vertex="#181818"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#a3a3a3"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#888888"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor
+ grid="#5b6672"
+ window_sliders="#a0a0a0"
+ movie_strip="#516987"
+ movieclip_strip="#20208f"
+ image_strip="#6d5881"
+ scene_strip="#4e983e"
+ audio_strip="#2e8f8f"
+ effect_strip="#a9547c"
+ transition_strip="#a25f6f"
+ meta_strip="#6d9183"
+ text_strip="#f49c1c"
+ frame_current="#c67f14"
+ time_scrub_background="#38383800"
+ time_marker_line="#18181860"
+ time_marker_line_selected="#ffffff60"
+ keyframe="#f49c1c"
+ draw_action="#50c8ff"
+ preview_back="#181818"
+ metadatabg="#181818"
+ metadatatext="#cccccc"
+ preview_range="#a14d0066"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#484848"
+ title="#cccccc"
+ text="#a6a6a6"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#48484842"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric
+ back="#484848"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#888888"
+ header_text_hi="#dff5ff"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#3e3e3eff"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor
+ line_numbers="#d0d0d0"
+ line_numbers_background="#383838"
+ selected_text="#005aa6"
+ cursor="#cccccc"
+ syntax_builtin="#f49c1c"
+ syntax_symbols="#a5a5a5"
+ syntax_special="#66d9ef"
+ syntax_preprocessor="#a5a5a5"
+ syntax_reserved="#a5a5a5"
+ syntax_comment="#696969"
+ syntax_string="#e6db5a"
+ syntax_numbers="#c89927"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#383838"
+ title="#cccccc"
+ text="#a5a5a5"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <node_editor>
+ <ThemeNodeEditor
+ node_selected="#ffa829"
+ node_active="#ffa829"
+ wire="#484848"
+ wire_inner="#484848"
+ wire_select="#ccccff"
+ selected_text="#ffa829"
+ node_backdrop="#484848ff"
+ converter_node="#383838"
+ color_node="#383838"
+ group_node="#383838ff"
+ group_socket_node="#383838"
+ frame_node="#383838ff"
+ matte_node="#383838"
+ distor_node="#383838"
+ noodle_curving="1"
+ grid_levels="0"
+ input_node="#383838"
+ output_node="#383838"
+ filter_node="#383838"
+ vector_node="#383838"
+ texture_node="#383838"
+ shader_node="#383838"
+ script_node="#383838"
+ pattern_node="#383838"
+ layout_node="#383838"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#64707c"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#484848"
+ list_title="#181818"
+ list_text="#181818"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <outliner>
+ <ThemeOutliner
+ match="#337f33"
+ selected_highlight="#353b41"
+ active="#404850"
+ selected_object="#e96a00"
+ active_object="#ffaf29"
+ edited_object="#00806266"
+ row_alternate="#ffffff07"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#7e8990"
+ title="#cccccc"
+ text="#181818"
+ text_hi="#f49c1c"
+ header="#525252ff"
+ header_text="#888888"
+ header_text_hi="#cccccc"
+ button="#727272ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo
+ info_selected="#404850"
+ info_selected_text="#ffaf29"
+ info_error="#181818ff"
+ info_error_text="#ff453a"
+ info_warning="#181818ff"
+ info_warning_text="#ff453a"
+ info_info="#181818ff"
+ info_info_text="#cccccc"
+ info_debug="#181818ff"
+ info_debug_text="#cccccc"
+ info_property="#181818ff"
+ info_property_text="#cccccc"
+ info_operator="#181818ff"
+ info_operator_text="#82d38a"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#7e8990"
+ title="#c8c6c9"
+ text="#282828"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <preferences>
+ <ThemePreferences>
+ <space>
+ <ThemeSpaceGeneric
+ back="#404040"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#363636ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#484848ff"
+ execution_buts="#4b4b4bff"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848a6"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemePreferences>
+ </preferences>
+ <console>
+ <ThemeConsole
+ line_output="#282828"
+ line_input="#cccccc"
+ line_info="#00aa00"
+ line_error="#dc6060"
+ cursor="#dc6060"
+ select="#f49c1c30"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#64707c"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor
+ marker_outline="#181818"
+ marker="#7f7f00"
+ active_marker="#cccccc"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ path_keyframe_before="#ffc4c4"
+ path_keyframe_after="#c4c4ff"
+ frame_current="#c69345"
+ time_scrub_background="#292929e6"
+ time_marker_line="#18181860"
+ time_marker_line_selected="#ffffff60"
+ strips="#181818"
+ strips_selected="#ff8c00"
+ metadatabg="#181818"
+ metadatatext="#ffffff"
+ handle_free="#181818"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#181818"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#181818"
+ handle_sel_auto_clamped="#181818"
+ handle_vertex="#181818"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="4"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#2d3236"
+ title="#cccccc"
+ text="#a6a6a6"
+ text_hi="#cccccc"
+ header="#525252ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#484848ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#484848"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#484848"
+ tab_inactive="#414141"
+ tab_back="#383838ff"
+ tab_outline="#484848"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#666666"
+ list_title="#181818"
+ list_text="#000000"
+ list_text_hi="#cccccc"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#484848"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#303030ff"
+ header_text="#cccccc"
+ header_text_hi="#cccccc"
+ button="#383838ff"
+ button_title="#cccccc"
+ button_text="#cccccc"
+ button_text_hi="#cccccc"
+ navigation_bar="#38383800"
+ execution_buts="#18181800"
+ tab_active="#383838"
+ tab_inactive="#383838"
+ tab_back="#383838ff"
+ tab_outline="#383838"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#484848"
+ title="#cccccc"
+ text="#cccccc"
+ text_hi="#cccccc"
+ header="#383838ff"
+ header_text="#a7a7a7"
+ header_text_hi="#cccccc"
+ button="#ccccccff"
+ button_title="#cccccc"
+ button_text="#181818"
+ button_text_hi="#cccccc"
+ navigation_bar="#38383800"
+ execution_buts="#00000000"
+ tab_active="#383838"
+ tab_inactive="#383838"
+ tab_back="#383838ff"
+ tab_outline="#383838"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242ff"
+ back="#484848ff"
+ sub_back="#484848ff"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
+ <bone_color_sets>
+ <ThemeBoneColorSet
+ normal="#ffa98b"
+ select="#ffb6a8"
+ active="#ffb6a8"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f7daa4"
+ select="#f7c2b1"
+ active="#f7c2b1"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#94ff7e"
+ select="#b8efa8"
+ active="#b8efa8"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#c2c6ff"
+ select="#8fdbff"
+ active="#8fdbff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#ff9dd7"
+ select="#ff9edc"
+ active="#ff9edc"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#cc95ff"
+ select="#d9a9ff"
+ active="#d9a9ff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#93f2c6"
+ select="#85dace"
+ active="#85dace"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#7bb3c9"
+ select="#a4cfdb"
+ active="#a4cfdb"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#ffd10c"
+ select="#becb00"
+ active="#becb00"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#585858"
+ select="#afafaf"
+ active="#afafaf"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#df9aff"
+ select="#dd9aff"
+ active="#dd9aff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#afe735"
+ select="#aad851"
+ active="#aad851"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#d6d6d6"
+ select="#e0e0e0"
+ active="#e0e0e0"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#ffaa88"
+ select="#ffac8e"
+ active="#ffac8e"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#35df4a"
+ select="#35d846"
+ active="#35d846"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#787878"
+ select="#787878"
+ active="#aeaeae"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.05"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle
+ points="10"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.05"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/print_friendly.xml b/release/scripts/presets/interface_theme/print_friendly.xml
new file mode 100644
index 00000000000..b607e29bbe4
--- /dev/null
+++ b/release/scripts/presets/interface_theme/print_friendly.xml
@@ -0,0 +1,1481 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface
+ menu_shadow_fac="0.3"
+ menu_shadow_width="4"
+ icon_alpha="1"
+ icon_saturation="0.5"
+ widget_emboss="#000000ff"
+ editor_outline="#000000"
+ widget_text_cursor="#3399e6"
+ axis_x="#ff3352"
+ axis_y="#8bdc00"
+ axis_z="#2890ff"
+ gizmo_hi="#ffffff"
+ gizmo_primary="#f5f14d"
+ gizmo_secondary="#63ffff"
+ gizmo_a="#4da84d"
+ gizmo_b="#a33535"
+ icon_scene="#000000ff"
+ icon_collection="#000000ff"
+ icon_object="#c7854eff"
+ icon_object_data="#008667ff"
+ icon_modifier="#4d7097ff"
+ icon_shading="#b65d65ff"
+ icon_folder="#e3c16eff"
+ icon_border_intensity="0"
+ >
+ <wcol_regular>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#668cccff"
+ item="#191919ff"
+ text="#1a1a1a"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-5"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#5680c2ff"
+ item="#191919ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-5"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#5094ffff"
+ item="#000000ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
+ <wcol_radio>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#5680c2e6"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#d8d8d8ff"
+ item="#5680c2ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="-8"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#5680c2e6"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-15"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#5680c2ff"
+ item="#000000ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#5680c2ff"
+ item="#80b1ffff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-10"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#d8d8d8ff"
+ item="#5680c2ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-4"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#5680c2ff"
+ item="#000000ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#d8d8d8ff"
+ item="#000000ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffcc"
+ inner_sel="#5680c2e6"
+ item="#d8d8d8ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#d8d8d8ff"
+ inner_sel="#585858ff"
+ item="#d8d8d8ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffef"
+ inner_sel="#5680c2e6"
+ item="#d8d8d8ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors
+ outline="#19191a"
+ inner="#19191aef"
+ inner_sel="#19191aef"
+ item="#19191aef"
+ text="#e6e6e6"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#00000000"
+ inner_sel="#5680c2e6"
+ item="#ffffff8f"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="38"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#a4a4a4ff"
+ item="#d8d8d8ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#646464b4"
+ item="#5094ffff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#00000000"
+ inner_sel="#5680c2ff"
+ item="#5094ffff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors
+ inner_anim="#73be4c"
+ inner_anim_sel="#5aa633"
+ inner_key="#f0eb64"
+ inner_key_sel="#d7d34b"
+ inner_driven="#b400ff"
+ inner_driven_sel="#9900e6"
+ inner_overridden="#6bf3cc"
+ inner_overridden_sel="#5fd9b6"
+ inner_changed="#cc7529"
+ inner_changed_sel="#e6852d"
+ blend="0.5"
+ >
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#5094ffff"
+ item="#28292dff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tab>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D
+ grid="#000000ff"
+ clipping_border_3d="#313131ff"
+ wire="#000000"
+ wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#00cc9e"
+ gp_vertex_size="3"
+ text_grease_pencil="#00e6b2"
+ object_selected="#cc5d00"
+ object_active="#ffaf29"
+ text_keyframe="#ddd700"
+ camera="#000000"
+ empty="#000000"
+ light="#00000028"
+ speaker="#000000"
+ vertex="#000000"
+ vertex_select="#00b38a"
+ vertex_size="3"
+ vertex_bevel="#00a5ff"
+ vertex_unreferenced="#000000"
+ edge_select="#00cc9e"
+ edge_seam="#db2512"
+ edge_sharp="#00ffff"
+ edge_crease="#cc0099"
+ edge_bevel="#00a5ff"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#ffcc7f"
+ face="#00000012"
+ face_select="#29cca766"
+ face_dot="#a1e6d6"
+ facedot_size="3"
+ freestyle_face_mark="#ffcc7f4d"
+ face_back="#ff0000b3"
+ face_front="#0000ffb3"
+ nurb_uline="#909000"
+ nurb_vline="#803060"
+ nurb_sel_uline="#f0ff40"
+ nurb_sel_vline="#f090a0"
+ act_spline="#89e689"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ lastsel_point="#ffffff"
+ extra_edge_len="#ff6149"
+ extra_edge_angle="#cccc00"
+ extra_face_angle="#b3b3ff"
+ extra_face_area="#00cc00"
+ editmesh_active="#00ff0081"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_pose="#50c8ff"
+ bone_pose_active="#8cffff"
+ bone_solid="#e6e6e6"
+ bone_locked_weight="#ff000080"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#b44d4d"
+ view_overlay="#000000"
+ transform="#000000"
+ frame_current="#60c040"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1"
+ object_origin_size="6"
+ >
+ <space>
+ <ThemeSpaceGradient
+ title="#000000"
+ text="#000000"
+ text_hi="#000000"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <gradients>
+ <ThemeGradientColors
+ background_type="SINGLE_COLOR"
+ high_gradient="#ffffff"
+ gradient="#e6e6e6"
+ >
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor
+ grid="#5b5b5b"
+ frame_current="#5680c2"
+ time_scrub_background="#d8d8d8ff"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ window_sliders="#969696"
+ channels_region="#999999"
+ dopesheet_channel="#2e6399"
+ dopesheet_subchannel="#7aa4cc"
+ channel_group="#278c0e"
+ active_channels_group="#4db135"
+ preview_range="#a14d0066"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="6"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#994030"
+ handle_sel_auto_clamped="#f0af90"
+ lastsel_point="#ffffff"
+ handle_vertex="#000000"
+ handle_vertex_select="#ff8500"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#d8d8d8"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser
+ selected_file="#76afff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#a4a4a4"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#d8d8d8ff"
+ button_title="#1a1a1a"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor
+ grid="#858585"
+ view_sliders="#969696"
+ dopesheet_channel="#5a85b2"
+ nla_track="#424242"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
+ preview_range="#a14d0066"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ frame_current="#5680c2"
+ time_scrub_background="#d8d8d8ff"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#d8d8d8"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#000000"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet
+ grid="#818181"
+ frame_current="#5680c2"
+ time_scrub_background="#d8d8d8ff"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ value_sliders="#000000"
+ view_sliders="#969696"
+ dopesheet_channel="#2e639924"
+ dopesheet_subchannel="#7aa4cc24"
+ channels="#b1b1b1ff"
+ channels_selected="#60c04044"
+ channel_group="#278c0e37"
+ active_channels_group="#4eb33555"
+ long_key="#1a151580"
+ long_key_selected="#ff8c00cc"
+ keyframe="#e8e8e8"
+ keyframe_selected="#ffbe33"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#94e575"
+ keyframe_jitter_selected="#61c042"
+ keyframe_movehold="#5c5656"
+ keyframe_movehold_selected="#ffaf23"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ keyframe_scale_factor="1"
+ summary="#d3660066"
+ preview_range="#a14d0066"
+ interpolation_line="#94e575cc"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#d8d8d8"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor
+ vertex="#000000"
+ vertex_select="#00b38a"
+ vertex_size="3"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ face="#ffffff0a"
+ face_select="#29cca766"
+ face_dot="#a1e6d6"
+ facedot_size="3"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#00000000"
+ face_front="#00000000"
+ editmesh_active="#ffffff80"
+ wire_edit="#c0c0c0"
+ edge_select="#00cc9e"
+ scope_back="#d8d8d8ff"
+ preview_stitch_face="#7f7f0033"
+ preview_stitch_edge="#ff00ff33"
+ preview_stitch_vert="#0000ff33"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#5680c2"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#d8d8d8"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor
+ grid="#000000"
+ window_sliders="#a0a0a0"
+ movie_strip="#516987"
+ movieclip_strip="#20208f"
+ image_strip="#6d5881"
+ scene_strip="#4e983e"
+ audio_strip="#2e8f8f"
+ effect_strip="#a9547c"
+ transition_strip="#a25f6f"
+ meta_strip="#6d9183"
+ text_strip="#a29700"
+ frame_current="#5680c2"
+ time_scrub_background="#d8d8d8ff"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ keyframe="#ff8500"
+ draw_action="#50c8ff"
+ preview_back="#a4a4a4"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ preview_range="#a14d0066"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#d8d8d8ff"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor
+ line_numbers="#d0d0d0"
+ line_numbers_background="#d8d8d8"
+ selected_text="#f7f7ff"
+ cursor="#ff0000"
+ syntax_builtin="#ff1961"
+ syntax_symbols="#ff734d"
+ syntax_special="#5f8800"
+ syntax_preprocessor="#ad80ff"
+ syntax_reserved="#c4753b"
+ syntax_comment="#939393"
+ syntax_string="#b5a549"
+ syntax_numbers="#50dbff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <node_editor>
+ <ThemeNodeEditor
+ node_selected="#f15800"
+ node_active="#f15800"
+ wire="#a7a7a7"
+ wire_inner="#999999"
+ wire_select="#ffa733"
+ selected_text="#7f7070"
+ node_backdrop="#e6e6e6ff"
+ converter_node="#66c4ff"
+ color_node="#ffcb4d"
+ group_node="#59b36ab9"
+ group_socket_node="#dfc300"
+ frame_node="#9b9b9ba0"
+ matte_node="#977474"
+ distor_node="#749797"
+ noodle_curving="0"
+ grid_levels="2"
+ input_node="#ff6675"
+ output_node="#ff6675"
+ filter_node="#6c696f"
+ vector_node="#9999ff"
+ texture_node="#ffc399"
+ shader_node="#a7ff99"
+ script_node="#6c696f"
+ pattern_node="#6c696f"
+ layout_node="#6c696f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#a5a5a5"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <outliner>
+ <ThemeOutliner
+ match="#337f33"
+ selected_highlight="#76afff"
+ active="#3b5689"
+ selected_object="#7d5454"
+ active_object="#ad3535"
+ edited_object="#0080624d"
+ row_alternate="#ffffffff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#d8d8d8"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo
+ info_selected="#76afff"
+ info_selected_text="#ffffff"
+ info_error="#990000ff"
+ info_error_text="#ffffff"
+ info_warning="#b36a00ff"
+ info_warning_text="#ffffff"
+ info_info="#5e8bcbff"
+ info_info_text="#ffffff"
+ info_debug="#d3d3d3ff"
+ info_debug_text="#000000"
+ info_property="#3ace87ff"
+ info_property_text="#ffffff"
+ info_operator="#3ace87ff"
+ info_operator_text="#ffffff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <preferences>
+ <ThemePreferences>
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#d8d8d8ff"
+ execution_buts="#d8d8d8ff"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemePreferences>
+ </preferences>
+ <console>
+ <ThemeConsole
+ line_output="#6080ff"
+ line_input="#ffffff"
+ line_info="#00aa00"
+ line_error="#dc6060"
+ cursor="#dc6060"
+ select="#ffffff30"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#000000"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#272727"
+ header_text_hi="#ffffff"
+ button="#7272727f"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ path_keyframe_before="#ffc4c4"
+ path_keyframe_after="#c4c4ff"
+ frame_current="#5680c2"
+ time_scrub_background="#d8d8d8ff"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#d8d8d8"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#d8d8d8"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#2f303599"
+ button_title="#ffffff"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#d8d8d8ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#76afff"
+ tab_inactive="#ffffff"
+ tab_back="#d8d8d8ff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#d8d8d8ff"
+ back="#ffffffcc"
+ sub_back="#a4a4a424"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
+ <bone_color_sets>
+ <ThemeBoneColorSet
+ normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle
+ points="12"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.3"
+ shadow_value="0.7"
+ >
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.3"
+ shadow_value="0.7"
+ >
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.3"
+ shadow_value="0.7"
+ >
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/white.xml b/release/scripts/presets/interface_theme/white.xml
new file mode 100644
index 00000000000..26ddf374c22
--- /dev/null
+++ b/release/scripts/presets/interface_theme/white.xml
@@ -0,0 +1,1470 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface
+ menu_shadow_fac="0.215574"
+ menu_shadow_width="13"
+ icon_alpha="1"
+ icon_saturation="1"
+ widget_emboss="#9e9e9e12"
+ editor_outline="#a5a5a5"
+ widget_text_cursor="#ffac0d"
+ axis_x="#ff0900"
+ axis_y="#93e700"
+ axis_z="#007bff"
+ gizmo_hi="#000000"
+ gizmo_primary="#fab100"
+ gizmo_secondary="#00e9e2"
+ gizmo_a="#4da84d"
+ gizmo_b="#a33535"
+ icon_scene="#505050ff"
+ icon_collection="#696969ff"
+ icon_object="#d66a00ff"
+ icon_object_data="#005302ff"
+ icon_modifier="#0023adff"
+ icon_shading="#fc0000ff"
+ icon_folder="#ffab00ff"
+ icon_border_intensity="0"
+ >
+ <wcol_regular>
+ <ThemeWidgetColors
+ outline="#dbdbdb"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#bbbbbbff"
+ text="#3d3d3d"
+ text_sel="#e2e2e2"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-5"
+ roundness="0.53471"
+ >
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors
+ outline="#dbdbdb"
+ inner="#e7e7e7ff"
+ inner_sel="#2ba5ffff"
+ item="#4c4c4cff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-5"
+ roundness="0.517903"
+ >
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors
+ outline="#cfcfcf"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#080808ff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.610632"
+ >
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
+ <wcol_radio>
+ <ThemeWidgetColors
+ outline="#f8f8f8"
+ inner="#f1f1f1ff"
+ inner_sel="#2ba5ffff"
+ item="#4c4c4cff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="0.450676"
+ >
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors
+ outline="#acacac"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#4c4c4cff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-3"
+ shadedown="0"
+ roundness="0.475886"
+ >
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors
+ outline="#9e9e9e"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#ffffffff"
+ text="#3f3f3f"
+ text_sel="#313131"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-15"
+ roundness="0.571429"
+ >
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors
+ outline="#acacac"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#4c4c4cff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.501096"
+ >
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors
+ outline="#cecece"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#4c4c4cff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.501096"
+ >
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors
+ outline="#cecece"
+ inner="#ffffffff"
+ inner_sel="#bfe4ffff"
+ item="#2ba5ffff"
+ text="#313131"
+ text_sel="#313131"
+ show_shaded="FALSE"
+ shadetop="-4"
+ shadedown="0"
+ roundness="0.522543"
+ >
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors
+ outline="#d8d8d8"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#4c4c4cff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.53471"
+ >
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors
+ outline="#d6d6d6"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#000000ff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="0.521008"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors
+ outline="#ffffff"
+ inner="#ffffffff"
+ inner_sel="#2492ffff"
+ item="#ffffffff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0"
+ >
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors
+ outline="#dddddd"
+ inner="#ffffffff"
+ inner_sel="#59b9ffff"
+ item="#ffffffff"
+ text="#313131"
+ text_sel="#313131"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.302521"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors
+ outline="#cecece"
+ inner="#ffffffff"
+ inner_sel="#2ba5ffff"
+ item="#2ba5ffff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="0.546219"
+ >
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#000000ff"
+ inner_sel="#59b9ffff"
+ item="#19191aef"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.1"
+ >
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#ffffffff"
+ inner_sel="#59b9ffff"
+ item="#ffffff8f"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="38"
+ shadedown="0"
+ roundness="0.282609"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors
+ outline="#757575"
+ inner="#9b9b9bff"
+ inner_sel="#59b9ffff"
+ item="#ffffffff"
+ text="#313131"
+ text_sel="#8b8b8b"
+ show_shaded="FALSE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors
+ outline="#bebebe"
+ inner="#ffffffff"
+ inner_sel="#59b9ffff"
+ item="#59b9ffff"
+ text="#313131"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.282609"
+ >
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors
+ outline="#2d2d2d"
+ inner="#ffffffff"
+ inner_sel="#59b9ffff"
+ item="#b3b3b3ff"
+ text="#4e4e4e"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.282609"
+ >
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors
+ inner_anim="#86e270"
+ inner_anim_sel="#97ff80"
+ inner_key="#ffbd11"
+ inner_key_sel="#ffe73a"
+ inner_driven="#cd7cf3"
+ inner_driven_sel="#d193e6"
+ inner_overridden="#5ef5f5"
+ inner_overridden_sel="#8cffff"
+ inner_changed="#ffa25d"
+ inner_changed_sel="#ffc193"
+ blend="1"
+ >
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors
+ outline="#e9e9e9"
+ inner="#f5f5f5ff"
+ inner_sel="#59b9ffff"
+ item="#2d2d2dff"
+ text="#313131"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="-19"
+ roundness="0.282609"
+ >
+ </ThemeWidgetColors>
+ </wcol_tab>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D
+ grid="#b2b2b253"
+ clipping_border_3d="#fafafaff"
+ wire="#313131"
+ wire_edit="#575757"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ text_grease_pencil="#ffa028"
+ object_selected="#ed5700"
+ object_active="#ffa028"
+ text_keyframe="#ddd700"
+ camera="#4c4c4c"
+ empty="#282926"
+ light="#722f0037"
+ speaker="#334635"
+ vertex="#000000"
+ vertex_select="#ff7f00"
+ vertex_size="3"
+ vertex_bevel="#00a5ff"
+ vertex_unreferenced="#000000"
+ edge_select="#ffa000"
+ edge_seam="#9f09db"
+ edge_sharp="#356cff"
+ edge_crease="#ff3a3a"
+ edge_bevel="#1c864c"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#7fff7f"
+ face="#00000010"
+ face_select="#ff850024"
+ face_dot="#ff8500"
+ facedot_size="3"
+ freestyle_face_mark="#7fff7f2b"
+ face_back="#ff000080"
+ face_front="#ffffff00"
+ nurb_uline="#909000"
+ nurb_vline="#803060"
+ nurb_sel_uline="#a6b12c"
+ nurb_sel_vline="#d4808e"
+ act_spline="#db2512"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ lastsel_point="#ffaf00"
+ extra_edge_len="#150806"
+ extra_edge_angle="#4d4d00"
+ extra_face_angle="#0000cc"
+ extra_face_area="#004d00"
+ editmesh_active="#ffaf006c"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_pose="#50c8ff"
+ bone_pose_active="#8cffff"
+ bone_solid="#c8c8c8"
+ bone_locked_weight="#ff000080"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#b44d4d"
+ view_overlay="#000000"
+ transform="#000000"
+ frame_current="#60c040"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1"
+ object_origin_size="6"
+ >
+ <space>
+ <ThemeSpaceGradient
+ title="#eeeeee"
+ text="#313131"
+ text_hi="#ffffff"
+ header="#ffffff00"
+ header_text="#000000"
+ header_text_hi="#000000"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#0e0e0e"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#59b9ff"
+ tab_inactive="#e4e4e4"
+ tab_back="#ddddddff"
+ tab_outline="#cecece"
+ >
+ <gradients>
+ <ThemeGradientColors
+ background_type="SINGLE_COLOR"
+ high_gradient="#ffffff"
+ gradient="#ffffff"
+ >
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff43"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor
+ grid="#b9d2ef"
+ frame_current="#0074e8"
+ time_scrub_background="#bae2ffca"
+ window_sliders="#a7a7a7"
+ channels_region="#ffffff"
+ dopesheet_channel="#0074e8"
+ dopesheet_subchannel="#72ade8"
+ channel_group="#94d49d"
+ active_channels_group="#5ea86f"
+ preview_range="#a14d0066"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="6"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#994030"
+ handle_sel_auto_clamped="#f0af90"
+ lastsel_point="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ff8500"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#e2f2ff"
+ title="#313131"
+ text="#313131"
+ text_hi="#202020"
+ header="#ffffffff"
+ header_text="#202020"
+ header_text_hi="#313131"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#141414"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff43"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#ffffff"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#050505"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser
+ selected_file="#0082ff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#252525"
+ text_hi="#000000"
+ header="#ffffffff"
+ header_text="#eeeeee"
+ header_text_hi="#000000"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#ffffffff"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor
+ grid="#cacaca"
+ view_sliders="#cfcfcf"
+ dopesheet_channel="#5a85b2"
+ nla_track="#424242"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
+ preview_range="#a14d0066"
+ strips="#ffb243"
+ strips_selected="#ff8c00"
+ transition_strips="#8cb2db"
+ transition_strips_selected="#2e75db"
+ meta_strips="#bd8ff6"
+ meta_strips_selected="#b37fdd"
+ sound_strips="#83b9b9"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
+ keyframe_border="#292929ff"
+ keyframe_border_selected="#1f1f1fff"
+ frame_current="#0074e8"
+ time_scrub_background="#bae2ffca"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#313131"
+ text="#313131"
+ text_hi="#313131"
+ header="#ffffffff"
+ header_text="#313131"
+ header_text_hi="#000000"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#313131"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff43"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#e7e7e7"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#000000"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet
+ grid="#bbbbbb"
+ frame_current="#0074e8"
+ time_scrub_background="#bae2ffca"
+ value_sliders="#3b3b3b"
+ view_sliders="#c0c0c0"
+ dopesheet_channel="#76bbff24"
+ dopesheet_subchannel="#b0f2ff24"
+ channels="#c0c0c031"
+ channels_selected="#8a8a8a31"
+ channel_group="#94d49d37"
+ active_channels_group="#5ea86f28"
+ long_key="#00000049"
+ long_key_selected="#ff8c00cc"
+ keyframe="#ffffff"
+ keyframe_selected="#ffbe33"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#94e575"
+ keyframe_jitter_selected="#61c042"
+ keyframe_movehold="#ccc1c1"
+ keyframe_movehold_selected="#ffaf23"
+ keyframe_border="#5f5f5fff"
+ keyframe_border_selected="#242424ff"
+ keyframe_scale_factor="1"
+ summary="#288fe859"
+ preview_range="#a14d0037"
+ interpolation_line="#94e575cc"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#313131"
+ text="#313131"
+ text_hi="#313131"
+ header="#ffffffff"
+ header_text="#1f1f1f"
+ header_text_hi="#000000"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#e5e5e5"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff43"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#d6d6d6"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#000000"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="3"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ face="#bbbbbb0a"
+ face_select="#ff85003c"
+ face_dot="#ff8500"
+ facedot_size="3"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#00000000"
+ face_front="#00000000"
+ editmesh_active="#ffffff80"
+ wire_edit="#dadada"
+ edge_select="#ff8500"
+ scope_back="#727272ff"
+ preview_stitch_face="#7f7f0033"
+ preview_stitch_edge="#ff00ff33"
+ preview_stitch_vert="#0000ff33"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ metadatabg="#000000"
+ metadatatext="#000000"
+ handle_free="#771c0d"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#b2574b"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#e9e9e9"
+ title="#313131"
+ text="#313131"
+ text_hi="#ffffff"
+ header="#ffffffff"
+ header_text="#eeeeee"
+ header_text_hi="#000000"
+ button="#ffffffd0"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff43"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor
+ grid="#404040"
+ window_sliders="#a0a0a0"
+ movie_strip="#8bb5e9"
+ movieclip_strip="#6a76da"
+ image_strip="#c9a4f1"
+ scene_strip="#67ca56"
+ audio_strip="#3ebebe"
+ effect_strip="#dd6ea2"
+ transition_strip="#d37c8f"
+ meta_strip="#6d9183"
+ text_strip="#dbda79"
+ frame_current="#0074e8"
+ time_scrub_background="#bae2ffca"
+ keyframe="#ff8500"
+ draw_action="#50c8ff"
+ preview_back="#b4b4b4"
+ metadatabg="#e2e2e2"
+ metadatatext="#747474"
+ preview_range="#a14d0066"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#313131"
+ text="#313131"
+ text_hi="#313131"
+ header="#ffffffff"
+ header_text="#3a3a3a"
+ header_text_hi="#000000"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#000000"
+ navigation_bar="#ffffff00"
+ execution_buts="#00000000"
+ tab_active="#59b9ff"
+ tab_inactive="#fafafa"
+ tab_back="#e0e0e0ff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff43"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#000000"
+ header="#ffffffff"
+ header_text="#383838"
+ header_text_hi="#000000"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#dadadaff"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor
+ line_numbers="#c0c0c0"
+ line_numbers_background="#f6f6fd"
+ selected_text="#b6c4ce"
+ cursor="#ff9100"
+ syntax_builtin="#ff1961"
+ syntax_symbols="#ee6d49"
+ syntax_special="#7fb800"
+ syntax_preprocessor="#ad80ff"
+ syntax_reserved="#c4753b"
+ syntax_comment="#4e4e4e"
+ syntax_string="#c9941d"
+ syntax_numbers="#0d9bc2"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#313131"
+ text="#313131"
+ text_hi="#313131"
+ header="#ffffff00"
+ header_text="#eeeeee"
+ header_text_hi="#000000"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff43"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <node_editor>
+ <ThemeNodeEditor
+ node_selected="#003bc9"
+ node_active="#0030ff"
+ wire="#999999"
+ wire_inner="#f1efff"
+ wire_select="#0099ff"
+ selected_text="#7f7070"
+ node_backdrop="#d3edffff"
+ converter_node="#66c4ff"
+ color_node="#ffe74d"
+ group_node="#8fdb58b9"
+ group_socket_node="#1a1a1a"
+ frame_node="#009eff12"
+ matte_node="#975b5b"
+ distor_node="#c5ffff"
+ noodle_curving="3"
+ input_node="#ff4e5d"
+ output_node="#0081ff"
+ filter_node="#b09bff"
+ vector_node="#9b80ff"
+ texture_node="#ff964b"
+ shader_node="#4fff8b"
+ script_node="#14c2c2"
+ pattern_node="#bbb8c0"
+ layout_node="#c6bfc9"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#edf7ff"
+ title="#ffffff"
+ text="#272727"
+ text_hi="#686868"
+ header="#ffffffff"
+ header_text="#353535"
+ header_text_hi="#000000"
+ button="#ffffff00"
+ button_title="#000000"
+ button_text="#252525"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#59b9ff"
+ tab_inactive="#f8f8f8"
+ tab_back="#ddddddff"
+ tab_outline="#e9e9e9"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#2e2e2e"
+ list_title="#000000"
+ list_text="#cccccc"
+ list_text_hi="#000000"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <outliner>
+ <ThemeOutliner
+ match="#0088ff"
+ selected_highlight="#b0deff"
+ active="#59b9ff"
+ selected_object="#e95900"
+ active_object="#ffffff"
+ edited_object="#85fcffff"
+ row_alternate="#00000007"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#ffffffff"
+ header_text="#000000"
+ header_text_hi="#000000"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#ffffff00"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo
+ info_selected="#2ba5ff"
+ info_selected_text="#ffffff"
+ info_error="#e90000ff"
+ info_error_text="#ffffff"
+ info_warning="#eb8b00ff"
+ info_warning_text="#ffffff"
+ info_info="#53bb00ff"
+ info_info_text="#ffffff"
+ info_debug="#7a7a7aff"
+ info_debug_text="#ffffff"
+ info_property="#0bdb65ff"
+ info_property_text="#ffffff"
+ info_operator="#00cea3ff"
+ info_operator_text="#ffffff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#eeeeee"
+ text="#000000"
+ text_hi="#000000"
+ header="#ffffffff"
+ header_text="#3a3a3a"
+ header_text_hi="#000000"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <preferences>
+ <ThemePreferences>
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#3a3a3a"
+ text="#363636"
+ text_hi="#4c4c4c"
+ header="#ffffffff"
+ header_text="#363636"
+ header_text_hi="#ffffff"
+ button="#424242ff"
+ button_title="#ffffff"
+ button_text="#e5e5e5"
+ button_text_hi="#ffffff"
+ navigation_bar="#ffffffff"
+ execution_buts="#ffffffff"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#232323ff"
+ tab_outline="#232323"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemePreferences>
+ </preferences>
+ <console>
+ <ThemeConsole
+ line_output="#2f69c5"
+ line_input="#3f3f3f"
+ line_info="#6d9900"
+ line_error="#cc005f"
+ cursor="#ff9100"
+ select="#00000030"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#ffffff"
+ text="#000000"
+ text_hi="#000000"
+ header="#ffffffff"
+ header_text="#3a3a3a"
+ header_text_hi="#000000"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#000000"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ path_keyframe_before="#ffc4c4"
+ path_keyframe_after="#c4c4ff"
+ frame_current="#5680c2"
+ time_scrub_background="#292929e6"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#eeeeee"
+ text="#000000"
+ text_hi="#000000"
+ header="#ffffffff"
+ header_text="#eeeeee"
+ header_text_hi="#000000"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#000000"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#ffffff"
+ title="#000000"
+ text="#000000"
+ text_hi="#000000"
+ header="#ffce67ff"
+ header_text="#3a3a3a"
+ header_text_hi="#000000"
+ button="#ffffffff"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#ffffff"
+ tab_back="#ffffffff"
+ tab_outline="#000000"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#2e2e2e"
+ title="#000000"
+ text="#838383"
+ text_hi="#000000"
+ header="#ebebebff"
+ header_text="#363636"
+ header_text_hi="#000000"
+ button="#353535ff"
+ button_title="#000000"
+ button_text="#3a3a3a"
+ button_text_hi="#000000"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#ffffff"
+ tab_inactive="#e4e4e4"
+ tab_back="#cececeff"
+ tab_outline="#cecece"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#ffffff12"
+ back="#f8f8f8ff"
+ sub_back="#00000007"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
+ <bone_color_sets>
+ <ThemeBoneColorSet
+ normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e2024"
+ select="#484c56"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle
+ points="12"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.5"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.5"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.1"
+ shadow_value="1"
+ >
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/xsi.xml b/release/scripts/presets/interface_theme/xsi.xml
new file mode 100644
index 00000000000..4ed66a2a2c6
--- /dev/null
+++ b/release/scripts/presets/interface_theme/xsi.xml
@@ -0,0 +1,1481 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface
+ menu_shadow_fac="0.536367"
+ menu_shadow_width="0"
+ icon_alpha="0.8"
+ icon_saturation="0.803436"
+ widget_emboss="#66666605"
+ editor_outline="#bebebe"
+ widget_text_cursor="#3399e6"
+ axis_x="#e70003"
+ axis_y="#00c81c"
+ axis_z="#220094"
+ gizmo_hi="#ffffff"
+ gizmo_primary="#f5f14d"
+ gizmo_secondary="#63ffff"
+ gizmo_a="#4da84d"
+ gizmo_b="#a33535"
+ icon_scene="#000000ff"
+ icon_collection="#000000ff"
+ icon_object="#003368ff"
+ icon_object_data="#313131ff"
+ icon_modifier="#383838ff"
+ icon_shading="#ac3a00ff"
+ icon_folder="#e3c16eff"
+ icon_border_intensity="0"
+ >
+ <wcol_regular>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#afadadff"
+ inner_sel="#dbd9d9ff"
+ item="#999999ff"
+ text="#080808"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="-6"
+ shadedown="2"
+ roundness="0.692096"
+ >
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors
+ outline="#0c0c0c"
+ inner="#8f8f8fff"
+ inner_sel="#f0ffe7ff"
+ item="#999999ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="TRUE"
+ shadetop="27"
+ shadedown="16"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors
+ outline="#757575"
+ inner="#b3b0b0ff"
+ inner_sel="#dddadaff"
+ item="#686868ff"
+ text="#ffffff"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="-18"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
+ <wcol_radio>
+ <ThemeWidgetColors
+ outline="#000000"
+ inner="#b3b1b0ff"
+ inner_sel="#dcd9d9ff"
+ item="#9c9c9cff"
+ text="#3c3c3c"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="-2"
+ shadedown="1"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors
+ outline="#989594"
+ inner="#414141ff"
+ inner_sel="#414141ff"
+ item="#3399ffff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-2"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors
+ outline="#383530"
+ inner="#7d957fff"
+ inner_sel="#b4d8b1ff"
+ item="#000000ff"
+ text="#4a3b36"
+ text_sel="#000000"
+ show_shaded="TRUE"
+ shadetop="-2"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors
+ outline="#888888"
+ inner="#aca6a6ff"
+ inner_sel="#ffffffff"
+ item="#aca8a7ff"
+ text="#1c1c1c"
+ text_sel="#1a1a1a"
+ show_shaded="TRUE"
+ shadetop="-3"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors
+ outline="#4b4b4b"
+ inner="#363333ff"
+ inner_sel="#363333ff"
+ item="#3399ffff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-5"
+ shadedown="5"
+ roundness="0.8"
+ >
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors
+ outline="#474747"
+ inner="#898989ff"
+ inner_sel="#3399ffff"
+ item="#c8c8c8ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="-5"
+ shadedown="5"
+ roundness="0.8"
+ >
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors
+ outline="#8b8b8b"
+ inner="#969594ff"
+ inner_sel="#7780aaff"
+ item="#bbbbbbff"
+ text="#2a2a2a"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="23"
+ shadedown="6"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors
+ outline="#514f52"
+ inner="#889399ff"
+ inner_sel="#5786acff"
+ item="#000000ff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="TRUE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors
+ outline="#474747"
+ inner="#aeaeaeff"
+ inner_sel="#aaa8a6ff"
+ item="#ccccccff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors
+ outline="#474747"
+ inner="#e3e4e2ff"
+ inner_sel="#a8a8a8ff"
+ item="#ccccccff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors
+ outline="#0a0a0a"
+ inner="#aca8a7ff"
+ inner_sel="#b1d1d8ff"
+ item="#1f8aaaff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors
+ outline="#a29b7f"
+ inner="#fff0cce6"
+ inner_sel="#2d2d2de6"
+ item="#000000ff"
+ text="#000000"
+ text_sel="#8d612c"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors
+ outline="#474747"
+ inner="#00000000"
+ inner_sel="#0e2b75ff"
+ item="#000000ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="-10"
+ shadedown="10"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors
+ outline="#82807f"
+ inner="#928c8bff"
+ inner_sel="#aaa8a6ff"
+ item="#9a9794ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="4"
+ shadedown="-5"
+ roundness="1"
+ >
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors
+ outline="#474747"
+ inner="#aaa8a6ff"
+ inner_sel="#aaa8a6ff"
+ item="#96c78eff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="3"
+ shadedown="-3"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors
+ outline="#adadad"
+ inner="#7f7f7f00"
+ inner_sel="#4286ff9a"
+ item="#4849ceff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors
+ inner_anim="#c9b200"
+ inner_anim_sel="#92af79"
+ inner_key="#9e575a"
+ inner_key_sel="#aa3323"
+ inner_driven="#c69cb1"
+ inner_driven_sel="#ecaacd"
+ inner_overridden="#19c3c3"
+ inner_overridden_sel="#118f8f"
+ inner_changed="#cc7529"
+ inner_changed_sel="#e6852d"
+ blend="0.919679"
+ >
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors
+ outline="#a6a6a6"
+ inner="#39586800"
+ inner_sel="#bebebeff"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="36"
+ shadedown="19"
+ roundness="0.4"
+ >
+ </ThemeWidgetColors>
+ </wcol_tab>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D
+ grid="#0000005f"
+ clipping_border_3d="#313131ff"
+ wire="#ff7a00"
+ wire_edit="#f7ca00"
+ gp_vertex="#4e98be"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ text_grease_pencil="#b5e61d"
+ object_selected="#e59b27"
+ object_active="#ffffff"
+ text_keyframe="#ddd700"
+ camera="#3600c3"
+ empty="#000000"
+ light="#00000028"
+ speaker="#c2e787"
+ vertex="#0001a6"
+ vertex_select="#ff2100"
+ vertex_size="3"
+ vertex_bevel="#00a5ff"
+ vertex_unreferenced="#000000"
+ edge_select="#ff001c"
+ edge_seam="#f0703b"
+ edge_sharp="#49a1ec"
+ edge_crease="#eb3bdd"
+ edge_bevel="#00a5ff"
+ edge_facesel="#272727"
+ freestyle_edge_mark="#7fff7f"
+ face="#90909099"
+ face_select="#a11f137c"
+ face_dot="#52f27e"
+ facedot_size="1"
+ freestyle_face_mark="#7fff7f33"
+ face_back="#ff0000b3"
+ face_front="#0000ffb3"
+ nurb_uline="#a5a5a5"
+ nurb_vline="#d77ab1"
+ nurb_sel_uline="#ffffff"
+ nurb_sel_vline="#f090a0"
+ act_spline="#95daa0"
+ handle_free="#c6c6c6"
+ handle_auto="#30b6e5"
+ handle_vect="#adafaf"
+ handle_sel_vect="#ffffff"
+ handle_align="#e277b1"
+ handle_sel_free="#f7fffc"
+ handle_sel_auto="#ffffff"
+ handle_sel_align="#ffffff"
+ lastsel_point="#ffffff"
+ extra_edge_len="#200000"
+ extra_edge_angle="#000000"
+ extra_face_angle="#cccccc"
+ extra_face_area="#cccccc"
+ editmesh_active="#ff2e00ff"
+ normal="#9cfcc8"
+ vertex_normal="#68a1db"
+ split_normal="#dd23dd"
+ bone_pose="#00a199"
+ bone_pose_active="#8cffff"
+ bone_solid="#006200"
+ bone_locked_weight="#ff000080"
+ bundle_solid="#c9c9c9"
+ camera_path="#000000"
+ skin_root="#000000"
+ view_overlay="#afafaf"
+ transform="#ffff00"
+ frame_current="#53c03b"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1"
+ object_origin_size="6"
+ >
+ <space>
+ <ThemeSpaceGradient
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#78787800"
+ header_text="#121212"
+ header_text_hi="#ffffff"
+ button="#aca8a700"
+ button_title="#000000"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#8b8484"
+ tab_back="#51725aff"
+ tab_outline="#0e0c0e"
+ >
+ <gradients>
+ <ThemeGradientColors
+ background_type="SINGLE_COLOR"
+ high_gradient="#6c6c6c"
+ gradient="#a3a3a3"
+ >
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors
+ header="#8b6985ff"
+ back="#f5ecec99"
+ sub_back="#cde2f59a"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor
+ grid="#918d8c"
+ frame_current="#ff1600"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ window_sliders="#4d4d4d"
+ channels_region="#4d4d4d"
+ dopesheet_channel="#aaa8a6"
+ dopesheet_subchannel="#aaa8a6"
+ channel_group="#8a9dac"
+ active_channels_group="#95adc1"
+ preview_range="#a14d0066"
+ vertex="#575757"
+ vertex_select="#ffffff"
+ vertex_size="6"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ handle_free="#252525"
+ handle_auto="#696969"
+ handle_vect="#191919"
+ handle_sel_vect="#ffffff"
+ handle_align="#1d1d1d"
+ handle_sel_free="#ececec"
+ handle_sel_auto="#d4d4d4"
+ handle_sel_align="#f3f3f3"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ lastsel_point="#000000"
+ handle_vertex="#525252"
+ handle_vertex_select="#f1f1f1"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#000000"
+ text="#a6a6a6"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca9a8ff"
+ button_title="#0e0e0e"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#aaa8a6"
+ list_title="#676767"
+ list_text="#222222"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser
+ selected_file="#4e88bd"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#a5a3a3"
+ title="#1300aa"
+ text="#222222"
+ text_hi="#ebebeb"
+ header="#6c7285ff"
+ header_text="#a7a7a7"
+ header_text_hi="#b8b8b8"
+ button="#a7a2a4ff"
+ button_title="#1b1b1b"
+ button_text="#144b00"
+ button_text_hi="#898c92"
+ navigation_bar="#00000023"
+ execution_buts="#444444ff"
+ tab_active="#928a8a"
+ tab_inactive="#a5a5a5"
+ tab_back="#86898dff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#0000000c"
+ back="#9090907e"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor
+ grid="#918d8c"
+ view_sliders="#b5b5b5"
+ dopesheet_channel="#b0b1b1"
+ nla_track="#7cac80"
+ active_action="#ffefb400"
+ active_action_unset="#8d898f45"
+ preview_range="#b1520066"
+ strips="#5a8a59"
+ strips_selected="#61ae7d"
+ transition_strips="#b67aff"
+ transition_strips_selected="#bd2cff"
+ meta_strips="#00880e"
+ meta_strips_selected="#78b463"
+ sound_strips="#a59c61"
+ sound_strips_selected="#b2aa8f"
+ tweak="#31c5ec"
+ tweak_duplicate="#6258ba"
+ keyframe_border="#e7eaa7ff"
+ keyframe_border_selected="#ffffffff"
+ frame_current="#a71100"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#000000"
+ text="#a6a6a6"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#a3a3a3"
+ header_text_hi="#cccccc"
+ button="#aca8a7ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#ded8d7"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000000"
+ back="#72727200"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#aca8a7"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#000000"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet
+ grid="#7f7f7f"
+ frame_current="#902119"
+ time_scrub_background="#7f837fe6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ value_sliders="#141414"
+ view_sliders="#4c4c4c"
+ dopesheet_channel="#9baeb924"
+ dopesheet_subchannel="#aaa8a624"
+ channels="#9baeb9ff"
+ channels_selected="#a0e7d944"
+ channel_group="#8a9dac37"
+ active_channels_group="#95adc155"
+ long_key="#00000080"
+ long_key_selected="#fffd00cc"
+ keyframe="#bfd39d"
+ keyframe_selected="#800000"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#ace493"
+ keyframe_jitter_selected="#61c042"
+ keyframe_movehold="#5c5656"
+ keyframe_movehold_selected="#ffaf23"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ keyframe_scale_factor="1"
+ summary="#afa99ab8"
+ preview_range="#a14d0066"
+ interpolation_line="#94e575cc"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#ffffff"
+ text="#252525"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#000000"
+ button_text="#111111"
+ button_text_hi="#a3a3a3"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#aaa8a6"
+ list_title="#cccccc"
+ list_text="#131313"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor
+ vertex="#000afa"
+ vertex_select="#a00200"
+ vertex_size="3"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ face="#00000032"
+ face_select="#ff00004b"
+ face_dot="#ffffff"
+ facedot_size="2"
+ freestyle_face_mark="#00000000"
+ face_back="#00000000"
+ face_front="#00000000"
+ editmesh_active="#00ff7580"
+ wire_edit="#d3d600"
+ edge_select="#ffe800"
+ scope_back="#aca8a7ff"
+ preview_stitch_face="#3639ae26"
+ preview_stitch_edge="#ff8500b2"
+ preview_stitch_vert="#ff85007f"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#e1d2c323"
+ uv_shadow="#707070ff"
+ uv_others="#ffe8a4ff"
+ frame_current="#60c040"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#000000"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#383838"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor
+ grid="#525252"
+ window_sliders="#777777"
+ movie_strip="#87a4c3"
+ movieclip_strip="#95add0"
+ image_strip="#c99ac0"
+ scene_strip="#91b1a0"
+ audio_strip="#a5a490"
+ effect_strip="#be8c76"
+ transition_strip="#d9777a"
+ meta_strip="#91918d"
+ text_strip="#a29700"
+ frame_current="#0183b8"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ keyframe="#ffeb89"
+ draw_action="#50c8ff"
+ preview_back="#000000"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ preview_range="#a14d0066"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#000000"
+ text="#a6a6a6"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#a3a3a3"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#111111"
+ button_text="#111111"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric
+ back="#b4b2b0"
+ title="#222222"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#b4b2b0ff"
+ header_text="#272727"
+ header_text_hi="#000000"
+ button="#79767aff"
+ button_title="#4c4c4c"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ navigation_bar="#9f9f9fff"
+ execution_buts="#00000000"
+ tab_active="#acacac"
+ tab_inactive="#888888"
+ tab_back="#929292ff"
+ tab_outline="#918f8e"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#9f9f9fff"
+ back="#cccccc00"
+ sub_back="#00000000"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor
+ line_numbers="#d0d0d0"
+ line_numbers_background="#a3a3a3"
+ selected_text="#f1e593"
+ cursor="#54da70"
+ syntax_builtin="#3162b2"
+ syntax_symbols="#4c4c4c"
+ syntax_special="#ca0c97"
+ syntax_preprocessor="#32008c"
+ syntax_reserved="#8c3c00"
+ syntax_comment="#535353"
+ syntax_string="#c31736"
+ syntax_numbers="#b62440"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#000000"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a700"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#222222"
+ button_text="#333333"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <node_editor>
+ <ThemeNodeEditor
+ node_selected="#ffffff"
+ node_active="#63ff00"
+ wire="#222222"
+ wire_inner="#727371"
+ wire_select="#ffffff"
+ selected_text="#ffffff"
+ node_backdrop="#d4d4d4ff"
+ converter_node="#56b68b"
+ color_node="#94b6a7"
+ group_node="#aca8a7ff"
+ group_socket_node="#79bef2"
+ frame_node="#d3cecdff"
+ matte_node="#79f2a0"
+ distor_node="#eef279"
+ noodle_curving="0"
+ grid_levels="2"
+ input_node="#ee8513"
+ output_node="#ff8b00"
+ filter_node="#ff0000"
+ vector_node="#94b6a7"
+ texture_node="#ee7402"
+ shader_node="#94b6a7"
+ script_node="#f2b077"
+ pattern_node="#a67c49"
+ layout_node="#000000"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#a3a3a3"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#333333"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#222222"
+ button_text="#222222"
+ button_text_hi="#c5c5c5"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#4d4d4d"
+ list_title="#383838"
+ list_text="#676767"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <outliner>
+ <ThemeOutliner
+ match="#aff193"
+ selected_highlight="#e9e9e9"
+ active="#ffffff"
+ selected_object="#000000"
+ active_object="#000000"
+ edited_object="#00806266"
+ row_alternate="#ffffff00"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#ffffff"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#0f0f0f"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo
+ info_selected="#6080ff"
+ info_selected_text="#ffffff"
+ info_error="#dc0000ff"
+ info_error_text="#000000"
+ info_warning="#dc8060ff"
+ info_warning_text="#000000"
+ info_info="#1d4383ff"
+ info_info_text="#000000"
+ info_debug="#c4c4c4ff"
+ info_debug_text="#000000"
+ info_property="#3ace87ff"
+ info_property_text="#ffffff"
+ info_operator="#3ace87ff"
+ info_operator_text="#ffffff"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <preferences>
+ <ThemePreferences>
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#222222"
+ text="#222222"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#4b4b4bff"
+ execution_buts="#4b4b4bff"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#96969eff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemePreferences>
+ </preferences>
+ <console>
+ <ThemeConsole
+ line_output="#6080ff"
+ line_input="#ffffff"
+ line_info="#00aa00"
+ line_error="#dc3a77"
+ cursor="#9cfcc8"
+ select="#ffffff30"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#0c0c0c"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#4d4d4dff"
+ button_title="#131313"
+ button_text="#131313"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor
+ marker_outline="#000000"
+ marker="#71cd7f"
+ active_marker="#ffffff"
+ selected_marker="#ff2f7a"
+ disabled_marker="#b54636"
+ locked_marker="#7f7f7f"
+ path_before="#22d8d1"
+ path_after="#5a7575"
+ path_keyframe_before="#ffc4c4"
+ path_keyframe_after="#c4c4ff"
+ frame_current="#f06868"
+ time_scrub_background="#292929e6"
+ time_marker_line="#00000060"
+ time_marker_line_selected="#ffffff60"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ >
+ <space>
+ <ThemeSpaceGeneric
+ back="#aca8a7"
+ title="#1a1a1a"
+ text="#a6a6a6"
+ text_hi="#ffffff"
+ header="#aca8a7ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#aca8a7ff"
+ button_title="#222222"
+ button_text="#222222"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#aca8a7"
+ tab_inactive="#bfbfbf"
+ tab_back="#bfbfbfff"
+ tab_outline="#d1cccb"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#00000004"
+ back="#72727280"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric
+ list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff"
+ >
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#bfbfbe"
+ title="#ffffff"
+ text="#6e6e6e"
+ text_hi="#ffffff"
+ header="#aaa7a4ff"
+ header_text="#ffffff"
+ header_text_hi="#fafafa"
+ button="#213142ff"
+ button_title="#ffffff"
+ button_text="#c5c5c5"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#c2bfbf"
+ tab_inactive="#aba8a6"
+ tab_back="#888888ff"
+ tab_outline="#313131"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#3d3d3dcc"
+ back="#383838b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric
+ back="#2e2e2e"
+ title="#ffffff"
+ text="#363636"
+ text_hi="#ffffff"
+ header="#aba8a7ff"
+ header_text="#1e1e1e"
+ header_text_hi="#ffffff"
+ button="#353535ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ navigation_bar="#00000000"
+ execution_buts="#00000000"
+ tab_active="#4b4b4b"
+ tab_inactive="#2b2b2b"
+ tab_back="#232323ff"
+ tab_outline="#232323"
+ >
+ <panelcolors>
+ <ThemePanelColors
+ header="#424242cc"
+ back="#333333b3"
+ sub_back="#0000003e"
+ >
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
+ <bone_color_sets>
+ <ThemeBoneColorSet
+ normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet
+ normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE"
+ >
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle
+ points="12"
+ font_kerning_style="FITTED"
+ shadow="2"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0"
+ shadow_value="1"
+ >
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="UNFITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0"
+ shadow_value="1"
+ >
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle
+ points="11"
+ font_kerning_style="UNFITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.0696518"
+ shadow_value="0"
+ >
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
index ec8f46724b5..6baa4c0a3ac 100644
--- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
+++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
@@ -2398,9 +2398,6 @@ def km_grease_pencil_stroke_paint_draw_brush(params):
# Draw - straight lines
("gpencil.draw", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
{"properties": [("mode", 'DRAW_STRAIGHT'), ("wait_for_input", False)]}),
- # Draw - poly lines
- ("gpencil.draw", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
- {"properties": [("mode", 'DRAW_POLY'), ("wait_for_input", False)]}),
# Erase
("gpencil.draw", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
{"properties": [("mode", 'ERASER'), ("wait_for_input", False)]}),
@@ -2720,11 +2717,11 @@ def km_grease_pencil_stroke_weight_mode(params):
items.extend([
# Brush strength
- ("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
+ ("wm.radial_control", {"type": 'U', "value": 'PRESS'},
{"properties": [("data_path_primary", 'tool_settings.gpencil_weight_paint.brush.strength')]}),
# Brush size
("wm.radial_control", {"type": 'S', "value": 'PRESS'},
- {"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.brush.size')]}),
+ {"properties": [("data_path_primary", 'tool_settings.gpencil_weight_paint.brush.size')]}),
# Context menu
*_template_items_context_panel("VIEW3D_PT_gpencil_weight_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
])
@@ -2760,10 +2757,10 @@ def km_grease_pencil_stroke_vertex_mode(params):
# Selection
*_grease_pencil_selection(params),
# Brush strength
- ("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
+ ("wm.radial_control", {"type": 'U', "value": 'PRESS'},
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
# Brush size
- ("wm.radial_control", {"type": 'F', "value": 'PRESS'},
+ ("wm.radial_control", {"type": 'S', "value": 'PRESS'},
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
# Display
*_grease_pencil_display(),
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 99508bf8fab..bcf1c285d2b 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -1891,16 +1891,34 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
self.gpencil_masking(layout, ob, md, True, True)
def GP_TINT(self, layout, ob, md):
- split = layout.split()
+ layout.row().prop(md, "tint_type", expand=True)
- col = split.column()
- col.prop(md, "color")
- col.prop(md, "factor")
+ if md.tint_type == 'UNIFORM':
+ col = layout.column()
+ col.prop(md, "color")
- row = layout.row()
- row.prop(md, "modify_color")
+ col.separator()
+ col.prop(md, "factor")
- self.gpencil_masking(layout, ob, md, False, True)
+ if md.tint_type == 'GRADIENT':
+ col = layout.column()
+ col.label(text="Colors:")
+ col.template_color_ramp(md, "colors")
+
+ col.separator()
+
+ col.label(text="Object:")
+ col.prop(md, "object", text="")
+
+ col.separator()
+ row = col.row(align=True)
+ row.prop(md, "radius")
+ row.prop(md, "factor")
+
+ col.separator()
+ col.prop(md, "vertex_mode")
+
+ self.gpencil_masking(layout, ob, md, True, True)
def GP_TIME(self, layout, ob, md):
gpd = ob.data
@@ -2165,25 +2183,6 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
self.gpencil_masking(layout, ob, md, False)
- def GP_VERTEXCOLOR(self, layout, ob, md):
- col = layout.column()
- col.label(text="Object:")
- col.prop(md, "object", text="")
-
- col.separator()
- row = col.row(align=True)
- row.prop(md, "radius")
- row.prop(md, "factor", text="Strength", slider=True)
-
- col.separator()
- col.label(text="Colors:")
- col.template_color_ramp(md, "colors")
-
- col.separator()
- col.prop(md, "vertex_mode")
-
- self.gpencil_masking(layout, ob, md, True, True)
-
classes = (
DATA_PT_modifiers,
diff --git a/release/scripts/startup/bl_ui/properties_data_shaderfx.py b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
index 48a851e8bef..1d4bf37b282 100644
--- a/release/scripts/startup/bl_ui/properties_data_shaderfx.py
+++ b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
@@ -56,7 +56,7 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
def FX_BLUR(self, layout, fx):
- layout.prop(fx, "use_dof_mode", text="Use as Depth Of Field")
+ layout.prop(fx, "use_dof_mode", text="Use Depth of Field")
layout.separator()
col = layout.column()
@@ -98,7 +98,7 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
layout.prop(fx, "rim_color")
layout.prop(fx, "mask_color")
- layout.prop(fx, "mode")
+ layout.prop(fx, "mode", text="Blend")
layout.prop(fx, "blur")
layout.prop(fx, "samples")
@@ -114,7 +114,7 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
layout.prop(fx, "samples")
layout.separator()
- layout.prop(fx, "use_object", text="Use Object As Pivot")
+ layout.prop(fx, "use_object", text="Use Object as Pivot")
if fx.use_object:
row = layout.row()
row.prop(fx, "object", text="Object")
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index fced848641e..95997b48680 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -632,8 +632,8 @@ class GreasePencilMaterialsPanel:
if ob.data.use_stroke_edit_mode:
row = layout.row(align=True)
row.operator("gpencil.stroke_change_color", text="Assign")
- row.operator("gpencil.color_select", text="Select").deselect = False
- row.operator("gpencil.color_select", text="Deselect").deselect = True
+ row.operator("gpencil.select_material", text="Select").deselect = False
+ row.operator("gpencil.select_material", text="Deselect").deselect = True
# stroke color
ma = None
if is_view3d and brush is not None:
@@ -692,10 +692,6 @@ class GreasePencilVertexcolorPanel:
row = layout.row(align=True)
row.prop(gp_settings, "vertex_color_factor", slider=True, text="Mix Factor")
- if tool == 'TINT' or is_vertex is True:
- row = layout.row(align=True)
- row.prop(gp_settings, "vertex_mode", text="Mode")
-
class GPENCIL_UL_layer(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index b50791050c4..34afcc09407 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -1065,13 +1065,16 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
row = layout.row(align=True)
row.prop(gp_settings, "fill_simplify_level", text="Simplify")
- else: # brush.gpencil_tool == 'DRAW':
+ else: # brush.gpencil_tool == 'DRAW/TINT':
row = layout.row(align=True)
row.prop(brush, "size", text="Radius")
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
row = layout.row(align=True)
row.prop(gp_settings, "pen_strength", slider=True)
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+ if brush.gpencil_tool == 'TINT':
+ row = layout.row(align=True)
+ row.prop(gp_settings, "vertex_mode", text="Mode")
# FIXME: tools must use their own UI drawing!
if tool.idname in {
@@ -1159,6 +1162,11 @@ def brush_basic_gpencil_vertex_settings(layout, _context, brush, *, compact=Fals
row.prop(gp_settings, "pen_strength", slider=True)
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+ if brush.gpencil_vertex_tool in {'DRAW', 'REPLACE'}:
+ row = layout.row(align=True)
+ row.prop(gp_settings, "vertex_mode", text="Mode")
+
+
classes = (
VIEW3D_MT_tools_projectpaint_clone,
)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 969f9b4bd1a..f8b291c0c5f 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1902,6 +1902,9 @@ class VIEW3D_MT_select_gpencil(Menu):
layout.operator("gpencil.select_alternate")
layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
+ if _context.mode == 'VERTEX_GPENCIL':
+ layout.operator("gpencil.select_vertex_color", text="Vertex Color")
+
layout.separator()
layout.operator("gpencil.select_first")
@@ -6948,8 +6951,9 @@ class VIEW3D_PT_gpencil_draw_context_menu(Panel):
gp_settings = brush.gpencil_settings
layout = self.layout
+ is_vertex = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT'
- if brush.gpencil_tool not in {'ERASE', 'CUTTER', 'EYEDROPPER'} and settings.color_mode == 'VERTEXCOLOR':
+ if brush.gpencil_tool not in {'ERASE', 'CUTTER', 'EYEDROPPER'} and is_vertex:
split = layout.split(factor=0.1)
split.prop(brush, "color", text="")
split.template_color_picker(brush, "color", value_slider=True)
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index eb7078213da..2a4394ee096 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -27,7 +27,7 @@
* \note Use #STRINGIFY() rather than defining with quotes.
*/
#define BLENDER_VERSION 283
-#define BLENDER_SUBVERSION 8
+#define BLENDER_SUBVERSION 9
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index aebe04f3a7a..f93003dc423 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -117,7 +117,7 @@ void BKE_camera_view_frame(const struct Scene *scene,
float r_vec[4][3]);
bool BKE_camera_view_frame_fit_to_scene(struct Depsgraph *depsgraph,
- struct Scene *scene,
+ const struct Scene *scene,
struct Object *camera_ob,
float r_co[3],
float *r_scale);
@@ -130,33 +130,34 @@ bool BKE_camera_view_frame_fit_to_coords(const struct Depsgraph *depsgraph,
/* Camera multi-view API */
-struct Object *BKE_camera_multiview_render(struct Scene *scene,
+struct Object *BKE_camera_multiview_render(const struct Scene *scene,
struct Object *camera,
const char *viewname);
-void BKE_camera_multiview_view_matrix(struct RenderData *rd,
+void BKE_camera_multiview_view_matrix(const struct RenderData *rd,
const struct Object *camera,
const bool is_left,
float r_viewmat[4][4]);
-void BKE_camera_multiview_model_matrix(struct RenderData *rd,
+void BKE_camera_multiview_model_matrix(const struct RenderData *rd,
const struct Object *camera,
const char *viewname,
float r_modelmat[4][4]);
-void BKE_camera_multiview_model_matrix_scaled(struct RenderData *rd,
+void BKE_camera_multiview_model_matrix_scaled(const struct RenderData *rd,
const struct Object *camera,
const char *viewname,
float r_modelmat[4][4]);
-void BKE_camera_multiview_window_matrix(struct RenderData *rd,
+void BKE_camera_multiview_window_matrix(const struct RenderData *rd,
const struct Object *camera,
const char *viewname,
float r_winmat[4][4]);
-float BKE_camera_multiview_shift_x(struct RenderData *rd,
+float BKE_camera_multiview_shift_x(const struct RenderData *rd,
const struct Object *camera,
const char *viewname);
-void BKE_camera_multiview_params(struct RenderData *rd,
+void BKE_camera_multiview_params(const struct RenderData *rd,
struct CameraParams *params,
const struct Object *camera,
const char *viewname);
-bool BKE_camera_multiview_spherical_stereo(struct RenderData *rd, const struct Object *camera);
+bool BKE_camera_multiview_spherical_stereo(const struct RenderData *rd,
+ const struct Object *camera);
/* Camera background image API */
struct CameraBGImage *BKE_camera_background_image_new(struct Camera *cam);
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index d5fb55af06c..96837f380d4 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -33,10 +33,10 @@ extern "C" {
struct ClothModifierData;
struct CollisionModifierData;
struct Depsgraph;
+struct GHash;
struct Mesh;
struct Object;
struct Scene;
-struct GHash;
#define DO_INLINE MALWAYS_INLINE
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 3284896795b..5d23029df9e 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -34,8 +34,10 @@ struct CurveMapping;
struct Depsgraph;
struct GHash;
struct ListBase;
+struct MDeformVert;
struct Main;
struct Material;
+struct MaterialGPencilStyle;
struct Object;
struct Scene;
struct SpaceImage;
@@ -47,8 +49,6 @@ struct bGPDlayer_Mask;
struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
-struct MaterialGPencilStyle;
-struct MDeformVert;
#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
#define GPENCIL_SIMPLIFY_ONPLAY(playing) \
@@ -193,6 +193,7 @@ void BKE_gpencil_layer_mask_remove_ref(struct bGPdata *gpd, const char *name);
struct bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(struct bGPDlayer *gpl, const char *name);
void BKE_gpencil_layer_mask_sort(struct bGPdata *gpd, struct bGPDlayer *gpl);
void BKE_gpencil_layer_mask_sort_all(struct bGPdata *gpd);
+void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames);
/* Brush */
struct Material *BKE_gpencil_brush_material_get(struct Brush *brush);
diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h
index 9562ace3c51..e6e82900f6d 100644
--- a/source/blender/blenkernel/BKE_idtype.h
+++ b/source/blender/blenkernel/BKE_idtype.h
@@ -70,7 +70,7 @@ typedef struct IDTypeInfo {
* Bitflag matching id_code, used for filtering (e.g. in file browser), see DNA_ID.h's
* FILTER_ID_XX enums.
*/
- int id_filter;
+ int64_t id_filter;
/**
* Define the position of this data-block type in the virtual list of all data in a Main that is
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 524bd3318f6..4ce740a1f5a 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -68,7 +68,7 @@ void BKE_render_result_stamp_info(struct Scene *scene,
* Fills in the static stamp data (i.e. everything except things that can change per frame).
* The caller is responsible for freeing the allocated memory.
*/
-struct StampData *BKE_stamp_info_from_scene_static(struct Scene *scene);
+struct StampData *BKE_stamp_info_from_scene_static(const struct Scene *scene);
bool BKE_stamp_is_known_field(const char *field_name);
void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf);
void BKE_stamp_info_from_imbuf(struct RenderResult *rr, struct ImBuf *ibuf);
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index c663ae76564..4ee255d4e61 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -98,16 +98,15 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd,
struct Scene *scene,
struct Object *object,
int direction);
-void multiresModifier_base_apply(struct MultiresModifierData *mmd,
- struct Scene *scene,
- struct Object *ob);
-void multiresModifier_subdivide(struct MultiresModifierData *mmd,
- struct Scene *scene,
- struct Object *ob,
- int updateblock,
- int simple);
-void multiresModifier_sync_levels_ex(struct Scene *scene,
- struct Object *ob_dst,
+void multiresModifier_base_apply(struct Depsgraph *depsgraph,
+ struct Object *object,
+ struct MultiresModifierData *mmd);
+void multiresModifier_subdivide_legacy(struct MultiresModifierData *mmd,
+ struct Scene *scene,
+ struct Object *ob,
+ int updateblock,
+ int simple);
+void multiresModifier_sync_levels_ex(struct Object *ob_dst,
struct MultiresModifierData *mmd_src,
struct MultiresModifierData *mmd_dst);
@@ -131,6 +130,10 @@ int multires_mdisp_corners(struct MDisps *s);
/* update multires data after topology changing */
void multires_topology_changed(struct Mesh *me);
+void multires_ensure_external_read(struct Mesh *mesh, int top_level);
+void multiresModifier_ensure_external_read(struct Mesh *mesh,
+ const struct MultiresModifierData *mmd);
+
/**** interpolation stuff ****/
void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v);
int mdisp_rot_face_to_crn(struct MVert *mvert,
@@ -145,18 +148,32 @@ int mdisp_rot_face_to_crn(struct MVert *mvert,
/* Reshaping, define in multires_reshape.c */
+bool multiresModifier_reshapeFromVertcos(struct Depsgraph *depsgraph,
+ struct Object *object,
+ struct MultiresModifierData *mmd,
+ const float (*vert_coords)[3],
+ const int num_vert_coords);
bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph,
struct MultiresModifierData *mmd,
struct Object *dst,
struct Object *src);
bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph,
- struct MultiresModifierData *mmd,
struct Object *ob,
- struct ModifierData *md);
+ struct MultiresModifierData *mmd,
+ struct ModifierData *deform_md);
bool multiresModifier_reshapeFromCCG(const int tot_level,
struct Mesh *coarse_mesh,
struct SubdivCCG *subdiv_ccg);
+/* Subdivide multires displacement once. */
+void multiresModifier_subdivide(struct Object *object, struct MultiresModifierData *mmd);
+
+/* Subdivide displacement to the given level.
+ * If level is lower than the current top level nothing happens. */
+void multiresModifier_subdivide_to_level(struct Object *object,
+ struct MultiresModifierData *mmd,
+ const int top_level);
+
/* Subdivision integration, defined in multires_subdiv.c */
struct SubdivSettings;
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index a8ebd32ad4d..886591d7728 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -76,9 +76,7 @@ bool BKE_object_shaderfx_use_time(struct Object *ob, struct ShaderFxData *md);
bool BKE_object_support_modifier_type_check(const struct Object *ob, int modifier_type);
-void BKE_object_link_modifiers(struct Scene *scene,
- struct Object *ob_dst,
- const struct Object *ob_src);
+void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_free_modifiers(struct Object *ob, const int flag);
void BKE_object_free_shaderfx(struct Object *ob, const int flag);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 9fd732027d1..881f3356a86 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -56,12 +56,12 @@ struct SubdivCCG;
struct SubdivCCG;
struct Tex;
struct ToolSettings;
-struct tPaletteColorHSV;
struct UnifiedPaintSettings;
struct View3D;
struct ViewLayer;
struct bContext;
struct bToolRef;
+struct tPaletteColorHSV;
enum eOverlayFlags;
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 8018178fcee..f78c7b66bb4 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -78,7 +78,7 @@ void BKE_scene_remove_rigidbody_object(struct Main *bmain,
const bool free_us);
bool BKE_scene_object_find(struct Scene *scene, struct Object *ob);
-struct Object *BKE_scene_object_find_by_name(struct Scene *scene, const char *name);
+struct Object *BKE_scene_object_find_by_name(const struct Scene *scene, const char *name);
/* Scene base iteration function.
* Define struct here, so no need to bother with alloc/free it.
@@ -118,8 +118,8 @@ struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAM
#endif
bool BKE_scene_camera_switch_update(struct Scene *scene);
-char *BKE_scene_find_marker_name(struct Scene *scene, int frame);
-char *BKE_scene_find_last_marker_name(struct Scene *scene, int frame);
+const char *BKE_scene_find_marker_name(const struct Scene *scene, int frame);
+const char *BKE_scene_find_last_marker_name(const struct Scene *scene, int frame);
int BKE_scene_frame_snap_by_seconds(struct Scene *scene, double interval_in_seconds, int cfra);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 2a45d89bad4..31951cc101a 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -393,7 +393,7 @@ void BKE_sequence_single_fix(struct Sequence *seq);
bool BKE_sequence_test_overlap(struct ListBase *seqbasep, struct Sequence *test);
void BKE_sequence_translate(struct Scene *scene, struct Sequence *seq, int delta);
void BKE_sequence_sound_init(struct Scene *scene, struct Sequence *seq);
-struct Sequence *BKE_sequencer_foreground_frame_get(struct Scene *scene, int frame);
+const struct Sequence *BKE_sequencer_foreground_frame_get(const struct Scene *scene, int frame);
struct ListBase *BKE_sequence_seqbase(struct ListBase *seqbase, struct Sequence *seq);
struct Sequence *BKE_sequence_metastrip(ListBase *seqbase /* = ed->seqbase */,
struct Sequence *meta /* = NULL */,
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index e6d931276bf..1298f25fcc4 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -105,7 +105,10 @@ typedef struct SoundInfo {
bool BKE_sound_info_get(struct Main *main, struct bSound *sound, SoundInfo *sound_info);
#if defined(WITH_AUDASPACE)
-AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume);
+AUD_Device *BKE_sound_mixdown(const struct Scene *scene,
+ AUD_DeviceSpecs specs,
+ int start,
+ float volume);
#endif
void BKE_sound_reset_scene_runtime(struct Scene *scene);
diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h
index 7fc740a4a9b..79605e99306 100644
--- a/source/blender/blenkernel/BKE_writeavi.h
+++ b/source/blender/blenkernel/BKE_writeavi.h
@@ -36,7 +36,7 @@ struct Scene;
typedef struct bMovieHandle {
int (*start_movie)(void *context_v,
- struct Scene *scene,
+ const struct Scene *scene,
struct RenderData *rd,
int rectx,
int recty,
@@ -55,14 +55,20 @@ typedef struct bMovieHandle {
void (*end_movie)(void *context_v);
/* Optional function. */
- void (*get_movie_path)(char *string, struct RenderData *rd, bool preview, const char *suffix);
+ void (*get_movie_path)(char *string,
+ const struct RenderData *rd,
+ bool preview,
+ const char *suffix);
void *(*context_create)(void);
void (*context_free)(void *context_v);
} bMovieHandle;
bMovieHandle *BKE_movie_handle_get(const char imtype);
-void BKE_movie_filepath_get(char *string, struct RenderData *rd, bool preview, const char *suffix);
+void BKE_movie_filepath_get(char *string,
+ const struct RenderData *rd,
+ bool preview,
+ const char *suffix);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h
index 9da28c849d9..467e6ab7242 100644
--- a/source/blender/blenkernel/BKE_writeffmpeg.h
+++ b/source/blender/blenkernel/BKE_writeffmpeg.h
@@ -62,7 +62,7 @@ struct ReportList;
struct Scene;
int BKE_ffmpeg_start(void *context_v,
- struct Scene *scene,
+ const struct Scene *scene,
struct RenderData *rd,
int rectx,
int recty,
@@ -80,14 +80,14 @@ int BKE_ffmpeg_append(void *context_v,
const char *suffix,
struct ReportList *reports);
void BKE_ffmpeg_filepath_get(char *string,
- struct RenderData *rd,
+ const struct RenderData *rd,
bool preview,
const char *suffix);
void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset);
void BKE_ffmpeg_image_type_verify(struct RenderData *rd, struct ImageFormatData *imf);
void BKE_ffmpeg_codec_settings_verify(struct RenderData *rd);
-bool BKE_ffmpeg_alpha_channel_is_supported(struct RenderData *rd);
+bool BKE_ffmpeg_alpha_channel_is_supported(const struct RenderData *rd);
int BKE_ffmpeg_property_add_string(struct RenderData *rd, const char *type, const char *str);
void BKE_ffmpeg_property_del(struct RenderData *rd, void *type, void *prop_);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 135168a6de4..047901b4c81 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -168,7 +168,12 @@ set(SRC
intern/modifier.c
intern/movieclip.c
intern/multires.c
- intern/multires_reshape_legacy.c
+ intern/multires_reshape.c
+ intern/multires_reshape_apply_base.c
+ intern/multires_reshape_ccg.c
+ intern/multires_reshape_smooth.c
+ intern/multires_reshape_util.c
+ intern/multires_reshape_vertcos.c
intern/multires_subdiv.c
intern/nla.c
intern/node.c
@@ -378,6 +383,7 @@ set(SRC
intern/data_transfer_intern.h
intern/lib_intern.h
intern/multires_inline.h
+ intern/multires_reshape.h
intern/pbvh_intern.h
intern/subdiv_converter.h
intern/subdiv_inline.h
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index d1a6ebb222c..1a2d8290609 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -666,7 +666,7 @@ static bool camera_frame_fit_calc_from_data(CameraParams *params,
/* don't move the camera, just yield the fit location */
/* r_scale only valid/useful for ortho cameras */
bool BKE_camera_view_frame_fit_to_scene(
- Depsgraph *depsgraph, Scene *scene, Object *camera_ob, float r_co[3], float *r_scale)
+ Depsgraph *depsgraph, const Scene *scene, Object *camera_ob, float r_co[3], float *r_scale)
{
CameraParams params;
CameraViewFrameData data_cb;
@@ -813,7 +813,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
}
/* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */
-void BKE_camera_multiview_view_matrix(RenderData *rd,
+void BKE_camera_multiview_view_matrix(const RenderData *rd,
const Object *camera,
const bool is_left,
float r_viewmat[4][4])
@@ -832,7 +832,7 @@ static bool camera_is_left(const char *viewname)
return true;
}
-void BKE_camera_multiview_model_matrix(RenderData *rd,
+void BKE_camera_multiview_model_matrix(const RenderData *rd,
const Object *camera,
const char *viewname,
float r_modelmat[4][4])
@@ -841,7 +841,7 @@ void BKE_camera_multiview_model_matrix(RenderData *rd,
normalize_m4(r_modelmat);
}
-void BKE_camera_multiview_model_matrix_scaled(RenderData *rd,
+void BKE_camera_multiview_model_matrix_scaled(const RenderData *rd,
const Object *camera,
const char *viewname,
float r_modelmat[4][4])
@@ -860,7 +860,7 @@ void BKE_camera_multiview_model_matrix_scaled(RenderData *rd,
}
}
-void BKE_camera_multiview_window_matrix(RenderData *rd,
+void BKE_camera_multiview_window_matrix(const RenderData *rd,
const Object *camera,
const char *viewname,
float r_winmat[4][4])
@@ -879,7 +879,7 @@ void BKE_camera_multiview_window_matrix(RenderData *rd,
copy_m4_m4(r_winmat, params.winmat);
}
-bool BKE_camera_multiview_spherical_stereo(RenderData *rd, const Object *camera)
+bool BKE_camera_multiview_spherical_stereo(const RenderData *rd, const Object *camera)
{
Camera *cam;
const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
@@ -903,9 +903,8 @@ bool BKE_camera_multiview_spherical_stereo(RenderData *rd, const Object *camera)
return false;
}
-static Object *camera_multiview_advanced(Scene *scene, Object *camera, const char *suffix)
+static Object *camera_multiview_advanced(const Scene *scene, Object *camera, const char *suffix)
{
- SceneRenderView *srv;
char name[MAX_NAME];
const char *camera_name = camera->id.name + 2;
const int len_name = strlen(camera_name);
@@ -914,7 +913,7 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha
name[0] = '\0';
/* we need to take the better match, thus the len_suffix_max test */
- for (srv = scene->r.views.first; srv; srv = srv->next) {
+ for (const SceneRenderView *srv = scene->r.views.first; srv; srv = srv->next) {
const int len_suffix = strlen(srv->suffix);
if ((len_suffix < len_suffix_max) || (len_name < len_suffix)) {
@@ -938,7 +937,7 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha
}
/* returns the camera to be used for render */
-Object *BKE_camera_multiview_render(Scene *scene, Object *camera, const char *viewname)
+Object *BKE_camera_multiview_render(const Scene *scene, Object *camera, const char *viewname)
{
const bool is_multiview = (camera != NULL) && (scene->r.scemode & R_MULTIVIEW) != 0;
@@ -993,7 +992,9 @@ static float camera_stereo3d_shift_x(const Object *camera, const char *viewname)
return shift;
}
-float BKE_camera_multiview_shift_x(RenderData *rd, const Object *camera, const char *viewname)
+float BKE_camera_multiview_shift_x(const RenderData *rd,
+ const Object *camera,
+ const char *viewname)
{
const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
Camera *data = camera->data;
@@ -1011,7 +1012,7 @@ float BKE_camera_multiview_shift_x(RenderData *rd, const Object *camera, const c
}
}
-void BKE_camera_multiview_params(RenderData *rd,
+void BKE_camera_multiview_params(const RenderData *rd,
CameraParams *params,
const Object *camera,
const char *viewname)
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index f38810322a8..3a86e3084d8 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -4822,7 +4822,7 @@ static bConstraintTypeInfo CTI_FOLLOWTRACK = {
followtrack_evaluate, /* evaluate */
};
-/* ----------- Camre Solver ------------- */
+/* ----------- Camera Solver ------------- */
static void camerasolver_new_data(void *cdata)
{
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 9919a0d7385..366137b5fa6 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -705,8 +705,7 @@ static void bb_allocateData(FluidObjectBB *bb, bool use_velocity, bool use_influ
}
bb->distances = MEM_malloc_arrayN(bb->total_cells, sizeof(float), "fluid_bb_distances");
- /* Initialize to infinity. */
- memset(bb->distances, 0x7f7f7f7f, sizeof(float) * bb->total_cells);
+ copy_vn_fl(bb->distances, bb->total_cells, FLT_MAX);
bb->valid = true;
}
@@ -3272,12 +3271,12 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *mds, Mesh *orgmesh, Obj
}
me = BKE_mesh_new_nomain(num_verts, 0, 0, num_faces * 3, num_faces);
- mverts = me->mvert;
- mpolys = me->mpoly;
- mloops = me->mloop;
if (!me) {
return NULL;
}
+ mverts = me->mvert;
+ mpolys = me->mpoly;
+ mloops = me->mloop;
/* Get size (dimension) but considering scaling scaling. */
copy_v3_v3(cell_size_scaled, mds->cell_size);
@@ -3674,8 +3673,9 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
/* Reset fluid if no fluid present (obviously)
* or if timeline gets reset to startframe */
- if (!mds->fluid || is_startframe) {
+ if (!mds->fluid) {
BKE_fluid_modifier_reset_ex(mmd, false);
+ BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me);
}
/* Guiding parent res pointer needs initialization */
@@ -3687,8 +3687,6 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
}
}
- BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me);
-
/* ensure that time parameters are initialized correctly before every step */
float fps = scene->r.frs_sec / scene->r.frs_sec_base;
mds->frame_length = DT_DEFAULT * (25.0f / fps) * mds->time_scale;
@@ -3743,10 +3741,9 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
baking_mesh = mds->cache_flag & FLUID_DOMAIN_BAKING_MESH;
baking_particles = mds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES;
baking_guide = mds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE;
- bake_outdated = mds->cache_flag &
- (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
- FLUID_DOMAIN_OUTDATED_NOISE | FLUID_DOMAIN_OUTDATED_MESH |
- FLUID_DOMAIN_OUTDATED_PARTICLES | FLUID_DOMAIN_OUTDATED_GUIDE);
+ bake_outdated = mds->cache_flag & (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES |
+ FLUID_DOMAIN_OUTDATED_GUIDE);
bool resume_data, resume_noise, resume_mesh, resume_particles, resume_guide;
resume_data = (!is_startframe) && (mds->cache_frame_pause_data == scene_framenr);
@@ -4897,7 +4894,6 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd)
mmd->flow->type = FLUID_FLOW_TYPE_SMOKE;
mmd->flow->behavior = FLUID_FLOW_BEHAVIOR_GEOMETRY;
- mmd->flow->type = FLUID_FLOW_TYPE_SMOKE;
mmd->flow->flags = FLUID_FLOW_ABSOLUTE | FLUID_FLOW_USE_PART_SIZE | FLUID_FLOW_USE_INFLOW;
}
else if (mmd->type & MOD_FLUID_TYPE_EFFEC) {
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 6cd2d36c188..c0b40721ccc 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1120,6 +1120,32 @@ void BKE_gpencil_layer_mask_sort_all(bGPdata *gpd)
}
}
+static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b)
+{
+ const bGPDframe *frame_a = a;
+ const bGPDframe *frame_b = b;
+
+ if (frame_a->framenum < frame_b->framenum) {
+ return -1;
+ }
+ if (frame_a->framenum > frame_b->framenum) {
+ return 1;
+ }
+ if (thunk != NULL) {
+ *((bool *)thunk) = true;
+ }
+ /* Sort selected last. */
+ if ((frame_a->flag & GP_FRAME_SELECT) && ((frame_b->flag & GP_FRAME_SELECT) == 0)) {
+ return 1;
+ }
+ return 0;
+}
+
+void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames)
+{
+ BLI_listbase_sort_r(&gpl->frames, gpencil_cb_cmp_frame, r_has_duplicate_frames);
+}
+
/* get the active gp-layer for editing */
bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd)
{
@@ -3909,6 +3935,9 @@ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig
/* Assign original point pointer. */
for (int i = 0; i < gps_orig->totpoints; i++) {
+ if (i > gps_eval->totpoints - 1) {
+ break;
+ }
bGPDspoint *pt_eval = &gps_eval->points[i];
pt_eval->runtime.pt_orig = &gps_orig->points[i];
pt_eval->runtime.idx_orig = i;
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 4220408749a..22ec1fe1b98 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -145,8 +145,10 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
BLI_duplicatelist(&image_dst->tiles, &image_src->tiles);
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- image_dst->gputexture[i] = NULL;
+ for (int eye = 0; eye < 2; eye++) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ image_dst->gputexture[i][eye] = NULL;
+ }
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
@@ -529,9 +531,11 @@ bool BKE_image_scale(Image *image, int width, int height)
bool BKE_image_has_opengl_texture(Image *ima)
{
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- if (ima->gputexture[i] != NULL) {
- return true;
+ for (int eye = 0; eye < 2; eye++) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ if (ima->gputexture[i][eye] != NULL) {
+ return true;
+ }
}
}
return false;
@@ -1813,7 +1817,7 @@ typedef struct StampData {
* \param use_dynamic: Also include data that can change on a per-frame basis.
*/
static void stampdata(
- Scene *scene, Object *camera, StampData *stamp_data, int do_prefix, bool use_dynamic)
+ const Scene *scene, Object *camera, StampData *stamp_data, int do_prefix, bool use_dynamic)
{
char text[256];
struct tm *tl;
@@ -1935,7 +1939,7 @@ static void stampdata(
}
if (use_dynamic && scene->r.stamp & R_STAMP_SEQSTRIP) {
- Sequence *seq = BKE_sequencer_foreground_frame_get(scene, scene->r.cfra);
+ const Sequence *seq = BKE_sequencer_foreground_frame_get(scene, scene->r.cfra);
if (seq) {
STRNCPY(text, seq->name + 2);
@@ -2479,7 +2483,7 @@ void BKE_render_result_stamp_info(Scene *scene,
}
}
-struct StampData *BKE_stamp_info_from_scene_static(Scene *scene)
+struct StampData *BKE_stamp_info_from_scene_static(const Scene *scene)
{
struct StampData *stamp_data;
@@ -3318,9 +3322,11 @@ static void image_free_tile(Image *ima, ImageTile *tile)
continue;
}
- if (ima->gputexture[i] != NULL) {
- GPU_texture_free(ima->gputexture[i]);
- ima->gputexture[i] = NULL;
+ for (int eye = 0; eye < 2; eye++) {
+ if (ima->gputexture[i][eye] != NULL) {
+ GPU_texture_free(ima->gputexture[i][eye]);
+ ima->gputexture[i][eye] = NULL;
+ }
}
}
@@ -3587,14 +3593,16 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la
BLI_strncpy(tile->label, label, sizeof(tile->label));
}
- /* Reallocate GPU tile array. */
- if (ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY] != NULL) {
- GPU_texture_free(ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY]);
- ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY] = NULL;
- }
- if (ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING] != NULL) {
- GPU_texture_free(ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING]);
- ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING] = NULL;
+ for (int eye = 0; eye < 2; eye++) {
+ /* Reallocate GPU tile array. */
+ if (ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][eye] != NULL) {
+ GPU_texture_free(ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][eye]);
+ ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][eye] = NULL;
+ }
+ if (ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING][eye] != NULL) {
+ GPU_texture_free(ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING][eye]);
+ ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING][eye] = NULL;
+ }
}
return tile;
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index c342185d0b8..27d4b8dd047 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -162,7 +162,8 @@ static void lib_id_clear_library_data_ex(Main *bmain, ID *id)
{
bNodeTree *ntree = NULL;
Key *key = NULL;
- const bool id_in_mainlist = (id->tag & LIB_TAG_NO_MAIN) == 0;
+ const bool id_in_mainlist = (id->tag & LIB_TAG_NO_MAIN) == 0 &&
+ (id->flag & LIB_EMBEDDED_DATA) == 0;
lib_id_library_local_paths(bmain, id->lib, id);
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index f0bab4c0aa2..ce8fcc4eeb9 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -1420,6 +1420,8 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
const CustomData_MeshMasks *mask,
bool take_ownership)
{
+ BLI_assert(mesh_src->id.tag & LIB_TAG_NO_MAIN);
+
/* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */
/* TODO(Sybren): the above claim came from 2.7x derived-mesh code (DM_to_mesh);
* check whether it is still true with Mesh */
@@ -1571,6 +1573,8 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)
{
+ BLI_assert(mesh_src->id.tag & LIB_TAG_NO_MAIN);
+
int a, totvert = mesh_src->totvert;
float *fp;
MVert *mvert;
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 7b655b2d8fc..e14803e4193 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -3576,6 +3576,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id,
if (id) {
/* ensure external data is transferred */
+ /* TODO(sergey): Use multiresModifier_ensure_external_read(). */
CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i);
}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index f3d65f584d1..4e97d0fc05c 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -57,6 +57,8 @@
#include "DEG_depsgraph_query.h"
+#include "multires_reshape.h"
+
#include <math.h>
#include <string.h>
@@ -645,7 +647,7 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
GridPaintMask *gpm;
multires_set_tot_mdisps(me, mmd->totlvl);
- CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+ multiresModifier_ensure_external_read(me, mmd);
mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
gpm = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
@@ -711,7 +713,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd,
MDisps *mdisps;
multires_set_tot_mdisps(me, mmd->totlvl);
- CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+ multiresModifier_ensure_external_read(me, mmd);
mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
multires_force_sculpt_rebuild(ob);
@@ -789,158 +791,7 @@ static DerivedMesh *subsurf_dm_create_local(Scene *scene,
return subsurf_make_derived_from_derived(dm, &smd, scene, NULL, flags);
}
-/* assumes no is normalized; return value's sign is negative if v is on
- * the other side of the plane */
-static float v3_dist_from_plane(float v[3], float center[3], float no[3])
-{
- float s[3];
- sub_v3_v3v3(s, v, center);
- return dot_v3v3(s, no);
-}
-
-void multiresModifier_base_apply(MultiresModifierData *mmd, Scene *scene, Object *ob)
-{
- DerivedMesh *cddm, *dispdm, *origdm;
- Mesh *me;
- const MeshElemMap *pmap;
- float(*origco)[3];
- int i, j, k, offset, totlvl;
-
- multires_force_sculpt_rebuild(ob);
-
- me = BKE_mesh_from_object(ob);
- totlvl = mmd->totlvl;
-
- /* nothing to do */
- if (!totlvl) {
- return;
- }
-
- /* XXX - probably not necessary to regenerate the cddm so much? */
-
- /* generate highest level with displacements */
- cddm = CDDM_from_mesh(me);
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- dispdm = multires_dm_create_local(
- scene, ob, cddm, totlvl, totlvl, 0, 0, MULTIRES_IGNORE_SIMPLIFY);
- cddm->release(cddm);
-
- /* copy the new locations of the base verts into the mesh */
- offset = dispdm->getNumVerts(dispdm) - me->totvert;
- for (i = 0; i < me->totvert; i++) {
- dispdm->getVertCo(dispdm, offset + i, me->mvert[i].co);
- }
-
- /* heuristic to produce a better-fitting base mesh */
-
- cddm = CDDM_from_mesh(me);
- pmap = cddm->getPolyMap(ob, cddm);
- origco = MEM_calloc_arrayN(me->totvert, 3 * sizeof(float), "multires apply base origco");
- for (i = 0; i < me->totvert; i++) {
- copy_v3_v3(origco[i], me->mvert[i].co);
- }
-
- for (i = 0; i < me->totvert; i++) {
- float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
- float dist;
- int tot = 0;
-
- /* don't adjust verts not used by at least one poly */
- if (!pmap[i].count) {
- continue;
- }
-
- /* find center */
- for (j = 0; j < pmap[i].count; j++) {
- const MPoly *p = &me->mpoly[pmap[i].indices[j]];
-
- /* this double counts, not sure if that's bad or good */
- for (k = 0; k < p->totloop; k++) {
- int vndx = me->mloop[p->loopstart + k].v;
- if (vndx != i) {
- add_v3_v3(center, origco[vndx]);
- tot++;
- }
- }
- }
- mul_v3_fl(center, 1.0f / tot);
-
- /* find normal */
- for (j = 0; j < pmap[i].count; j++) {
- const MPoly *p = &me->mpoly[pmap[i].indices[j]];
- MPoly fake_poly;
- MLoop *fake_loops;
- float(*fake_co)[3];
- float no[3];
-
- /* set up poly, loops, and coords in order to call
- * BKE_mesh_calc_poly_normal_coords() */
- fake_poly.totloop = p->totloop;
- fake_poly.loopstart = 0;
- fake_loops = MEM_malloc_arrayN(p->totloop, sizeof(MLoop), "fake_loops");
- fake_co = MEM_malloc_arrayN(p->totloop, 3 * sizeof(float), "fake_co");
-
- for (k = 0; k < p->totloop; k++) {
- int vndx = me->mloop[p->loopstart + k].v;
-
- fake_loops[k].v = k;
-
- if (vndx == i) {
- copy_v3_v3(fake_co[k], center);
- }
- else {
- copy_v3_v3(fake_co[k], origco[vndx]);
- }
- }
-
- BKE_mesh_calc_poly_normal_coords(&fake_poly, fake_loops, (const float(*)[3])fake_co, no);
- MEM_freeN(fake_loops);
- MEM_freeN(fake_co);
-
- add_v3_v3(avg_no, no);
- }
- normalize_v3(avg_no);
-
- /* push vertex away from the plane */
- dist = v3_dist_from_plane(me->mvert[i].co, center, avg_no);
- copy_v3_v3(push, avg_no);
- mul_v3_fl(push, dist);
- add_v3_v3(me->mvert[i].co, push);
- }
-
- MEM_freeN(origco);
- cddm->release(cddm);
-
- /* Vertices were moved around, need to update normals after all the vertices are updated
- * Probably this is possible to do in the loop above, but this is rather tricky because
- * we don't know all needed vertices' coordinates there yet.
- */
- BKE_mesh_calc_normals(me);
-
- /* subdivide the mesh to highest level without displacements */
- cddm = CDDM_from_mesh(me);
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- origdm = subsurf_dm_create_local(scene,
- ob,
- cddm,
- totlvl,
- 0,
- 0,
- mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE,
- 0,
- false,
- SUBSURF_IGNORE_SIMPLIFY);
- cddm->release(cddm);
-
- /* calc disps */
- multiresModifier_disp_run(
- dispdm, me, NULL, CALC_DISPLACEMENTS, origdm->getGridData(origdm), totlvl);
-
- origdm->release(origdm);
- dispdm->release(dispdm);
-}
-
-static void multires_subdivide(
+static void multires_subdivide_legacy(
MultiresModifierData *mmd, Scene *scene, Object *ob, int totlvl, int updateblock, int simple)
{
Mesh *me = ob->data;
@@ -1038,10 +889,10 @@ static void multires_subdivide(
multires_set_tot_level(ob, mmd, totlvl);
}
-void multiresModifier_subdivide(
+void multiresModifier_subdivide_legacy(
MultiresModifierData *mmd, Scene *scene, Object *ob, int updateblock, int simple)
{
- multires_subdivide(mmd, scene, ob, mmd->totlvl + 1, updateblock, simple);
+ multires_subdivide_legacy(mmd, scene, ob, mmd->totlvl + 1, updateblock, simple);
}
static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3])
@@ -1293,7 +1144,7 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm, Scene *scene)
me = ccgdm->multires.ob->data;
mmd = ccgdm->multires.mmd;
multires_set_tot_mdisps(me, mmd->totlvl);
- CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+ multiresModifier_ensure_external_read(me, mmd);
mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
if (mdisps) {
@@ -1521,7 +1372,7 @@ DerivedMesh *multires_make_derived_from_derived(
}
multires_set_tot_mdisps(me, mmd->totlvl);
- CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+ multiresModifier_ensure_external_read(me, mmd);
/*run displacement*/
multiresModifier_disp_run(result, ob->data, dm, APPLY_DISPLACEMENTS, subGridData, mmd->totlvl);
@@ -2277,7 +2128,8 @@ void multires_load_old(Object *ob, Mesh *me)
multires_load_old_vcols(me);
multires_load_old_face_flags(me);
- /* multiresModifier_subdivide (actually, multires_subdivide) expects polys, not tessfaces! */
+ /* multiresModifier_subdivide_legacy (actually, multires_subdivide_legacy) expects polys, not
+ * tessfaces! */
BKE_mesh_convert_mfaces_to_mpolys(me);
/* Add a multires modifier to the object */
@@ -2289,7 +2141,7 @@ void multires_load_old(Object *ob, Mesh *me)
BLI_insertlinkbefore(&ob->modifiers, md, mmd);
for (i = 0; i < me->mr->level_count - 1; i++) {
- multiresModifier_subdivide(mmd, NULL, ob, 1, 0);
+ multiresModifier_subdivide_legacy(mmd, NULL, ob, 1, 0);
}
mmd->lvl = mmd->totlvl;
@@ -2314,8 +2166,7 @@ void multires_load_old(Object *ob, Mesh *me)
/* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them
* such that 'ob_dst' has the same total number of levels as 'ob_src'. */
-void multiresModifier_sync_levels_ex(Scene *scene,
- Object *ob_dst,
+void multiresModifier_sync_levels_ex(Object *ob_dst,
MultiresModifierData *mmd_src,
MultiresModifierData *mmd_dst)
{
@@ -2324,7 +2175,7 @@ void multiresModifier_sync_levels_ex(Scene *scene,
}
if (mmd_src->totlvl > mmd_dst->totlvl) {
- multires_subdivide(mmd_dst, scene, ob_dst, mmd_src->totlvl, false, mmd_dst->simple);
+ multiresModifier_subdivide_to_level(ob_dst, mmd_dst, mmd_src->totlvl);
}
else {
multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl);
@@ -2346,7 +2197,7 @@ static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
}
if (mmd_src && mmd_dst) {
- multiresModifier_sync_levels_ex(scene, ob_dst, mmd_src, mmd_dst);
+ multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst);
}
}
@@ -2373,7 +2224,7 @@ static void multires_apply_smat(struct Depsgraph *UNUSED(depsgraph),
}
/* Make sure layer present. */
Mesh *mesh = (Mesh *)object->data;
- CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop);
+ multiresModifier_ensure_external_read(mesh, mmd);
if (!CustomData_get_layer(&mesh->ldata, CD_MDISPS)) {
return;
}
@@ -2467,6 +2318,44 @@ void multires_topology_changed(Mesh *me)
}
}
+/* Makes sure data from an external file is fully read.
+ *
+ * Since the multires data files only contain displacement vectors without knowledge about
+ * subdivision level some extra work is needed. Namely make is to all displacement grids have
+ * proper level and number of displacement vectors set. */
+void multires_ensure_external_read(struct Mesh *mesh, int top_level)
+{
+ if (!CustomData_external_test(&mesh->ldata, CD_MDISPS)) {
+ return;
+ }
+
+ MDisps *mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
+ if (mdisps == NULL) {
+ mdisps = CustomData_add_layer(&mesh->ldata, CD_MDISPS, CD_DEFAULT, NULL, mesh->totloop);
+ }
+
+ const int totloop = mesh->totloop;
+
+ for (int i = 0; i < totloop; ++i) {
+ if (mdisps[i].level != top_level) {
+ MEM_SAFE_FREE(mdisps[i].disps);
+ }
+
+ /* NOTE: CustomData_external_read will take care of allocation of displacement vectors if
+ * they are missing. */
+
+ const int totdisp = multires_grid_tot[top_level];
+ mdisps[i].totdisp = totdisp;
+ mdisps[i].level = top_level;
+ }
+
+ CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop);
+}
+void multiresModifier_ensure_external_read(struct Mesh *mesh, const MultiresModifierData *mmd)
+{
+ multires_ensure_external_read(mesh, mmd->totlvl);
+}
+
/***************** Multires interpolation stuff *****************/
/* Find per-corner coordinate with given per-face UV coord */
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
new file mode 100644
index 00000000000..a29398b24a0
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -0,0 +1,236 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_math_vector.h"
+
+#include "BKE_customdata.h"
+#include "BKE_lib_id.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
+#include "BKE_multires.h"
+#include "BKE_subdiv.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "multires_reshape.h"
+
+/* ================================================================================================
+ * Reshape from object.
+ */
+
+bool multiresModifier_reshapeFromVertcos(struct Depsgraph *depsgraph,
+ struct Object *object,
+ struct MultiresModifierData *mmd,
+ const float (*vert_coords)[3],
+ const int num_vert_coords)
+{
+ MultiresReshapeContext reshape_context;
+ if (!multires_reshape_context_create_from_object(&reshape_context, depsgraph, object, mmd)) {
+ return false;
+ }
+ multires_reshape_store_original_grids(&reshape_context);
+ multires_reshape_ensure_grids(object->data, reshape_context.top.level);
+ if (!multires_reshape_assign_final_coords_from_vertcos(
+ &reshape_context, vert_coords, num_vert_coords)) {
+ multires_reshape_context_free(&reshape_context);
+ return false;
+ }
+ multires_reshape_smooth_object_grids_with_details(&reshape_context);
+ multires_reshape_object_grids_to_tangent_displacement(&reshape_context);
+ multires_reshape_context_free(&reshape_context);
+ return true;
+}
+
+/* Returns truth on success, false otherwise.
+ *
+ * This function might fail in cases like source and destination not having
+ * matched amount of vertices. */
+bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph,
+ struct MultiresModifierData *mmd,
+ struct Object *dst,
+ struct Object *src)
+{
+ struct Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ struct Object *src_eval = DEG_get_evaluated_object(depsgraph, src);
+ Mesh *src_mesh_eval = mesh_get_eval_final(depsgraph, scene_eval, src_eval, &CD_MASK_BAREMESH);
+
+ int num_deformed_verts;
+ float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(src_mesh_eval, &num_deformed_verts);
+
+ const bool result = multiresModifier_reshapeFromVertcos(
+ depsgraph, dst, mmd, deformed_verts, num_deformed_verts);
+
+ MEM_freeN(deformed_verts);
+
+ return result;
+}
+
+/* ================================================================================================
+ * Reshape from modifier.
+ */
+
+bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph,
+ struct Object *object,
+ struct MultiresModifierData *mmd,
+ struct ModifierData *deform_md)
+{
+ MultiresModifierData highest_mmd = *mmd;
+ highest_mmd.sculptlvl = highest_mmd.totlvl;
+ highest_mmd.lvl = highest_mmd.totlvl;
+ highest_mmd.renderlvl = highest_mmd.totlvl;
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+
+ /* Create mesh for the multires, ignoring any further modifiers (leading
+ * deformation modifiers will be applied though). */
+ Mesh *multires_mesh = BKE_multires_create_mesh(depsgraph, scene_eval, &highest_mmd, object);
+ int num_deformed_verts;
+ float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(multires_mesh, &num_deformed_verts);
+
+ /* Apply deformation modifier on the multires, */
+ const ModifierEvalContext modifier_ctx = {
+ .depsgraph = depsgraph,
+ .object = object,
+ .flag = MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY,
+ };
+ modwrap_deformVerts(
+ deform_md, &modifier_ctx, multires_mesh, deformed_verts, multires_mesh->totvert);
+ BKE_id_free(NULL, multires_mesh);
+
+ /* Reshaping */
+ bool result = multiresModifier_reshapeFromVertcos(
+ depsgraph, object, &highest_mmd, deformed_verts, num_deformed_verts);
+
+ /* Cleanup */
+ MEM_freeN(deformed_verts);
+
+ return result;
+}
+
+/* ================================================================================================
+ * Reshape from grids.
+ */
+
+bool multiresModifier_reshapeFromCCG(const int tot_level,
+ Mesh *coarse_mesh,
+ struct SubdivCCG *subdiv_ccg)
+{
+ MultiresReshapeContext reshape_context;
+ if (!multires_reshape_context_create_from_ccg(
+ &reshape_context, subdiv_ccg, coarse_mesh, tot_level)) {
+ return false;
+ }
+
+ multires_ensure_external_read(coarse_mesh, reshape_context.top.level);
+
+ multires_reshape_store_original_grids(&reshape_context);
+ multires_reshape_ensure_grids(coarse_mesh, reshape_context.top.level);
+ if (!multires_reshape_assign_final_coords_from_ccg(&reshape_context, subdiv_ccg)) {
+ multires_reshape_context_free(&reshape_context);
+ return false;
+ }
+ multires_reshape_smooth_object_grids_with_details(&reshape_context);
+ multires_reshape_object_grids_to_tangent_displacement(&reshape_context);
+ multires_reshape_context_free(&reshape_context);
+ return true;
+}
+
+/* ================================================================================================
+ * Subdivision.
+ */
+
+void multiresModifier_subdivide(Object *object, MultiresModifierData *mmd)
+{
+ const int top_level = mmd->totlvl + 1;
+ multiresModifier_subdivide_to_level(object, mmd, top_level);
+}
+
+void multiresModifier_subdivide_to_level(struct Object *object,
+ struct MultiresModifierData *mmd,
+ const int top_level)
+{
+ if (top_level <= mmd->totlvl) {
+ return;
+ }
+
+ Mesh *coarse_mesh = object->data;
+ MultiresReshapeContext reshape_context;
+
+ /* There was no multires at all, all displacement is at 0. Can simply make sure all mdisps grids
+ * are allocated at a proper level and return. */
+ const bool has_mdisps = CustomData_has_layer(&coarse_mesh->ldata, CD_MDISPS);
+ if (!has_mdisps) {
+ CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_CALLOC, NULL, coarse_mesh->totloop);
+ }
+ if (!has_mdisps || top_level == 1) {
+ multires_reshape_ensure_grids(coarse_mesh, top_level);
+ multires_set_tot_level(object, mmd, top_level);
+ return;
+ }
+
+ multires_flush_sculpt_updates(object);
+
+ if (!multires_reshape_context_create_from_subdivide(&reshape_context, object, mmd, top_level)) {
+ return;
+ }
+ multires_reshape_store_original_grids(&reshape_context);
+ multires_reshape_ensure_grids(coarse_mesh, reshape_context.top.level);
+ multires_reshape_assign_final_coords_from_orig_mdisps(&reshape_context);
+ multires_reshape_smooth_object_grids(&reshape_context);
+ multires_reshape_object_grids_to_tangent_displacement(&reshape_context);
+ multires_reshape_context_free(&reshape_context);
+
+ multires_set_tot_level(object, mmd, top_level);
+}
+
+/* ================================================================================================
+ * Apply base.
+ */
+
+void multiresModifier_base_apply(struct Depsgraph *depsgraph,
+ Object *object,
+ MultiresModifierData *mmd)
+{
+ multires_force_sculpt_rebuild(object);
+
+ MultiresReshapeContext reshape_context;
+ if (!multires_reshape_context_create_from_object(&reshape_context, depsgraph, object, mmd)) {
+ return;
+ }
+
+ multires_reshape_assign_final_coords_from_mdisps(&reshape_context);
+ multires_reshape_apply_base_update_mesh_coords(&reshape_context);
+ multires_reshape_apply_base_refit_base_mesh(&reshape_context);
+ multires_reshape_apply_base_refine_subdiv(&reshape_context);
+ multires_reshape_object_grids_to_tangent_displacement(&reshape_context);
+
+ multires_reshape_context_free(&reshape_context);
+}
diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h
new file mode 100644
index 00000000000..9029d19ae88
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_reshape.h
@@ -0,0 +1,327 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#ifndef __BKE_INTERN_MULTIRES_RESHAPE_H__
+#define __BKE_INTERN_MULTIRES_RESHAPE_H__
+
+#include "BLI_sys_types.h"
+
+struct Depsgraph;
+struct GridPaintMask;
+struct MDisps;
+struct Mesh;
+struct MultiresModifierData;
+struct Object;
+struct Subdiv;
+struct SubdivCCG;
+
+typedef struct MultiresReshapeContext {
+ /* Base mesh from original object.
+ * NOTE: Does NOT include any leading modifiers in it. */
+ struct Mesh *base_mesh;
+
+ /* Subdivision surface created for multires modifier.
+ *
+ * The coarse mesh of this subdivision surface is a base mesh with all deformation modifiers
+ * leading multires applied on it. */
+ struct Subdiv *subdiv;
+ bool need_free_subdiv;
+
+ struct {
+ /* Level at which displacement is being assigned to.
+ * It will be propagated up from this level to top.level. */
+ int level;
+
+ /* Grid size for reshape.level. */
+ int grid_size;
+ } reshape;
+
+ struct {
+ /* Top level of the displacement grids.
+ * The displacement will be propagated up to this level. */
+ int level;
+
+ /* Grid size for top.level. */
+ int grid_size;
+ } top;
+
+ struct {
+ /* Copy of original displacement and painting masks. */
+ struct MDisps *mdisps;
+ struct GridPaintMask *grid_paint_masks;
+ } orig;
+
+ /* Number of grids which are required for base_mesh. */
+ int num_grids;
+
+ /* Destination displacement and mask.
+ * Points to a custom data on a destination mesh. */
+ struct MDisps *mdisps;
+ struct GridPaintMask *grid_paint_masks;
+
+ /* Indexed by face index, gives first grid index of the face. */
+ int *face_start_grid_index;
+
+ /* Indexed by grid index, contains face (poly) index in the base mesh from which the grid has
+ * been created (in other words, index of a poly which contains loop corresponding to the grid
+ * index). */
+ int *grid_to_face_index;
+
+ /* Indexed by ptex face index, gives first grid index of the ptex face.
+ *
+ * For non-quad base faces ptex face is created for every face corner, so it's similar to a
+ * grid in this case. In this case start grid index will be the only one for this ptex face.
+ *
+ * For quad base faces there is a single ptex face but 4 grids. So in this case there will be
+ * 4 grids for the ptex, starting at a value stored in this mapping. */
+ int *ptex_start_grid_index;
+
+ /* Indexed by base face index, returns first ptex face index corresponding
+ * to that base face. */
+ int *face_ptex_offset;
+} MultiresReshapeContext;
+
+/**
+ * Coordinate which identifies element of a grid.
+ * This is directly related on how #CD_MDISPS stores displacement.
+ */
+typedef struct GridCoord {
+ int grid_index;
+ float u, v;
+} GridCoord;
+
+/**
+ * Coordinate within ptex, which is what OpenSubdiv API operates on.
+ */
+typedef struct PTexCoord {
+ int ptex_face_index;
+ float u, v;
+} PTexCoord;
+
+/**
+ * Element of a grid data stored in the destination mesh.
+ * This is where reshaped coordinates and mask values will be written to.
+ */
+typedef struct ReshapeGridElement {
+ float *displacement;
+ float *mask;
+} ReshapeGridElement;
+
+typedef struct ReshapeConstGridElement {
+ float displacement[3];
+ float mask;
+} ReshapeConstGridElement;
+
+/* -------------------------------------------------------------------- */
+/** \name Construct/destruct reshape context.
+ * \{ */
+
+/* Create subdivision surface descriptor which is configured for surface evaluation at a given
+ * multires modifier. */
+struct Subdiv *multires_reshape_create_subdiv(struct Depsgraph *depsgraph,
+ struct Object *object,
+ const struct MultiresModifierData *mmd);
+
+bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context,
+ struct Depsgraph *depsgraph,
+ struct Object *object,
+ struct MultiresModifierData *mmd);
+
+bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_context,
+ struct SubdivCCG *subdiv_ccg,
+ struct Mesh *base_mesh,
+ int top_level);
+
+bool multires_reshape_context_create_from_subdivide(MultiresReshapeContext *reshape_context,
+ struct Object *object,
+ struct MultiresModifierData *mmd,
+ int top_level);
+
+void multires_reshape_context_free(MultiresReshapeContext *reshape_context);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Helper accessors.
+ * \{ */
+
+/* For the given grid index get index of face it was created for. */
+int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_context,
+ int grid_index);
+
+/* For the given grid index get corner of a face it was created for. */
+int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index);
+
+bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index);
+
+/* For the given grid index get index of corresponding ptex face. */
+int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_context,
+ int grid_index);
+
+/* Convert normalized coordinate within a grid to a normalized coordinate within a ptex face. */
+PTexCoord multires_reshape_grid_coord_to_ptex(const MultiresReshapeContext *reshape_context,
+ const GridCoord *grid_coord);
+
+/* Convert a normalized coordinate within a ptex face to a normalized coordinate within a grid. */
+GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *reshape_context,
+ const PTexCoord *ptex_coord);
+
+/* Calculate tangent matrix which converts displacement to a object vector.
+ * Is calculated for the given surface derivatives at a given base face corner. */
+void multires_reshape_tangent_matrix_for_corner(const MultiresReshapeContext *reshape_context,
+ const int face_index,
+ const int corner,
+ const float dPdu[3],
+ const float dPdv[3],
+ float r_tangent_matrix[3][3]);
+
+/* Get grid elements which are to be reshaped at a given or ptex coordinate.
+ * The data is coming from final custom mdata layers. */
+ReshapeGridElement multires_reshape_grid_element_for_grid_coord(
+ const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord);
+ReshapeGridElement multires_reshape_grid_element_for_ptex_coord(
+ const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord);
+
+/* Get original grid element for the given coordinate. */
+ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(
+ const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sample limit surface of the base mesh.
+ * \{ */
+
+/* Evaluate limit surface created from base mesh.
+ * This is the limit surface which defines tangent space for MDisps. */
+void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *reshape_context,
+ const GridCoord *grid_coord,
+ float r_P[3],
+ float r_tangent_matrix[3][3]);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Custom data preparation.
+ * \{ */
+
+/* Make sure custom data is allocated for the given level. */
+void multires_reshape_ensure_grids(struct Mesh *mesh, const int level);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Functions specific to reshaping from a set of vertices in a object position.
+ * \{ */
+
+/* Returns truth if all coordinates were assigned.
+ *
+ * False will be returned if the number of vertex coordinates did not match required number of
+ * vertices at a reshape level. */
+bool multires_reshape_assign_final_coords_from_vertcos(
+ const MultiresReshapeContext *reshape_context,
+ const float (*vert_coords)[3],
+ const int num_vert_coords);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Functions specific to reshaping from CCG.
+ * \{ */
+
+/* NOTE: Displacement grids to be at least at a reshape level.
+ *
+ * Return truth if all coordinates have been updated. */
+bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext *reshape_context,
+ struct SubdivCCG *subdiv_ccg);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Functions specific to reshaping from MDISPS.
+ * \{ */
+
+/* Reads and writes to the current mesh CD_MDISPS. */
+void multires_reshape_assign_final_coords_from_mdisps(
+ const MultiresReshapeContext *reshape_context);
+
+/* Reads from original CD_MIDTSPS, writes to the current mesh CD_MDISPS. */
+void multires_reshape_assign_final_coords_from_orig_mdisps(
+ const MultiresReshapeContext *reshape_context);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Displacement smooth.
+ * \{ */
+
+/* Operates on a displacement grids (CD_MDISPS) which contains object space coordinates stored for
+ * the reshape level.
+ *
+ * The result is grids which are defining mesh with a smooth surface and details starting from
+ * reshape level up to top level added back from original displacement grids. */
+void multires_reshape_smooth_object_grids_with_details(
+ const MultiresReshapeContext *reshape_context);
+
+/* Operates on a displacement grids (CD_MDISPS) which contains object space-coordinates stored for
+ * the reshape level.
+ *
+ * Makes it so surface on top level looks smooth. Details are not preserved
+ */
+void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Displacement, space conversion.
+ * \{ */
+
+/* Store original grid data, so then it's possible to calculate delta from it and add
+ * high-frequency content on top of reshaped grids. */
+void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_context);
+
+void multires_reshape_object_grids_to_tangent_displacement(
+ const MultiresReshapeContext *reshape_context);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Apply base.
+ * \{ */
+
+/* Update mesh coordinates to the final positions of displacement in object space.
+ * This is effectively desired position of base mesh vertices after canceling out displacement.
+ *
+ * NOTE: Expects that mesh's CD_MDISPS has been set to object space positions. */
+void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *reshape_context);
+
+/* Perform better fitting of the base mesh so its subdivided version brings vertices to their
+ * desired locations. */
+void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape_context);
+
+/* Refine subdivision surface to the new positions of the base mesh. */
+void multires_reshape_apply_base_refine_subdiv(MultiresReshapeContext *reshape_context);
+
+/** \} */
+
+#endif /* __BKE_INTERN_MULTIRES_RESHAPE_H__ */
diff --git a/source/blender/blenkernel/intern/multires_reshape_apply_base.c b/source/blender/blenkernel/intern/multires_reshape_apply_base.c
new file mode 100644
index 00000000000..e05b5bb3179
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_reshape_apply_base.c
@@ -0,0 +1,158 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "multires_reshape.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_math_vector.h"
+
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_subdiv_eval.h"
+
+void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *reshape_context)
+{
+ Mesh *base_mesh = reshape_context->base_mesh;
+ const int grid_size = reshape_context->top.grid_size;
+ const int grid_index = grid_size * grid_size - 1;
+ for (int i = 0; i < base_mesh->totloop; ++i) {
+ MDisps *displacement_grid = &reshape_context->mdisps[i];
+ const MLoop *loop = &base_mesh->mloop[i];
+ MVert *vert = &base_mesh->mvert[loop->v];
+ copy_v3_v3(vert->co, displacement_grid->disps[grid_index]);
+ }
+}
+
+/* Assumes no is normalized; return value's sign is negative if v is on the other side of the
+ * plane. */
+static float v3_dist_from_plane(float v[3], float center[3], float no[3])
+{
+ float s[3];
+ sub_v3_v3v3(s, v, center);
+ return dot_v3v3(s, no);
+}
+
+void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape_context)
+{
+ Mesh *base_mesh = reshape_context->base_mesh;
+
+ MeshElemMap *pmap;
+ int *pmap_mem;
+ BKE_mesh_vert_poly_map_create(&pmap,
+ &pmap_mem,
+ base_mesh->mpoly,
+ base_mesh->mloop,
+ base_mesh->totvert,
+ base_mesh->totpoly,
+ base_mesh->totloop);
+
+ float(*origco)[3] = MEM_calloc_arrayN(
+ base_mesh->totvert, 3 * sizeof(float), "multires apply base origco");
+ for (int i = 0; i < base_mesh->totvert; i++) {
+ copy_v3_v3(origco[i], base_mesh->mvert[i].co);
+ }
+
+ for (int i = 0; i < base_mesh->totvert; i++) {
+ float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
+
+ /* Don't adjust vertices not used by at least one poly. */
+ if (!pmap[i].count) {
+ continue;
+ }
+
+ /* Find center. */
+ int tot = 0;
+ for (int j = 0; j < pmap[i].count; j++) {
+ const MPoly *p = &base_mesh->mpoly[pmap[i].indices[j]];
+
+ /* This double counts, not sure if that's bad or good. */
+ for (int k = 0; k < p->totloop; k++) {
+ const int vndx = base_mesh->mloop[p->loopstart + k].v;
+ if (vndx != i) {
+ add_v3_v3(center, origco[vndx]);
+ tot++;
+ }
+ }
+ }
+ mul_v3_fl(center, 1.0f / tot);
+
+ /* Find normal. */
+ for (int j = 0; j < pmap[i].count; j++) {
+ const MPoly *p = &base_mesh->mpoly[pmap[i].indices[j]];
+ MPoly fake_poly;
+ MLoop *fake_loops;
+ float(*fake_co)[3];
+ float no[3];
+
+ /* Set up poly, loops, and coords in order to call BKE_mesh_calc_poly_normal_coords(). */
+ fake_poly.totloop = p->totloop;
+ fake_poly.loopstart = 0;
+ fake_loops = MEM_malloc_arrayN(p->totloop, sizeof(MLoop), "fake_loops");
+ fake_co = MEM_malloc_arrayN(p->totloop, 3 * sizeof(float), "fake_co");
+
+ for (int k = 0; k < p->totloop; k++) {
+ const int vndx = base_mesh->mloop[p->loopstart + k].v;
+
+ fake_loops[k].v = k;
+
+ if (vndx == i) {
+ copy_v3_v3(fake_co[k], center);
+ }
+ else {
+ copy_v3_v3(fake_co[k], origco[vndx]);
+ }
+ }
+
+ BKE_mesh_calc_poly_normal_coords(&fake_poly, fake_loops, (const float(*)[3])fake_co, no);
+ MEM_freeN(fake_loops);
+ MEM_freeN(fake_co);
+
+ add_v3_v3(avg_no, no);
+ }
+ normalize_v3(avg_no);
+
+ /* Push vertex away from the plane. */
+ const float dist = v3_dist_from_plane(base_mesh->mvert[i].co, center, avg_no);
+ copy_v3_v3(push, avg_no);
+ mul_v3_fl(push, dist);
+ add_v3_v3(base_mesh->mvert[i].co, push);
+ }
+
+ MEM_freeN(origco);
+ MEM_freeN(pmap);
+ MEM_freeN(pmap_mem);
+
+ /* Vertices were moved around, need to update normals after all the vertices are updated
+ * Probably this is possible to do in the loop above, but this is rather tricky because
+ * we don't know all needed vertices' coordinates there yet. */
+ BKE_mesh_calc_normals(base_mesh);
+}
+
+void multires_reshape_apply_base_refine_subdiv(MultiresReshapeContext *reshape_context)
+{
+ BKE_subdiv_eval_update_from_mesh(reshape_context->subdiv, reshape_context->base_mesh, NULL);
+}
diff --git a/source/blender/blenkernel/intern/multires_reshape_ccg.c b/source/blender/blenkernel/intern/multires_reshape_ccg.c
new file mode 100644
index 00000000000..1f8c782ed46
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_reshape_ccg.c
@@ -0,0 +1,72 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "multires_reshape.h"
+
+#include <string.h>
+
+#include "BLI_utildefines.h"
+
+#include "BKE_ccg.h"
+#include "BKE_subdiv_ccg.h"
+
+bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext *reshape_context,
+ struct SubdivCCG *subdiv_ccg)
+{
+ CCGKey reshape_level_key;
+ BKE_subdiv_ccg_key(&reshape_level_key, subdiv_ccg, reshape_context->reshape.level);
+
+ const int reshape_grid_size = reshape_context->reshape.grid_size;
+ const float reshape_grid_size_1_inv = 1.0f / (((float)reshape_grid_size) - 1.0f);
+
+ int num_grids = subdiv_ccg->num_grids;
+ for (int grid_index = 0; grid_index < num_grids; ++grid_index) {
+ CCGElem *ccg_grid = subdiv_ccg->grids[grid_index];
+ for (int y = 0; y < reshape_grid_size; ++y) {
+ const float v = (float)y * reshape_grid_size_1_inv;
+ for (int x = 0; x < reshape_grid_size; ++x) {
+ const float u = (float)x * reshape_grid_size_1_inv;
+
+ GridCoord grid_coord;
+ grid_coord.grid_index = grid_index;
+ grid_coord.u = u;
+ grid_coord.v = v;
+
+ ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(
+ reshape_context, &grid_coord);
+
+ BLI_assert(grid_element.displacement != NULL);
+ memcpy(grid_element.displacement,
+ CCG_grid_elem_co(&reshape_level_key, ccg_grid, x, y),
+ sizeof(float) * 3);
+
+ if (reshape_level_key.has_mask) {
+ BLI_assert(grid_element.mask != NULL);
+ *grid_element.mask = *CCG_grid_elem_mask(&reshape_level_key, ccg_grid, x, y);
+ }
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/source/blender/blenkernel/intern/multires_reshape_legacy.c b/source/blender/blenkernel/intern/multires_reshape_legacy.c
deleted file mode 100644
index 0a8248b25f1..00000000000
--- a/source/blender/blenkernel/intern/multires_reshape_legacy.c
+++ /dev/null
@@ -1,1056 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2018 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup bke
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_scene_types.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_math_vector.h"
-#include "BLI_task.h"
-
-#include "BKE_ccg.h"
-#include "BKE_lib_id.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
-#include "BKE_modifier.h"
-#include "BKE_multires.h"
-#include "BKE_subdiv.h"
-#include "BKE_subdiv_ccg.h"
-#include "BKE_subdiv_eval.h"
-#include "BKE_subdiv_foreach.h"
-#include "BKE_subdiv_mesh.h"
-
-#include "DEG_depsgraph_query.h"
-
-static void multires_reshape_init_mmd(MultiresModifierData *reshape_mmd,
- const MultiresModifierData *mmd)
-{
- *reshape_mmd = *mmd;
-}
-
-static void multires_reshape_init_mmd_top_level(MultiresModifierData *reshape_mmd,
- const MultiresModifierData *mmd)
-{
- *reshape_mmd = *mmd;
- reshape_mmd->lvl = reshape_mmd->totlvl;
-}
-
-/* =============================================================================
- * General reshape implementation, reused by all particular cases.
- */
-
-typedef struct MultiresReshapeContext {
- Subdiv *subdiv;
- const Mesh *coarse_mesh;
- MDisps *mdisps;
- GridPaintMask *grid_paint_mask;
- int top_grid_size;
- int top_level;
- /* Indexed by coarse face index, returns first ptex face index corresponding
- * to that coarse face. */
- int *face_ptex_offset;
-} MultiresReshapeContext;
-
-static void multires_reshape_allocate_displacement_grid(MDisps *displacement_grid, const int level)
-{
- const int grid_size = BKE_subdiv_grid_size_from_level(level);
- const int grid_area = grid_size * grid_size;
- float(*disps)[3] = MEM_calloc_arrayN(grid_area, 3 * sizeof(float), "multires disps");
- if (displacement_grid->disps != NULL) {
- MEM_freeN(displacement_grid->disps);
- }
- displacement_grid->disps = disps;
- displacement_grid->totdisp = grid_area;
- displacement_grid->level = level;
-}
-
-static void multires_reshape_ensure_displacement_grid(MDisps *displacement_grid, const int level)
-{
- if (displacement_grid->disps != NULL && displacement_grid->level == level) {
- return;
- }
- multires_reshape_allocate_displacement_grid(displacement_grid, level);
-}
-
-static void multires_reshape_ensure_displacement_grids(Mesh *mesh, const int grid_level)
-{
- const int num_grids = mesh->totloop;
- MDisps *mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- multires_reshape_ensure_displacement_grid(&mdisps[grid_index], grid_level);
- }
-}
-
-static void multires_reshape_ensure_mask_grids(Mesh *mesh, const int grid_level)
-{
- GridPaintMask *grid_paint_masks = CustomData_get_layer(&mesh->ldata, CD_GRID_PAINT_MASK);
- if (grid_paint_masks == NULL) {
- return;
- }
- const int num_grids = mesh->totloop;
- const int grid_size = BKE_subdiv_grid_size_from_level(grid_level);
- const int grid_area = grid_size * grid_size;
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- GridPaintMask *grid_paint_mask = &grid_paint_masks[grid_index];
- if (grid_paint_mask->level == grid_level) {
- continue;
- }
- grid_paint_mask->level = grid_level;
- if (grid_paint_mask->data) {
- MEM_freeN(grid_paint_mask->data);
- }
- grid_paint_mask->data = MEM_calloc_arrayN(grid_area, sizeof(float), "gpm.data");
- }
-}
-
-static void multires_reshape_ensure_grids(Mesh *mesh, const int grid_level)
-{
- multires_reshape_ensure_displacement_grids(mesh, grid_level);
- multires_reshape_ensure_mask_grids(mesh, grid_level);
-}
-
-/* Convert normalized coordinate within a grid to a normalized coordinate within
- * a ptex face. */
-static void multires_reshape_corner_coord_to_ptex(const MPoly *coarse_poly,
- const int corner,
- const float corner_u,
- const float corner_v,
- float *r_ptex_face_u,
- float *r_ptex_face_v)
-{
- if (coarse_poly->totloop == 4) {
- float grid_u, grid_v;
- BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
- BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, r_ptex_face_u, r_ptex_face_v);
- }
- else {
- *r_ptex_face_u = corner_u;
- *r_ptex_face_v = corner_v;
- }
-}
-
-/* NOTE: The tangent vectors are measured in ptex face normalized coordinates,
- * which is different from grid tangent. */
-static void multires_reshape_sample_surface(Subdiv *subdiv,
- const MPoly *coarse_poly,
- const int corner,
- const float corner_u,
- const float corner_v,
- const int ptex_face_index,
- float r_P[3],
- float r_dPdu[3],
- float r_dPdv[3])
-{
- float ptex_face_u, ptex_face_v;
- multires_reshape_corner_coord_to_ptex(
- coarse_poly, corner, corner_u, corner_v, &ptex_face_u, &ptex_face_v);
- BKE_subdiv_eval_limit_point_and_derivatives(
- subdiv, ptex_face_index, ptex_face_u, ptex_face_v, r_P, r_dPdu, r_dPdv);
-}
-
-static void multires_reshape_tangent_matrix_for_corner(const MPoly *coarse_poly,
- const int coarse_corner,
- const float dPdu[3],
- const float dPdv[3],
- float r_tangent_matrix[3][3])
-{
- /* For a quad faces we would need to flip the tangent, since they will use
- * use different coordinates within displacement grid comparent to ptex
- * face. */
- const bool is_quad = (coarse_poly->totloop == 4);
- const int tangent_corner = is_quad ? coarse_corner : 0;
- BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, tangent_corner);
-}
-
-static void multires_reshape_vertex_from_final_data(MultiresReshapeContext *ctx,
- const int ptex_face_index,
- const float corner_u,
- const float corner_v,
- const int coarse_poly_index,
- const int coarse_corner,
- const float final_P[3],
- const float final_mask)
-{
- Subdiv *subdiv = ctx->subdiv;
- const int grid_size = ctx->top_grid_size;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- const int loop_index = coarse_poly->loopstart + coarse_corner;
- /* Evaluate limit surface. */
- float P[3], dPdu[3], dPdv[3];
- multires_reshape_sample_surface(
- subdiv, coarse_poly, coarse_corner, corner_u, corner_v, ptex_face_index, P, dPdu, dPdv);
- /* Construct tangent matrix which matches orientation of the current
- * displacement grid. */
- float tangent_matrix[3][3], inv_tangent_matrix[3][3];
- multires_reshape_tangent_matrix_for_corner(
- coarse_poly, coarse_corner, dPdu, dPdv, tangent_matrix);
- invert_m3_m3(inv_tangent_matrix, tangent_matrix);
- /* Convert object coordinate to a tangent space of displacement grid. */
- float D[3];
- sub_v3_v3v3(D, final_P, P);
- float tangent_D[3];
- mul_v3_m3v3(tangent_D, inv_tangent_matrix, D);
- /* Calculate index of element within the grid. */
- float grid_u, grid_v;
- BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
- const int grid_x = (grid_u * (grid_size - 1) + 0.5f);
- const int grid_y = (grid_v * (grid_size - 1) + 0.5f);
- const int index = grid_y * grid_size + grid_x;
- /* Write tangent displacement. */
- MDisps *displacement_grid = &ctx->mdisps[loop_index];
- copy_v3_v3(displacement_grid->disps[index], tangent_D);
- /* Write mask grid. */
- if (ctx->grid_paint_mask != NULL) {
- GridPaintMask *grid_paint_mask = &ctx->grid_paint_mask[loop_index];
- BLI_assert(grid_paint_mask->level == displacement_grid->level);
- grid_paint_mask->data[index] = final_mask;
- }
-}
-
-/* =============================================================================
- * Helpers to propagate displacement to higher levels.
- */
-
-typedef struct MultiresPropagateData {
- /* Number of displacement grids. */
- int num_grids;
- /* Resolution level up to which displacement is known. */
- int reshape_level;
- /* Resolution up to which propagation is happening, affecting all the
- * levels in [reshape_level + 1, top_level]. */
- int top_level;
- /* Grid sizes at the corresponding levels. */
- int reshape_grid_size;
- int top_grid_size;
- /* Keys to access CCG at different levels. */
- CCGKey reshape_level_key;
- CCGKey top_level_key;
- /* Original grid data, before any updates for reshape.
- * Contains data at the reshape_level resolution level. */
- CCGElem **orig_grids_data;
- /* Custom data layers from a coarse mesh. */
- MDisps *mdisps;
- GridPaintMask *grid_paint_mask;
-} MultiresPropagateData;
-
-static CCGElem **allocate_grids(CCGKey *key, int num_grids)
-{
- CCGElem **grids = MEM_calloc_arrayN(num_grids, sizeof(CCGElem *), "reshape grids*");
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- grids[grid_index] = MEM_calloc_arrayN(
- key->elem_size, key->grid_area, "reshape orig_grids_data elems");
- }
- return grids;
-}
-
-static void free_grids(CCGElem **grids, int num_grids)
-{
- if (grids == NULL) {
- return;
- }
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- MEM_freeN(grids[grid_index]);
- }
- MEM_freeN(grids);
-}
-
-/* Initialize element sizes and offsets. */
-static void multires_reshape_init_key_layers(CCGKey *key, const MultiresPropagateData *data)
-{
- key->elem_size = 3 * sizeof(float);
- if (data->grid_paint_mask != NULL) {
- key->mask_offset = 3 * sizeof(float);
- key->elem_size += sizeof(float);
- key->has_mask = true;
- }
- else {
- key->mask_offset = -1;
- key->has_mask = false;
- }
- /* We never have normals in original grids. */
- key->normal_offset = -1;
- key->has_normals = false;
-}
-
-/* Initialize key used to access reshape grids at given level. */
-static void multires_reshape_init_level_key(CCGKey *key,
- const MultiresPropagateData *data,
- const int level)
-{
- key->level = level;
- /* Init layers. */
- multires_reshape_init_key_layers(key, data);
- /* By default, only 3 floats for coordinate, */
- key->grid_size = BKE_subdiv_grid_size_from_level(key->level);
- key->grid_area = key->grid_size * key->grid_size;
- key->grid_bytes = key->elem_size * key->grid_area;
-}
-
-static void multires_reshape_store_original_grids(MultiresPropagateData *data)
-{
- const int num_grids = data->num_grids;
- /* Original data to be backed up. */
- const MDisps *mdisps = data->mdisps;
- const GridPaintMask *grid_paint_mask = data->grid_paint_mask;
- /* Allocate grids for backup. */
- CCGKey *orig_key = &data->reshape_level_key;
- CCGElem **orig_grids_data = allocate_grids(orig_key, num_grids);
- /* Fill in grids. */
- const int orig_grid_size = data->reshape_grid_size;
- const int top_grid_size = data->top_grid_size;
- const int skip = (top_grid_size - 1) / (orig_grid_size - 1);
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- CCGElem *orig_grid = orig_grids_data[grid_index];
- for (int y = 0; y < orig_grid_size; y++) {
- const int top_y = y * skip;
- for (int x = 0; x < orig_grid_size; x++) {
- const int top_x = x * skip;
- const int top_index = top_y * top_grid_size + top_x;
- memcpy(CCG_grid_elem_co(orig_key, orig_grid, x, y),
- mdisps[grid_index].disps[top_index],
- sizeof(float) * 3);
- if (orig_key->has_mask) {
- *CCG_grid_elem_mask(
- orig_key, orig_grid, x, y) = grid_paint_mask[grid_index].data[top_index];
- }
- }
- }
- }
- /* Store in the context. */
- data->orig_grids_data = orig_grids_data;
-}
-
-static void multires_reshape_propagate_prepare(MultiresPropagateData *data,
- Mesh *coarse_mesh,
- const int reshape_level,
- const int top_level)
-{
- BLI_assert(reshape_level <= top_level);
- memset(data, 0, sizeof(*data));
- data->num_grids = coarse_mesh->totloop;
- data->reshape_level = reshape_level;
- data->top_level = top_level;
- if (reshape_level == top_level) {
- /* Nothing to do, reshape will happen on the whole grid content. */
- return;
- }
- data->mdisps = CustomData_get_layer(&coarse_mesh->ldata, CD_MDISPS);
- data->grid_paint_mask = CustomData_get_layer(&coarse_mesh->ldata, CD_GRID_PAINT_MASK);
- data->top_grid_size = BKE_subdiv_grid_size_from_level(top_level);
- data->reshape_grid_size = BKE_subdiv_grid_size_from_level(reshape_level);
- /* Initialize keys to access CCG at different levels. */
- multires_reshape_init_level_key(&data->reshape_level_key, data, data->reshape_level);
- multires_reshape_init_level_key(&data->top_level_key, data, data->top_level);
- /* Make a copy of grids before reshaping, so we can calculate deltas
- * later on. */
- multires_reshape_store_original_grids(data);
-}
-
-static void multires_reshape_propagate_prepare_from_mmd(MultiresPropagateData *data,
- struct Depsgraph *depsgraph,
- Object *object,
- const MultiresModifierData *mmd,
- const int top_level,
- const bool use_render_params)
-{
- /* TODO(sergey): Find mode reliable way of getting current level. */
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Mesh *mesh = object->data;
- const int level = multires_get_level(scene_eval, object, mmd, use_render_params, true);
- multires_reshape_propagate_prepare(data, mesh, level, top_level);
-}
-
-/* Calculate delta of changed reshape level data layers. Delta goes to a
- * grids at top level (meaning, the result grids are only partially filled
- * in). */
-static void multires_reshape_calculate_delta(MultiresPropagateData *data,
- CCGElem **delta_grids_data)
-{
- const int num_grids = data->num_grids;
- /* At this point those custom data layers has updated data for the
- * level we are propagating from. */
- const MDisps *mdisps = data->mdisps;
- const GridPaintMask *grid_paint_mask = data->grid_paint_mask;
- CCGKey *reshape_key = &data->reshape_level_key;
- CCGKey *delta_level_key = &data->top_level_key;
- /* Calculate delta. */
- const int top_grid_size = data->top_grid_size;
- const int reshape_grid_size = data->reshape_grid_size;
- const int delta_grid_size = data->top_grid_size;
- const int skip = (top_grid_size - 1) / (reshape_grid_size - 1);
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- /*const*/ CCGElem *orig_grid = data->orig_grids_data[grid_index];
- CCGElem *delta_grid = delta_grids_data[grid_index];
- for (int y = 0; y < reshape_grid_size; y++) {
- const int top_y = y * skip;
- for (int x = 0; x < reshape_grid_size; x++) {
- const int top_x = x * skip;
- const int top_index = top_y * delta_grid_size + top_x;
- sub_v3_v3v3(CCG_grid_elem_co(delta_level_key, delta_grid, top_x, top_y),
- mdisps[grid_index].disps[top_index],
- CCG_grid_elem_co(reshape_key, orig_grid, x, y));
- if (delta_level_key->has_mask) {
- const float old_mask_value = *CCG_grid_elem_mask(reshape_key, orig_grid, x, y);
- const float new_mask_value = grid_paint_mask[grid_index].data[top_index];
- *CCG_grid_elem_mask(delta_level_key, delta_grid, top_x, top_y) = new_mask_value -
- old_mask_value;
- }
- }
- }
- }
-}
-
-/* Makes it so delta is propagated onto all the higher levels, but is also
- * that this delta is smoothed in a way that it does not cause artifacts on
- * boundaries. */
-
-typedef struct MultiresPropagateCornerData {
- float coord_delta[3];
- float mask_delta;
-} MultiresPropagateCornerData;
-
-BLI_INLINE void multires_reshape_propagate_init_patch_corners(
- MultiresPropagateData *data,
- CCGElem *delta_grid,
- const int patch_x,
- const int patch_y,
- MultiresPropagateCornerData r_corners[4])
-{
- CCGKey *delta_level_key = &data->top_level_key;
- const int orig_grid_size = data->reshape_grid_size;
- const int top_grid_size = data->top_grid_size;
- const int skip = (top_grid_size - 1) / (orig_grid_size - 1);
- const int x = patch_x * skip;
- const int y = patch_y * skip;
- /* Store coordinate deltas. */
- copy_v3_v3(r_corners[0].coord_delta, CCG_grid_elem_co(delta_level_key, delta_grid, x, y));
- copy_v3_v3(r_corners[1].coord_delta, CCG_grid_elem_co(delta_level_key, delta_grid, x + skip, y));
- copy_v3_v3(r_corners[2].coord_delta, CCG_grid_elem_co(delta_level_key, delta_grid, x, y + skip));
- copy_v3_v3(r_corners[3].coord_delta,
- CCG_grid_elem_co(delta_level_key, delta_grid, x + skip, y + skip));
- if (delta_level_key->has_mask) {
- r_corners[0].mask_delta = *CCG_grid_elem_mask(delta_level_key, delta_grid, x, y);
- r_corners[1].mask_delta = *CCG_grid_elem_mask(delta_level_key, delta_grid, x + skip, y);
- r_corners[2].mask_delta = *CCG_grid_elem_mask(delta_level_key, delta_grid, x, y + skip);
- r_corners[3].mask_delta = *CCG_grid_elem_mask(delta_level_key, delta_grid, x + skip, y + skip);
- }
-}
-
-BLI_INLINE void multires_reshape_propagate_interpolate_coord(
- float delta[3], const MultiresPropagateCornerData corners[4], const float weights[4])
-{
- interp_v3_v3v3v3v3(delta,
- corners[0].coord_delta,
- corners[1].coord_delta,
- corners[2].coord_delta,
- corners[3].coord_delta,
- weights);
-}
-
-BLI_INLINE float multires_reshape_propagate_interpolate_mask(
- const MultiresPropagateCornerData corners[4], const float weights[4])
-{
- return corners[0].mask_delta * weights[0] + corners[1].mask_delta * weights[1] +
- corners[2].mask_delta * weights[2] + corners[3].mask_delta * weights[3];
-}
-
-BLI_INLINE void multires_reshape_propagate_and_smooth_delta_grid_patch(MultiresPropagateData *data,
- CCGElem *delta_grid,
- const int patch_x,
- const int patch_y)
-{
- CCGKey *delta_level_key = &data->top_level_key;
- const int orig_grid_size = data->reshape_grid_size;
- const int top_grid_size = data->top_grid_size;
- const int skip = (top_grid_size - 1) / (orig_grid_size - 1);
- const float skip_inv = 1.0f / (float)skip;
- MultiresPropagateCornerData corners[4];
- multires_reshape_propagate_init_patch_corners(data, delta_grid, patch_x, patch_y, corners);
- const int start_x = patch_x * skip;
- const int start_y = patch_y * skip;
- for (int y = 0; y <= skip; y++) {
- const float v = (float)y * skip_inv;
- const int final_y = start_y + y;
- for (int x = 0; x <= skip; x++) {
- const float u = (float)x * skip_inv;
- const int final_x = start_x + x;
- const float linear_weights[4] = {
- (1.0f - u) * (1.0f - v), u * (1.0f - v), (1.0f - u) * v, u * v};
- multires_reshape_propagate_interpolate_coord(
- CCG_grid_elem_co(delta_level_key, delta_grid, final_x, final_y),
- corners,
- linear_weights);
- if (delta_level_key->has_mask) {
- float *mask = CCG_grid_elem_mask(delta_level_key, delta_grid, final_x, final_y);
- *mask = multires_reshape_propagate_interpolate_mask(corners, linear_weights);
- }
- }
- }
-}
-
-BLI_INLINE void multires_reshape_propagate_and_smooth_delta_grid(MultiresPropagateData *data,
- CCGElem *delta_grid)
-{
- const int orig_grid_size = data->reshape_grid_size;
- for (int patch_y = 0; patch_y < orig_grid_size - 1; patch_y++) {
- for (int patch_x = 0; patch_x < orig_grid_size - 1; patch_x++) {
- multires_reshape_propagate_and_smooth_delta_grid_patch(data, delta_grid, patch_x, patch_y);
- }
- }
-}
-
-/* Entry point to propagate+smooth. */
-static void multires_reshape_propagate_and_smooth_delta(MultiresPropagateData *data,
- CCGElem **delta_grids_data)
-{
- const int num_grids = data->num_grids;
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- CCGElem *delta_grid = delta_grids_data[grid_index];
- multires_reshape_propagate_and_smooth_delta_grid(data, delta_grid);
- }
-}
-
-/* Apply smoothed deltas on the actual data layers. */
-static void multires_reshape_propagate_apply_delta(MultiresPropagateData *data,
- CCGElem **delta_grids_data)
-{
- const int num_grids = data->num_grids;
- /* At this point those custom data layers has updated data for the
- * level we are propagating from. */
- MDisps *mdisps = data->mdisps;
- GridPaintMask *grid_paint_mask = data->grid_paint_mask;
- CCGKey *orig_key = &data->reshape_level_key;
- CCGKey *delta_level_key = &data->top_level_key;
- CCGElem **orig_grids_data = data->orig_grids_data;
- const int orig_grid_size = data->reshape_grid_size;
- const int top_grid_size = data->top_grid_size;
- const int skip = (top_grid_size - 1) / (orig_grid_size - 1);
- /* Restore grid values at the reshape level. Those values are to be changed
- * to the accommodate for the smooth delta. */
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- CCGElem *orig_grid = orig_grids_data[grid_index];
- for (int y = 0; y < orig_grid_size; y++) {
- const int top_y = y * skip;
- for (int x = 0; x < orig_grid_size; x++) {
- const int top_x = x * skip;
- const int top_index = top_y * top_grid_size + top_x;
- copy_v3_v3(mdisps[grid_index].disps[top_index],
- CCG_grid_elem_co(orig_key, orig_grid, x, y));
- if (grid_paint_mask != NULL) {
- grid_paint_mask[grid_index].data[top_index] = *CCG_grid_elem_mask(
- orig_key, orig_grid, x, y);
- }
- }
- }
- }
- /* Add smoothed delta to all the levels. */
- for (int grid_index = 0; grid_index < num_grids; grid_index++) {
- CCGElem *delta_grid = delta_grids_data[grid_index];
- for (int y = 0; y < top_grid_size; y++) {
- for (int x = 0; x < top_grid_size; x++) {
- const int top_index = y * top_grid_size + x;
- add_v3_v3(mdisps[grid_index].disps[top_index],
- CCG_grid_elem_co(delta_level_key, delta_grid, x, y));
- if (delta_level_key->has_mask) {
- grid_paint_mask[grid_index].data[top_index] += *CCG_grid_elem_mask(
- delta_level_key, delta_grid, x, y);
- }
- }
- }
- }
-}
-
-static void multires_reshape_propagate(MultiresPropagateData *data)
-{
- if (data->reshape_level == data->top_level) {
- return;
- }
- const int num_grids = data->num_grids;
- /* Calculate delta made at the reshape level. */
- CCGKey *delta_level_key = &data->top_level_key;
- CCGElem **delta_grids_data = allocate_grids(delta_level_key, num_grids);
- multires_reshape_calculate_delta(data, delta_grids_data);
- /* Propagate deltas to the higher levels. */
- multires_reshape_propagate_and_smooth_delta(data, delta_grids_data);
- /* Finally, apply smoothed deltas. */
- multires_reshape_propagate_apply_delta(data, delta_grids_data);
- /* Cleanup. */
- free_grids(delta_grids_data, num_grids);
-}
-
-static void multires_reshape_propagate_free(MultiresPropagateData *data)
-{
- free_grids(data->orig_grids_data, data->num_grids);
-}
-
-/* =============================================================================
- * Reshape from deformed vertex coordinates.
- */
-
-typedef struct MultiresReshapeFromDeformedVertsContext {
- MultiresReshapeContext reshape_ctx;
- const float (*deformed_verts)[3];
- int num_deformed_verts;
-} MultiresReshapeFromDeformedVertsContext;
-
-static bool multires_reshape_topology_info(const SubdivForeachContext *foreach_context,
- const int num_vertices,
- const int UNUSED(num_edges),
- const int UNUSED(num_loops),
- const int UNUSED(num_polygons))
-{
- MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
- if (num_vertices != ctx->num_deformed_verts) {
- return false;
- }
- return true;
-}
-
-/* Will run reshaping for all grid elements which are adjacent to the given
- * one. This is the way to ensure continuity of displacement stored in the
- * grids across the inner boundaries of the grids. */
-static void multires_reshape_neighour_boundary_vertices(MultiresReshapeContext *ctx,
- const int UNUSED(ptex_face_index),
- const float corner_u,
- const float corner_v,
- const int coarse_poly_index,
- const int coarse_corner,
- const float final_P[3],
- const float final_mask)
-{
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- const int num_corners = coarse_poly->totloop;
- const int start_ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
- const bool is_quad = (coarse_poly->totloop == 4);
- if (corner_u == 1.0f && corner_v == 1.0f) {
- for (int current_corner = 0; current_corner < num_corners; current_corner++) {
- if (current_corner == coarse_corner) {
- continue;
- }
- const int current_ptex_face_index = is_quad ? start_ptex_face_index :
- start_ptex_face_index + current_corner;
- multires_reshape_vertex_from_final_data(ctx,
- current_ptex_face_index,
- 1.0f,
- 1.0f,
- coarse_poly_index,
- current_corner,
- final_P,
- final_mask);
- }
- }
- else if (corner_u == 1.0f) {
- const float next_corner_index = (coarse_corner + 1) % num_corners;
- const float next_corner_u = corner_v;
- const float next_corner_v = 1.0f;
- const int next_ptex_face_index = is_quad ? start_ptex_face_index :
- start_ptex_face_index + next_corner_index;
- multires_reshape_vertex_from_final_data(ctx,
- next_ptex_face_index,
- next_corner_u,
- next_corner_v,
- coarse_poly_index,
- next_corner_index,
- final_P,
- final_mask);
- }
- else if (corner_v == 1.0f) {
- const float prev_corner_index = (coarse_corner + num_corners - 1) % num_corners;
- const float prev_corner_u = 1.0f;
- const float prev_corner_v = corner_u;
- const int prev_ptex_face_index = is_quad ? start_ptex_face_index :
- start_ptex_face_index + prev_corner_index;
- multires_reshape_vertex_from_final_data(ctx,
- prev_ptex_face_index,
- prev_corner_u,
- prev_corner_v,
- coarse_poly_index,
- prev_corner_index,
- final_P,
- final_mask);
- }
-}
-
-static void multires_reshape_vertex(MultiresReshapeFromDeformedVertsContext *ctx,
- const int ptex_face_index,
- const float u,
- const float v,
- const int coarse_poly_index,
- const int coarse_corner,
- const int subdiv_vertex_index)
-{
- const float *final_P = ctx->deformed_verts[subdiv_vertex_index];
- const Mesh *coarse_mesh = ctx->reshape_ctx.coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- const bool is_quad = (coarse_poly->totloop == 4);
- float corner_u, corner_v;
- int actual_coarse_corner;
- if (is_quad) {
- actual_coarse_corner = BKE_subdiv_rotate_quad_to_corner(u, v, &corner_u, &corner_v);
- }
- else {
- actual_coarse_corner = coarse_corner;
- corner_u = u;
- corner_v = v;
- }
- multires_reshape_vertex_from_final_data(&ctx->reshape_ctx,
- ptex_face_index,
- corner_u,
- corner_v,
- coarse_poly_index,
- actual_coarse_corner,
- final_P,
- 0.0f);
- multires_reshape_neighour_boundary_vertices(&ctx->reshape_ctx,
- ptex_face_index,
- corner_u,
- corner_v,
- coarse_poly_index,
- actual_coarse_corner,
- final_P,
- 0.0f);
-}
-
-static void multires_reshape_vertex_inner(const SubdivForeachContext *foreach_context,
- void *UNUSED(tls_v),
- const int ptex_face_index,
- const float u,
- const float v,
- const int coarse_poly_index,
- const int coarse_corner,
- const int subdiv_vertex_index)
-{
- MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
- multires_reshape_vertex(
- ctx, ptex_face_index, u, v, coarse_poly_index, coarse_corner, subdiv_vertex_index);
-}
-
-static void multires_reshape_vertex_every_corner(
- const struct SubdivForeachContext *foreach_context,
- void *UNUSED(tls_v),
- const int ptex_face_index,
- const float u,
- const float v,
- const int UNUSED(coarse_vertex_index),
- const int coarse_poly_index,
- const int coarse_corner,
- const int subdiv_vertex_index)
-{
- MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
- multires_reshape_vertex(
- ctx, ptex_face_index, u, v, coarse_poly_index, coarse_corner, subdiv_vertex_index);
-}
-
-static void multires_reshape_vertex_every_edge(const struct SubdivForeachContext *foreach_context,
- void *UNUSED(tls_v),
- const int ptex_face_index,
- const float u,
- const float v,
- const int UNUSED(coarse_edge_index),
- const int coarse_poly_index,
- const int coarse_corner,
- const int subdiv_vertex_index)
-{
- MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
- multires_reshape_vertex(
- ctx, ptex_face_index, u, v, coarse_poly_index, coarse_corner, subdiv_vertex_index);
-}
-
-static Subdiv *multires_create_subdiv_for_reshape(struct Depsgraph *depsgraph,
- /*const*/ Object *object,
- const MultiresModifierData *mmd)
-{
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
- Mesh *deformed_mesh = mesh_get_eval_deform(
- depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
- SubdivSettings subdiv_settings;
- BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
- Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, deformed_mesh);
- if (!BKE_subdiv_eval_update_from_mesh(subdiv, deformed_mesh, NULL)) {
- BKE_subdiv_free(subdiv);
- return NULL;
- }
- return subdiv;
-}
-
-static bool multires_reshape_from_vertcos(struct Depsgraph *depsgraph,
- Object *object,
- const MultiresModifierData *mmd,
- const float (*deformed_verts)[3],
- const int num_deformed_verts,
- const bool use_render_params)
-{
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Mesh *coarse_mesh = object->data;
- MDisps *mdisps = CustomData_get_layer(&coarse_mesh->ldata, CD_MDISPS);
- /* Pick maximum between multires level and displacement level.
- * This is because mesh can be used by objects with multires at different
- * levels.
- *
- * TODO(sergey): At this point it should be possible to always use
- * mdisps->level. */
- const int top_level = max_ii(mmd->totlvl, mdisps->level);
- /* Make sure displacement grids are ready. */
- multires_reshape_ensure_grids(coarse_mesh, top_level);
- /* Initialize subdivision surface. */
- Subdiv *subdiv = multires_create_subdiv_for_reshape(depsgraph, object, mmd);
- if (subdiv == NULL) {
- return false;
- }
- /* Construct context. */
- MultiresReshapeFromDeformedVertsContext reshape_deformed_verts_ctx = {
- .reshape_ctx =
- {
- .subdiv = subdiv,
- .coarse_mesh = coarse_mesh,
- .mdisps = mdisps,
- .grid_paint_mask = NULL,
- .top_grid_size = BKE_subdiv_grid_size_from_level(top_level),
- .top_level = top_level,
- .face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv),
- },
- .deformed_verts = deformed_verts,
- .num_deformed_verts = num_deformed_verts,
- };
- SubdivForeachContext foreach_context = {
- .topology_info = multires_reshape_topology_info,
- .vertex_inner = multires_reshape_vertex_inner,
- .vertex_every_edge = multires_reshape_vertex_every_edge,
- .vertex_every_corner = multires_reshape_vertex_every_corner,
- .user_data = &reshape_deformed_verts_ctx,
- };
- /* Initialize mesh rasterization settings. */
- SubdivToMeshSettings mesh_settings;
- BKE_multires_subdiv_mesh_settings_init(
- &mesh_settings, scene_eval, object, mmd, use_render_params, true);
- /* Initialize propagation to higher levels. */
- MultiresPropagateData propagate_data;
- multires_reshape_propagate_prepare_from_mmd(
- &propagate_data, depsgraph, object, mmd, top_level, use_render_params);
- /* Run all the callbacks. */
- BKE_subdiv_foreach_subdiv_geometry(subdiv, &foreach_context, &mesh_settings, coarse_mesh);
- BKE_subdiv_free(subdiv);
- /* Update higher levels if needed. */
- multires_reshape_propagate(&propagate_data);
- multires_reshape_propagate_free(&propagate_data);
- return true;
-}
-
-/* =============================================================================
- * Reshape from object.
- */
-
-/* Returns truth on success, false otherwise.
- *
- * This function might fail in cases like source and destination not having
- * matched amount of vertices. */
-bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph,
- MultiresModifierData *mmd,
- Object *dst,
- Object *src)
-{
- /* Would be cool to support this eventually, but it is very tricky to match
- * vertices order even for meshes, when mixing meshes and other objects it's
- * even more tricky. */
- if (src->type != OB_MESH) {
- return false;
- }
- MultiresModifierData reshape_mmd;
- multires_reshape_init_mmd(&reshape_mmd, mmd);
- /* Get evaluated vertices locations to reshape to. */
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *src_eval = DEG_get_evaluated_object(depsgraph, src);
- Mesh *src_mesh_eval = mesh_get_eval_final(depsgraph, scene_eval, src_eval, &CD_MASK_BAREMESH);
- int num_deformed_verts;
- float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(src_mesh_eval, &num_deformed_verts);
- bool result = multires_reshape_from_vertcos(
- depsgraph, dst, &reshape_mmd, deformed_verts, num_deformed_verts, false);
- MEM_freeN(deformed_verts);
- return result;
-}
-
-/* =============================================================================
- * Reshape from modifier.
- */
-
-bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph,
- MultiresModifierData *mmd,
- Object *object,
- ModifierData *md)
-{
- MultiresModifierData highest_mmd;
- /* It is possible that the current subdivision level of multires is lower
- * that it's maximum possible one (i.e., viewport is set to a lower level
- * for the performance purposes). But even then, we want all the multires
- * levels to be reshaped. Most accurate way to do so is to ignore all
- * simplifications and calculate deformation modifier for the highest
- * possible multires level.
- * Alternative would be propagate displacement from current level to a
- * higher ones, but that is likely to cause artifacts. */
- multires_reshape_init_mmd_top_level(&highest_mmd, mmd);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- /* Perform sanity checks and early output. */
- if (multires_get_level(scene_eval, object, &highest_mmd, false, true) == 0) {
- return false;
- }
- /* Create mesh for the multires, ignoring any further modifiers (leading
- * deformation modifiers will be applied though). */
- Mesh *multires_mesh = BKE_multires_create_mesh(depsgraph, scene_eval, &highest_mmd, object);
- int num_deformed_verts;
- float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(multires_mesh, &num_deformed_verts);
- /* Apply deformation modifier on the multires, */
- const ModifierEvalContext modifier_ctx = {
- .depsgraph = depsgraph,
- .object = object,
- .flag = MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY,
- };
- modwrap_deformVerts(md, &modifier_ctx, multires_mesh, deformed_verts, multires_mesh->totvert);
- BKE_id_free(NULL, multires_mesh);
- /* Reshaping */
- bool result = multires_reshape_from_vertcos(
- depsgraph, object, &highest_mmd, deformed_verts, num_deformed_verts, false);
- /* Cleanup */
- MEM_freeN(deformed_verts);
- return result;
-}
-
-/* =============================================================================
- * Reshape from grids.
- */
-
-typedef struct ReshapeFromCCGTaskData {
- MultiresReshapeContext reshape_ctx;
- const CCGKey *key;
- /*const*/ CCGElem **grids;
-} ReshapeFromCCGTaskData;
-
-static void reshape_from_ccg_task(void *__restrict userdata,
- const int coarse_poly_index,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- ReshapeFromCCGTaskData *data = userdata;
- const CCGKey *key = data->key;
- /*const*/ CCGElem **grids = data->grids;
- const Mesh *coarse_mesh = data->reshape_ctx.coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- const int key_grid_size = key->grid_size;
- const int key_grid_size_1 = key_grid_size - 1;
- const int resolution = key_grid_size;
- const float resolution_1_inv = 1.0f / (float)(resolution - 1);
- const int start_ptex_face_index = data->reshape_ctx.face_ptex_offset[coarse_poly_index];
- const bool is_quad = (coarse_poly->totloop == 4);
- for (int corner = 0; corner < coarse_poly->totloop; corner++) {
- for (int y = 0; y < resolution; y++) {
- const float corner_v = y * resolution_1_inv;
- for (int x = 0; x < resolution; x++) {
- const float corner_u = x * resolution_1_inv;
- /* Quad faces consists of a single ptex face. */
- const int ptex_face_index = is_quad ? start_ptex_face_index :
- start_ptex_face_index + corner;
- float grid_u, grid_v;
- BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
- /*const*/ CCGElem *grid = grids[coarse_poly->loopstart + corner];
- /*const*/ CCGElem *grid_element = CCG_grid_elem(
- key, grid, key_grid_size_1 * grid_u, key_grid_size_1 * grid_v);
- const float *final_P = CCG_elem_co(key, grid_element);
- float final_mask = 0.0f;
- if (key->has_mask) {
- final_mask = *CCG_elem_mask(key, grid_element);
- }
- multires_reshape_vertex_from_final_data(&data->reshape_ctx,
- ptex_face_index,
- corner_u,
- corner_v,
- coarse_poly_index,
- corner,
- final_P,
- final_mask);
- }
- }
- }
-}
-
-bool multiresModifier_reshapeFromCCG(const int tot_level, Mesh *coarse_mesh, SubdivCCG *subdiv_ccg)
-{
- CCGKey key;
- BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
- /* Sanity checks. */
- if (coarse_mesh->totloop != subdiv_ccg->num_grids) {
- /* Grids are supposed to eb created for each face-cornder (aka loop). */
- return false;
- }
- MDisps *mdisps = CustomData_get_layer(&coarse_mesh->ldata, CD_MDISPS);
- if (mdisps == NULL) {
- /* Multires displacement has been removed before current changes were
- * applies to all the levels. */
- return false;
- }
- GridPaintMask *grid_paint_mask = CustomData_get_layer(&coarse_mesh->ldata, CD_GRID_PAINT_MASK);
- Subdiv *subdiv = subdiv_ccg->subdiv;
- /* Pick maximum between multires level and displacement level.
- * This is because mesh can be used by objects with multires at different
- * levels.
- *
- * TODO(sergey): At this point it should be possible to always use
- * mdisps->level. */
- const int top_level = max_ii(tot_level, mdisps->level);
- /* Make sure displacement grids are ready. */
- multires_reshape_ensure_grids(coarse_mesh, top_level);
- /* Construct context. */
- ReshapeFromCCGTaskData data = {
- .reshape_ctx =
- {
- .subdiv = subdiv,
- .coarse_mesh = coarse_mesh,
- .mdisps = mdisps,
- .grid_paint_mask = grid_paint_mask,
- .top_grid_size = BKE_subdiv_grid_size_from_level(top_level),
- .top_level = top_level,
- .face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv),
- },
- .key = &key,
- .grids = subdiv_ccg->grids,
- };
- /* Initialize propagation to higher levels. */
- MultiresPropagateData propagate_data;
- multires_reshape_propagate_prepare(&propagate_data, coarse_mesh, key.level, top_level);
- /* Threaded grids iteration. */
- TaskParallelSettings parallel_range_settings;
- BLI_parallel_range_settings_defaults(&parallel_range_settings);
- BLI_task_parallel_range(
- 0, coarse_mesh->totpoly, &data, reshape_from_ccg_task, &parallel_range_settings);
- /* Update higher levels if needed. */
- multires_reshape_propagate(&propagate_data);
- multires_reshape_propagate_free(&propagate_data);
- return true;
-}
diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c
new file mode 100644
index 00000000000..0a9a17d7bd8
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c
@@ -0,0 +1,1064 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "multires_reshape.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+#include "BLI_task.h"
+
+#include "BKE_multires.h"
+#include "BKE_subdiv.h"
+#include "BKE_subdiv_eval.h"
+#include "BKE_subdiv_foreach.h"
+#include "BKE_subdiv_mesh.h"
+
+#include "opensubdiv_converter_capi.h"
+#include "opensubdiv_evaluator_capi.h"
+#include "opensubdiv_topology_refiner_capi.h"
+
+#include "subdiv_converter.h"
+
+typedef struct SurfacePoint {
+ float P[3];
+ float tangent_matrix[3][3];
+} SurfacePoint;
+
+typedef struct SurfaceGrid {
+ SurfacePoint *points;
+} SurfaceGrid;
+
+typedef struct Vertex {
+ /* All grid coordinates which the vertex corresponding to.
+ * For a vertices which are created from inner points of grids there is always one coordinate. */
+ int num_grid_coords;
+ GridCoord *grid_coords;
+
+ bool is_infinite_sharp;
+} Vertex;
+
+typedef struct Corner {
+ const Vertex *vertex;
+ int grid_index;
+} Corner;
+
+typedef struct Dace {
+ int start_corner_index;
+ int num_corners;
+} Dace;
+
+typedef struct MultiresReshapeSmoothContext {
+ const MultiresReshapeContext *reshape_context;
+
+ // Geometry at a reshape multires level.
+ struct {
+ int num_vertices;
+ Vertex *vertices;
+
+ int num_corners;
+ Corner *corners;
+
+ int num_faces;
+ Dace *faces;
+ } geometry;
+
+ /* Subdivision surface created for geometry at a reshape level. */
+ Subdiv *reshape_subdiv;
+
+ SurfaceGrid *base_surface_grids;
+} MultiresReshapeSmoothContext;
+
+/* ================================================================================================
+ * Masks.
+ */
+
+/* Interpolate mask grid at a reshape level.
+ * Will return 0 if there is no masks custom data layer. */
+static float interpolate_masks_grid(const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const GridCoord *grid_coord)
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+ if (reshape_context->grid_paint_masks == NULL) {
+ return 0.0f;
+ }
+
+ const GridPaintMask *grid = &reshape_context->orig.grid_paint_masks[grid_coord->grid_index];
+ const int grid_size = BKE_subdiv_grid_size_from_level(grid->level);
+ const int grid_size_1 = grid_size - 1;
+ const float grid_size_1_inv = 1.0f / (float)(grid_size_1);
+
+ const float x_f = grid_coord->u * grid_size_1;
+ const float y_f = grid_coord->v * grid_size_1;
+
+ const int x_i = x_f;
+ const int y_i = y_f;
+ const int x_n_i = (x_i == grid_size - 1) ? (x_i) : (x_i + 1);
+ const int y_n_i = (y_i == grid_size - 1) ? (y_i) : (y_i + 1);
+
+ const int corners[4][2] = {{x_i, y_i}, {x_n_i, y_i}, {x_n_i, y_n_i}, {x_i, y_n_i}};
+ float mask_elements[4];
+ for (int i = 0; i < 4; ++i) {
+ GridCoord corner_grid_coord;
+ corner_grid_coord.grid_index = grid_coord->grid_index;
+ corner_grid_coord.u = corners[i][0] * grid_size_1_inv;
+ corner_grid_coord.v = corners[i][1] * grid_size_1_inv;
+
+ ReshapeConstGridElement element = multires_reshape_orig_grid_element_for_grid_coord(
+ reshape_context, &corner_grid_coord);
+ mask_elements[i] = element.mask;
+ }
+
+ const float u = x_f - x_i;
+ const float v = y_f - y_i;
+ const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), (1.0f - u) * v, u * v};
+
+ return mask_elements[0] * weights[0] + mask_elements[1] * weights[1] +
+ mask_elements[2] * weights[2] + mask_elements[3] * weights[3];
+}
+
+/* ================================================================================================
+ * Surface.
+ */
+
+static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ const int num_grids = reshape_context->num_grids;
+ const int grid_size = reshape_context->top.grid_size;
+ const int grid_area = grid_size * grid_size;
+
+ SurfaceGrid *surface_grid = MEM_malloc_arrayN(num_grids, sizeof(SurfaceGrid), "delta grids");
+
+ for (int grid_index = 0; grid_index < num_grids; ++grid_index) {
+ surface_grid[grid_index].points = MEM_calloc_arrayN(
+ sizeof(SurfacePoint), grid_area, "delta grid dispalcement");
+ }
+
+ reshape_smooth_context->base_surface_grids = surface_grid;
+}
+
+static void base_surface_grids_free(MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ if (reshape_smooth_context->base_surface_grids == NULL) {
+ return;
+ }
+
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ const int num_grids = reshape_context->num_grids;
+ for (int grid_index = 0; grid_index < num_grids; ++grid_index) {
+ MEM_freeN(reshape_smooth_context->base_surface_grids[grid_index].points);
+ }
+ MEM_freeN(reshape_smooth_context->base_surface_grids);
+}
+
+static SurfacePoint *base_surface_grids_read(
+ const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord)
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ const int grid_index = grid_coord->grid_index;
+ const int grid_size = reshape_context->top.grid_size;
+ const int grid_x = lround(grid_coord->u * (grid_size - 1));
+ const int grid_y = lround(grid_coord->v * (grid_size - 1));
+ const int grid_element_index = grid_y * grid_size + grid_x;
+
+ SurfaceGrid *surface_grid = &reshape_smooth_context->base_surface_grids[grid_index];
+ return &surface_grid->points[grid_element_index];
+}
+
+static void base_surface_grids_write(const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const GridCoord *grid_coord,
+ float P[3],
+ float tangent_matrix[3][3])
+{
+ SurfacePoint *point = base_surface_grids_read(reshape_smooth_context, grid_coord);
+ copy_v3_v3(point->P, P);
+ copy_m3_m3(point->tangent_matrix, tangent_matrix);
+}
+
+/* ================================================================================================
+ * Evaluation of subdivision surface at a reshape level.
+ */
+
+typedef void (*ForeachTopLevelGridCoordCallback)(
+ const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const PTexCoord *ptex_coord,
+ const GridCoord *grid_coord,
+ void *userdata_v);
+
+typedef struct ForeachTopLevelGridCoordTaskData {
+ const MultiresReshapeSmoothContext *reshape_smooth_context;
+
+ int inner_grid_size;
+ float inner_grid_size_1_inv;
+
+ ForeachTopLevelGridCoordCallback callback;
+ void *callback_userdata_v;
+} ForeachHighLevelCoordTaskData;
+
+/* Find grid index which given face was created for. */
+static int get_face_grid_index(const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const Dace *face)
+{
+ const Corner *first_corner = &reshape_smooth_context->geometry.corners[face->start_corner_index];
+ const int grid_index = first_corner->grid_index;
+
+#ifndef NDEBUG
+ for (int face_corner = 0; face_corner < face->num_corners; ++face_corner) {
+ const int corner_index = face->start_corner_index + face_corner;
+ const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
+ BLI_assert(corner->grid_index == grid_index);
+ }
+#endif
+
+ return grid_index;
+}
+
+static GridCoord *vertex_grid_coord_with_grid_index(const Vertex *vertex, const int grid_index)
+{
+ for (int i = 0; i < vertex->num_grid_coords; ++i) {
+ if (vertex->grid_coords[i].grid_index == grid_index) {
+ return &vertex->grid_coords[i];
+ }
+ }
+ return NULL;
+}
+
+/* Get grid coordinates which correspond to corners of the given face.
+ * All the grid coordinates will be from the same grid index. */
+static void grid_coords_from_face_vertices(
+ const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const Dace *face,
+ const GridCoord *grid_coords[])
+{
+ BLI_assert(face->num_corners == 4);
+
+ const int grid_index = get_face_grid_index(reshape_smooth_context, face);
+ BLI_assert(grid_index != -1);
+
+ for (int i = 0; i < face->num_corners; ++i) {
+ const int corner_index = face->start_corner_index + i;
+ const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
+ grid_coords[i] = vertex_grid_coord_with_grid_index(corner->vertex, grid_index);
+ BLI_assert(grid_coords[i] != NULL);
+ }
+}
+
+static float lerp(float t, float a, float b)
+{
+ return (a + t * (b - a));
+}
+
+static void interpolate_grid_coord(GridCoord *result,
+ const GridCoord *face_grid_coords[4],
+ const float u,
+ const float v)
+{
+ /*
+ * v
+ * ^
+ * | (3) -------- (2)
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | (0) -------- (1)
+ * *--------------------------> u
+ */
+
+ const float u01 = lerp(u, face_grid_coords[0]->u, face_grid_coords[1]->u);
+ const float u32 = lerp(u, face_grid_coords[3]->u, face_grid_coords[2]->u);
+
+ const float v03 = lerp(v, face_grid_coords[0]->v, face_grid_coords[3]->v);
+ const float v12 = lerp(v, face_grid_coords[1]->v, face_grid_coords[2]->v);
+
+ result->grid_index = face_grid_coords[0]->grid_index;
+ result->u = lerp(v, u01, u32);
+ result->v = lerp(u, v03, v12);
+}
+
+static void foreach_toplevel_grid_coord_task(void *__restrict userdata_v,
+ const int face_index,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ ForeachHighLevelCoordTaskData *data = userdata_v;
+
+ const MultiresReshapeSmoothContext *reshape_smooth_context = data->reshape_smooth_context;
+ const int inner_grid_size = data->inner_grid_size;
+ const float inner_grid_size_1_inv = data->inner_grid_size_1_inv;
+
+ const Dace *face = &reshape_smooth_context->geometry.faces[face_index];
+ const GridCoord *face_grid_coords[4];
+ grid_coords_from_face_vertices(reshape_smooth_context, face, face_grid_coords);
+
+ for (int y = 0; y < inner_grid_size; ++y) {
+ const float ptex_v = (float)y * inner_grid_size_1_inv;
+ for (int x = 0; x < inner_grid_size; ++x) {
+ const float ptex_u = (float)x * inner_grid_size_1_inv;
+
+ PTexCoord ptex_coord;
+ ptex_coord.ptex_face_index = face_index;
+ ptex_coord.u = ptex_u;
+ ptex_coord.v = ptex_v;
+
+ GridCoord grid_coord;
+ interpolate_grid_coord(&grid_coord, face_grid_coords, ptex_u, ptex_v);
+
+ data->callback(reshape_smooth_context, &ptex_coord, &grid_coord, data->callback_userdata_v);
+ }
+ }
+}
+
+static void foreach_toplevel_grid_coord(const MultiresReshapeSmoothContext *reshape_smooth_context,
+ ForeachTopLevelGridCoordCallback callback,
+ void *callback_userdata_v)
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+ const int level_difference = (reshape_context->top.level - reshape_context->reshape.level);
+
+ ForeachHighLevelCoordTaskData data;
+ data.reshape_smooth_context = reshape_smooth_context;
+ data.inner_grid_size = (1 << level_difference) + 1;
+ data.inner_grid_size_1_inv = 1.0f / (float)(data.inner_grid_size - 1);
+ data.callback = callback;
+ data.callback_userdata_v = callback_userdata_v;
+
+ TaskParallelSettings parallel_range_settings;
+ BLI_parallel_range_settings_defaults(&parallel_range_settings);
+ parallel_range_settings.min_iter_per_thread = 1;
+
+ const int num_faces = reshape_smooth_context->geometry.num_faces;
+ BLI_task_parallel_range(
+ 0, num_faces, &data, foreach_toplevel_grid_coord_task, &parallel_range_settings);
+}
+
+/* ================================================================================================
+ * Generation of a topology information for OpenSubdiv converter.
+ *
+ * Calculates vertices, their coordinates in the original grids, and connections of them so then
+ * it's easy to create OpenSubdiv's topology refiner. */
+
+static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context,
+ const MultiresReshapeContext *reshape_context)
+{
+ reshape_smooth_context->reshape_context = reshape_context;
+
+ reshape_smooth_context->geometry.num_vertices = 0;
+ reshape_smooth_context->geometry.vertices = NULL;
+ reshape_smooth_context->geometry.num_corners = 0;
+ reshape_smooth_context->geometry.corners = NULL;
+
+ reshape_smooth_context->reshape_subdiv = NULL;
+ reshape_smooth_context->base_surface_grids = NULL;
+}
+
+static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ if (reshape_smooth_context->geometry.vertices != NULL) {
+ for (int i = 0; i < reshape_smooth_context->geometry.num_vertices; ++i) {
+ MEM_SAFE_FREE(reshape_smooth_context->geometry.vertices[i].grid_coords);
+ }
+ }
+ MEM_SAFE_FREE(reshape_smooth_context->geometry.vertices);
+ MEM_SAFE_FREE(reshape_smooth_context->geometry.corners);
+ MEM_SAFE_FREE(reshape_smooth_context->geometry.faces);
+}
+
+static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ if (reshape_smooth_context->reshape_subdiv == NULL) {
+ return;
+ }
+ BKE_subdiv_free(reshape_smooth_context->reshape_subdiv);
+}
+
+static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ context_free_geometry(reshape_smooth_context);
+ context_free_subdiv(reshape_smooth_context);
+ base_surface_grids_free(reshape_smooth_context);
+}
+
+static bool foreach_topology_info(const SubdivForeachContext *foreach_context,
+ const int num_vertices,
+ const int UNUSED(num_edges),
+ const int num_loops,
+ const int num_polygons)
+{
+ MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
+
+ /* NOTE: Calloc so the counters are re-set to 0 "for free". */
+ reshape_smooth_context->geometry.num_vertices = num_vertices;
+ reshape_smooth_context->geometry.vertices = MEM_calloc_arrayN(
+ sizeof(Vertex), num_vertices, "smooth vertices");
+
+ reshape_smooth_context->geometry.num_corners = num_loops;
+ reshape_smooth_context->geometry.corners = MEM_malloc_arrayN(
+ sizeof(Corner), num_loops, "smooth corners");
+
+ reshape_smooth_context->geometry.num_faces = num_polygons;
+ reshape_smooth_context->geometry.faces = MEM_malloc_arrayN(
+ sizeof(Dace), num_polygons, "smooth faces");
+
+ return true;
+}
+
+static void foreach_single_vertex(const SubdivForeachContext *foreach_context,
+ const GridCoord *grid_coord,
+ const int subdiv_vertex_index)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
+
+ BLI_assert(subdiv_vertex_index < reshape_smooth_context->geometry.num_vertices);
+
+ Vertex *vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
+
+ vertex->grid_coords = MEM_reallocN(vertex->grid_coords,
+ sizeof(Vertex) * (vertex->num_grid_coords + 1));
+ vertex->grid_coords[vertex->num_grid_coords] = *grid_coord;
+ ++vertex->num_grid_coords;
+}
+
+/* TODO(sergey): De-duplicate with similar function in multires_reshape_vertcos.c */
+static void foreach_vertex(const SubdivForeachContext *foreach_context,
+ const PTexCoord *ptex_coord,
+ const int subdiv_vertex_index)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ const GridCoord grid_coord = multires_reshape_ptex_coord_to_grid(reshape_context, ptex_coord);
+ const int face_index = multires_reshape_grid_to_face_index(reshape_context,
+ grid_coord.grid_index);
+
+ const Mesh *base_mesh = reshape_context->base_mesh;
+ const MPoly *base_poly = &base_mesh->mpoly[face_index];
+ const int num_corners = base_poly->totloop;
+ const int start_grid_index = reshape_context->face_start_grid_index[face_index];
+ const int corner = grid_coord.grid_index - start_grid_index;
+
+ if (grid_coord.u == 0.0f && grid_coord.v == 0.0f) {
+ for (int current_corner = 0; current_corner < num_corners; ++current_corner) {
+ GridCoord corner_grid_coord = grid_coord;
+ corner_grid_coord.grid_index = start_grid_index + current_corner;
+ foreach_single_vertex(foreach_context, &corner_grid_coord, subdiv_vertex_index);
+ }
+ return;
+ }
+
+ foreach_single_vertex(foreach_context, &grid_coord, subdiv_vertex_index);
+
+ if (grid_coord.u == 0.0f) {
+ GridCoord prev_grid_coord;
+ prev_grid_coord.grid_index = start_grid_index + ((corner + num_corners - 1) % num_corners);
+ prev_grid_coord.u = grid_coord.v;
+ prev_grid_coord.v = 0.0f;
+
+ foreach_single_vertex(foreach_context, &prev_grid_coord, subdiv_vertex_index);
+ }
+
+ if (grid_coord.v == 0.0f) {
+ GridCoord next_grid_coord;
+ next_grid_coord.grid_index = start_grid_index + ((corner + 1) % num_corners);
+ next_grid_coord.u = 0.0f;
+ next_grid_coord.v = grid_coord.u;
+
+ foreach_single_vertex(foreach_context, &next_grid_coord, subdiv_vertex_index);
+ }
+}
+
+static void foreach_vertex_inner(const struct SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int ptex_face_index,
+ const float ptex_face_u,
+ const float ptex_face_v,
+ const int UNUSED(coarse_poly_index),
+ const int UNUSED(coarse_corner),
+ const int subdiv_vertex_index)
+{
+ const PTexCoord ptex_coord = {
+ .ptex_face_index = ptex_face_index,
+ .u = ptex_face_u,
+ .v = ptex_face_v,
+ };
+ foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
+}
+
+static void foreach_vertex_every_corner(const struct SubdivForeachContext *foreach_context,
+ void *UNUSED(tls_v),
+ const int ptex_face_index,
+ const float ptex_face_u,
+ const float ptex_face_v,
+ const int UNUSED(coarse_vertex_index),
+ const int UNUSED(coarse_face_index),
+ const int UNUSED(coarse_face_corner),
+ const int subdiv_vertex_index)
+{
+ const PTexCoord ptex_coord = {
+ .ptex_face_index = ptex_face_index,
+ .u = ptex_face_u,
+ .v = ptex_face_v,
+ };
+ foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
+}
+
+static void foreach_vertex_every_edge(const struct SubdivForeachContext *foreach_context,
+ void *UNUSED(tls_v),
+ const int ptex_face_index,
+ const float ptex_face_u,
+ const float ptex_face_v,
+ const int UNUSED(coarse_edge_index),
+ const int UNUSED(coarse_face_index),
+ const int UNUSED(coarse_face_corner),
+ const int subdiv_vertex_index)
+{
+ const PTexCoord ptex_coord = {
+ .ptex_face_index = ptex_face_index,
+ .u = ptex_face_u,
+ .v = ptex_face_v,
+ };
+ foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
+}
+
+static void foreach_loop(const struct SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int UNUSED(ptex_face_index),
+ const float UNUSED(ptex_face_u),
+ const float UNUSED(ptex_face_v),
+ const int UNUSED(coarse_loop_index),
+ const int coarse_poly_index,
+ const int coarse_corner,
+ const int subdiv_loop_index,
+ const int subdiv_vertex_index,
+ const int UNUSED(subdiv_edge_index))
+{
+ MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ BLI_assert(subdiv_loop_index < reshape_smooth_context->geometry.num_corners);
+
+ Corner *corner = &reshape_smooth_context->geometry.corners[subdiv_loop_index];
+ corner->vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
+
+ const int first_grid_index = reshape_context->face_start_grid_index[coarse_poly_index];
+ corner->grid_index = first_grid_index + coarse_corner;
+}
+
+static void foreach_poly(const SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int UNUSED(coarse_poly_index),
+ const int subdiv_poly_index,
+ const int start_loop_index,
+ const int num_loops)
+{
+ MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
+
+ BLI_assert(subdiv_poly_index < reshape_smooth_context->geometry.num_faces);
+
+ Dace *face = &reshape_smooth_context->geometry.faces[subdiv_poly_index];
+ face->start_corner_index = start_loop_index;
+ face->num_corners = num_loops;
+}
+
+static void foreach_vertex_of_loose_edge(const struct SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int UNUSED(coarse_edge_index),
+ const float UNUSED(u),
+ const int vertex_index)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
+ Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
+
+ if (vertex->num_grid_coords != 0) {
+ vertex->is_infinite_sharp = true;
+ }
+}
+
+static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ SubdivForeachContext foreach_context = {
+ .topology_info = foreach_topology_info,
+ .vertex_inner = foreach_vertex_inner,
+ .vertex_every_corner = foreach_vertex_every_corner,
+ .vertex_every_edge = foreach_vertex_every_edge,
+ .loop = foreach_loop,
+ .poly = foreach_poly,
+ .vertex_of_loose_edge = foreach_vertex_of_loose_edge,
+ .user_data = reshape_smooth_context,
+ };
+
+ SubdivToMeshSettings mesh_settings;
+ mesh_settings.resolution = (1 << reshape_context->reshape.level) + 1;
+ mesh_settings.use_optimal_display = false;
+
+ /* TODO(sergey): Tell the foreach() to ignore loose vertices. */
+ BKE_subdiv_foreach_subdiv_geometry(
+ reshape_context->subdiv, &foreach_context, &mesh_settings, reshape_context->base_mesh);
+}
+
+/* ================================================================================================
+ * Generation of OpenSubdiv evaluator for topology created form reshape level.
+ */
+
+static OpenSubdiv_SchemeType get_scheme_type(const OpenSubdiv_Converter *UNUSED(converter))
+{
+ return OSD_SCHEME_CATMARK;
+}
+
+static OpenSubdiv_VtxBoundaryInterpolation get_vtx_boundary_interpolation(
+ const struct OpenSubdiv_Converter *converter)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+ const SubdivSettings *settings = &reshape_context->subdiv->settings;
+
+ return BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(settings);
+}
+
+static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
+ const OpenSubdiv_Converter *converter)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+ const SubdivSettings *settings = &reshape_context->subdiv->settings;
+
+ return BKE_subdiv_converter_fvar_linear_from_settings(settings);
+}
+
+static bool specifies_full_topology(const OpenSubdiv_Converter *UNUSED(converter))
+{
+ return false;
+}
+
+static int get_num_faces(const OpenSubdiv_Converter *converter)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
+
+ return reshape_smooth_context->geometry.num_faces;
+}
+
+static int get_num_vertices(const OpenSubdiv_Converter *converter)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
+
+ return reshape_smooth_context->geometry.num_vertices;
+}
+
+static int get_num_face_vertices(const OpenSubdiv_Converter *converter, int face_index)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
+ const Dace *face = &reshape_smooth_context->geometry.faces[face_index];
+
+ return face->num_corners;
+}
+
+static void get_face_vertices(const OpenSubdiv_Converter *converter,
+ int face_index,
+ int *face_vertices)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
+ const Dace *face = &reshape_smooth_context->geometry.faces[face_index];
+
+ for (int i = 0; i < face->num_corners; ++i) {
+ const int corner_index = face->start_corner_index + i;
+ const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
+ face_vertices[i] = corner->vertex - reshape_smooth_context->geometry.vertices;
+ }
+}
+
+static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter, int vertex_index)
+{
+ const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
+ Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
+
+ return vertex->is_infinite_sharp;
+}
+
+static void converter_init(const MultiresReshapeSmoothContext *reshape_smooth_context,
+ OpenSubdiv_Converter *converter)
+{
+ converter->getSchemeType = get_scheme_type;
+ converter->getVtxBoundaryInterpolation = get_vtx_boundary_interpolation;
+ converter->getFVarLinearInterpolation = get_fvar_linear_interpolation;
+ converter->specifiesFullTopology = specifies_full_topology;
+
+ converter->getNumFaces = get_num_faces;
+ converter->getNumEdges = NULL;
+ converter->getNumVertices = get_num_vertices;
+
+ converter->getNumFaceVertices = get_num_face_vertices;
+ converter->getFaceVertices = get_face_vertices;
+ converter->getFaceEdges = NULL;
+
+ converter->getEdgeVertices = NULL;
+ converter->getNumEdgeFaces = NULL;
+ converter->getEdgeFaces = NULL;
+ converter->getEdgeSharpness = NULL;
+
+ converter->getNumVertexEdges = NULL;
+ converter->getVertexEdges = NULL;
+ converter->getNumVertexFaces = NULL;
+ converter->getVertexFaces = NULL;
+ converter->isInfiniteSharpVertex = is_infinite_sharp_vertex;
+ converter->getVertexSharpness = NULL;
+
+ converter->getNumUVLayers = NULL;
+ converter->precalcUVLayer = NULL;
+ converter->finishUVLayer = NULL;
+ converter->getNumUVCoordinates = NULL;
+ converter->getFaceCornerUVIndex = NULL;
+
+ converter->freeUserData = NULL;
+
+ converter->user_data = (void *)reshape_smooth_context;
+}
+
+/* Create subdiv descriptor created for topology at a reshape level, */
+static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+ const SubdivSettings *settings = &reshape_context->subdiv->settings;
+
+ OpenSubdiv_Converter converter;
+ converter_init(reshape_smooth_context, &converter);
+
+ Subdiv *reshape_subdiv = BKE_subdiv_new_from_converter(settings, &converter);
+ BKE_subdiv_eval_begin(reshape_subdiv);
+
+ reshape_smooth_context->reshape_subdiv = reshape_subdiv;
+
+ BKE_subdiv_converter_free(&converter);
+}
+
+/* Callback to provide coarse position for subdivision surface topology at a reshape level. */
+typedef void(ReshapeSubdivCoarsePositionCb)(
+ const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const Vertex *vertex,
+ float r_P[3]);
+
+/* Refine subdivision surface topology at a reshape level for new coarse verticies positions. */
+static void reshape_subdiv_refine(const MultiresReshapeSmoothContext *reshape_smooth_context,
+ ReshapeSubdivCoarsePositionCb coarse_position_cb)
+{
+ Subdiv *reshape_subdiv = reshape_smooth_context->reshape_subdiv;
+
+ /* TODO(sergey): For non-trivial coarse_position_cb we should multi-thread this loop. */
+
+ const int num_vertices = reshape_smooth_context->geometry.num_vertices;
+ for (int i = 0; i < num_vertices; ++i) {
+ const Vertex *vertex = &reshape_smooth_context->geometry.vertices[i];
+ float P[3];
+ coarse_position_cb(reshape_smooth_context, vertex, P);
+ reshape_subdiv->evaluator->setCoarsePositions(reshape_subdiv->evaluator, P, i, 1);
+ }
+ reshape_subdiv->evaluator->refine(reshape_subdiv->evaluator);
+}
+
+BLI_INLINE const GridCoord *reshape_subdiv_refine_vertex_grid_coord(const Vertex *vertex)
+{
+ if (vertex->num_grid_coords == 0) {
+ /* This is a loose vertex, the coordinate is not important. */
+ /* TODO(sergey): Once the subdiv_foreach() supports properly ignoring loose elements this
+ * should become an assert instead. */
+ return NULL;
+ }
+ /* NOTE: All grid coordinates will point to the same object position, so can be simple and use
+ * first grid coordinate. */
+ return &vertex->grid_coords[0];
+}
+
+/* Version of reshape_subdiv_refine() which uses coarse position from original grids. */
+static void reshape_subdiv_refine_orig_P(
+ const MultiresReshapeSmoothContext *reshape_smooth_context, const Vertex *vertex, float r_P[3])
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+ const GridCoord *grid_coord = reshape_subdiv_refine_vertex_grid_coord(vertex);
+
+ /* Check whether this is a loose vertex. */
+ if (grid_coord == NULL) {
+ zero_v3(r_P);
+ return;
+ }
+
+ float limit_P[3];
+ float tangent_matrix[3][3];
+ multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, limit_P, tangent_matrix);
+
+ const ReshapeConstGridElement orig_grid_element =
+ multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
+
+ float D[3];
+ mul_v3_m3v3(D, tangent_matrix, orig_grid_element.displacement);
+
+ add_v3_v3v3(r_P, limit_P, D);
+}
+static void reshape_subdiv_refine_orig(const MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ reshape_subdiv_refine(reshape_smooth_context, reshape_subdiv_refine_orig_P);
+}
+
+/* Version of reshape_subdiv_refine() which uses coarse position from final grids. */
+static void reshape_subdiv_refine_final_P(
+ const MultiresReshapeSmoothContext *reshape_smooth_context, const Vertex *vertex, float r_P[3])
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+ const GridCoord *grid_coord = reshape_subdiv_refine_vertex_grid_coord(vertex);
+
+ /* Check whether this is a loose vertex. */
+ if (grid_coord == NULL) {
+ zero_v3(r_P);
+ return;
+ }
+
+ const ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(
+ reshape_context, grid_coord);
+
+ /* NOTE: At this point in reshape/propagate pipeline grid displacement is actually storing object
+ * vertices coordinates. */
+ copy_v3_v3(r_P, grid_element.displacement);
+}
+static void reshape_subdiv_refine_final(const MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ reshape_subdiv_refine(reshape_smooth_context, reshape_subdiv_refine_final_P);
+}
+
+static void reshape_subdiv_evaluate_limit_at_grid(
+ const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const PTexCoord *ptex_coord,
+ const GridCoord *grid_coord,
+ float limit_P[3],
+ float r_tangent_matrix[3][3])
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ float dPdu[3], dPdv[3];
+ BKE_subdiv_eval_limit_point_and_derivatives(reshape_smooth_context->reshape_subdiv,
+ ptex_coord->ptex_face_index,
+ ptex_coord->u,
+ ptex_coord->v,
+ limit_P,
+ dPdu,
+ dPdv);
+
+ const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
+ BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, corner);
+}
+
+/* ================================================================================================
+ * Evaluation of base surface.
+ */
+
+static void evaluate_base_surface_grids_callback(
+ const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const PTexCoord *ptex_coord,
+ const GridCoord *grid_coord,
+ void *UNUSED(userdata_v))
+{
+ float limit_P[3];
+ float tangent_matrix[3][3];
+ reshape_subdiv_evaluate_limit_at_grid(
+ reshape_smooth_context, ptex_coord, grid_coord, limit_P, tangent_matrix);
+
+ base_surface_grids_write(reshape_smooth_context, grid_coord, limit_P, tangent_matrix);
+}
+
+static void evaluate_base_surface_grids(const MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ foreach_toplevel_grid_coord(reshape_smooth_context, evaluate_base_surface_grids_callback, NULL);
+}
+
+/* ================================================================================================
+ * Evaluation of new surface.
+ */
+
+/* Evaluate final position of the original (pre-sculpt-edit) point position at a given grid
+ * coordinate. */
+static void evaluate_final_original_point(
+ const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const GridCoord *grid_coord,
+ float r_orig_final_P[3])
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ /* Element of an original MDISPS grid) */
+ const ReshapeConstGridElement orig_grid_element =
+ multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
+
+ /* Limit surface of the base mesh. */
+ float base_mesh_limit_P[3];
+ float base_mesh_tangent_matrix[3][3];
+ multires_reshape_evaluate_limit_at_grid(
+ reshape_context, grid_coord, base_mesh_limit_P, base_mesh_tangent_matrix);
+
+ /* Convert original displacement from tangent space to object space. */
+ float orig_displacement[3];
+ mul_v3_m3v3(orig_displacement, base_mesh_tangent_matrix, orig_grid_element.displacement);
+
+ /* Final point = limit surface + displacement. */
+ add_v3_v3v3(r_orig_final_P, base_mesh_limit_P, orig_displacement);
+}
+
+static void evaluate_higher_grid_positions_with_details_callback(
+ const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const PTexCoord *ptex_coord,
+ const GridCoord *grid_coord,
+ void *UNUSED(userdata_v))
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+
+ /* Position of the original veretx at top level. */
+ float orig_final_P[3];
+ evaluate_final_original_point(reshape_smooth_context, grid_coord, orig_final_P);
+
+ /* Original surface point on sculpt level (sculpt level before edits in sculpt mode). */
+ const SurfacePoint *orig_sculpt_point = base_surface_grids_read(reshape_smooth_context,
+ grid_coord);
+
+ /* Difference between original top level and original sculpt level in object space. */
+ float original_detail_delta[3];
+ sub_v3_v3v3(original_detail_delta, orig_final_P, orig_sculpt_point->P);
+
+ /* Difference between original top level and original sculpt level in tangent space of original
+ * sculpt level. */
+ float original_detail_delta_tangent[3];
+ float original_sculpt_tangent_matrix_inv[3][3];
+ invert_m3_m3(original_sculpt_tangent_matrix_inv, orig_sculpt_point->tangent_matrix);
+ mul_v3_m3v3(
+ original_detail_delta_tangent, original_sculpt_tangent_matrix_inv, original_detail_delta);
+
+ /* Limit surface of smoothed (subdivided) edited sculpt level. */
+ float smooth_limit_P[3];
+ float smooth_tangent_matrix[3][3];
+ reshape_subdiv_evaluate_limit_at_grid(
+ reshape_smooth_context, ptex_coord, grid_coord, smooth_limit_P, smooth_tangent_matrix);
+
+ /* Add original detail to the smoothed surface. */
+ float smooth_delta[3];
+ mul_v3_m3v3(smooth_delta, smooth_tangent_matrix, original_detail_delta_tangent);
+
+ /* Grid element of the result.
+ *
+ * NOTE: Displacement is storing object space coordinate. */
+ ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(reshape_context,
+ grid_coord);
+
+ add_v3_v3v3(grid_element.displacement, smooth_limit_P, smooth_delta);
+}
+static void evaluate_higher_grid_positions_with_details(
+ const MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ foreach_toplevel_grid_coord(
+ reshape_smooth_context, evaluate_higher_grid_positions_with_details_callback, NULL);
+}
+
+static void evaluate_higher_grid_positions_callback(
+ const MultiresReshapeSmoothContext *reshape_smooth_context,
+ const PTexCoord *ptex_coord,
+ const GridCoord *grid_coord,
+ void *UNUSED(userdata_v))
+{
+ const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+ Subdiv *reshape_subdiv = reshape_smooth_context->reshape_subdiv;
+
+ ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(reshape_context,
+ grid_coord);
+
+ /* Surface. */
+
+ float P[3];
+ BKE_subdiv_eval_limit_point(
+ reshape_subdiv, ptex_coord->ptex_face_index, ptex_coord->u, ptex_coord->v, P);
+
+ copy_v3_v3(grid_element.displacement, P);
+
+ /* Masks. */
+ if (grid_element.mask != NULL) {
+ *grid_element.mask = interpolate_masks_grid(reshape_smooth_context, grid_coord);
+ }
+}
+
+static void evaluate_higher_grid_positions(
+ const MultiresReshapeSmoothContext *reshape_smooth_context)
+{
+ foreach_toplevel_grid_coord(
+ reshape_smooth_context, evaluate_higher_grid_positions_callback, NULL);
+}
+/* ================================================================================================
+ * Entry point.
+ */
+
+void multires_reshape_smooth_object_grids_with_details(
+ const MultiresReshapeContext *reshape_context)
+{
+ const int level_difference = (reshape_context->top.level - reshape_context->reshape.level);
+ if (level_difference == 0) {
+ /* Early output. */
+ return;
+ }
+
+ MultiresReshapeSmoothContext reshape_smooth_context;
+ context_init(&reshape_smooth_context, reshape_context);
+
+ geometry_create(&reshape_smooth_context);
+
+ reshape_subdiv_create(&reshape_smooth_context);
+
+ base_surface_grids_allocate(&reshape_smooth_context);
+ reshape_subdiv_refine_orig(&reshape_smooth_context);
+ evaluate_base_surface_grids(&reshape_smooth_context);
+
+ reshape_subdiv_refine_final(&reshape_smooth_context);
+ evaluate_higher_grid_positions_with_details(&reshape_smooth_context);
+
+ context_free(&reshape_smooth_context);
+}
+
+void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context)
+{
+ const int level_difference = (reshape_context->top.level - reshape_context->reshape.level);
+ if (level_difference == 0) {
+ /* Early output. */
+ return;
+ }
+
+ MultiresReshapeSmoothContext reshape_smooth_context;
+ context_init(&reshape_smooth_context, reshape_context);
+
+ geometry_create(&reshape_smooth_context);
+
+ reshape_subdiv_create(&reshape_smooth_context);
+
+ reshape_subdiv_refine_final(&reshape_smooth_context);
+ evaluate_higher_grid_positions(&reshape_smooth_context);
+
+ context_free(&reshape_smooth_context);
+}
diff --git a/source/blender/blenkernel/intern/multires_reshape_util.c b/source/blender/blenkernel/intern/multires_reshape_util.c
new file mode 100644
index 00000000000..f9271e37672
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_reshape_util.c
@@ -0,0 +1,739 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "multires_reshape.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_task.h"
+
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_multires.h"
+#include "BKE_subdiv.h"
+#include "BKE_subdiv_eval.h"
+#include "BKE_subdiv_ccg.h"
+#include "BKE_subdiv_foreach.h"
+#include "BKE_subdiv_mesh.h"
+
+#include "DEG_depsgraph_query.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Construct/destruct reshape context.
+ * \{ */
+
+/* Create subdivision surface descriptor which is configured for surface evaluation at a given
+ * multires modifier. */
+Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgraph,
+ /*const*/ Object *object,
+ const MultiresModifierData *mmd)
+{
+ Mesh *coarse_mesh;
+
+ if (depsgraph != NULL) {
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
+ coarse_mesh = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
+ }
+ else {
+ coarse_mesh = (Mesh *)object->data;
+ }
+
+ SubdivSettings subdiv_settings;
+ BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
+ Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, coarse_mesh);
+ if (!BKE_subdiv_eval_update_from_mesh(subdiv, coarse_mesh, NULL)) {
+ BKE_subdiv_free(subdiv);
+ return NULL;
+ }
+ return subdiv;
+}
+
+static void context_zero(MultiresReshapeContext *reshape_context)
+{
+ memset(reshape_context, 0, sizeof(*reshape_context));
+}
+
+static void context_init_lookup(MultiresReshapeContext *reshape_context)
+{
+ const Mesh *base_mesh = reshape_context->base_mesh;
+ const MPoly *mpoly = base_mesh->mpoly;
+ const int num_faces = base_mesh->totpoly;
+
+ reshape_context->face_start_grid_index = MEM_malloc_arrayN(
+ sizeof(int), num_faces, "face_start_grid_index");
+ int num_grids = 0;
+ int num_ptex_faces = 0;
+ for (int face_index = 0; face_index < num_faces; ++face_index) {
+ const int num_corners = mpoly[face_index].totloop;
+ reshape_context->face_start_grid_index[face_index] = num_grids;
+ num_grids += num_corners;
+ num_ptex_faces += (num_corners == 4) ? 1 : num_corners;
+ }
+
+ reshape_context->grid_to_face_index = MEM_malloc_arrayN(
+ sizeof(int), num_grids, "grid_to_face_index");
+ reshape_context->ptex_start_grid_index = MEM_malloc_arrayN(
+ sizeof(int), num_ptex_faces, "ptex_start_grid_index");
+ for (int face_index = 0, grid_index = 0, ptex_index = 0; face_index < num_faces; ++face_index) {
+ const int num_corners = mpoly[face_index].totloop;
+ const int num_face_ptex_faces = (num_corners == 4) ? 1 : num_corners;
+ for (int i = 0; i < num_face_ptex_faces; ++i) {
+ reshape_context->ptex_start_grid_index[ptex_index + i] = grid_index + i;
+ }
+ for (int corner = 0; corner < num_corners; ++corner, ++grid_index) {
+ reshape_context->grid_to_face_index[grid_index] = face_index;
+ }
+ ptex_index += num_face_ptex_faces;
+ }
+
+ /* Store number of grids, which will be used for sanity checks. */
+ reshape_context->num_grids = num_grids;
+}
+
+static void context_init_grid_pointers(MultiresReshapeContext *reshape_context)
+{
+ Mesh *base_mesh = reshape_context->base_mesh;
+ reshape_context->mdisps = CustomData_get_layer(&base_mesh->ldata, CD_MDISPS);
+ reshape_context->grid_paint_masks = CustomData_get_layer(&base_mesh->ldata, CD_GRID_PAINT_MASK);
+}
+
+static void context_init_commoon(MultiresReshapeContext *reshape_context)
+{
+ BLI_assert(reshape_context->subdiv != NULL);
+ BLI_assert(reshape_context->base_mesh != NULL);
+
+ reshape_context->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(reshape_context->subdiv),
+
+ context_init_lookup(reshape_context);
+ context_init_grid_pointers(reshape_context);
+}
+
+static bool context_is_valid(MultiresReshapeContext *reshape_context)
+{
+ if (reshape_context->mdisps == NULL) {
+ /* Multires displacement has been removed before current changes were applies. */
+ return false;
+ }
+ return true;
+}
+
+static bool context_verify_or_free(MultiresReshapeContext *reshape_context)
+{
+ const bool is_valid = context_is_valid(reshape_context);
+ if (!is_valid) {
+ multires_reshape_context_free(reshape_context);
+ }
+ return is_valid;
+}
+
+bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context,
+ Depsgraph *depsgraph,
+ Object *object,
+ MultiresModifierData *mmd)
+{
+ context_zero(reshape_context);
+
+ const bool use_render_params = false;
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Mesh *base_mesh = (Mesh *)object->data;
+
+ reshape_context->base_mesh = base_mesh;
+
+ reshape_context->subdiv = multires_reshape_create_subdiv(depsgraph, object, mmd);
+ reshape_context->need_free_subdiv = true;
+
+ reshape_context->reshape.level = multires_get_level(
+ scene_eval, object, mmd, use_render_params, true);
+ reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level(
+ reshape_context->reshape.level);
+
+ reshape_context->top.level = mmd->totlvl;
+ reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
+
+ context_init_commoon(reshape_context);
+
+ return context_verify_or_free(reshape_context);
+}
+
+bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_context,
+ SubdivCCG *subdiv_ccg,
+ Mesh *base_mesh,
+ int top_level)
+{
+ context_zero(reshape_context);
+
+ reshape_context->base_mesh = base_mesh;
+
+ reshape_context->subdiv = subdiv_ccg->subdiv;
+ reshape_context->need_free_subdiv = false;
+
+ reshape_context->reshape.level = subdiv_ccg->level;
+ reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level(
+ reshape_context->reshape.level);
+
+ reshape_context->top.level = top_level;
+ reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
+
+ context_init_commoon(reshape_context);
+
+ return context_verify_or_free(reshape_context);
+}
+
+bool multires_reshape_context_create_from_subdivide(MultiresReshapeContext *reshape_context,
+ struct Object *object,
+ struct MultiresModifierData *mmd,
+ int top_level)
+{
+ context_zero(reshape_context);
+
+ Mesh *base_mesh = (Mesh *)object->data;
+
+ reshape_context->base_mesh = base_mesh;
+
+ reshape_context->subdiv = multires_reshape_create_subdiv(NULL, object, mmd);
+ reshape_context->need_free_subdiv = true;
+
+ reshape_context->reshape.level = mmd->totlvl;
+ reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level(
+ reshape_context->reshape.level);
+
+ reshape_context->top.level = top_level;
+ reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
+
+ context_init_commoon(reshape_context);
+
+ return context_verify_or_free(reshape_context);
+}
+
+static void free_original_grids(MultiresReshapeContext *reshape_context)
+{
+ MDisps *orig_mdisps = reshape_context->orig.mdisps;
+ GridPaintMask *orig_grid_paint_masks = reshape_context->orig.grid_paint_masks;
+
+ if (orig_mdisps == NULL && orig_grid_paint_masks == NULL) {
+ return;
+ }
+
+ const int num_grids = reshape_context->num_grids;
+ for (int grid_index = 0; grid_index < num_grids; grid_index++) {
+ if (orig_mdisps != NULL) {
+ MDisps *orig_grid = &orig_mdisps[grid_index];
+ MEM_SAFE_FREE(orig_grid->disps);
+ }
+ if (orig_grid_paint_masks != NULL) {
+ GridPaintMask *orig_paint_mask_grid = &orig_grid_paint_masks[grid_index];
+ MEM_SAFE_FREE(orig_paint_mask_grid->data);
+ }
+ }
+
+ MEM_SAFE_FREE(orig_mdisps);
+ MEM_SAFE_FREE(orig_grid_paint_masks);
+}
+
+void multires_reshape_context_free(MultiresReshapeContext *reshape_context)
+{
+ if (reshape_context->need_free_subdiv) {
+ BKE_subdiv_free(reshape_context->subdiv);
+ }
+
+ free_original_grids(reshape_context);
+
+ MEM_freeN(reshape_context->face_start_grid_index);
+ MEM_freeN(reshape_context->ptex_start_grid_index);
+ MEM_freeN(reshape_context->grid_to_face_index);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Helper accessors.
+ * \{ */
+
+/* For the given grid index get index of face it was created for. */
+int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_context,
+ int grid_index)
+{
+ BLI_assert(grid_index >= 0);
+ BLI_assert(grid_index < reshape_context->num_grids);
+
+ /* TODO(sergey): Optimization: when SubdivCCG is known we can calculate face index using
+ * SubdivCCG::grid_faces and SubdivCCG::faces, saving memory used by grid_to_face_index. */
+
+ return reshape_context->grid_to_face_index[grid_index];
+}
+
+/* For the given grid index get corner of a face it was created for. */
+int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index)
+{
+ BLI_assert(grid_index >= 0);
+ BLI_assert(grid_index < reshape_context->num_grids);
+
+ /* TODO(sergey): Optimization: when SubdivCCG is known we can calculate face index using
+ * SubdivCCG::grid_faces and SubdivCCG::faces, saving memory used by grid_to_face_index. */
+
+ const int face_index = multires_reshape_grid_to_face_index(reshape_context, grid_index);
+ return grid_index - reshape_context->face_start_grid_index[face_index];
+}
+
+bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index)
+{
+ const MPoly *coarse_poly = &reshape_context->base_mesh->mpoly[face_index];
+ return (coarse_poly->totloop == 4);
+}
+
+/* For the given grid index get index of corresponding ptex face. */
+int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_context,
+ int grid_index)
+{
+ const int face_index = multires_reshape_grid_to_face_index(reshape_context, grid_index);
+ const int corner = multires_reshape_grid_to_corner(reshape_context, grid_index);
+ const bool is_quad = multires_reshape_is_quad_face(reshape_context, face_index);
+ return reshape_context->face_ptex_offset[face_index] + (is_quad ? 0 : corner);
+}
+
+/* Convert normalized coordinate within a grid to a normalized coordinate within a ptex face. */
+PTexCoord multires_reshape_grid_coord_to_ptex(const MultiresReshapeContext *reshape_context,
+ const GridCoord *grid_coord)
+{
+ PTexCoord ptex_coord;
+
+ ptex_coord.ptex_face_index = multires_reshape_grid_to_ptex_index(reshape_context,
+ grid_coord->grid_index);
+
+ float corner_u, corner_v;
+ BKE_subdiv_grid_uv_to_ptex_face_uv(grid_coord->u, grid_coord->v, &corner_u, &corner_v);
+
+ const int face_index = multires_reshape_grid_to_face_index(reshape_context,
+ grid_coord->grid_index);
+ const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
+ if (multires_reshape_is_quad_face(reshape_context, face_index)) {
+ float grid_u, grid_v;
+ BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
+ BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &ptex_coord.u, &ptex_coord.v);
+ }
+ else {
+ ptex_coord.u = corner_u;
+ ptex_coord.v = corner_v;
+ }
+
+ return ptex_coord;
+}
+
+/* Convert a normalized coordinate within a ptex face to a normalized coordinate within a grid. */
+GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *reshape_context,
+ const PTexCoord *ptex_coord)
+{
+ GridCoord grid_coord;
+
+ const int start_grid_index = reshape_context->ptex_start_grid_index[ptex_coord->ptex_face_index];
+ const int face_index = reshape_context->grid_to_face_index[start_grid_index];
+
+ int corner_delta;
+ if (multires_reshape_is_quad_face(reshape_context, face_index)) {
+ corner_delta = BKE_subdiv_rotate_quad_to_corner(
+ ptex_coord->u, ptex_coord->v, &grid_coord.u, &grid_coord.v);
+ }
+ else {
+ corner_delta = 0;
+ grid_coord.u = ptex_coord->u;
+ grid_coord.v = ptex_coord->v;
+ }
+ grid_coord.grid_index = start_grid_index + corner_delta;
+
+ BKE_subdiv_ptex_face_uv_to_grid_uv(grid_coord.u, grid_coord.v, &grid_coord.u, &grid_coord.v);
+
+ return grid_coord;
+}
+
+void multires_reshape_tangent_matrix_for_corner(const MultiresReshapeContext *reshape_context,
+ const int face_index,
+ const int corner,
+ const float dPdu[3],
+ const float dPdv[3],
+ float r_tangent_matrix[3][3])
+{
+ /* For a quad faces we would need to flip the tangent, since they will use
+ * use different coordinates within displacement grid compared to the ptex face. */
+ const bool is_quad = multires_reshape_is_quad_face(reshape_context, face_index);
+ const int tangent_corner = is_quad ? corner : 0;
+ BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, tangent_corner);
+}
+
+ReshapeGridElement multires_reshape_grid_element_for_grid_coord(
+ const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
+{
+ ReshapeGridElement grid_element = {NULL, NULL};
+
+ const int grid_size = reshape_context->top.grid_size;
+ const int grid_x = lround(grid_coord->u * (grid_size - 1));
+ const int grid_y = lround(grid_coord->v * (grid_size - 1));
+ const int grid_element_index = grid_y * grid_size + grid_x;
+
+ if (reshape_context->mdisps != NULL) {
+ MDisps *displacement_grid = &reshape_context->mdisps[grid_coord->grid_index];
+ grid_element.displacement = displacement_grid->disps[grid_element_index];
+ }
+
+ if (reshape_context->grid_paint_masks != NULL) {
+ GridPaintMask *grid_paint_mask = &reshape_context->grid_paint_masks[grid_coord->grid_index];
+ grid_element.mask = &grid_paint_mask->data[grid_element_index];
+ }
+
+ return grid_element;
+}
+
+ReshapeGridElement multires_reshape_grid_element_for_ptex_coord(
+ const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord)
+{
+ GridCoord grid_coord = multires_reshape_ptex_coord_to_grid(reshape_context, ptex_coord);
+ return multires_reshape_grid_element_for_grid_coord(reshape_context, &grid_coord);
+}
+
+ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(
+ const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
+{
+ ReshapeConstGridElement grid_element = {{0.0f, 0.0f, 0.0f}, 0.0f};
+
+ const MDisps *mdisps = reshape_context->orig.mdisps;
+ if (mdisps != NULL) {
+ const MDisps *displacement_grid = &mdisps[grid_coord->grid_index];
+ if (displacement_grid->disps != NULL) {
+ const int grid_size = BKE_subdiv_grid_size_from_level(displacement_grid->level);
+ const int grid_x = lround(grid_coord->u * (grid_size - 1));
+ const int grid_y = lround(grid_coord->v * (grid_size - 1));
+ const int grid_element_index = grid_y * grid_size + grid_x;
+ copy_v3_v3(grid_element.displacement, displacement_grid->disps[grid_element_index]);
+ }
+ }
+
+ const GridPaintMask *grid_paint_masks = reshape_context->orig.grid_paint_masks;
+ if (grid_paint_masks != NULL) {
+ const GridPaintMask *paint_mask_grid = &grid_paint_masks[grid_coord->grid_index];
+ if (paint_mask_grid->data != NULL) {
+ const int grid_size = BKE_subdiv_grid_size_from_level(paint_mask_grid->level);
+ const int grid_x = lround(grid_coord->u * (grid_size - 1));
+ const int grid_y = lround(grid_coord->v * (grid_size - 1));
+ const int grid_element_index = grid_y * grid_size + grid_x;
+ grid_element.mask = paint_mask_grid->data[grid_element_index];
+ }
+ }
+
+ return grid_element;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sample limit surface of the base mesh.
+ * \{ */
+
+void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *reshape_context,
+ const GridCoord *grid_coord,
+ float r_P[3],
+ float r_tangent_matrix[3][3])
+{
+ float dPdu[3], dPdv[3];
+ const PTexCoord ptex_coord = multires_reshape_grid_coord_to_ptex(reshape_context, grid_coord);
+ Subdiv *subdiv = reshape_context->subdiv;
+ BKE_subdiv_eval_limit_point_and_derivatives(
+ subdiv, ptex_coord.ptex_face_index, ptex_coord.u, ptex_coord.v, r_P, dPdu, dPdv);
+
+ const int face_index = multires_reshape_grid_to_face_index(reshape_context,
+ grid_coord->grid_index);
+ const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
+ multires_reshape_tangent_matrix_for_corner(
+ reshape_context, face_index, corner, dPdu, dPdv, r_tangent_matrix);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Custom data preparation.
+ * \{ */
+
+static void allocate_displacement_grid(MDisps *displacement_grid, const int level)
+{
+ const int grid_size = BKE_subdiv_grid_size_from_level(level);
+ const int grid_area = grid_size * grid_size;
+ float(*disps)[3] = MEM_calloc_arrayN(grid_area, 3 * sizeof(float), "multires disps");
+ if (displacement_grid->disps != NULL) {
+ MEM_freeN(displacement_grid->disps);
+ }
+ /* TODO(sergey): Preserve data on the old level. */
+ displacement_grid->disps = disps;
+ displacement_grid->totdisp = grid_area;
+ displacement_grid->level = level;
+}
+
+static void ensure_displacement_grid(MDisps *displacement_grid, const int level)
+{
+ if (displacement_grid->disps != NULL && displacement_grid->level >= level) {
+ return;
+ }
+ allocate_displacement_grid(displacement_grid, level);
+}
+
+static void ensure_displacement_grids(Mesh *mesh, const int grid_level)
+{
+ const int num_grids = mesh->totloop;
+ MDisps *mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
+ for (int grid_index = 0; grid_index < num_grids; grid_index++) {
+ ensure_displacement_grid(&mdisps[grid_index], grid_level);
+ }
+}
+
+static void ensure_mask_grids(Mesh *mesh, const int level)
+{
+ GridPaintMask *grid_paint_masks = CustomData_get_layer(&mesh->ldata, CD_GRID_PAINT_MASK);
+ if (grid_paint_masks == NULL) {
+ return;
+ }
+ const int num_grids = mesh->totloop;
+ const int grid_size = BKE_subdiv_grid_size_from_level(level);
+ const int grid_area = grid_size * grid_size;
+ for (int grid_index = 0; grid_index < num_grids; grid_index++) {
+ GridPaintMask *grid_paint_mask = &grid_paint_masks[grid_index];
+ if (grid_paint_mask->level >= level) {
+ continue;
+ }
+ grid_paint_mask->level = level;
+ if (grid_paint_mask->data) {
+ MEM_freeN(grid_paint_mask->data);
+ }
+ /* TODO(sergey): Preserve data on the old level. */
+ grid_paint_mask->data = MEM_calloc_arrayN(grid_area, sizeof(float), "gpm.data");
+ }
+}
+
+void multires_reshape_ensure_grids(Mesh *mesh, const int level)
+{
+ ensure_displacement_grids(mesh, level);
+ ensure_mask_grids(mesh, level);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Displacement, space conversion.
+ * \{ */
+
+void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_context)
+{
+ const MDisps *mdisps = reshape_context->mdisps;
+ const GridPaintMask *grid_paint_masks = reshape_context->grid_paint_masks;
+
+ MDisps *orig_mdisps = MEM_dupallocN(mdisps);
+ GridPaintMask *orig_grid_paint_masks = NULL;
+ if (grid_paint_masks != NULL) {
+ orig_grid_paint_masks = MEM_dupallocN(grid_paint_masks);
+ }
+
+ const int num_grids = reshape_context->num_grids;
+ for (int grid_index = 0; grid_index < num_grids; grid_index++) {
+ MDisps *orig_grid = &orig_mdisps[grid_index];
+ /* Ignore possibly invalid/non-allocated original grids. They will be replaced with 0 original
+ * data when accessed during reshape process.
+ * Reshape process will ensure all grids are on top level, but that happens on separate set of
+ * grids which eventually replaces original one. */
+ if (orig_grid->disps != NULL) {
+ orig_grid->disps = MEM_dupallocN(orig_grid->disps);
+ }
+ if (orig_grid_paint_masks != NULL) {
+ GridPaintMask *orig_paint_mask_grid = &orig_grid_paint_masks[grid_index];
+ if (orig_paint_mask_grid->data != NULL) {
+ orig_paint_mask_grid->data = MEM_dupallocN(orig_paint_mask_grid->data);
+ }
+ }
+ }
+
+ reshape_context->orig.mdisps = orig_mdisps;
+ reshape_context->orig.grid_paint_masks = orig_grid_paint_masks;
+}
+
+typedef void (*ForeachGridCoordinateCallback)(const MultiresReshapeContext *reshape_context,
+ const GridCoord *grid_coord,
+ void *userdata_v);
+
+typedef struct ForeachGridCoordinateTaskData {
+ const MultiresReshapeContext *reshape_context;
+
+ int grid_size;
+ float grid_size_1_inv;
+
+ ForeachGridCoordinateCallback callback;
+ void *callback_userdata_v;
+} ForeachGridCoordinateTaskData;
+
+static void foreach_grid_face_coordinate_task(void *__restrict userdata_v,
+ const int face_index,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ ForeachGridCoordinateTaskData *data = userdata_v;
+
+ const MultiresReshapeContext *reshape_context = data->reshape_context;
+
+ const Mesh *base_mesh = data->reshape_context->base_mesh;
+ const MPoly *mpoly = base_mesh->mpoly;
+ const int grid_size = data->grid_size;
+ const float grid_size_1_inv = 1.0f / (((float)grid_size) - 1.0f);
+
+ const int num_corners = mpoly[face_index].totloop;
+ int grid_index = reshape_context->face_start_grid_index[face_index];
+ for (int corner = 0; corner < num_corners; ++corner, ++grid_index) {
+ for (int y = 0; y < grid_size; ++y) {
+ const float v = (float)y * grid_size_1_inv;
+ for (int x = 0; x < grid_size; ++x) {
+ const float u = (float)x * grid_size_1_inv;
+
+ GridCoord grid_coord;
+ grid_coord.grid_index = grid_index;
+ grid_coord.u = u;
+ grid_coord.v = v;
+
+ data->callback(data->reshape_context, &grid_coord, data->callback_userdata_v);
+ }
+ }
+ }
+}
+
+/* Run given callback for every grid coordinate at a given level. */
+static void foreach_grid_coordinate(const MultiresReshapeContext *reshape_context,
+ const int level,
+ ForeachGridCoordinateCallback callback,
+ void *userdata_v)
+{
+ ForeachGridCoordinateTaskData data;
+ data.reshape_context = reshape_context;
+ data.grid_size = BKE_subdiv_grid_size_from_level(level);
+ data.grid_size_1_inv = 1.0f / (((float)data.grid_size) - 1.0f);
+ data.callback = callback;
+ data.callback_userdata_v = userdata_v;
+
+ TaskParallelSettings parallel_range_settings;
+ BLI_parallel_range_settings_defaults(&parallel_range_settings);
+ parallel_range_settings.min_iter_per_thread = 1;
+
+ const Mesh *base_mesh = reshape_context->base_mesh;
+ const int num_faces = base_mesh->totpoly;
+ BLI_task_parallel_range(
+ 0, num_faces, &data, foreach_grid_face_coordinate_task, &parallel_range_settings);
+}
+
+static void object_grid_element_to_tangent_displacement(
+ const MultiresReshapeContext *reshape_context,
+ const GridCoord *grid_coord,
+ void *UNUSED(userdata_v))
+{
+ float P[3];
+ float tangent_matrix[3][3];
+ multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
+
+ float inv_tangent_matrix[3][3];
+ invert_m3_m3(inv_tangent_matrix, tangent_matrix);
+
+ ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(reshape_context,
+ grid_coord);
+
+ float D[3];
+ sub_v3_v3v3(D, grid_element.displacement, P);
+
+ float tangent_D[3];
+ mul_v3_m3v3(tangent_D, inv_tangent_matrix, D);
+
+ copy_v3_v3(grid_element.displacement, tangent_D);
+}
+
+void multires_reshape_object_grids_to_tangent_displacement(
+ const MultiresReshapeContext *reshape_context)
+{
+ foreach_grid_coordinate(reshape_context,
+ reshape_context->top.level,
+ object_grid_element_to_tangent_displacement,
+ NULL);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name MDISPS.
+ * \{ */
+
+/* TODO(sergey): Make foreach_grid_coordinate more accessible and move this functionality to
+ * own file. */
+
+static void assign_final_coords_from_mdisps(const MultiresReshapeContext *reshape_context,
+ const GridCoord *grid_coord,
+ void *UNUSED(userdata_v))
+{
+ float P[3];
+ float tangent_matrix[3][3];
+ multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
+
+ ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(reshape_context,
+ grid_coord);
+ float D[3];
+ mul_v3_m3v3(D, tangent_matrix, grid_element.displacement);
+
+ add_v3_v3v3(grid_element.displacement, P, D);
+}
+
+void multires_reshape_assign_final_coords_from_mdisps(
+ const MultiresReshapeContext *reshape_context)
+{
+ foreach_grid_coordinate(
+ reshape_context, reshape_context->top.level, assign_final_coords_from_mdisps, NULL);
+}
+
+static void assign_final_coords_from_orig_mdisps(const MultiresReshapeContext *reshape_context,
+ const GridCoord *grid_coord,
+ void *UNUSED(userdata_v))
+{
+ float P[3];
+ float tangent_matrix[3][3];
+ multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
+
+ const ReshapeConstGridElement orig_grid_element =
+ multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
+
+ float D[3];
+ mul_v3_m3v3(D, tangent_matrix, orig_grid_element.displacement);
+
+ ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(reshape_context,
+ grid_coord);
+ add_v3_v3v3(grid_element.displacement, P, D);
+}
+
+void multires_reshape_assign_final_coords_from_orig_mdisps(
+ const MultiresReshapeContext *reshape_context)
+{
+ foreach_grid_coordinate(
+ reshape_context, reshape_context->top.level, assign_final_coords_from_orig_mdisps, NULL);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/multires_reshape_vertcos.c b/source/blender/blenkernel/intern/multires_reshape_vertcos.c
new file mode 100644
index 00000000000..5aff0b3caa2
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_reshape_vertcos.c
@@ -0,0 +1,212 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "multires_reshape.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_math_vector.h"
+
+#include "BKE_subdiv_foreach.h"
+#include "BKE_subdiv_mesh.h"
+
+typedef struct MultiresReshapeAssignVertcosContext {
+ const MultiresReshapeContext *reshape_context;
+
+ const float (*vert_coords)[3];
+ const int num_vert_coords;
+} MultiresReshapeAssignVertcosContext;
+
+/**
+ * Set single displacement grid value at a reshape level to a corresponding vertex coordinate.
+ * This function will be called for every side of a boundary grid points for inner coordinates.
+ */
+static void multires_reshape_vertcos_foreach_single_vertex(
+ const SubdivForeachContext *foreach_context,
+ const GridCoord *grid_coord,
+ const int subdiv_vertex_index)
+{
+ MultiresReshapeAssignVertcosContext *reshape_vertcos_context = foreach_context->user_data;
+ const float *coordinate = reshape_vertcos_context->vert_coords[subdiv_vertex_index];
+
+ ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(
+ reshape_vertcos_context->reshape_context, grid_coord);
+ BLI_assert(grid_element.displacement != NULL);
+ copy_v3_v3(grid_element.displacement, coordinate);
+}
+
+/* TODO(sergey): De-duplicate with similar function in multires_reshape_smooth.c */
+static void multires_reshape_vertcos_foreach_vertex(const SubdivForeachContext *foreach_context,
+ const PTexCoord *ptex_coord,
+ const int subdiv_vertex_index)
+{
+ const MultiresReshapeAssignVertcosContext *reshape_vertcos_context = foreach_context->user_data;
+ const MultiresReshapeContext *reshape_context = reshape_vertcos_context->reshape_context;
+
+ const GridCoord grid_coord = multires_reshape_ptex_coord_to_grid(reshape_context, ptex_coord);
+ const int face_index = multires_reshape_grid_to_face_index(reshape_context,
+ grid_coord.grid_index);
+
+ const Mesh *base_mesh = reshape_context->base_mesh;
+ const MPoly *base_poly = &base_mesh->mpoly[face_index];
+ const int num_corners = base_poly->totloop;
+ const int start_grid_index = reshape_context->face_start_grid_index[face_index];
+ const int corner = grid_coord.grid_index - start_grid_index;
+
+ if (grid_coord.u == 0.0f && grid_coord.v == 0.0f) {
+ for (int current_corner = 0; current_corner < num_corners; ++current_corner) {
+ GridCoord corner_grid_coord = grid_coord;
+ corner_grid_coord.grid_index = start_grid_index + current_corner;
+ multires_reshape_vertcos_foreach_single_vertex(
+ foreach_context, &corner_grid_coord, subdiv_vertex_index);
+ }
+ return;
+ }
+
+ multires_reshape_vertcos_foreach_single_vertex(
+ foreach_context, &grid_coord, subdiv_vertex_index);
+
+ if (grid_coord.u == 0.0f) {
+ GridCoord prev_grid_coord;
+ prev_grid_coord.grid_index = start_grid_index + ((corner + num_corners - 1) % num_corners);
+ prev_grid_coord.u = grid_coord.v;
+ prev_grid_coord.v = 0.0f;
+
+ multires_reshape_vertcos_foreach_single_vertex(
+ foreach_context, &prev_grid_coord, subdiv_vertex_index);
+ }
+
+ if (grid_coord.v == 0.0f) {
+ GridCoord next_grid_coord;
+ next_grid_coord.grid_index = start_grid_index + ((corner + 1) % num_corners);
+ next_grid_coord.u = 0.0f;
+ next_grid_coord.v = grid_coord.u;
+
+ multires_reshape_vertcos_foreach_single_vertex(
+ foreach_context, &next_grid_coord, subdiv_vertex_index);
+ }
+}
+
+/* SubdivForeachContext::topology_info() */
+static bool multires_reshape_vertcos_foreach_topology_info(
+ const SubdivForeachContext *foreach_context,
+ const int num_vertices,
+ const int UNUSED(num_edges),
+ const int UNUSED(num_loops),
+ const int UNUSED(num_polygons))
+{
+ MultiresReshapeAssignVertcosContext *reshape_vertcos_context = foreach_context->user_data;
+ if (num_vertices != reshape_vertcos_context->num_vert_coords) {
+ return false;
+ }
+ return true;
+}
+
+/* SubdivForeachContext::vertex_inner() */
+static void multires_reshape_vertcos_foreach_vertex_inner(
+ const SubdivForeachContext *foreach_context,
+ void *UNUSED(tls_v),
+ const int ptex_face_index,
+ const float ptex_face_u,
+ const float ptex_face_v,
+ const int UNUSED(coarse_face_index),
+ const int UNUSED(coarse_face_corner),
+ const int subdiv_vertex_index)
+{
+ const PTexCoord ptex_coord = {
+ .ptex_face_index = ptex_face_index,
+ .u = ptex_face_u,
+ .v = ptex_face_v,
+ };
+ multires_reshape_vertcos_foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
+}
+
+/* SubdivForeachContext::vertex_every_corner() */
+static void multires_reshape_vertcos_foreach_vertex_every_corner(
+ const struct SubdivForeachContext *foreach_context,
+ void *UNUSED(tls_v),
+ const int ptex_face_index,
+ const float ptex_face_u,
+ const float ptex_face_v,
+ const int UNUSED(coarse_vertex_index),
+ const int UNUSED(coarse_face_index),
+ const int UNUSED(coarse_face_corner),
+ const int subdiv_vertex_index)
+{
+ const PTexCoord ptex_coord = {
+ .ptex_face_index = ptex_face_index,
+ .u = ptex_face_u,
+ .v = ptex_face_v,
+ };
+ multires_reshape_vertcos_foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
+}
+
+/* SubdivForeachContext::vertex_every_edge() */
+static void multires_reshape_vertcos_foreach_vertex_every_edge(
+ const struct SubdivForeachContext *foreach_context,
+ void *UNUSED(tls_v),
+ const int ptex_face_index,
+ const float ptex_face_u,
+ const float ptex_face_v,
+ const int UNUSED(coarse_edge_index),
+ const int UNUSED(coarse_face_index),
+ const int UNUSED(coarse_face_corner),
+ const int subdiv_vertex_index)
+{
+ const PTexCoord ptex_coord = {
+ .ptex_face_index = ptex_face_index,
+ .u = ptex_face_u,
+ .v = ptex_face_v,
+ };
+ multires_reshape_vertcos_foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
+}
+
+/* Set displacement grids values at a reshape level to a object coordinates of the the given
+ * source. */
+bool multires_reshape_assign_final_coords_from_vertcos(
+ const MultiresReshapeContext *reshape_context,
+ const float (*vert_coords)[3],
+ const int num_vert_coords)
+{
+ MultiresReshapeAssignVertcosContext reshape_vertcos_context = {
+ .reshape_context = reshape_context,
+ .vert_coords = vert_coords,
+ .num_vert_coords = num_vert_coords,
+ };
+
+ SubdivForeachContext foreach_context = {
+ .topology_info = multires_reshape_vertcos_foreach_topology_info,
+ .vertex_inner = multires_reshape_vertcos_foreach_vertex_inner,
+ .vertex_every_edge = multires_reshape_vertcos_foreach_vertex_every_edge,
+ .vertex_every_corner = multires_reshape_vertcos_foreach_vertex_every_corner,
+ .user_data = &reshape_vertcos_context,
+ };
+
+ SubdivToMeshSettings mesh_settings;
+ mesh_settings.resolution = (1 << reshape_context->reshape.level) + 1;
+ mesh_settings.use_optimal_display = false;
+
+ return BKE_subdiv_foreach_subdiv_geometry(
+ reshape_context->subdiv, &foreach_context, &mesh_settings, reshape_context->base_mesh);
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 41f7531ed85..d7247518f9e 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -524,7 +524,7 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
return true;
}
-void BKE_object_link_modifiers(Scene *scene, struct Object *ob_dst, const struct Object *ob_src)
+void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src)
{
ModifierData *md;
BKE_object_free_modifiers(ob_dst, 0);
@@ -562,7 +562,7 @@ void BKE_object_link_modifiers(Scene *scene, struct Object *ob_dst, const struct
if (md->type == eModifierType_Multires) {
/* Has to be done after mod creation, but *before* we actually copy its settings! */
multiresModifier_sync_levels_ex(
- scene, ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd);
+ ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd);
}
modifier_copyData(md, nmd);
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 6ca14ec9197..98638b6c865 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -740,7 +740,7 @@ bool BKE_scene_object_find(Scene *scene, Object *ob)
return false;
}
-Object *BKE_scene_object_find_by_name(Scene *scene, const char *name)
+Object *BKE_scene_object_find_by_name(const Scene *scene, const char *name)
{
for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
view_layer = view_layer->next) {
@@ -999,10 +999,10 @@ bool BKE_scene_camera_switch_update(Scene *scene)
return false;
}
-char *BKE_scene_find_marker_name(Scene *scene, int frame)
+const char *BKE_scene_find_marker_name(const Scene *scene, int frame)
{
- ListBase *markers = &scene->markers;
- TimeMarker *m1, *m2;
+ const ListBase *markers = &scene->markers;
+ const TimeMarker *m1, *m2;
/* search through markers for match */
for (m1 = markers->first, m2 = markers->last; m1 && m2; m1 = m1->next, m2 = m2->prev) {
@@ -1024,9 +1024,9 @@ char *BKE_scene_find_marker_name(Scene *scene, int frame)
/* return the current marker for this frame,
* we can have more than 1 marker per frame, this just returns the first :/ */
-char *BKE_scene_find_last_marker_name(Scene *scene, int frame)
+const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame)
{
- TimeMarker *marker, *best_marker = NULL;
+ const TimeMarker *marker, *best_marker = NULL;
int best_frame = -MAXFRAME * 2;
for (marker = scene->markers.first; marker; marker = marker->next) {
if (marker->frame == frame) {
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index 0846c6c90a6..aa4066b643f 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -682,7 +682,6 @@ void BKE_sequencer_cache_put(
key->nfra = cfra - seq->start;
key->type = type;
key->cost = cost;
- key->cache_owner = cache;
key->link_prev = NULL;
key->link_next = NULL;
key->is_temp_cache = true;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index ea53726a94d..827cccc6bd6 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -4603,10 +4603,10 @@ void BKE_sequence_sound_init(Scene *scene, Sequence *seq)
}
}
-Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame)
+const Sequence *BKE_sequencer_foreground_frame_get(const Scene *scene, int frame)
{
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- Sequence *seq, *best_seq = NULL;
+ const Editing *ed = scene->ed;
+ const Sequence *seq, *best_seq = NULL;
int best_machine = -1;
if (!ed) {
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index df7597b7f01..47b02654104 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -135,7 +135,7 @@ static int sound_cfra;
static char **audio_device_names = NULL;
#endif
-BLI_INLINE void sound_verify_evaluated_id(ID *id)
+BLI_INLINE void sound_verify_evaluated_id(const ID *id)
{
UNUSED_VARS_NDEBUG(id);
/* This is a bit tricky and not quite reliable, but good enough check.
@@ -504,7 +504,7 @@ void BKE_sound_load(Main *bmain, bSound *sound)
sound_load_audio(bmain, sound, true);
}
-AUD_Device *BKE_sound_mixdown(Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
+AUD_Device *BKE_sound_mixdown(const Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
{
sound_verify_evaluated_id(&scene->id);
return AUD_openMixdownDevice(specs, scene->sound_scene, volume, start / FPS);
diff --git a/source/blender/blenkernel/intern/subdiv_displacement_multires.c b/source/blender/blenkernel/intern/subdiv_displacement_multires.c
index 1f78cf4eb3b..50b2b3c7c46 100644
--- a/source/blender/blenkernel/intern/subdiv_displacement_multires.c
+++ b/source/blender/blenkernel/intern/subdiv_displacement_multires.c
@@ -47,6 +47,7 @@ typedef struct MultiresDisplacementData {
int grid_size;
/* Mesh is used to read external displacement. */
Mesh *mesh;
+ const MultiresModifierData *mmd;
const MPoly *mpoly;
const MDisps *mdisps;
/* Indexed by ptex face index, contains polygon/corner which corresponds
@@ -328,9 +329,7 @@ static int displacement_get_face_corner(MultiresDisplacementData *data,
static void initialize(SubdivDisplacement *displacement)
{
MultiresDisplacementData *data = displacement->user_data;
- Mesh *mesh = data->mesh;
- /* Make sure external displacement is read. */
- CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop);
+ multiresModifier_ensure_external_read(data->mesh, data->mmd);
data->is_initialized = true;
}
@@ -421,6 +420,7 @@ static void displacement_init_data(SubdivDisplacement *displacement,
data->subdiv = subdiv;
data->grid_size = BKE_subdiv_grid_size_from_level(mmd->totlvl);
data->mesh = mesh;
+ data->mmd = mmd;
data->mpoly = mesh->mpoly;
data->mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
data->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c
index 0f56fc5ec21..347e2843423 100644
--- a/source/blender/blenkernel/intern/subdiv_foreach.c
+++ b/source/blender/blenkernel/intern/subdiv_foreach.c
@@ -1772,6 +1772,21 @@ static void subdiv_foreach_single_geometry_vertices(SubdivForeachTaskContext *ct
}
}
+static void subdiv_foreach_mark_non_loose_geometry(SubdivForeachTaskContext *ctx)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *loop = &coarse_mloop[coarse_poly->loopstart + corner];
+ BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, loop->e);
+ BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map, loop->v);
+ }
+ }
+}
+
static void subdiv_foreach_single_thread_tasks(SubdivForeachTaskContext *ctx)
{
/* NOTE: In theory, we can try to skip allocation of TLS here, but in
@@ -1785,6 +1800,15 @@ static void subdiv_foreach_single_thread_tasks(SubdivForeachTaskContext *ctx)
/* Run callbacks which are supposed to be run once per shared geometry. */
subdiv_foreach_single_geometry_vertices(ctx, tls);
subdiv_foreach_tls_free(ctx, tls);
+
+ const SubdivForeachContext *foreach_context = ctx->foreach_context;
+ const bool is_loose_geometry_tagged = (foreach_context->vertex_every_edge != NULL &&
+ foreach_context->vertex_every_corner != NULL);
+ const bool is_loose_geometry_tags_needed = (foreach_context->vertex_loose != NULL ||
+ foreach_context->vertex_of_loose_edge != NULL);
+ if (is_loose_geometry_tagged && is_loose_geometry_tags_needed) {
+ subdiv_foreach_mark_non_loose_geometry(ctx);
+ }
}
static void subdiv_foreach_task(void *__restrict userdata,
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index 19425a0d80b..4635db98514 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -43,7 +43,7 @@
/* ********************** general blender movie support ***************************** */
static int start_stub(void *UNUSED(context_v),
- Scene *UNUSED(scene),
+ const Scene *UNUSED(scene),
RenderData *UNUSED(rd),
int UNUSED(rectx),
int UNUSED(recty),
@@ -85,7 +85,7 @@ static void context_free_stub(void *UNUSED(context_v))
/* callbacks */
static int start_avi(void *context_v,
- Scene *scene,
+ const Scene *scene,
RenderData *rd,
int rectx,
int recty,
@@ -102,7 +102,7 @@ static int append_avi(void *context_v,
int recty,
const char *suffix,
ReportList *reports);
-static void filepath_avi(char *string, RenderData *rd, bool preview, const char *suffix);
+static void filepath_avi(char *string, const RenderData *rd, bool preview, const char *suffix);
static void *context_create_avi(void);
static void context_free_avi(void *context_v);
#endif /* WITH_AVI */
@@ -158,7 +158,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
#ifdef WITH_AVI
-static void filepath_avi(char *string, RenderData *rd, bool preview, const char *suffix)
+static void filepath_avi(char *string, const RenderData *rd, bool preview, const char *suffix)
{
int sfra, efra;
@@ -196,7 +196,7 @@ static void filepath_avi(char *string, RenderData *rd, bool preview, const char
}
static int start_avi(void *context_v,
- Scene *UNUSED(scene),
+ const Scene *UNUSED(scene),
RenderData *rd,
int rectx,
int recty,
@@ -316,7 +316,7 @@ static void context_free_avi(void *context_v)
#endif /* WITH_AVI */
/* similar to BKE_image_path_from_imformat() */
-void BKE_movie_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix)
+void BKE_movie_filepath_get(char *string, const RenderData *rd, bool preview, const char *suffix)
{
bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype);
if (mh && mh->get_movie_path) {
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index deb9592b4f9..7e5d99617e4 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -114,8 +114,11 @@ typedef struct FFMpegContext {
static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value);
static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float value);
static void ffmpeg_set_expert_options(RenderData *rd);
-static void ffmpeg_filepath_get(
- FFMpegContext *context, char *string, struct RenderData *rd, bool preview, const char *suffix);
+static void ffmpeg_filepath_get(FFMpegContext *context,
+ char *string,
+ const struct RenderData *rd,
+ bool preview,
+ const char *suffix);
/* Delete a picture buffer */
@@ -338,7 +341,7 @@ static const char **get_file_extensions(int format)
/* Write a frame to the output file */
static int write_video_frame(
- FFMpegContext *context, RenderData *rd, int cfra, AVFrame *frame, ReportList *reports)
+ FFMpegContext *context, const RenderData *rd, int cfra, AVFrame *frame, ReportList *reports)
{
int got_output;
int ret, success = 1;
@@ -1217,7 +1220,7 @@ static void flush_ffmpeg(FFMpegContext *context)
/* Get the output filename-- similar to the other output formats */
static void ffmpeg_filepath_get(
- FFMpegContext *context, char *string, RenderData *rd, bool preview, const char *suffix)
+ FFMpegContext *context, char *string, const RenderData *rd, bool preview, const char *suffix)
{
char autosplit[20];
@@ -1282,13 +1285,13 @@ static void ffmpeg_filepath_get(
BLI_path_suffix(string, FILE_MAX, suffix, "");
}
-void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix)
+void BKE_ffmpeg_filepath_get(char *string, const RenderData *rd, bool preview, const char *suffix)
{
ffmpeg_filepath_get(NULL, string, rd, preview, suffix);
}
int BKE_ffmpeg_start(void *context_v,
- struct Scene *scene,
+ const struct Scene *scene,
RenderData *rd,
int rectx,
int recty,
@@ -1846,7 +1849,7 @@ void BKE_ffmpeg_codec_settings_verify(RenderData *rd)
ffmpeg_set_expert_options(rd);
}
-bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd)
+bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd)
{
int codec = rd->ffcodecdata.codec;
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index bf4b90db14f..fa50bf202a8 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -5743,7 +5743,7 @@ static float ff_quad_form_factor(float *p, float *n, float *q0, float *q1, float
static __m128 sse_approx_acos(__m128 x)
{
- /* needs a better approximation than taylor expansion of acos, since that
+ /* needs a better approximation than Taylor expansion of acos, since that
* gives big errors for near 1.0 values, sqrt(2 * x) * acos(1 - x) should work
* better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */
diff --git a/source/blender/blenlib/intern/voronoi_2d.c b/source/blender/blenlib/intern/voronoi_2d.c
index eb718c5e8c6..6bd9a16cd55 100644
--- a/source/blender/blenlib/intern/voronoi_2d.c
+++ b/source/blender/blenlib/intern/voronoi_2d.c
@@ -766,24 +766,25 @@ static int voronoi_addTriangulationPoint(const float coord[2],
return (*triangulated_points_total) - 1;
}
-static void voronoi_addTriangle(int v1, int v2, int v3, int (**triangles)[3], int *triangles_total)
+static void voronoi_addTriangle(
+ int v1, int v2, int v3, int (**r_triangles)[3], int *r_triangles_total)
{
int *triangle;
- if (*triangles) {
- *triangles = MEM_reallocN(*triangles, sizeof(int[3]) * (*triangles_total + 1));
+ if (*r_triangles) {
+ *r_triangles = MEM_reallocN(*r_triangles, sizeof(int[3]) * (*r_triangles_total + 1));
}
else {
- *triangles = MEM_callocN(sizeof(int[3]), "trianglulation triangles");
+ *r_triangles = MEM_callocN(sizeof(int[3]), "trianglulation triangles");
}
- triangle = (int *)&(*triangles)[(*triangles_total)];
+ triangle = (int *)&(*r_triangles)[(*r_triangles_total)];
triangle[0] = v1;
triangle[1] = v2;
triangle[2] = v3;
- (*triangles_total)++;
+ (*r_triangles_total)++;
}
void BLI_voronoi_triangulate(const VoronoiSite *sites,
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 3059caf83f1..0fbc9c661f3 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1891,9 +1891,11 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
if (ima->cache) {
oldnewmap_insert(fd->imamap, ima->cache, ima->cache, 0);
}
- for (a = 0; a < TEXTARGET_COUNT; a++) {
- if (ima->gputexture[a] != NULL) {
- oldnewmap_insert(fd->imamap, ima->gputexture[a], ima->gputexture[a], 0);
+ for (int eye = 0; eye < 2; eye++) {
+ for (a = 0; a < TEXTARGET_COUNT; a++) {
+ if (ima->gputexture[a][eye] != NULL) {
+ oldnewmap_insert(fd->imamap, ima->gputexture[a][eye], ima->gputexture[a][eye], 0);
+ }
}
}
if (ima->rr) {
@@ -1937,8 +1939,10 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
if (ima->cache == NULL) {
ima->gpuflag = 0;
ima->gpuframenr = INT_MAX;
- for (i = 0; i < TEXTARGET_COUNT; i++) {
- ima->gputexture[i] = NULL;
+ for (int eye = 0; eye < 2; eye++) {
+ for (i = 0; i < TEXTARGET_COUNT; i++) {
+ ima->gputexture[i][eye] = NULL;
+ }
}
ima->rr = NULL;
}
@@ -1946,8 +1950,10 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
slot->render = newimaadr(fd, slot->render);
}
- for (i = 0; i < TEXTARGET_COUNT; i++) {
- ima->gputexture[i] = newimaadr(fd, ima->gputexture[i]);
+ for (int eye = 0; eye < 2; eye++) {
+ for (i = 0; i < TEXTARGET_COUNT; i++) {
+ ima->gputexture[i][eye] = newimaadr(fd, ima->gputexture[i][eye]);
+ }
}
ima->rr = newimaadr(fd, ima->rr);
}
@@ -4140,14 +4146,18 @@ static void direct_link_image(FileData *fd, Image *ima)
if (!ima->cache) {
ima->gpuflag = 0;
ima->gpuframenr = INT_MAX;
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- ima->gputexture[i] = NULL;
+ for (int eye = 0; eye < 2; eye++) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ ima->gputexture[i][eye] = NULL;
+ }
}
ima->rr = NULL;
}
else {
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- ima->gputexture[i] = newimaadr(fd, ima->gputexture[i]);
+ for (int eye = 0; eye < 2; eye++) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ ima->gputexture[i][eye] = newimaadr(fd, ima->gputexture[i][eye]);
+ }
}
ima->rr = newimaadr(fd, ima->rr);
}
@@ -5774,8 +5784,8 @@ static void direct_link_gpencil_modifiers(FileData *fd, ListBase *lb)
BKE_curvemapping_initialize(gpmd->curve_thickness);
}
}
- else if (md->type == eGpencilModifierType_Vertexcolor) {
- VertexcolorGpencilModifierData *gpmd = (VertexcolorGpencilModifierData *)md;
+ else if (md->type == eGpencilModifierType_Tint) {
+ TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
gpmd->colorband = newdataadr(fd, gpmd->colorband);
gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
if (gpmd->curve_intensity) {
@@ -5799,14 +5809,6 @@ static void direct_link_gpencil_modifiers(FileData *fd, ListBase *lb)
BKE_curvemapping_initialize(gpmd->curve_intensity);
}
}
- else if (md->type == eGpencilModifierType_Tint) {
- TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
- gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
- if (gpmd->curve_intensity) {
- direct_link_curvemapping(fd, gpmd->curve_intensity);
- BKE_curvemapping_initialize(gpmd->curve_intensity);
- }
- }
else if (md->type == eGpencilModifierType_Opacity) {
OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 0ce32d234a8..e561b4a07f7 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1070,8 +1070,8 @@ static void do_version_curvemapping_walker(Main *bmain, void (*callback)(CurveMa
callback(gpmd->curve_intensity);
}
}
- else if (md->type == eGpencilModifierType_Vertexcolor) {
- VertexcolorGpencilModifierData *gpmd = (VertexcolorGpencilModifierData *)md;
+ else if (md->type == eGpencilModifierType_Tint) {
+ TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
if (gpmd->curve_intensity) {
callback(gpmd->curve_intensity);
@@ -1098,13 +1098,6 @@ static void do_version_curvemapping_walker(Main *bmain, void (*callback)(CurveMa
callback(gpmd->curve_intensity);
}
}
- else if (md->type == eGpencilModifierType_Tint) {
- TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
-
- if (gpmd->curve_intensity) {
- callback(gpmd->curve_intensity);
- }
- }
}
}
@@ -2548,7 +2541,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
V3D_SHOW_MODE_SHADE_OVERRIDE = (1 << 15),
};
View3D *v3d = (View3D *)sl;
- float alpha = v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE ? 0.0f : 1.0f;
+ float alpha = (v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE) ? 0.0f : 1.0f;
v3d->overlay.texture_paint_mode_opacity = alpha;
v3d->overlay.vertex_paint_mode_opacity = alpha;
v3d->overlay.weight_paint_mode_opacity = alpha;
@@ -4653,10 +4646,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
case eGpencilModifierType_Noise: {
NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md;
- mmd->factor /= 25.0f;
- mmd->factor_thickness = mmd->factor;
- mmd->factor_strength = mmd->factor;
- mmd->factor_uvs = mmd->factor;
+ float factor = mmd->factor / 25.0f;
+ mmd->factor = (mmd->flag & GP_NOISE_MOD_LOCATION) ? factor : 0.0f;
+ mmd->factor_thickness = (mmd->flag & GP_NOISE_MOD_STRENGTH) ? factor : 0.0f;
+ mmd->factor_strength = (mmd->flag & GP_NOISE_MOD_THICKNESS) ? factor : 0.0f;
+ mmd->factor_uvs = (mmd->flag & GP_NOISE_MOD_UV) ? factor : 0.0f;
+
mmd->noise_scale = (mmd->flag & GP_NOISE_FULL_STROKE) ? 0.0f : 1.0f;
if (mmd->curve_intensity == NULL) {
@@ -4730,16 +4725,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
break;
}
- case eGpencilModifierType_Vertexcolor: {
- VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
- if (mmd->curve_intensity == NULL) {
- mmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
- if (mmd->curve_intensity) {
- BKE_curvemapping_initialize(mmd->curve_intensity);
- }
- }
- break;
- }
default:
break;
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index f0127330b1b..53c63ef980b 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -627,7 +627,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
BKE_id_delete(bmain, brush);
}
- /* Rename and fix materials. */
+ /* Rename and fix materials and enable default object lights on. */
if (app_template && STREQ(app_template, "2D_Animation")) {
Material *ma = NULL;
rename_id_for_versioning(bmain, ID_MA, "Black", "Solid Stroke");
@@ -654,6 +654,11 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
if (ma != NULL) {
ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
}
+
+ Object *ob = BLI_findstring(&bmain->objects, "Stroke", offsetof(ID, name) + 2);
+ if (ob && ob->type == OB_GPENCIL) {
+ ob->dtx |= OB_USE_GPENCIL_LIGHTS;
+ }
}
/* Reset all grease pencil brushes. */
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index 2fefa56fbe5..205106d7820 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -192,6 +192,10 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
btheme->space_node.grid_levels = U_theme_default.space_node.grid_levels;
}
+ if (!USER_VERSION_ATLEAST(283, 9)) {
+ FROM_DEFAULT_V4_UCHAR(space_info.info_warning);
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index a9c5008062b..a92404b2372 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1844,8 +1844,8 @@ static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase)
write_curvemapping(wd, gpmd->curfalloff);
}
}
- else if (md->type == eGpencilModifierType_Vertexcolor) {
- VertexcolorGpencilModifierData *gpmd = (VertexcolorGpencilModifierData *)md;
+ else if (md->type == eGpencilModifierType_Tint) {
+ TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
if (gpmd->colorband) {
writestruct(wd, DATA, ColorBand, 1, gpmd->colorband);
}
@@ -1871,12 +1871,6 @@ static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase)
write_curvemapping(wd, gpmd->curve_intensity);
}
}
- else if (md->type == eGpencilModifierType_Tint) {
- TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
- if (gpmd->curve_intensity) {
- write_curvemapping(wd, gpmd->curve_intensity);
- }
- }
}
}
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
index c3667c364bc..55403cc35d3 100644
--- a/source/blender/blentranslation/BLT_translation.h
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -89,7 +89,7 @@ bool BLT_lang_is_ime_supported(void);
* NOTE: We translate BLT_I18NCONTEXT_DEFAULT as BLT_I18NCONTEXT_DEFAULT_BPY in Python,
* as we can't use "natural" None value in rna string properties... :/
* The void string "" is also interpreted as BLT_I18NCONTEXT_DEFAULT.
- * For perf reason, we only use the first char to detect this context,
+ * For performance reason, we only use the first char to detect this context,
* so other contexts should never start with the same char!
*/
#define BLT_I18NCONTEXT_DEFAULT NULL
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index d14b7a51a94..b4e78453226 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -788,7 +788,7 @@ void BM_log_redo(BMesh *bm, BMLog *log)
/* Currently at the beginning of the undo stack, move to first entry */
entry = log->entries.first;
}
- else if (entry && entry->next) {
+ else if (entry->next) {
/* Move to next undo entry */
entry = entry->next;
}
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 6fc53da4940..1ab318a8946 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -3164,7 +3164,7 @@ static void regularize_profile_orientation(BevelParams *bp, BMEdge *bme)
}
else {
/* The opposite side as the first direction because we're moving the other way. */
- edgehalf->leftv->is_profile_start = !toward_bv ^ right_highest;
+ edgehalf->leftv->is_profile_start = (!toward_bv) ^ right_highest;
}
/* The next jump will in the opposite direction relative to the BevVert. */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index c512300200e..442b4aa406a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -321,7 +321,7 @@ void DepsgraphNodeBuilder::begin_build()
for (IDNode *id_node : graph_->id_nodes) {
/* It is possible that the ID does not need to have CoW version in which case id_cow is the
* same as id_orig. Additionally, such ID might have been removed, which makes the check
- * for whether id_cow is expanded to access freed memory. In orderr to deal with this we
+ * for whether id_cow is expanded to access freed memory. In order to deal with this we
* check whether CoW is needed based on a scalar value which does not lead to access of
* possibly deleted memory.
* Additionally, this saves some space in the map by skipping mapping for datablocks which
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 35a45cc97f4..9447c365c48 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -777,6 +777,8 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
if (!lbake->resource_only) {
BLI_mutex_unlock(lbake->mutex);
}
+
+ EEVEE_volumes_free_smoke_textures();
}
/* Cache as in draw cache not light cache. */
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 61ca2317572..1e08741db26 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -786,8 +786,8 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
if (pinfo->do_grid_update) {
scene_orig->eevee.light_cache_data->flag |= LIGHTCACHE_UPDATE_GRID;
}
- /* If we update grid we need to update the cubemaps too.
- * So always refresh cubemaps. */
+ /* If we update grid we need to update the cube-maps too.
+ * So always refresh cube-maps. */
scene_orig->eevee.light_cache_data->flag |= LIGHTCACHE_UPDATE_CUBE;
/* Tag the lightcache to auto update. */
scene_orig->eevee.light_cache_data->flag |= LIGHTCACHE_UPDATE_AUTO;
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 0f084ba306b..52fb8b3cced 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -125,7 +125,7 @@ extern struct DrawEngineType draw_engine_eevee_type;
} \
((void)0)
-BLI_INLINE bool eevee_hdri_preview_overlay_enabled(View3D *v3d)
+BLI_INLINE bool eevee_hdri_preview_overlay_enabled(const View3D *v3d)
{
/* Only show the HDRI Preview in Shading Preview in the Viewport. */
if (v3d == NULL || v3d->shading.type != OB_MATERIAL) {
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 8c1c72a3c20..41f8dddf0fb 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -178,8 +178,6 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const float *viewport_size = DRW_viewport_size_get();
- BLI_listbase_clear(&e_data.smoke_domains);
-
const int tile_size = scene_eval->eevee.volumetric_tile_size;
/* Find Froxel Texture resolution. */
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index bef49efd3f9..f78826b2980 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -183,7 +183,7 @@ static void external_draw_scene_do(void *vedata)
Scene *scene = draw_ctx->scene;
RegionView3D *rv3d = draw_ctx->rv3d;
ARegion *region = draw_ctx->region;
- RenderEngineType *type;
+ const RenderEngineType *type;
DRW_state_reset_ex(DRW_STATE_DEFAULT & ~DRW_STATE_DEPTH_LESS_EQUAL);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 4b6059f1474..e7914a1b86c 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -33,16 +33,16 @@ extern DrawEngineType draw_engine_gpencil_type;
struct GPENCIL_Data;
struct GPENCIL_StorageList;
+struct GPUBatch;
+struct GPUVertBuf;
+struct GPUVertFormat;
+struct GpencilBatchCache;
struct MaterialGPencilStyle;
struct Object;
struct RenderEngine;
struct RenderLayer;
-struct bGPDstroke;
struct View3D;
-struct GpencilBatchCache;
-struct GPUBatch;
-struct GPUVertBuf;
-struct GPUVertFormat;
+struct bGPDstroke;
/* used to convert pixel scale. */
#define GPENCIL_PIXEL_FACTOR 2000.0f
diff --git a/source/blender/draw/engines/overlay/overlay_image.c b/source/blender/draw/engines/overlay/overlay_image.c
index 8536c642cb6..f81c51f0883 100644
--- a/source/blender/draw/engines/overlay/overlay_image.c
+++ b/source/blender/draw/engines/overlay/overlay_image.c
@@ -117,6 +117,9 @@ static void camera_background_images_stereo_setup(Scene *scene,
/* show only left or right camera */
iuser->multiview_eye = v3d->stereo3d_camera;
}
+ else {
+ iuser->multiview_eye = v3d->multiview_eye;
+ }
BKE_image_multiview_index(ima, iuser);
}
@@ -366,7 +369,9 @@ void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob)
* see: T59347 */
int size[2] = {0};
if (ima != NULL) {
- tex = GPU_texture_from_blender(ima, ob->iuser, NULL, GL_TEXTURE_2D);
+ ImageUser iuser = *ob->iuser;
+ camera_background_images_stereo_setup(draw_ctx->scene, draw_ctx->v3d, ima, &iuser);
+ tex = GPU_texture_from_blender(ima, &iuser, NULL, GL_TEXTURE_2D);
if (tex) {
size[0] = GPU_texture_orig_width(tex);
size[1] = GPU_texture_orig_height(tex);
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index 0ab67d620ee..bc052e60009 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -203,7 +203,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
/* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
* But this is a workaround for a missing update tagging from operators. */
if (scene->display.shading.type != wpd->shading.type ||
- XRAY_ENABLED(v3d) != XRAY_ENABLED((&scene->display))) {
+ (v3d && (XRAY_ENABLED(v3d) != XRAY_ENABLED(&scene->display)))) {
wpd->view_updated = true;
}
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index b91ca7cf070..742489c7311 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -212,8 +212,10 @@ static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
DRW_shgroup_hair_create_sub(ob, psys, md, grp);
}
-/* Decide what colortype to draw the object with.
- * In some cases it can be overwritten by workbench_material_setup(). */
+/**
+ * Decide what color-type to draw the object with.
+ * In some cases it can be overwritten by #workbench_material_setup().
+ */
static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
Object *ob,
bool *r_sculpt_pbvh,
@@ -527,6 +529,8 @@ void workbench_draw_finish(void *ved)
{
WORKBENCH_Data *vedata = ved;
workbench_volume_draw_finish(vedata);
+ /* Reset default view. */
+ DRW_view_set_active(NULL);
}
static void workbench_engine_free(void)
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 8ed7bb25336..6c767102803 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -78,10 +78,10 @@ struct rcti;
typedef struct DRWCallBuffer DRWCallBuffer;
typedef struct DRWInterface DRWInterface;
typedef struct DRWPass DRWPass;
+typedef struct DRWShaderLibrary DRWShaderLibrary;
typedef struct DRWShadingGroup DRWShadingGroup;
typedef struct DRWUniform DRWUniform;
typedef struct DRWView DRWView;
-typedef struct DRWShaderLibrary DRWShaderLibrary;
/* TODO Put it somewhere else? */
typedef struct BoundSphere {
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 6d81d82a6cf..d718522bdb4 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1120,7 +1120,7 @@ static void use_drw_engine(DrawEngineType *engine)
/* Gather all draw engines needed and store them in DST.enabled_engines
* That also define the rendering order of engines */
-static void drw_engines_enable_from_engine(RenderEngineType *engine_type, eDrawType drawtype)
+static void drw_engines_enable_from_engine(const RenderEngineType *engine_type, eDrawType drawtype)
{
switch (drawtype) {
case OB_WIRE:
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 7b08f44921f..7f9a6f578b7 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -558,13 +558,12 @@ void DRW_shader_library_add_file(DRWShaderLibrary *lib, char *lib_code, const ch
if (index > -1) {
lib->libs[index] = lib_code;
BLI_strncpy(lib->libs_name[index], lib_name, MAX_LIB_NAME);
+ lib->libs_deps[index] = drw_shader_dependencies_get(lib, lib_code);
}
else {
printf("Error: Too many libraries. Cannot add %s.\n", lib_name);
BLI_assert(0);
}
-
- lib->libs_deps[index] = drw_shader_dependencies_get(lib, lib_code);
}
/* Return an allocN'ed string containing the shader code with its dependencies prepended.
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index ebde475a075..24ffc60453b 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -71,6 +71,7 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
@@ -916,7 +917,8 @@ static bool acf_group_setting_valid(bAnimContext *ac,
/* for now, all settings are supported, though some are only conditionally */
switch (setting) {
/* unsupported */
- case ACHANNEL_SETTING_SOLO: /* Only available in NLA Editor for tracks */
+ case ACHANNEL_SETTING_SOLO: /* Only available in NLA Editor for tracks */
+ case ACHANNEL_SETTING_PINNED: /* Only for NLA actions */
return false;
/* conditionally supported */
@@ -1963,6 +1965,25 @@ static int acf_dsskey_icon(bAnimListElem *UNUSED(ale))
return ICON_SHAPEKEY_DATA;
}
+/* check if some setting exists for this channel */
+static bool acf_dsskey_setting_valid(bAnimContext *ac,
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
+{
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
+
+ /* mute is only supported for NLA */
+ case ACHANNEL_SETTING_MUTE:
+ return ((ac) && (ac->spacetype == SPACE_NLA));
+
+ default:
+ return false;
+ }
+}
+
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac),
eAnimChannel_Settings setting,
@@ -2029,9 +2050,9 @@ static bAnimChannelType ACF_DSSKEY = {
acf_generic_idblock_name_prop, /* name prop */
acf_dsskey_icon, /* icon */
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsskey_setting_flag, /* flag for setting */
- acf_dsskey_setting_ptr, /* pointer for setting */
+ acf_dsskey_setting_valid, /* has setting */
+ acf_dsskey_setting_flag, /* flag for setting */
+ acf_dsskey_setting_ptr, /* pointer for setting */
};
/* World Expander ------------------------------------------- */
@@ -3155,6 +3176,8 @@ static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac),
/* unsupported */
case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
case ACHANNEL_SETTING_SOLO: /* nla editor only */
+ case ACHANNEL_SETTING_MOD_OFF:
+ case ACHANNEL_SETTING_PINNED: /* nla actions only */
return false;
/* always available */
@@ -3335,6 +3358,9 @@ static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac),
case ACHANNEL_SETTING_EXPAND: /* mask layers are more like F-Curves than groups */
case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
case ACHANNEL_SETTING_SOLO: /* nla editor only */
+ case ACHANNEL_SETTING_MOD_OFF:
+ case ACHANNEL_SETTING_PINNED: /* nla actions only */
+ case ACHANNEL_SETTING_MUTE:
return false;
/* always available */
@@ -4112,10 +4138,6 @@ void ANIM_channel_draw(
/* just skip - drawn as widget now */
offset += ICON_WIDTH;
}
- else if (ale->type == ANIMTYPE_GPLAYER) {
- /* just skip - drawn as a widget */
- offset += ICON_WIDTH;
- }
}
/* step 5) draw name ............................................... */
@@ -4163,8 +4185,16 @@ void ANIM_channel_draw(
}
/* step 6) draw backdrops behind mute+protection toggles + (sliders) ....................... */
- /* reset offset - now goes from RHS of panel */
- offset = 0;
+ /* - Reset offset - now goes from RHS of panel.
+ * - Exception for graph editor, which needs extra space for the scroll bar.
+ */
+ if (ac->spacetype == SPACE_GRAPH &&
+ ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_GROUP)) {
+ offset = V2D_SCROLL_WIDTH;
+ }
+ else {
+ offset = 0;
+ }
/* TODO: when drawing sliders, make those draw instead of these toggles if not enough space */
@@ -4207,10 +4237,17 @@ void ANIM_channel_draw(
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
offset += ICON_WIDTH;
}
+
+ /* grease pencil visibility... */
if (ale->type == ANIMTYPE_GPLAYER) {
offset += ICON_WIDTH;
}
+ /* modifiers toggle... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
+ offset += ICON_WIDTH;
+ }
+
/* pinned... */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PINNED)) {
offset += ICON_WIDTH;
@@ -4957,8 +4994,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
/* modifiers disable */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
- /* hack: extra spacing, to avoid touching the mute toggle */
- offset -= ICON_WIDTH * 1.2f;
+ offset -= ICON_WIDTH;
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_MOD_OFF);
}
@@ -5073,37 +5109,19 @@ void ANIM_channel_draw_widgets(const bContext *C,
else if (ale->type == ANIMTYPE_GPLAYER) {
bGPdata *gpd = (bGPdata *)ale->id;
if ((gpd != NULL) && ((gpd->flag & GP_DATA_ANNOTATIONS) == 0)) {
- /* Add some offset to make it more pleasing to the eye. */
- offset += SLIDER_WIDTH / 2.1f;
+ /* Reset slider offset, in order to add special gp icons. */
+ offset += SLIDER_WIDTH;
char *gp_rna_path = NULL;
bGPDlayer *gpl = (bGPDlayer *)ale->data;
- const short width = SLIDER_WIDTH / 5;
/* Create the RNA pointers. */
RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, &ptr);
RNA_id_pointer_create(ale->id, &id_ptr);
int icon;
- /* Layer opacity. */
- UI_block_emboss_set(block, UI_EMBOSS);
- prop = RNA_struct_find_property(&ptr, "opacity");
- gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
- if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
- uiDefAutoButR(block,
- &ptr,
- prop,
- array_index,
- "",
- ICON_NONE,
- offset,
- ymid,
- width * 3,
- channel_height);
- }
- MEM_freeN(gp_rna_path);
-
/* Mask Layer. */
+ offset -= ICON_WIDTH;
UI_block_emboss_set(block, UI_EMBOSS_NONE);
prop = RNA_struct_find_property(&ptr, "use_mask_layer");
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
@@ -5121,14 +5139,15 @@ void ANIM_channel_draw_widgets(const bContext *C,
array_index,
"",
icon,
- offset + (width * 3),
+ offset,
ymid,
- width,
+ ICON_WIDTH,
channel_height);
}
MEM_freeN(gp_rna_path);
/* Layer onion skinning switch. */
+ offset -= ICON_WIDTH;
prop = RNA_struct_find_property(&ptr, "use_onion_skinning");
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
@@ -5140,7 +5159,27 @@ void ANIM_channel_draw_widgets(const bContext *C,
array_index,
"",
icon,
- offset + (width * 4),
+ offset,
+ ymid,
+ ICON_WIDTH,
+ channel_height);
+ }
+ MEM_freeN(gp_rna_path);
+
+ /* Layer opacity. */
+ const short width = SLIDER_WIDTH * 0.6;
+ offset -= width;
+ UI_block_emboss_set(block, UI_EMBOSS);
+ prop = RNA_struct_find_property(&ptr, "opacity");
+ gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
+ if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
+ uiDefAutoButR(block,
+ &ptr,
+ prop,
+ array_index,
+ "",
+ ICON_NONE,
+ offset,
ymid,
width,
channel_height);
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index 98fcb9c5ce5..439b8071deb 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -368,9 +368,7 @@ void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
if (ale->update & ANIM_UPDATE_ORDER) {
ale->update &= ~ANIM_UPDATE_ORDER;
if (gpl) {
- /* While correct & we could enable it: 'posttrans_gpd_clean' currently
- * both sorts and removes doubles, so this is not necessary here. */
- // gpencil_sort_frames(gpl);
+ BKE_gpencil_layer_frames_sort(gpl, NULL);
}
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 4b0a4bcf46b..8dfc9cd8d1a 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1715,22 +1715,33 @@ static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data,
/* loop over layers as the conditions are acceptable (top-Down order) */
for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
/* only if selected */
- if (ANIMCHANNEL_SELOK(SEL_GPL(gpl))) {
- /* only if editable */
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
- /* active... */
- if (!(filter_mode & ANIMFILTER_ACTIVE) || (gpl->flag & GP_LAYER_ACTIVE)) {
- /* skip layer if the name doesn't match the filter string */
- if ((ads) && (ads->searchstr[0] != '\0')) {
- if (name_matches_dopesheet_filter(ads, gpl->info) == false) {
- continue;
- }
- }
- /* add to list */
- ANIMCHANNEL_NEW_CHANNEL(gpl, ANIMTYPE_GPLAYER, gpd, NULL);
- }
- }
+ if (!ANIMCHANNEL_SELOK(SEL_GPL(gpl))) {
+ continue;
+ }
+
+ /* only if editable */
+ if ((filter_mode & ANIMFILTER_FOREDIT) && !EDITABLE_GPL(gpl)) {
+ continue;
+ }
+
+ /* active... */
+ if ((filter_mode & ANIMFILTER_ACTIVE) && (gpl->flag & GP_LAYER_ACTIVE) == 0) {
+ continue;
}
+
+ /* skip layer if the name doesn't match the filter string */
+ if (ads != NULL && ads->searchstr[0] != '\0' &&
+ name_matches_dopesheet_filter(ads, gpl->info) == false) {
+ continue;
+ }
+
+ /* Skip empty layers. */
+ if (BLI_listbase_is_empty(&gpl->frames)) {
+ continue;
+ }
+
+ /* add to list */
+ ANIMCHANNEL_NEW_CHANNEL(gpl, ANIMTYPE_GPLAYER, gpd, NULL);
}
return items;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 22a42d56fcd..c290a2ac70a 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -2709,7 +2709,7 @@ void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
/* ******************************************* */
/* AUTO KEYFRAME */
-bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
+bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
{
float cfra = (float)CFRA; // XXX for now, this will do
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 721953f41c8..6f9769f9785 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -673,7 +673,7 @@ bool ANIM_keyingset_find_id(KeyingSet *ks, ID *id)
/* Getters for Active/Indices ----------------------------- */
/* Get the active Keying Set for the Scene provided */
-KeyingSet *ANIM_scene_get_active_keyingset(Scene *scene)
+KeyingSet *ANIM_scene_get_active_keyingset(const Scene *scene)
{
/* if no scene, we've got no hope of finding the Keying Set */
if (scene == NULL) {
@@ -728,7 +728,7 @@ int ANIM_scene_get_keyingset_index(Scene *scene, KeyingSet *ks)
}
/* Get Keying Set to use for Auto-Keyframing some transforms */
-KeyingSet *ANIM_get_keyingset_for_autokeying(Scene *scene, const char *transformKSName)
+KeyingSet *ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
{
/* get KeyingSet to use
* - use the active KeyingSet if defined (and user wants to use it for all autokeying),
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index d1352c66f75..1b147663a7e 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -609,6 +609,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.gpencil_draw.draw
brush.gpencil_draw.erase
brush.gpencil_draw.fill
+ brush.gpencil_draw.tint
brush.paint_texture.airbrush
brush.paint_texture.clone
brush.paint_texture.draw
@@ -622,6 +623,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.paint_vertex.average
brush.paint_vertex.blur
brush.paint_vertex.draw
+ brush.paint_vertex.replace
brush.paint_vertex.smear
brush.paint_weight.average
brush.paint_weight.blur
@@ -638,8 +640,11 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.sculpt.blob
brush.sculpt.clay
brush.sculpt.clay_strips
+ brush.sculpt.clay_thumb
+ brush.sculpt.cloth
brush.sculpt.crease
brush.sculpt.draw
+ brush.sculpt.draw_face_sets
brush.sculpt.draw_sharp
brush.sculpt.elastic_deform
brush.sculpt.fill
@@ -703,6 +708,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
ops.gpencil.sculpt_twist
ops.gpencil.sculpt_weight
ops.gpencil.stroke_cutter
+ ops.gpencil.transform_fill
ops.mesh.bevel
ops.mesh.bisect
ops.mesh.dupli_extrude_cursor
@@ -776,6 +782,7 @@ if(WITH_BLENDER)
# images
data_to_c_simple(../../../../release/datafiles/splash.png SRC)
data_to_c_simple(../../../../release/datafiles/splash_2x.png SRC)
+ data_to_c_simple(../../../../release/datafiles/alert_icons.png SRC)
# XXX These are handy, but give nasty "false changes" in svn :/
# svg_to_png(../../../../release/datafiles/blender_icons.svg
# ../../../../release/datafiles/blender_icons16.png
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 512e1ec6270..4083169d65c 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -58,8 +58,8 @@ set(SRC
gpencil_undo.c
gpencil_utils.c
gpencil_uv.c
- gpencil_vertex_paint.c
gpencil_vertex_ops.c
+ gpencil_vertex_paint.c
gpencil_weight_paint.c
gpencil_intern.h
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 9b33e999a25..e5d332a86de 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -3179,7 +3179,7 @@ void GPENCIL_OT_color_unlock_all(wmOperatorType *ot)
/* ***************** Select all strokes using color ************************ */
-static int gpencil_color_select_exec(bContext *C, wmOperator *op)
+static int gpencil_select_material_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
@@ -3249,15 +3249,15 @@ static int gpencil_color_select_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_color_select(wmOperatorType *ot)
+void GPENCIL_OT_select_material(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Color";
- ot->idname = "GPENCIL_OT_color_select";
- ot->description = "Select all Grease Pencil strokes using current color";
+ ot->name = "Select Material";
+ ot->idname = "GPENCIL_OT_select_material";
+ ot->description = "Select/Deselect all Grease Pencil strokes using current material";
/* callbacks */
- ot->exec = gpencil_color_select_exec;
+ ot->exec = gpencil_select_material_exec;
ot->poll = gpencil_active_color_poll;
/* flags */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 2d36e426835..a12fd81e032 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -407,7 +407,7 @@ void GPENCIL_OT_select_less(struct wmOperatorType *ot);
void GPENCIL_OT_select_first(struct wmOperatorType *ot);
void GPENCIL_OT_select_last(struct wmOperatorType *ot);
void GPENCIL_OT_select_alternate(struct wmOperatorType *ot);
-void GPENCIL_OT_select_color(struct wmOperatorType *ot);
+void GPENCIL_OT_select_vertex_color(struct wmOperatorType *ot);
void GPENCIL_OT_duplicate(struct wmOperatorType *ot);
void GPENCIL_OT_delete(struct wmOperatorType *ot);
@@ -552,7 +552,7 @@ void GPENCIL_OT_color_hide(struct wmOperatorType *ot);
void GPENCIL_OT_color_reveal(struct wmOperatorType *ot);
void GPENCIL_OT_color_lock_all(struct wmOperatorType *ot);
void GPENCIL_OT_color_unlock_all(struct wmOperatorType *ot);
-void GPENCIL_OT_color_select(struct wmOperatorType *ot);
+void GPENCIL_OT_select_material(struct wmOperatorType *ot);
void GPENCIL_OT_set_active_material(struct wmOperatorType *ot);
/* convert old 2.7 files to 2.8 */
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 275075c38db..233bebfc9b6 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -544,7 +544,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_select_first);
WM_operatortype_append(GPENCIL_OT_select_last);
WM_operatortype_append(GPENCIL_OT_select_alternate);
- WM_operatortype_append(GPENCIL_OT_select_color);
+ WM_operatortype_append(GPENCIL_OT_select_vertex_color);
WM_operatortype_append(GPENCIL_OT_duplicate);
WM_operatortype_append(GPENCIL_OT_delete);
@@ -653,7 +653,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_color_reveal);
WM_operatortype_append(GPENCIL_OT_color_lock_all);
WM_operatortype_append(GPENCIL_OT_color_unlock_all);
- WM_operatortype_append(GPENCIL_OT_color_select);
+ WM_operatortype_append(GPENCIL_OT_select_material);
/* Editing (Time) --------------- */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 46788eba370..e7586d95d29 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1653,9 +1653,6 @@ static void gp_session_validatebuffer(tGPsdata *p)
/* reset flags */
gpd->runtime.sbuffer_sflag = 0;
- /* reset region */
- gpd->runtime.ar = NULL;
-
/* reset inittime */
p->inittime = 0.0;
@@ -1884,7 +1881,6 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p)
/* setup active color */
/* region where paint was originated */
- p->gpd->runtime.ar = CTX_wm_region(C);
int totcol = p->ob->totcol;
gp_init_colors(p);
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 96522d1750c..66c0131cd61 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -1157,8 +1157,6 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
/* set GP datablock */
tgpi->gpd = gpd;
- /* region where paint was originated */
- tgpi->gpd->runtime.ar = tgpi->region;
/* if brush doesn't exist, create a new set (fix damaged files from old versions) */
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 26b68707d55..133891cda13 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -1655,7 +1655,50 @@ void GPENCIL_OT_select(wmOperatorType *ot)
}
/* Select by Vertex Color. */
-static bool gpencil_select_color_poll(bContext *C)
+/* Helper to create a hash of colors. */
+static void gpencil_selected_hue_table(bContext *C,
+ Object *ob,
+ const int threshold,
+ GHash *hue_table)
+{
+ const float range = pow(10, 5 - threshold);
+ float hsv[3];
+
+ /* Extract all colors. */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+ if ((gps->flag & GP_STROKE_SELECT) == 0) {
+ continue;
+ }
+
+ /* Read all points to get all colors selected. */
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (((pt->flag & GP_SPOINT_SELECT) == 0) || (pt->vert_color[3] == 0.0f)) {
+ continue;
+ }
+ /* Round Hue value. */
+ rgb_to_hsv_compat_v(pt->vert_color, hsv);
+ uint key = truncf(hsv[0] * range);
+ if (!BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) {
+ BLI_ghash_insert(hue_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+}
+
+static bool gpencil_select_vertex_color_poll(bContext *C)
{
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
@@ -1678,38 +1721,46 @@ static bool gpencil_select_color_poll(bContext *C)
return false;
}
-static int gpencil_select_color_exec(bContext *C, wmOperator *op)
+static int gpencil_select_vertex_color_exec(bContext *C, wmOperator *op)
{
- const float threshold = RNA_float_get(op->ptr, "threshold");
-
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
+
+ const float threshold = RNA_int_get(op->ptr, "threshold");
+ const int selectmode = gpencil_select_mode_from_vertex(ts->gpencil_selectmode_vertex);
bGPdata *gpd = (bGPdata *)ob->data;
- if (!GPENCIL_VERTEX_MODE(gpd)) {
- return OPERATOR_CANCELLED;
- }
+ const float range = pow(10, 5 - threshold);
- Paint *paint = &ts->gp_vertexpaint->paint;
- Brush *brush = paint->brush;
bool done = false;
- float hsv_brush[3], hsv_stroke[3];
- rgb_to_hsv_compat_v(brush->rgb, hsv_brush);
+ /* Create a hash table with all selected colors. */
+ GHash *hue_table = BLI_ghash_int_new(__func__);
+ gpencil_selected_hue_table(C, ob, threshold, hue_table);
+ if (BLI_ghash_len(hue_table) == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Select before some Vertex to use as a filter color");
+ BLI_ghash_free(hue_table, NULL, NULL);
+
+ return OPERATOR_CANCELLED;
+ }
- /* Select any visible stroke that uses this color */
+ /* Select any visible stroke that uses any of these colors. */
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
bGPDspoint *pt;
int i;
bool gps_selected = false;
/* Check all stroke points. */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->vert_color[3] < 0.03f) {
+ if (pt->vert_color[3] == 0.0f) {
continue;
}
- rgb_to_hsv_compat_v(pt->vert_color, hsv_stroke);
- /* Only check Hue to get full value and saturation ranges. */
- if (compare_ff(hsv_stroke[0], hsv_brush[0], threshold)) {
+ /* Only check Hue to get value and saturation full ranges. */
+ float hsv[3];
+ /* Round Hue value. */
+ rgb_to_hsv_compat_v(pt->vert_color, hsv);
+ uint key = truncf(hsv[0] * range);
+
+ if (BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) {
pt->flag |= GP_SPOINT_SELECT;
gps_selected = true;
}
@@ -1718,6 +1769,15 @@ static int gpencil_select_color_exec(bContext *C, wmOperator *op)
if (gps_selected) {
gps->flag |= GP_STROKE_SELECT;
done = true;
+
+ /* Extend stroke selection. */
+ if (selectmode == GP_SELECTMODE_STROKE) {
+ bGPDspoint *pt1 = NULL;
+
+ for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) {
+ pt1->flag |= GP_SPOINT_SELECT;
+ }
+ }
}
}
CTX_DATA_END;
@@ -1733,27 +1793,41 @@ static int gpencil_select_color_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
}
+ /* Free memory. */
+ if (hue_table != NULL) {
+ BLI_ghash_free(hue_table, NULL, NULL);
+ }
+
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_select_color(wmOperatorType *ot)
+void GPENCIL_OT_select_vertex_color(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Select Color";
- ot->idname = "GPENCIL_OT_select_color";
- ot->description = "Select all strokes with same color";
+ ot->name = "Select Vertex Color";
+ ot->idname = "GPENCIL_OT_select_vertex_color";
+ ot->description = "Select all points with similar vertex color of current selected";
/* callbacks */
- ot->exec = gpencil_select_color_exec;
- ot->poll = gpencil_select_color_poll;
+ ot->exec = gpencil_select_vertex_color_exec;
+ ot->poll = gpencil_select_vertex_color_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_float(ot->srna, "threshold", 0.01f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
+ prop = RNA_def_int(
+ ot->srna,
+ "threshold",
+ 0,
+ 0,
+ 5,
+ "Threshold",
+ "Tolerance of the selection. Higher values select a wider range of similar colors",
+ 0,
+ 5);
/* avoid re-using last var */
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index a975af1c19a..7fe6f374766 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -2583,10 +2583,9 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc,
bGPDspoint pt_dummy, pt_dummy_ps;
float boundbox_min[2] = {0.0f};
float boundbox_max[2] = {0.0f};
- float zerov3[3];
/* Check we have something to use (only for old files). */
- if (equals_v3v3(zerov3, gps->boundbox_min)) {
+ if (is_zero_v3(gps->boundbox_min)) {
BKE_gpencil_stroke_boundingbox_calc(gps);
}
diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
index c730d1b493e..45dc22bafba 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_paint.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -104,6 +104,7 @@ typedef struct tGP_BrushVertexpaintData {
bGPdata *gpd;
Brush *brush;
+ float linear_color[3];
eGPDvertex_brush_Flag flag;
eGP_Vertex_SelectMaskFlag mask;
@@ -444,7 +445,7 @@ static bool brush_tint_apply(tGP_BrushVertexpaintData *gso,
/* Premult. */
mul_v3_fl(pt->vert_color, pt->vert_color[3]);
/* "Alpha over" blending. */
- interp_v3_v3v3(pt->vert_color, pt->vert_color, brush->rgb, inf);
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, gso->linear_color, inf);
pt->vert_color[3] = pt->vert_color[3] * (1.0 - inf) + inf;
/* Un-premult. */
if (pt->vert_color[3] > 0.0f) {
@@ -463,7 +464,7 @@ static bool brush_tint_apply(tGP_BrushVertexpaintData *gso,
/* Premult. */
mul_v3_fl(gps->vert_color_fill, gps->vert_color_fill[3]);
/* "Alpha over" blending. */
- interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, brush->rgb, inf_fill);
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, gso->linear_color, inf_fill);
gps->vert_color_fill[3] = gps->vert_color_fill[3] * (1.0 - inf_fill) + inf_fill;
/* Un-premult. */
if (gps->vert_color_fill[3] > 0.0f) {
@@ -483,19 +484,15 @@ static bool brush_replace_apply(tGP_BrushVertexpaintData *gso, bGPDstroke *gps,
/* Apply color to Stroke point. */
if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
- copy_v3_v3(pt->vert_color, brush->rgb);
- /* If not mix color, full replace. */
- if (pt->vert_color[3] == 0.0f) {
- pt->vert_color[3] = 1.0f;
+ if (pt->vert_color[3] > 0.0f) {
+ copy_v3_v3(pt->vert_color, gso->linear_color);
}
}
/* Apply color to Fill area (all with same color and factor). */
if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
- copy_v3_v3(gps->vert_color_fill, brush->rgb);
- /* If not mix color, full replace. */
- if (gps->vert_color_fill[3] == 0.0f) {
- gps->vert_color_fill[3] = 1.0f;
+ if (gps->vert_color_fill[3] > 0.0f) {
+ copy_v3_v3(gps->vert_color_fill, gso->linear_color);
}
}
@@ -731,6 +728,7 @@ static bool gp_vertexpaint_brush_init(bContext *C, wmOperator *op)
op->customdata = gso;
gso->brush = paint->brush;
+ srgb_to_linearrgb_v3_v3(gso->linear_color, gso->brush->rgb);
BKE_curvemapping_initialize(gso->brush->curve);
gso->is_painting = false;
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index c1f5eddd8df..a2ad343da37 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -48,6 +48,9 @@ extern char datatoc_blender_icons32_png[];
extern int datatoc_prvicons_png_size;
extern char datatoc_prvicons_png[];
+extern int datatoc_alert_icons_png_size;
+extern char datatoc_alert_icons_png[];
+
extern int datatoc_splash_png_size;
extern char datatoc_splash_png[];
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 06af48cd476..a523e924e54 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -30,6 +30,7 @@ extern "C" {
struct ARegion;
struct FileSelectParams;
+struct Scene;
struct ScrArea;
struct SpaceFile;
struct bContext;
@@ -133,9 +134,13 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y);
void ED_operatormacros_file(void);
-void ED_fileselect_clear(struct wmWindowManager *wm, struct ScrArea *sa, struct SpaceFile *sfile);
+void ED_fileselect_clear(struct wmWindowManager *wm,
+ struct Scene *owner_scene,
+ struct SpaceFile *sfile);
-void ED_fileselect_exit(struct wmWindowManager *wm, struct ScrArea *sa, struct SpaceFile *sfile);
+void ED_fileselect_exit(struct wmWindowManager *wm,
+ struct Scene *owner_scene,
+ struct SpaceFile *sfile);
void ED_fileselect_window_params_get(const struct wmWindow *win,
int win_size[2],
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 8dd162ea538..66aa301f08c 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -33,13 +33,13 @@ struct ListBase;
struct PointerRNA;
struct Brush;
+struct GP_SpaceConversion;
struct bGPDframe;
struct bGPDlayer;
struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
struct tGPspoint;
-struct GP_SpaceConversion;
struct ARegion;
struct Depsgraph;
@@ -47,8 +47,8 @@ struct Main;
struct RegionView3D;
struct ReportList;
struct Scene;
-struct ToolSettings;
struct ScrArea;
+struct ToolSettings;
struct View3D;
struct ViewLayer;
struct bContext;
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 2f81e28b496..6cac3e60531 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -259,13 +259,13 @@ void ANIM_keyingset_infos_exit(void);
/* -------- */
/* Get the active KeyingSet for the given scene */
-struct KeyingSet *ANIM_scene_get_active_keyingset(struct Scene *scene);
+struct KeyingSet *ANIM_scene_get_active_keyingset(const struct Scene *scene);
/* Get the index of the Keying Set provided, for the given Scene */
int ANIM_scene_get_keyingset_index(struct Scene *scene, struct KeyingSet *ks);
/* Get Keying Set to use for Auto-Keyframing some transforms */
-struct KeyingSet *ANIM_get_keyingset_for_autokeying(struct Scene *scene,
+struct KeyingSet *ANIM_get_keyingset_for_autokeying(const struct Scene *scene,
const char *tranformKSName);
/* Dynamically populate an enum of Keying Sets */
@@ -442,7 +442,7 @@ void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const ch
(U.autokey_flag & AUTOKEY_FLAG_##flag))
/* auto-keyframing feature - checks for whether anything should be done for the current frame */
-bool autokeyframe_cfra_can_key(struct Scene *scene, struct ID *id);
+bool autokeyframe_cfra_can_key(const struct Scene *scene, struct ID *id);
/* ************ Keyframe Checking ******************** */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 1dd40f27fbb..0785b0e97f7 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -431,6 +431,7 @@ int ED_region_generic_tools_region_snap_size(const struct ARegion *region, int s
bool ED_region_overlap_isect_x(const ARegion *region, const int event_x);
bool ED_region_overlap_isect_y(const ARegion *region, const int event_y);
bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2]);
+bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2]);
bool ED_region_overlap_isect_x_with_margin(const ARegion *region,
const int event_x,
const int margin);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 7b9e4cfe7bf..f882d6be9a2 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -581,7 +581,7 @@ void ED_draw_object_facemap(struct Depsgraph *depsgraph,
const float col[4],
const int facemap);
-struct RenderEngineType *ED_view3d_engine_type(struct Scene *scene, int drawtype);
+struct RenderEngineType *ED_view3d_engine_type(const struct Scene *scene, int drawtype);
bool ED_view3d_context_activate(struct bContext *C);
void ED_view3d_draw_setup_view(struct wmWindow *win,
@@ -598,7 +598,7 @@ struct Object *ED_view3d_give_object_under_cursor(struct bContext *C, const int
bool ED_view3d_is_object_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *region, bool do_clip);
void ED_view3d_update_viewmat(struct Depsgraph *depsgraph,
- struct Scene *scene,
+ const struct Scene *scene,
struct View3D *v3d,
struct ARegion *region,
float viewmat[4][4],
@@ -648,7 +648,7 @@ bool ED_view3d_camera_lock_sync(const struct Depsgraph *depsgraph,
struct View3D *v3d,
struct RegionView3D *rv3d);
-bool ED_view3d_camera_autokey(struct Scene *scene,
+bool ED_view3d_camera_autokey(const struct Scene *scene,
struct ID *id_key,
struct bContext *C,
const bool do_rotate,
@@ -670,9 +670,9 @@ bool ED_view3d_distance_set_from_location(struct RegionView3D *rv3d,
const float dist_co[3],
const float dist_min);
-float ED_scene_grid_scale(struct Scene *scene, const char **grid_unit);
-float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit);
-void ED_view3d_grid_steps(struct Scene *scene,
+float ED_scene_grid_scale(const struct Scene *scene, const char **grid_unit);
+float ED_view3d_grid_scale(const struct Scene *scene, struct View3D *v3d, const char **grid_unit);
+void ED_view3d_grid_steps(const struct Scene *scene,
struct View3D *v3d,
struct RegionView3D *rv3d,
float *r_grid_steps);
@@ -681,7 +681,7 @@ float ED_view3d_grid_view_scale(struct Scene *scene,
struct RegionView3D *rv3d,
const char **grid_unit);
-void ED_scene_draw_fps(struct Scene *scene, int xoffset, int *yoffset);
+void ED_scene_draw_fps(const struct Scene *scene, int xoffset, int *yoffset);
/* view matrix properties utilities */
/* unused */
@@ -708,7 +708,7 @@ void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrAr
/* view3d_draw_legacy.c */
/* Try avoid using these more move out of legacy. */
-void ED_view3d_draw_bgpic_test(struct Scene *scene,
+void ED_view3d_draw_bgpic_test(const struct Scene *scene,
struct Depsgraph *depsgraph,
struct ARegion *region,
struct View3D *v3d,
diff --git a/source/blender/editors/include/ED_view3d_offscreen.h b/source/blender/editors/include/ED_view3d_offscreen.h
index f69d8367dca..539a4d13ccd 100644
--- a/source/blender/editors/include/ED_view3d_offscreen.h
+++ b/source/blender/editors/include/ED_view3d_offscreen.h
@@ -34,16 +34,16 @@ extern "C" {
#endif
/* ********* exports for space_view3d/ module for offscreen rendering ********** */
-struct Depsgraph;
-struct Scene;
-struct View3D;
struct ARegion;
+struct Depsgraph;
struct GPUOffScreen;
struct GPUViewport;
+struct Scene;
+struct View3D;
struct View3DShading;
void ED_view3d_draw_offscreen(struct Depsgraph *depsgraph,
- struct Scene *scene,
+ const struct Scene *scene,
eDrawType drawtype,
struct View3D *v3d,
struct ARegion *region,
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index dba95c5106e..3e416cd8057 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1124,7 +1124,9 @@ uiBut *uiDefIconButO_ptr(uiBlock *block,
short width,
short height,
const char *tip);
-
+uiBut *uiDefButImage(
+ uiBlock *block, void *imbuf, int x, int y, short width, short height, const uchar color[4]);
+uiBut *uiDefButAlert(uiBlock *block, int icon, int x, int y, short width, short height);
uiBut *uiDefIconTextBut(uiBlock *block,
int type,
int retval,
@@ -1805,7 +1807,7 @@ uiLayout *UI_block_layout(uiBlock *block,
int size,
int em,
int padding,
- struct uiStyle *style);
+ const struct uiStyle *style);
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout);
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y);
@@ -2431,8 +2433,8 @@ int UI_fontstyle_height_max(const struct uiFontStyle *fs);
void UI_draw_icon_tri(float x, float y, char dir, const float[4]);
-struct uiStyle *UI_style_get(void); /* use for fonts etc */
-struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */
+const struct uiStyle *UI_style_get(void); /* use for fonts etc */
+const struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */
/* linker workaround ack! */
void UI_template_fix_linking(void);
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 6bf0cb8952d..a304c76bc9d 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -52,6 +52,17 @@ typedef struct IconFile {
#define PREVIEW_DEFAULT_HEIGHT 128
+typedef enum eAlertIcon {
+ ALERT_ICON_WARNING = 0,
+ ALERT_ICON_QUESTION = 1,
+ ALERT_ICON_ERROR = 2,
+ ALERT_ICON_INFO = 3,
+ ALERT_ICON_BLENDER = 4,
+ ALERT_ICON_MAX,
+} eAlertIcon;
+
+struct ImBuf *UI_alert_image(eAlertIcon icon);
+
/*
* Resizable Icons for Blender
*/
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index ecdae3ead6b..ff9719d4674 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -250,13 +250,17 @@ char UI_view2d_rect_in_scrollers(const struct ARegion *region,
const struct rcti *rect);
/* cached text drawing in v2d, to allow pixel-aligned draw as post process */
-void UI_view2d_text_cache_add(
- struct View2D *v2d, float x, float y, const char *str, size_t str_len, const char col[4]);
+void UI_view2d_text_cache_add(struct View2D *v2d,
+ float x,
+ float y,
+ const char *str,
+ size_t str_len,
+ const unsigned char col[4]);
void UI_view2d_text_cache_add_rectf(struct View2D *v2d,
const struct rctf *rect_view,
const char *str,
size_t str_len,
- const char col[4]);
+ const unsigned char col[4]);
void UI_view2d_text_cache_draw(struct ARegion *region);
/* operators */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index a0a3d0a3b85..3d8c0da78ea 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -366,7 +366,7 @@ void UI_block_translate(uiBlock *block, int x, int y)
static void ui_block_bounds_calc_text(uiBlock *block, float offset)
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
uiBut *bt, *init_col_bt, *col_bt;
int i = 0, j, x1addval = offset;
@@ -4439,6 +4439,48 @@ uiBut *uiDefBut(uiBlock *block,
return but;
}
+uiBut *uiDefButImage(
+ uiBlock *block, void *imbuf, int x, int y, short width, short height, const uchar color[4])
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_IMAGE, 0, "", x, y, width, height, imbuf, 0, 0, 0, 0, "");
+ if (color) {
+ copy_v4_v4_uchar(but->col, color);
+ }
+ else {
+ but->col[0] = 255;
+ but->col[1] = 255;
+ but->col[2] = 255;
+ but->col[3] = 255;
+ }
+ ui_but_update(but);
+ return but;
+}
+
+uiBut *uiDefButAlert(uiBlock *block, int icon, int x, int y, short width, short height)
+{
+ struct ImBuf *ibuf = UI_alert_image(icon);
+
+ if (icon == ALERT_ICON_BLENDER) {
+ return uiDefButImage(block, ibuf, x, y, width, height, NULL);
+ }
+ else {
+ uchar icon_color[4];
+ ThemeColorID color_id = TH_INFO_WARNING;
+ if (icon == ALERT_ICON_ERROR) {
+ color_id = TH_INFO_ERROR;
+ }
+ else if (icon == ALERT_ICON_INFO) {
+ color_id = TH_INFO_INFO;
+ }
+ else if (icon == ALERT_ICON_QUESTION) {
+ color_id = TH_INFO_PROPERTY;
+ }
+ UI_GetThemeColorType4ubv(color_id, SPACE_INFO, icon_color);
+ return uiDefButImage(block, ibuf, x, y, width, height, icon_color);
+ }
+}
+
/**
* if \a _x_ is a power of two (only one bit) return the power,
* otherwise return -1.
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index c9a46e00520..f6da9663daf 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -169,7 +169,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *region, void *arg)
wmKeyMapItem *kmi;
PointerRNA ptr;
uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
IDProperty *prop;
const char *idname = shortcut_get_operator_property(C, but, &prop);
@@ -225,7 +225,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *region, void *arg)
wmKeyMapItem *kmi;
PointerRNA ptr;
uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
int kmi_id;
IDProperty *prop;
const char *idname = shortcut_get_operator_property(C, but, &prop);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index e8e74e77425..2800d808889 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -707,9 +707,6 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region),
return;
}
- float facx = 1.0f;
- float facy = 1.0f;
-
int w = BLI_rcti_size_x(rect);
int h = BLI_rcti_size_y(rect);
@@ -722,10 +719,18 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region),
# endif
GPU_blend(true);
+ /* Combine with premultiplied alpha. */
+ GPU_blend_set_func_separate(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
if (w != ibuf->x || h != ibuf->y) {
- facx = (float)w / (float)ibuf->x;
- facy = (float)h / (float)ibuf->y;
+ /* We scale the bitmap, rather than have OGL do a worse job. */
+ IMB_scaleImBuf(ibuf, w, h);
+ }
+
+ float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ if (but->col[3] != 0) {
+ /* Optionally use uiBut's col to recolor the image. */
+ rgba_uchar_to_float(col, but->col);
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
@@ -738,11 +743,14 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region),
GL_UNSIGNED_BYTE,
GL_NEAREST,
ibuf->rect,
- facx,
- facy,
- NULL);
+ 1.0f,
+ 1.0f,
+ col);
GPU_blend(false);
+ /* Reset default. */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
# if 0
// restore scissortest
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 833631f871d..f4dd114c312 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -58,6 +58,7 @@
#include "BKE_unit.h"
#include "BKE_paint.h"
#include "BKE_curveprofile.h"
+#include "BKE_movieclip.h"
#include "IMB_colormanagement.h"
@@ -2847,10 +2848,9 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
*/
static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, const float x)
{
- uiStyle *style = UI_style_get(); // XXX pass on as arg
- uiFontStyle *fstyle = &style->widget;
+ /* XXX pass on as arg. */
+ uiFontStyle fstyle = UI_style_get()->widget;
const float aspect = but->block->aspect;
- const short fstyle_points_prev = fstyle->points;
float startx = but->rect.xmin;
float starty_dummy = 0.0f;
@@ -2860,13 +2860,13 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
ui_block_to_window_fl(data->region, but->block, &startx, &starty_dummy);
- ui_fontscale(&fstyle->points, aspect);
+ ui_fontscale(&fstyle.points, aspect);
- UI_fontstyle_set(fstyle);
+ UI_fontstyle_set(&fstyle);
- if (fstyle->kerning == 1) {
+ if (fstyle.kerning == 1) {
/* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ BLF_enable(fstyle.uifont_id, BLF_KERNING_DEFAULT);
}
ui_but_text_password_hide(password_str, but, false);
@@ -2888,7 +2888,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
while (i > 0) {
if (BLI_str_cursor_step_prev_utf8(str, but->ofs, &i)) {
/* 0.25 == scale factor for less sensitivity */
- if (BLF_width(fstyle->uifont_id, str + i, (str_last - str) - i) > (startx - x) * 0.25f) {
+ if (BLF_width(fstyle.uifont_id, str + i, (str_last - str) - i) > (startx - x) * 0.25f) {
break;
}
}
@@ -2912,7 +2912,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
but->pos = pos_prev = ((str_last - str) - but->ofs);
while (true) {
- cdist = startx + BLF_width(fstyle->uifont_id, str + but->ofs, (str_last - str) - but->ofs);
+ cdist = startx + BLF_width(fstyle.uifont_id, str + but->ofs, (str_last - str) - but->ofs);
/* check if position is found */
if (cdist < x) {
@@ -2944,13 +2944,11 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
}
}
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fstyle.kerning == 1) {
+ BLF_disable(fstyle.uifont_id, BLF_KERNING_DEFAULT);
}
ui_but_text_password_hide(password_str, but, true);
-
- fstyle->points = fstyle_points_prev;
}
static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, const float x)
@@ -7339,8 +7337,10 @@ static bool ui_numedit_but_TRACKPREVIEW(
}
if (!scopes->track_locked) {
- if (scopes->marker->framenr != scopes->framenr) {
- scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr);
+ const MovieClip *clip = CTX_data_edit_movieclip(C);
+ int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scopes->framenr);
+ if (scopes->marker->framenr != clip_framenr) {
+ scopes->marker = BKE_tracking_marker_ensure(scopes->track, clip_framenr);
}
scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 3e07023e52d..a37b49f5b6e 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -177,6 +177,30 @@ static const IconType icontypes[] = {
# include "UI_icons.h"
};
+/* ********** Alert Icons ********** */
+
+# define ALERT_IMG_SIZE 256
+
+ImBuf *UI_alert_image(eAlertIcon icon)
+{
+# ifdef WITH_HEADLESS
+ return NULL
+# else
+ ImBuf *ibuf;
+ icon = MIN2(icon, ALERT_ICON_MAX - 1);
+ const int left = icon * ALERT_IMG_SIZE;
+ const rcti crop = {left, left + ALERT_IMG_SIZE - 1, 0, ALERT_IMG_SIZE - 1};
+ ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_alert_icons_png,
+ datatoc_alert_icons_png_size,
+ IB_rect,
+ NULL,
+ "alert_icon");
+ IMB_rect_crop(ibuf, &crop);
+ IMB_premultiply_alpha(ibuf);
+ return ibuf;
+# endif
+}
+
/* **************************************************** */
static DrawInfo *def_internal_icon(
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index a2e239884a3..e2b4e8f2958 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -839,7 +839,7 @@ const struct uiWidgetColors *ui_tooltip_get_theme(void);
void ui_draw_widget_menu_back_color(const rcti *rect, bool use_shadow, const float color[4]);
void ui_draw_widget_menu_back(const rcti *rect, bool use_shadow);
-void ui_draw_tooltip_background(struct uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
+void ui_draw_tooltip_background(const struct uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
extern void ui_draw_but(
const struct bContext *C, ARegion *region, struct uiStyle *style, uiBut *but, rcti *rect);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 1aa2670942f..64ff9d02cdc 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -91,7 +91,7 @@ typedef struct uiLayoutRoot {
uiMenuHandleFunc handlefunc;
void *argv;
- uiStyle *style;
+ const uiStyle *style;
uiBlock *block;
uiLayout *layout;
} uiLayoutRoot;
@@ -499,7 +499,7 @@ static void ui_item_array(uiLayout *layout,
bool compact,
bool show_text)
{
- uiStyle *style = layout->root->style;
+ const uiStyle *style = layout->root->style;
uiBut *but;
PropertyType type;
PropertySubType subtype;
@@ -3707,7 +3707,7 @@ static void ui_litem_layout_root(uiLayout *litem)
/* box layout */
static void ui_litem_estimate_box(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
ui_litem_estimate_column(litem, true);
@@ -3722,7 +3722,7 @@ static void ui_litem_estimate_box(uiLayout *litem)
static void ui_litem_layout_box(uiLayout *litem)
{
uiLayoutItemBx *box = (uiLayoutItemBx *)litem;
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiBut *but;
int w, h;
@@ -3767,7 +3767,7 @@ static void ui_litem_layout_box(uiLayout *litem)
/* multi-column layout, automatically flowing to the next */
static void ui_litem_estimate_column_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
uiItem *item;
int col, x, y, emh, emy, miny, itemw, itemh, maxw = 0;
@@ -3832,7 +3832,7 @@ static void ui_litem_estimate_column_flow(uiLayout *litem)
static void ui_litem_layout_column_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
uiItem *item;
int col, x, y, w, emh, emy, miny, itemw, itemh;
@@ -4071,7 +4071,7 @@ static void ui_litem_grid_flow_compute(ListBase *items,
static void ui_litem_estimate_grid_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
const int space_x = style->columnspace;
@@ -4199,7 +4199,7 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
static void ui_litem_layout_grid_flow(uiLayout *litem)
{
int i;
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
uiItem *item;
@@ -5092,8 +5092,15 @@ static void ui_layout_add_padding_button(uiLayoutRoot *root)
}
}
-uiLayout *UI_block_layout(
- uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, uiStyle *style)
+uiLayout *UI_block_layout(uiBlock *block,
+ int dir,
+ int type,
+ int x,
+ int y,
+ int size,
+ int em,
+ int padding,
+ const uiStyle *style)
{
uiLayout *layout;
uiLayoutRoot *root;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 70d64ff26ab..1f5855aed9e 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -434,7 +434,7 @@ void UI_panel_end(
static void ui_offset_panel_block(uiBlock *block)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
/* compute bounds and offset */
ui_block_bounds_calc(block);
@@ -1938,7 +1938,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active)
// #define USE_FLAT_INACTIVE
const bool is_left = RGN_ALIGN_ENUM_FROM_MASK(region->alignment != RGN_ALIGN_RIGHT);
View2D *v2d = &region->v2d;
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
const uiFontStyle *fstyle = &style->widget;
const int fontid = fstyle->uifont_id;
short fstyle_points = fstyle->points;
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index f75f4c054a3..062a8383061 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -104,13 +104,12 @@ static float ui_pie_menu_title_width(const char *name, int icon)
uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, const wmEvent *event)
{
- uiStyle *style;
+ const uiStyle *style = UI_style_get_dpi();
uiPieMenu *pie;
short event_type;
wmWindow *win = CTX_wm_window(C);
- style = UI_style_get_dpi();
pie = MEM_callocN(sizeof(*pie), "pie menu");
pie->block_radial = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index 1d066b6bbb1..9ceb864b278 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -310,7 +310,7 @@ uiPopupBlockHandle *ui_popup_menu_create(
bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
{
wmWindow *window = CTX_wm_window(C);
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
uiPopupBlockHandle *handle;
uiPopupMenu *pup;
@@ -380,7 +380,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
const char *block_name,
int icon)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu");
uiBut *but;
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 4e4854c8209..d3cd1ebd837 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -94,7 +94,7 @@ static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
{
BLI_assert(pup->ui_size_x != 0);
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
UI_block_flag_enable(pup->block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index 4481ad54d1a..89eb0658d5e 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -498,7 +498,7 @@ static void ui_searchbox_region_free_cb(ARegion *region)
ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but)
{
wmWindow *win = CTX_wm_window(C);
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
static ARegionType type;
ARegion *region;
uiSearchboxData *data;
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index c18c78c22a6..02c69e5cef6 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -1158,7 +1158,7 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
wmWindow *win = CTX_wm_window(C);
const int winx = WM_window_pixels_x(win);
const int winy = WM_window_pixels_y(win);
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
static ARegionType type;
ARegion *region;
int fonth, fontw;
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 192571044b9..fa1f222d27f 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -351,7 +351,7 @@ void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs,
/* ************** helpers ************************ */
/* XXX: read a style configure */
-uiStyle *UI_style_get(void)
+const uiStyle *UI_style_get(void)
{
#if 0
uiStyle *style = NULL;
@@ -364,9 +364,9 @@ uiStyle *UI_style_get(void)
}
/* for drawing, scaled with DPI setting */
-uiStyle *UI_style_get_dpi(void)
+const uiStyle *UI_style_get_dpi(void)
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
static uiStyle _style;
_style = *style;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index b752a1a1429..f11e3a1f5f0 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -591,11 +591,9 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
DEG_relations_tag_update(bmain);
}
else {
- if (id) {
- Main *bmain = CTX_data_main(C);
- id_single_user(C, id, &template_ui->ptr, template_ui->prop);
- DEG_relations_tag_update(bmain);
- }
+ Main *bmain = CTX_data_main(C);
+ id_single_user(C, id, &template_ui->ptr, template_ui->prop);
+ DEG_relations_tag_update(bmain);
}
}
break;
@@ -1137,7 +1135,7 @@ static void template_ID_tabs(bContext *C,
const int but_height = UI_UNIT_Y * 1.1;
uiBlock *block = uiLayoutGetBlock(layout);
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
ListBase ordered;
BKE_id_ordered_list(&ordered, template->idlb);
@@ -3049,7 +3047,7 @@ static void colorband_tools_dofunc(bContext *C, void *coba_v, int event)
static uiBlock *colorband_tools_func(bContext *C, ARegion *region, void *coba_v)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
ColorBand *coba = coba_v;
uiBlock *block;
short yco = 0, menuwidth = 10 * UI_UNIT_X;
@@ -7135,7 +7133,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
uiLayout *ui_abs;
uiBlock *block;
uiBut *but;
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
int width;
int icon;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 31a1c150b12..b61d54e6cff 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -4990,22 +4990,37 @@ static void ui_draw_popover_back_impl(const uiWidgetColors *wcol,
if (ELEM(direction, UI_DIR_UP, UI_DIR_DOWN)) {
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv(wcol->inner);
+
+ const bool is_down = (direction == UI_DIR_DOWN);
+ const int sign = is_down ? 1 : -1;
+ float y = is_down ? rect->ymax : rect->ymin;
+
GPU_blend(true);
immBegin(GPU_PRIM_TRIS, 3);
- if (direction == UI_DIR_DOWN) {
- const float y = rect->ymax;
- immVertex2f(pos, cent_x - unit_half, y);
- immVertex2f(pos, cent_x + unit_half, y);
- immVertex2f(pos, cent_x, y + unit_half);
- }
- else {
- const float y = rect->ymin;
- immVertex2f(pos, cent_x - unit_half, y);
- immVertex2f(pos, cent_x + unit_half, y);
- immVertex2f(pos, cent_x, y - unit_half);
- }
+ immUniformColor4ub(UNPACK3(wcol->outline), 166);
+ immVertex2f(pos, cent_x - unit_half, y);
+ immVertex2f(pos, cent_x + unit_half, y);
+ immVertex2f(pos, cent_x, y + sign * unit_half);
immEnd();
+
+ y = y - sign * round(U.pixelsize * 1.41);
+
+ GPU_blend(false);
+ immBegin(GPU_PRIM_TRIS, 3);
+ immUniformColor4ub(0, 0, 0, 0);
+ immVertex2f(pos, cent_x - unit_half, y);
+ immVertex2f(pos, cent_x + unit_half, y);
+ immVertex2f(pos, cent_x, y + sign * unit_half);
+ immEnd();
+
+ GPU_blend(true);
+ immBegin(GPU_PRIM_TRIS, 3);
+ immUniformColor4ubv(wcol->inner);
+ immVertex2f(pos, cent_x - unit_half, y);
+ immVertex2f(pos, cent_x + unit_half, y);
+ immVertex2f(pos, cent_x, y + sign * unit_half);
+ immEnd();
+
immUnbindProgram();
}
@@ -5235,7 +5250,7 @@ void ui_draw_widget_menu_back(const rcti *rect, bool use_shadow)
ui_draw_widget_back_color(UI_WTYPE_MENU_BACK, use_shadow, rect, NULL);
}
-void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
+void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
{
uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
wt->state(wt, 0, 0);
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index af32143df33..ad2e32149d8 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -243,7 +243,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
{
bool tot_changed = false, do_init;
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
@@ -2146,7 +2146,7 @@ static MemArena *g_v2d_strings_arena = NULL;
static View2DString *g_v2d_strings = NULL;
void UI_view2d_text_cache_add(
- View2D *v2d, float x, float y, const char *str, size_t str_len, const char col[4])
+ View2D *v2d, float x, float y, const char *str, size_t str_len, const uchar col[4])
{
int mval[2];
@@ -2177,7 +2177,7 @@ void UI_view2d_text_cache_add(
/* no clip (yet) */
void UI_view2d_text_cache_add_rectf(
- View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const char col[4])
+ View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const uchar col[4])
{
rcti rect;
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 7eea9e6a697..2c9803d1dd3 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -2155,7 +2155,7 @@ static void VIEW2D_OT_scroller_activate(wmOperatorType *ot)
static int reset_exec(bContext *C, wmOperator *UNUSED(op))
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
ARegion *region = CTX_wm_region(C);
View2D *v2d = &region->v2d;
int winx, winy;
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index 1c4bc33240a..cd91aa1e491 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -80,6 +80,9 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
+ ED_object_sculptmode_exit(C, depsgraph);
+
BKE_sculpt_mask_layers_ensure(ob, NULL);
Mesh *mesh = ob->data;
@@ -209,6 +212,11 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
Object *new_ob = ED_object_add_type(C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits);
BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob, &CD_MASK_EVERYTHING, true);
+ /* Remove the Face Sets as they need to be recreated when entering Sculpt Mode in the new object.
+ * TODO(pablodobarro): In the future we can try to preserve them from the original mesh. */
+ Mesh *new_ob_mesh = new_ob->data;
+ CustomData_free_layers(&new_ob_mesh->pdata, CD_SCULPT_FACE_SETS, new_ob_mesh->totpoly);
+
if (RNA_boolean_get(op->ptr, "apply_shrinkwrap")) {
BKE_shrinkwrap_mesh_nearest_surface_deform(C, new_ob, ob);
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index a4546780dd9..3a1781b941a 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -3382,11 +3382,9 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
if (use_add) {
/* In add mode, we add relative shape key offset. */
- if (kb) {
- const float *rco = CustomData_bmesh_get_n(
- &em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative);
- sub_v3_v3v3(co, co, rco);
- }
+ const float *rco = CustomData_bmesh_get_n(
+ &em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative);
+ sub_v3_v3v3(co, co, rco);
madd_v3_v3fl(eve->co, co, blend);
}
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index edc2f15813c..f06b6a4db2a 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -282,7 +282,9 @@ static bool ed_object_mode_generic_exit_ex(struct Main *bmain,
ED_object_posemode_exit_ex(bmain, ob);
}
}
- else if ((ob->type == OB_GPENCIL) && ((ob->mode & OB_MODE_OBJECT) == 0)) {
+ else if (ob->type == OB_GPENCIL) {
+ /* Accounted for above. */
+ BLI_assert((ob->mode & OB_MODE_OBJECT) == 0);
if (only_test) {
return true;
}
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index bac40b35102..31c4f96693c 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -686,7 +686,7 @@ static int modifier_apply_obdata(
}
if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
- if (!multiresModifier_reshapeFromDeformModifier(depsgraph, mmd, ob, md_eval)) {
+ if (!multiresModifier_reshapeFromDeformModifier(depsgraph, ob, mmd, md_eval)) {
BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
return 0;
}
@@ -1375,26 +1375,25 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
static int multires_subdivide_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
+ Object *object = ED_object_active_context(C);
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
- op, ob, eModifierType_Multires);
+ op, object, eModifierType_Multires);
if (!mmd) {
return OPERATOR_CANCELLED;
}
- multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple);
+ multiresModifier_subdivide(object, mmd);
ED_object_iter_other(
- CTX_data_main(C), ob, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
+ CTX_data_main(C), object, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object);
- if (ob->mode & OB_MODE_SCULPT) {
+ if (object->mode & OB_MODE_SCULPT) {
/* ensure that grid paint mask layer is created */
- BKE_sculpt_mask_layers_ensure(ob, mmd);
+ BKE_sculpt_mask_layers_ensure(object, mmd);
}
return OPERATOR_FINISHED;
@@ -1614,19 +1613,19 @@ void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
/********************* multires apply base ***********************/
static int multires_base_apply_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *object = ED_object_active_context(C);
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
- op, ob, eModifierType_Multires);
+ op, object, eModifierType_Multires);
if (!mmd) {
return OPERATOR_CANCELLED;
}
- multiresModifier_base_apply(mmd, scene, ob);
+ multiresModifier_base_apply(depsgraph, object, mmd);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index c7bba43758f..29bf9e88853 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1586,7 +1586,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob_dst->id, ID_RECALC_COPY_ON_WRITE);
break;
case MAKE_LINKS_MODIFIERS:
- BKE_object_link_modifiers(scene, ob_dst, ob_src);
+ BKE_object_link_modifiers(ob_dst, ob_src);
DEG_id_tag_update(&ob_dst->id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
break;
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 8d268be5a78..631cd961e66 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -207,7 +207,6 @@ typedef enum eSymmetryAxes {
typedef struct QuadriFlowJob {
/* from wmJob */
struct Object *owner;
- struct Main *bmain;
short *stop, *do_update;
float *progress;
@@ -318,13 +317,13 @@ static void quadriflow_update_job(void *customdata, float progress, int *cancel)
*(qj->progress) = progress;
}
-static Mesh *remesh_symmetry_bisect(Main *bmain, Mesh *mesh, eSymmetryAxes symmetry_axes)
+static Mesh *remesh_symmetry_bisect(Mesh *mesh, eSymmetryAxes symmetry_axes)
{
MirrorModifierData mmd = {{0}};
mmd.tolerance = QUADRIFLOW_MIRROR_BISECT_TOLERANCE;
Mesh *mesh_bisect, *mesh_bisect_temp;
- mesh_bisect = BKE_mesh_copy(bmain, mesh);
+ mesh_bisect = BKE_mesh_copy_for_eval(mesh, false);
int axis;
float plane_co[3], plane_no[3];
@@ -342,12 +341,12 @@ static Mesh *remesh_symmetry_bisect(Main *bmain, Mesh *mesh, eSymmetryAxes symme
mesh_bisect = BKE_mesh_mirror_bisect_on_mirror_plane(
&mmd, mesh_bisect, axis, plane_co, plane_no);
if (mesh_bisect_temp != mesh_bisect) {
- BKE_id_free(bmain, mesh_bisect_temp);
+ BKE_id_free(NULL, mesh_bisect_temp);
}
}
}
- BKE_id_free(bmain, mesh);
+ BKE_id_free(NULL, mesh);
return mesh_bisect;
}
@@ -405,10 +404,10 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
/* Run Quadriflow bisect operations on a copy of the mesh to keep the code readable without
* freeing the original ID */
- bisect_mesh = BKE_mesh_copy(qj->bmain, mesh);
+ bisect_mesh = BKE_mesh_copy_for_eval(mesh, false);
/* Bisect the input mesh using the paint symmetry settings */
- bisect_mesh = remesh_symmetry_bisect(qj->bmain, bisect_mesh, qj->symmetry_axes);
+ bisect_mesh = remesh_symmetry_bisect(bisect_mesh, qj->symmetry_axes);
new_mesh = BKE_mesh_remesh_quadriflow_to_mesh_nomain(
bisect_mesh,
@@ -424,7 +423,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
quadriflow_update_job,
(void *)qj);
- BKE_id_free(qj->bmain, bisect_mesh);
+ BKE_id_free(NULL, bisect_mesh);
if (new_mesh == NULL) {
*do_update = true;
@@ -501,7 +500,6 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op)
QuadriFlowJob *job = MEM_mallocN(sizeof(QuadriFlowJob), "QuadriFlowJob");
job->owner = CTX_data_active_object(C);
- job->bmain = CTX_data_main(C);
job->target_faces = RNA_int_get(op->ptr, "target_faces");
job->seed = RNA_int_get(op->ptr, "seed");
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index cff7052ca58..a083675ca01 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2351,7 +2351,7 @@ static void ed_panel_draw(const bContext *C,
int em,
bool vertical)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
/* draw panel */
uiBlock *block = UI_block_begin(C, region, pt->idname, UI_EMBOSS);
@@ -2734,7 +2734,7 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
void ED_region_header_layout(const bContext *C, ARegion *region)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
uiBlock *block;
uiLayout *layout;
HeaderType *ht;
@@ -2960,7 +2960,7 @@ void ED_region_info_draw_multiline(ARegion *region,
const bool full_redraw)
{
const int header_height = UI_UNIT_Y;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
int fontid = style->widget.uifont_id;
int scissor[4];
int num_lines = 0;
@@ -3175,7 +3175,6 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const
ctx.fontid = fontid;
ctx.xmin = xmin;
ctx.ymin = ymin;
- ctx.vertical_offset = vertical_offset;
ctx.current_y = ofs_y;
ctx.vertical_offset = vertical_offset;
IMB_metadata_foreach(ibuf, metadata_custom_draw_fields, &ctx);
@@ -3266,7 +3265,7 @@ void ED_region_image_metadata_draw(
{
float box_y;
rctf rect;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
if (!ibuf->metadata) {
return;
@@ -3521,7 +3520,7 @@ void ED_region_cache_draw_background(ARegion *region)
void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y)
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
int fontid = style->widget.uifont_id;
char numstr[32];
float font_dims[2] = {0.0f, 0.0f};
diff --git a/source/blender/editors/screen/area_query.c b/source/blender/editors/screen/area_query.c
index f8a6b301911..2cccd9a2ba5 100644
--- a/source/blender/editors/screen/area_query.c
+++ b/source/blender/editors/screen/area_query.c
@@ -61,6 +61,18 @@ bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2])
ED_region_overlap_isect_y(region, event_xy[1]));
}
+bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2])
+{
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (ED_region_is_overlap(area->spacetype, region->regiontype)) {
+ if (ED_region_overlap_isect_xy(region, event_xy)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_ar_gutter)
{
*r_ar_gutter = region->winrct;
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index f497b80e0f4..de9e70f8e06 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -59,8 +59,8 @@ set(SRC
paint_vertex_weight_ops.c
paint_vertex_weight_utils.c
sculpt.c
- sculpt_multiplane_scrape.c
sculpt_cloth.c
+ sculpt_multiplane_scrape.c
sculpt_pose.c
sculpt_undo.c
sculpt_uv.c
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 5a830a90092..79c4becd405 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -356,9 +356,6 @@ static void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_se
if (ss->face_sets[vert_map->indices[j]] > 0) {
ss->face_sets[vert_map->indices[j]] = abs(face_set);
}
- else {
- ss->face_sets[vert_map->indices[j]] = -abs(face_set);
- }
}
} break;
case PBVH_BMESH:
@@ -628,6 +625,10 @@ static bool sculpt_vertex_is_boundary(SculptSession *ss, const int index)
return false;
}
+ if (!SCULPT_vertex_all_face_sets_visible_get(ss, index)) {
+ return false;
+ }
+
for (int i = 0; i < vert_map->count; i++) {
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
unsigned f_adj_v[2];
@@ -836,7 +837,7 @@ void SCULPT_floodfill_execute(
sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, from_v, ni)
{
const int to_v = ni.index;
- if (flood->visited_vertices[to_v] == 0) {
+ if (flood->visited_vertices[to_v] == 0 && SCULPT_vertex_visible_get(ss, to_v)) {
flood->visited_vertices[to_v] = 1;
if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) {
@@ -1633,17 +1634,11 @@ static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *a
#define EDGE_DISTANCE_INF -1
-static float *sculpt_boundary_edges_automasking_init(Sculpt *sd,
- Object *ob,
+static float *sculpt_boundary_edges_automasking_init(Object *ob,
+ int propagation_steps,
float *automask_factor)
{
SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
- const int propagation_steps = brush->automasking_boundary_edges_propagation_steps;
-
- if (!sculpt_automasking_enabled(ss, brush)) {
- return NULL;
- }
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
BLI_assert(!"Boundary Edges masking: pmap missing");
@@ -1693,6 +1688,10 @@ static void sculpt_automasking_init(Sculpt *sd, Object *ob)
Brush *brush = BKE_paint_brush(&sd->paint);
const int totvert = SCULPT_vertex_count_get(ss);
+ if (!sculpt_automasking_enabled(ss, brush)) {
+ return;
+ }
+
ss->cache->automask = MEM_callocN(sizeof(float) * SCULPT_vertex_count_get(ss),
"automask_factor");
@@ -1711,7 +1710,8 @@ static void sculpt_automasking_init(Sculpt *sd, Object *ob)
if (brush->automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
SCULPT_vertex_random_access_init(ss);
- sculpt_boundary_edges_automasking_init(sd, ob, ss->cache->automask);
+ sculpt_boundary_edges_automasking_init(
+ ob, brush->automasking_boundary_edges_propagation_steps, ss->cache->automask);
}
}
@@ -3401,7 +3401,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.index,
tls->thread_id);
- if (fade > 0.05f && SCULPT_vertex_all_face_sets_visible_get(ss, vd.index)) {
+ if (fade > 0.05f) {
SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set);
}
}
@@ -3662,6 +3662,10 @@ void SCULPT_relax_vertex(SculptSession *ss,
if (count > 0) {
mul_v3_fl(smooth_pos, 1.0f / (float)count);
}
+ else {
+ copy_v3_v3(r_final_pos, vd->co);
+ return;
+ }
float plane[4];
float smooth_closest_plane[3];
@@ -3672,6 +3676,12 @@ void SCULPT_relax_vertex(SculptSession *ss,
else {
copy_v3_v3(vno, vd->fno);
}
+
+ if (is_zero_v3(vno)) {
+ copy_v3_v3(r_final_pos, vd->co);
+ return;
+ }
+
plane_from_point_normal_v3(plane, vd->co, vno);
closest_to_plane_v3(smooth_closest_plane, plane, smooth_pos);
sub_v3_v3v3(final_disp, smooth_closest_plane, vd->co);
@@ -9143,6 +9153,10 @@ static void sculpt_filter_cache_free(SculptSession *ss)
if (ss->filter_cache->prev_face_set) {
MEM_freeN(ss->filter_cache->prev_face_set);
}
+ if (ss->filter_cache->automask) {
+ MEM_freeN(ss->filter_cache->automask);
+ }
+
MEM_freeN(ss->filter_cache);
ss->filter_cache = NULL;
}
@@ -9310,7 +9324,8 @@ static void mesh_filter_task_cb(void *__restrict userdata,
break;
}
case MESH_FILTER_RELAX: {
- SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), false, val);
+ SCULPT_relax_vertex(
+ ss, &vd, clamp_f(fade * ss->filter_cache->automask[vd.index], 0.0f, 1.0f), false, val);
sub_v3_v3v3(disp, val, vd.co);
break;
}
@@ -9443,6 +9458,16 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
+ if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_RELAX) {
+ const int totvert = SCULPT_vertex_count_get(ss);
+ ss->filter_cache->automask = MEM_mallocN(totvert * sizeof(float),
+ "Relax filter edge automask");
+ for (int i = 0; i < totvert; i++) {
+ ss->filter_cache->automask[i] = 1.0f;
+ }
+ sculpt_boundary_edges_automasking_init(ob, 1, ss->filter_cache->automask);
+ }
+
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -10844,7 +10869,7 @@ static int sculpt_face_set_create_invoke(bContext *C, wmOperator *op, const wmEv
if (mode == SCULPT_FACE_SET_VISIBLE) {
for (int i = 0; i < tot_vert; i++) {
- if (SCULPT_vertex_visible_get(ss, i) && SCULPT_vertex_all_face_sets_visible_get(ss, i)) {
+ if (SCULPT_vertex_visible_get(ss, i)) {
SCULPT_vertex_face_set_set(ss, i, next_face_set);
}
}
@@ -11017,6 +11042,18 @@ static int sculpt_face_sets_change_visibility_invoke(bContext *C,
SCULPT_face_sets_visibility_invert(ss);
}
+ /* For modes that use the cursor active vertex, update the rotation origin for viewport
+ * navigation. */
+ if (ELEM(mode, SCULPT_FACE_SET_VISIBILITY_TOGGLE, SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE)) {
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ float location[3];
+ copy_v3_v3(location, SCULPT_active_vertex_co_get(ss));
+ mul_m4_v3(ob->obmat, location);
+ copy_v3_v3(ups->average_stroke_accum, location);
+ ups->average_stroke_counter = 1;
+ ups->last_stroke_valid = true;
+ }
+
/* Sync face sets visibility and vertex visibility. */
SCULPT_visibility_sync_all_face_sets_to_vertices(ss);
@@ -11084,12 +11121,13 @@ static int sculpt_face_sets_randomize_colors_invoke(bContext *C,
int totnode;
Mesh *mesh = ob->data;
- int new_seed = BLI_hash_int(PIL_check_seconds_timer_i() & UINT_MAX);
- mesh->face_sets_color_seed = new_seed;
+ mesh->face_sets_color_seed += 1;
if (ss->face_sets) {
- mesh->face_sets_color_default = ss->face_sets[0];
+ const int random_index = clamp_i(
+ ss->totpoly * BLI_hash_int_01(mesh->face_sets_color_seed), 0, max_ii(0, ss->totpoly - 1));
+ mesh->face_sets_color_default = ss->face_sets[random_index];
}
- BKE_pbvh_face_sets_color_set(pbvh, new_seed, mesh->face_sets_color_default);
+ BKE_pbvh_face_sets_color_set(pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
for (int i = 0; i < totnode; i++) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 7f90f86edd4..4e36ae7aa5e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -663,6 +663,9 @@ typedef struct FilterCache {
float *prev_mask;
float mask_expand_initial_co[3];
+ /* Used to prevent undesired results on certain mesh filters. */
+ float *automask;
+
int new_face_set;
int *prev_face_set;
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 34b4967beaf..6b9d3fd054a 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -259,8 +259,6 @@ typedef struct {
MovieTrackingTrack *track;
MovieTrackingMarker *marker;
- /** current frame number */
- int framenr;
/** position of marker in pixel coords */
float marker_pos[2];
/** position and dimensions of marker pattern in pixel coords */
@@ -283,14 +281,12 @@ static void to_pixel_space(float r[2], float a[2], int width, int height)
static void marker_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
{
MarkerUpdateCb *cb = (MarkerUpdateCb *)arg_cb;
- MovieTrackingMarker *marker;
if (!cb->compact) {
return;
}
- marker = BKE_tracking_marker_ensure(cb->track, cb->framenr);
-
+ MovieTrackingMarker *marker = cb->marker;
marker->flag = cb->marker_flag;
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
@@ -299,14 +295,12 @@ static void marker_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
static void marker_block_handler(bContext *C, void *arg_cb, int event)
{
MarkerUpdateCb *cb = (MarkerUpdateCb *)arg_cb;
- MovieTrackingMarker *marker;
int width, height;
bool ok = false;
BKE_movieclip_get_size(cb->clip, cb->user, &width, &height);
- marker = BKE_tracking_marker_ensure(cb->track, cb->framenr);
-
+ MovieTrackingMarker *marker = cb->marker;
if (event == B_MARKER_POS) {
marker->pos[0] = cb->marker_pos[0] / width;
marker->pos[1] = cb->marker_pos[1] / height;
@@ -452,7 +446,8 @@ void uiTemplateMarker(uiLayout *layout,
user = userptr->data;
track = trackptr->data;
- marker = BKE_tracking_marker_get(track, user->framenr);
+ int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
+ marker = BKE_tracking_marker_get(track, clip_framenr);
cb = MEM_callocN(sizeof(MarkerUpdateCb), "uiTemplateMarker update_cb");
cb->compact = compact;
@@ -461,7 +456,6 @@ void uiTemplateMarker(uiLayout *layout,
cb->track = track;
cb->marker = marker;
cb->marker_flag = marker->flag;
- cb->framenr = user->framenr;
if (compact) {
block = uiLayoutGetBlock(layout);
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index e5c82a4a80e..72c140011a9 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -296,7 +296,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *region)
SpaceClip *sc = CTX_wm_space_clip(C);
View2D *v2d = &region->v2d;
MovieClip *clip = ED_space_clip_get_clip(sc);
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
int fontid = style->widget.uifont_id;
if (!clip) {
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 1332eb51baa..d7682a41570 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -170,7 +170,6 @@ static void file_draw_string(int sx,
eFontStyle_Align align,
const uchar col[4])
{
- uiStyle *style;
uiFontStyle fs;
rcti rect;
char fname[FILE_MAXFILE];
@@ -179,7 +178,7 @@ static void file_draw_string(int sx,
return;
}
- style = UI_style_get();
+ const uiStyle *style = UI_style_get();
fs = style->widgetlabel;
BLI_strncpy(fname, string, FILE_MAXFILE);
@@ -382,7 +381,6 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
char filename[FILE_MAX + 12];
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
- ScrArea *sa = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
BLI_join_dirfile(orgname, sizeof(orgname), sfile->params->dir, oldname);
@@ -410,7 +408,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
}
/* to make sure we show what is on disk */
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
}
ED_region_tag_redraw(region);
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index d72bc31e656..169abfb9a10 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1649,10 +1649,9 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
struct FSMenu *fsmenu = ED_fsmenu_get();
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
/* refresh system directory menu */
fsmenu_refresh_system_category(fsmenu);
@@ -1988,7 +1987,6 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
const bool do_diropen = RNA_boolean_get(op->ptr, "open");
if (!sfile->params) {
@@ -2047,13 +2045,13 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
/* set timer to smoothly view newly generated file */
/* max 30 frs/sec */
if (sfile->smoothscroll_timer != NULL) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
+ WM_event_remove_timer(wm, CTX_wm_window(C), sfile->smoothscroll_timer);
}
sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0);
sfile->scroll_offset = 0;
/* reload dir to make sure we're seeing what's in the directory */
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
if (do_diropen) {
BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir));
@@ -2302,11 +2300,10 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
if (sfile->params) {
sfile->params->flag ^= FILE_HIDE_DOT;
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -2491,7 +2488,6 @@ int file_delete_exec(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
int numfiles = filelist_files_ensure(sfile->files);
const char *error_message = NULL;
@@ -2520,7 +2516,7 @@ int file_delete_exec(bContext *C, wmOperator *op)
}
}
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 903698b1ace..188f3417ddc 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -268,6 +268,12 @@ typedef struct FileListEntryPreview {
ImBuf *img;
} FileListEntryPreview;
+/* Dummy wrapper around FileListEntryPreview to ensure we do not access freed memory when freeing
+ * tasks' data (see T74609). */
+typedef struct FileListEntryPreviewTaskData {
+ FileListEntryPreview *preview;
+} FileListEntryPreviewTaskData;
+
typedef struct FileListFilter {
uint64_t filter;
uint64_t filter_id;
@@ -1254,7 +1260,8 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool,
int UNUSED(threadid))
{
FileListEntryCache *cache = BLI_task_pool_userdata(pool);
- FileListEntryPreview *preview = taskdata;
+ FileListEntryPreviewTaskData *preview_taskdata = taskdata;
+ FileListEntryPreview *preview = preview_taskdata->preview;
ThumbSource source = 0;
@@ -1283,10 +1290,8 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool,
preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source);
IMB_thumb_path_unlock(preview->path);
- /* Used to tell free func to not free anything.
- * Note that we do not care about cas result here,
- * we only want value attribution itself to be atomic (and memory barier).*/
- atomic_cas_uint32(&preview->flags, preview->flags, 0);
+ /* That way task freeing function won't free th preview, since it does not own it anymore. */
+ atomic_cas_ptr((void **)&preview_taskdata->preview, preview, NULL);
BLI_thread_queue_push(cache->previews_done, preview);
// printf("%s: End (%d)...\n", __func__, threadid);
@@ -1296,16 +1301,18 @@ static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool),
void *taskdata,
int UNUSED(threadid))
{
- FileListEntryPreview *preview = taskdata;
+ FileListEntryPreviewTaskData *preview_taskdata = taskdata;
+ FileListEntryPreview *preview = preview_taskdata->preview;
- /* If preview->flag is empty, it means that preview has already been generated and
- * added to done queue, we do not own it anymore. */
- if (preview->flags) {
+ /* preview_taskdata->preview is atomically set to NULL once preview has been processed and sent
+ * to previews_done queue. */
+ if (preview != NULL) {
if (preview->img) {
IMB_freeImBuf(preview->img);
}
MEM_freeN(preview);
}
+ MEM_freeN(preview_taskdata);
}
static void filelist_cache_preview_ensure_running(FileListEntryCache *cache)
@@ -1322,11 +1329,10 @@ static void filelist_cache_preview_ensure_running(FileListEntryCache *cache)
static void filelist_cache_previews_clear(FileListEntryCache *cache)
{
- FileListEntryPreview *preview;
-
if (cache->previews_pool) {
BLI_task_pool_cancel(cache->previews_pool);
+ FileListEntryPreview *preview;
while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) {
// printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path,
// preview->img);
@@ -1374,9 +1380,13 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
filelist_cache_preview_ensure_running(cache);
+
+ FileListEntryPreviewTaskData *preview_taskdata = MEM_mallocN(sizeof(*preview_taskdata),
+ __func__);
+ preview_taskdata->preview = preview;
BLI_task_pool_push_ex(cache->previews_pool,
filelist_cache_preview_runf,
- preview,
+ preview_taskdata,
true,
filelist_cache_preview_freef,
TASK_PRIORITY_LOW);
@@ -3057,12 +3067,12 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void filelist_readjob_stop(wmWindowManager *wm, ScrArea *sa)
+void filelist_readjob_stop(wmWindowManager *wm, Scene *owner_scene)
{
- WM_jobs_kill_type(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
+ WM_jobs_kill_type(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR);
}
-int filelist_readjob_running(wmWindowManager *wm, ScrArea *sa)
+int filelist_readjob_running(wmWindowManager *wm, Scene *owner_scene)
{
- return WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
+ return WM_jobs_test(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR);
}
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 654a86b1702..e39594bf1da 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -129,8 +129,8 @@ bool filelist_islibrary(struct FileList *filelist, char *dir, char **group);
void filelist_freelib(struct FileList *filelist);
void filelist_readjob_start(struct FileList *filelist, const struct bContext *C);
-void filelist_readjob_stop(struct wmWindowManager *wm, struct ScrArea *sa);
-int filelist_readjob_running(struct wmWindowManager *wm, struct ScrArea *sa);
+void filelist_readjob_stop(struct wmWindowManager *wm, struct Scene *owner_scene);
+int filelist_readjob_running(struct wmWindowManager *wm, struct Scene *owner_scene);
bool filelist_cache_previews_update(struct FileList *filelist);
void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index c0b859122a8..d07db12eeac 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -639,7 +639,7 @@ FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d,
float file_string_width(const char *str)
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
float width;
UI_fontstyle_set(&style->widget);
@@ -661,12 +661,12 @@ float file_font_pointsize(void)
#if 0
float s;
char tmp[2] = "X";
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
UI_fontstyle_set(&style->widget);
s = BLF_height(style->widget.uifont_id, tmp);
return style->widget.points;
#else
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
UI_fontstyle_set(&style->widget);
return style->widget.points * UI_DPI_FAC;
#endif
@@ -829,10 +829,9 @@ void ED_file_change_dir(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
if (sfile->params) {
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
/* Clear search string, it is very rare to want to keep that filter while changing dir,
* and usually very annoying to keep it actually! */
@@ -951,11 +950,11 @@ int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
return match;
}
-void ED_fileselect_clear(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
+void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile)
{
/* only NULL in rare cases - [#29734] */
if (sfile->files) {
- filelist_readjob_stop(wm, sa);
+ filelist_readjob_stop(wm, owner_scene);
filelist_freelib(sfile->files);
filelist_clear(sfile->files);
}
@@ -964,7 +963,7 @@ void ED_fileselect_clear(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
-void ED_fileselect_exit(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
+void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile)
{
if (!sfile) {
return;
@@ -990,7 +989,7 @@ void ED_fileselect_exit(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
folderlist_free(sfile->folders_next);
if (sfile->files) {
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, owner_scene, sfile);
filelist_free(sfile->files);
MEM_freeN(sfile->files);
sfile->files = NULL;
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 11d759b5b75..50ee64da9c8 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -191,7 +191,7 @@ static void file_exit(wmWindowManager *wm, ScrArea *sa)
sfile->previews_timer = NULL;
}
- ED_fileselect_exit(wm, sa, sfile);
+ ED_fileselect_exit(wm, NULL, sfile);
}
static SpaceLink *file_duplicate(SpaceLink *sl)
@@ -301,7 +301,7 @@ static void file_refresh(const bContext *C, ScrArea *sa)
sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
if (filelist_force_reset(sfile->files)) {
- filelist_readjob_stop(wm, sa);
+ filelist_readjob_stop(wm, CTX_data_scene(C));
filelist_clear(sfile->files);
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 34ff61749b2..c62fd53431b 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2351,7 +2351,7 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports)
else {
BKE_reportf(reports,
RPT_WARNING,
- "Packed library image: %s from library %s can't be saved",
+ "Packed library image can't be saved: \"%s\" from \"%s\"",
ima->id.name + 2,
ima->id.lib->name);
}
@@ -2359,7 +2359,7 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports)
else if (!is_format_writable) {
BKE_reportf(reports,
RPT_WARNING,
- "Image %s can't be saved automatically, must use a different file format",
+ "Image can't be saved, use a different file format: \"%s\"",
ima->id.name + 2);
}
else {
@@ -2368,7 +2368,7 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports)
if (BLI_gset_haskey(unique_paths, ima->name)) {
BKE_reportf(reports,
RPT_WARNING,
- "File path used by more than one saved image: %s",
+ "Multiple images can't be saved to an identical path: \"%s\"",
ima->name);
}
else {
@@ -2376,11 +2376,8 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports)
}
}
else {
- BKE_reportf(reports,
- RPT_WARNING,
- "Image %s can't be saved, no valid file path: %s",
- ima->id.name + 2,
- ima->name);
+ BKE_reportf(
+ reports, RPT_WARNING, "Image can't be saved, no valid file path: \"%s\"", ima->name);
}
}
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index dc546e5baf5..42a8a746eef 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -262,18 +262,22 @@ static void image_keymap(struct wmKeyConfig *keyconf)
}
/* dropboxes */
-static bool image_drop_poll(bContext *UNUSED(C),
+static bool image_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
+ const wmEvent *event,
const char **UNUSED(tooltip))
{
+ ScrArea *area = CTX_wm_area(C);
+ if (ED_region_overlap_isect_any_xy(area, &event->x)) {
+ return false;
+ }
if (drag->type == WM_DRAG_PATH) {
/* rule might not work? */
if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
static void image_drop_copy(wmDrag *drag, wmDropBox *drop)
diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c
index 0a5ca81484c..60170276a16 100644
--- a/source/blender/editors/space_info/info_draw.c
+++ b/source/blender/editors/space_info/info_draw.c
@@ -53,7 +53,7 @@ static enum eTextViewContext_LineFlag report_line_data(TextViewContext *tvc,
/* Zebra striping for background. */
int bg_id = (report->flag & SELECT) ? TH_INFO_SELECTED : TH_BACK;
- int shade = tvc->iter_tmp % 2 ? 4 : -4;
+ int shade = (tvc->iter_tmp % 2) ? 4 : -4;
UI_GetThemeColorShade4ubv(bg_id, shade, bg);
/* Icon color and backgound depend of report type. */
@@ -61,7 +61,10 @@ static enum eTextViewContext_LineFlag report_line_data(TextViewContext *tvc,
int icon_fg_id;
int icon_bg_id;
- if (report->type & RPT_ERROR_ALL) {
+ if (tvc->iter_char_begin != 0) {
+ *r_icon = ICON_NONE;
+ }
+ else if (report->type & RPT_ERROR_ALL) {
icon_fg_id = TH_INFO_ERROR_TEXT;
icon_bg_id = TH_INFO_ERROR;
*r_icon = ICON_CANCEL;
@@ -115,14 +118,13 @@ static void report_textview_init__internal(TextViewContext *tvc)
{
const Report *report = tvc->iter;
const char *str = report->message;
- const char *next_str = strchr(str + tvc->iter_char, '\n');
-
- if (next_str) {
- tvc->iter_char_next = (int)(next_str - str);
- }
- else {
- tvc->iter_char_next = report->len;
+ for (int i = tvc->iter_char_end - 1; i >= 0; i -= 1) {
+ if (str[i] == '\n') {
+ tvc->iter_char_begin = i + 1;
+ return;
+ }
}
+ tvc->iter_char_begin = 0;
}
static int report_textview_skip__internal(TextViewContext *tvc)
@@ -152,7 +154,8 @@ static int report_textview_begin(TextViewContext *tvc)
tvc->iter_tmp = 0;
if (tvc->iter && report_textview_skip__internal(tvc)) {
/* init the newline iterator */
- tvc->iter_char = 0;
+ const Report *report = tvc->iter;
+ tvc->iter_char_end = report->len;
report_textview_init__internal(tvc);
return true;
@@ -172,12 +175,13 @@ static int report_textview_step(TextViewContext *tvc)
/* simple case, but no newline support */
const Report *report = tvc->iter;
- if (report->len <= tvc->iter_char_next) {
+ if (tvc->iter_char_begin <= 0) {
tvc->iter = (void *)((Link *)tvc->iter)->prev;
if (tvc->iter && report_textview_skip__internal(tvc)) {
tvc->iter_tmp++;
- tvc->iter_char = 0; /* reset start */
+ report = tvc->iter;
+ tvc->iter_char_end = report->len; /* reset start */
report_textview_init__internal(tvc);
return true;
@@ -188,7 +192,7 @@ static int report_textview_step(TextViewContext *tvc)
}
else {
/* step to the next newline */
- tvc->iter_char = tvc->iter_char_next + 1;
+ tvc->iter_char_end = tvc->iter_char_begin - 1;
report_textview_init__internal(tvc);
return true;
@@ -198,8 +202,8 @@ static int report_textview_step(TextViewContext *tvc)
static void report_textview_line_get(TextViewContext *tvc, const char **r_line, int *r_len)
{
const Report *report = tvc->iter;
- *r_line = report->message + tvc->iter_char;
- *r_len = tvc->iter_char_next - tvc->iter_char;
+ *r_line = report->message + tvc->iter_char_begin;
+ *r_len = tvc->iter_char_end - tvc->iter_char_begin;
}
static void info_textview_draw_rect_calc(const ARegion *region,
diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h
index 54b7c477791..8eef4ef5d56 100644
--- a/source/blender/editors/space_info/textview.h
+++ b/source/blender/editors/space_info/textview.h
@@ -65,10 +65,10 @@ typedef struct TextViewContext {
void (*const_colors)(struct TextViewContext *tvc, unsigned char bg_sel[4]);
const void *iter;
int iter_index;
- /** Char index, used for multi-line report display. */
- int iter_char;
- /** Same as 'iter_char', next new-line. */
- int iter_char_next;
+ /** Used for internal multi-line iteration. */
+ int iter_char_begin;
+ /** The last character (not inclusive). */
+ int iter_char_end;
/** Internal iterator use. */
int iter_tmp;
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 905e3eddc97..56176c1cb92 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -604,7 +604,7 @@ static void nla_draw_strip_text(AnimData *adt,
(nlt->flag & NLATRACK_SOLO) == 0);
char str[256];
size_t str_len;
- char col[4];
+ uchar col[4];
/* just print the name and the range */
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
@@ -652,7 +652,7 @@ static void nla_draw_strip_frames_text(
NlaTrack *UNUSED(nlt), NlaStrip *strip, View2D *v2d, float UNUSED(yminc), float ymaxc)
{
const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */
- const char col[4] = {220, 220, 220, 255}; /* light gray */
+ const uchar col[4] = {220, 220, 220, 255}; /* light gray */
char numstr[32];
size_t numstr_len;
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 025de1c898c..f679bcc4e15 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -2450,7 +2450,7 @@ void NODE_OT_tree_socket_move(wmOperatorType *ot)
static bool node_shader_script_update_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- RenderEngineType *type = RE_engines_find(scene->r.engine);
+ const RenderEngineType *type = RE_engines_find(scene->r.engine);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
Text *text;
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 3e88a7a7b88..1b34f85f800 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -2252,9 +2252,6 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case eGpencilModifierType_Armature:
data.icon = ICON_MOD_ARMATURE;
break;
- case eGpencilModifierType_Vertexcolor:
- data.icon = ICON_MOD_NORMALEDIT;
- break;
/* Default */
default:
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 4cd93b5d257..a99e1b63119 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -678,8 +678,8 @@ static void object_delete_cb(bContext *C,
return;
}
- // check also library later
- if ((ob->mode && OB_MODE_EDIT) && BKE_object_is_in_editmode(ob)) {
+ /* Check also library later. */
+ if ((ob->mode & OB_MODE_EDIT) && BKE_object_is_in_editmode(ob)) {
ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
}
BKE_id_delete(bmain, ob);
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
index b9e97a19b82..d2f2411c538 100644
--- a/source/blender/editors/space_script/script_edit.c
+++ b/source/blender/editors/space_script/script_edit.c
@@ -67,12 +67,12 @@ void SCRIPT_OT_python_file_run(wmOperatorType *ot)
ot->name = "Run Python File";
ot->description = "Run Python file";
ot->idname = "SCRIPT_OT_python_file_run";
- ot->flag = OPTYPE_UNDO;
/* api callbacks */
ot->exec = run_pyfile_exec;
ot->poll = ED_operator_areaactive;
+ /* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "Path", "");
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index ef192f6c9db..864e518f182 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -542,7 +542,7 @@ static void draw_seq_handle(View2D *v2d,
}
if ((G.moving & G_TRANSFORM_SEQ) || (seq->flag & whichsel)) {
- const char col[4] = {255, 255, 255, 255};
+ const uchar col[4] = {255, 255, 255, 255};
char numstr[32];
size_t numstr_len;
@@ -574,7 +574,7 @@ static void draw_seq_text(View2D *v2d,
char str[32 + FILE_MAX];
size_t str_len;
const char *name = seq->name + 2;
- char col[4];
+ uchar col[4];
/* note, all strings should include 'name' */
if (name[0] == '\0') {
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 48c522c5e1b..1e628bbc39b 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -291,7 +291,7 @@ static int txtfmt_py_literal_numeral(const char *string, char prev_fmt)
}
/* Previous was a number; if immediately followed by '.' it's a floating point decimal number.
* Note: keep the decimal point, it's needed to allow leading zeros. */
- if ((prev_fmt == FMT_TYPE_NUMERAL) && (first == '.')) {
+ if (first == '.') {
return txtfmt_py_find_numeral_inner(string);
}
/* "Imaginary" part of a complex number ends with 'j' */
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 8ec7d5a166b..020c58270fc 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -436,35 +436,50 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *region)
ED_view3d_stop_render_preview(wm, region);
}
-static bool view3d_ob_drop_poll(bContext *UNUSED(C),
+static bool view3d_drop_id_in_main_region_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ ID_Type id_type)
+{
+ ScrArea *area = CTX_wm_area(C);
+ if (ED_region_overlap_isect_any_xy(area, &event->x)) {
+ return false;
+ }
+ return WM_drag_ID(drag, id_type) != NULL;
+}
+
+static bool view3d_ob_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
+ const wmEvent *event,
const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, ID_OB) != NULL;
+ return view3d_drop_id_in_main_region_poll(C, drag, event, ID_OB);
}
-static bool view3d_collection_drop_poll(bContext *UNUSED(C),
+static bool view3d_collection_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
+ const wmEvent *event,
const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, ID_GR) != NULL;
+ return view3d_drop_id_in_main_region_poll(C, drag, event, ID_GR);
}
-static bool view3d_mat_drop_poll(bContext *UNUSED(C),
+static bool view3d_mat_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
+ const wmEvent *event,
const char **UNUSED(tooltip))
{
- return WM_drag_ID(drag, ID_MA) != NULL;
+ return view3d_drop_id_in_main_region_poll(C, drag, event, ID_MA);
}
-static bool view3d_ima_drop_poll(bContext *UNUSED(C),
+static bool view3d_ima_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
+ const wmEvent *event,
const char **UNUSED(tooltip))
{
+ if (ED_region_overlap_isect_any_xy(CTX_wm_area(C), &event->x)) {
+ return false;
+ }
if (drag->type == WM_DRAG_PATH) {
/* rule might not work? */
return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index 260546738f4..d812ed530ce 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -101,7 +101,7 @@ typedef struct View3DCameraControl {
void *obtfm;
} View3DCameraControl;
-BLI_INLINE Object *view3d_cameracontrol_object(View3DCameraControl *vctrl)
+BLI_INLINE Object *view3d_cameracontrol_object(const View3DCameraControl *vctrl)
{
return vctrl->root_parent ? vctrl->root_parent : vctrl->ctx_v3d->camera;
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 087fce9e4fd..dbbbbc2af54 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -109,7 +109,7 @@
* \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
*/
void ED_view3d_update_viewmat(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
View3D *v3d,
ARegion *region,
float viewmat[4][4],
@@ -208,7 +208,7 @@ static void view3d_main_region_setup_view(Depsgraph *depsgraph,
}
static void view3d_main_region_setup_offscreen(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
View3D *v3d,
ARegion *region,
float viewmat[4][4],
@@ -222,7 +222,10 @@ static void view3d_main_region_setup_offscreen(Depsgraph *depsgraph,
GPU_matrix_set(rv3d->viewmat);
}
-static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
+static bool view3d_stereo3d_active(wmWindow *win,
+ const Scene *scene,
+ View3D *v3d,
+ RegionView3D *rv3d)
{
if ((scene->r.scemode & R_MULTIVIEW) == 0) {
return false;
@@ -842,7 +845,7 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bo
/* ******************** other elements ***************** */
/** could move this elsewhere, but tied into #ED_view3d_grid_scale */
-float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
+float ED_scene_grid_scale(const Scene *scene, const char **grid_unit)
{
/* apply units */
if (scene->unit.system) {
@@ -863,13 +866,13 @@ float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
return 1.0f;
}
-float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
+float ED_view3d_grid_scale(const Scene *scene, View3D *v3d, const char **grid_unit)
{
return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
#define STEPS_LEN 8
-void ED_view3d_grid_steps(Scene *scene,
+void ED_view3d_grid_steps(const Scene *scene,
View3D *v3d,
RegionView3D *rv3d,
float r_grid_steps[STEPS_LEN])
@@ -1562,7 +1565,7 @@ static void view3d_draw_view(const bContext *C, ARegion *region)
DRW_draw_view(C);
}
-RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype)
+RenderEngineType *ED_view3d_engine_type(const Scene *scene, int drawtype)
{
/*
* Temporary viewport draw modes until we have a proper system.
@@ -1606,7 +1609,7 @@ void view3d_main_region_draw(const bContext *C, ARegion *region)
* \{ */
static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
View3D *v3d,
ARegion *region,
float winmat[4][4],
@@ -1630,7 +1633,7 @@ static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph,
}
void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
eDrawType drawtype,
View3D *v3d,
ARegion *region,
@@ -2395,7 +2398,7 @@ void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixSto
* \note The info that this uses is updated in #ED_refresh_viewport_fps,
* which currently gets called during #SCREEN_OT_animation_step.
*/
-void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset)
+void ED_scene_draw_fps(const Scene *scene, int xoffset, int *yoffset)
{
ScreenFrameRateInfo *fpsi = scene->fps_info;
char printable[16];
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 2ced545a108..610c40c37eb 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -202,7 +202,7 @@ void view3d_winmatrix_set(struct Depsgraph *depsgraph,
const View3D *v3d,
const rcti *rect);
void view3d_viewmatrix_set(struct Depsgraph *depsgraph,
- Scene *scene,
+ const struct Scene *scene,
const View3D *v3d,
RegionView3D *rv3d,
const float rect_scale[2]);
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index f6ec5c93e7f..e7153ddd361 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -586,8 +586,11 @@ bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionV
}
}
-bool ED_view3d_camera_autokey(
- Scene *scene, ID *id_key, struct bContext *C, const bool do_rotate, const bool do_translate)
+bool ED_view3d_camera_autokey(const Scene *scene,
+ ID *id_key,
+ struct bContext *C,
+ const bool do_rotate,
+ const bool do_translate)
{
if (autokeyframe_cfra_can_key(scene, id_key)) {
const float cfra = (float)CFRA;
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 9b0c987c451..ee41b73ed16 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -807,7 +807,7 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
* \note don't set windows active in here, is used by renderwin too.
*/
void view3d_viewmatrix_set(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
const View3D *v3d,
RegionView3D *rv3d,
const float rect_scale[2])
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index 5f5a173932c..afa7b02a1f6 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -65,8 +65,6 @@ set(SRC
transform_gizmo_3d.c
transform_gizmo_extrude_3d.c
transform_input.c
- transform_ops.c
- transform_orientations.c
transform_mode.c
transform_mode_align.c
transform_mode_baketime.c
@@ -98,6 +96,8 @@ set(SRC
transform_mode_trackball.c
transform_mode_translate.c
transform_mode_vert_slide.c
+ transform_ops.c
+ transform_orientations.c
transform_snap.c
transform_snap_object.c
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index f93a3ec260b..4ccb97b7a00 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -830,25 +830,6 @@ bool FrameOnMouseSide(char side, float frame, float cframe)
/* ********************* ACTION EDITOR ****************** */
-static int gpf_cmp_frame(void *thunk, const void *a, const void *b)
-{
- const bGPDframe *frame_a = a;
- const bGPDframe *frame_b = b;
-
- if (frame_a->framenum < frame_b->framenum) {
- return -1;
- }
- if (frame_a->framenum > frame_b->framenum) {
- return 1;
- }
- *((bool *)thunk) = true;
- /* selected last */
- if ((frame_a->flag & GP_FRAME_SELECT) && ((frame_b->flag & GP_FRAME_SELECT) == 0)) {
- return 1;
- }
- return 0;
-}
-
static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b)
{
const MaskLayerShape *frame_a = a;
@@ -881,7 +862,7 @@ static void posttrans_gpd_clean(bGPdata *gpd)
bGPDframe *gpf, *gpfn;
bool is_double = false;
- BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &is_double);
+ BKE_gpencil_layer_frames_sort(gpl, &is_double);
if (is_double) {
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h
index a8a930cc156..6180f6d3477 100644
--- a/source/blender/editors/transform/transform_mode.h
+++ b/source/blender/editors/transform/transform_mode.h
@@ -27,9 +27,9 @@
struct AnimData;
struct LinkNode;
-struct TransInfo;
-struct TransDataContainer;
struct TransData;
+struct TransDataContainer;
+struct TransInfo;
struct wmOperator;
/* header of TransDataEdgeSlideVert, TransDataEdgeSlideEdge */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 41bb51340fc..4623cc61d29 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -3048,7 +3048,6 @@ static void UV_OT_select_linked(wmOperatorType *ot)
ot->name = "Select Linked";
ot->description = "Select all UV vertices linked to the active UV map";
ot->idname = "UV_OT_select_linked";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = uv_select_linked_exec;
@@ -3485,6 +3484,10 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima,
/** \} */
+#define UV_SELECT_ISLAND_LIMIT \
+ float limit[2]; \
+ uvedit_pixel_to_float(sima, limit, 0.05f)
+
/* -------------------------------------------------------------------- */
/** \name Box Select Operator
* \{ */
@@ -3518,6 +3521,8 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
pinned = RNA_boolean_get(op->ptr, "pinned");
+ UV_SELECT_ISLAND_LIMIT;
+
bool changed_multi = false;
uint objects_len = 0;
@@ -3569,24 +3574,34 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
continue;
}
+ bool has_selected = false;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) {
-
- /* UV_SYNC_SELECTION - can't do pinned selection */
- if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
+ if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) {
+ /* UV_SYNC_SELECTION - can't do pinned selection */
+ if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ has_selected = true;
+ }
}
- }
- else if (pinned) {
- if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ else if (pinned) {
+ if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ }
}
}
}
+ if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) {
+ UvNearestHit hit = {
+ .ob = obedit,
+ .efa = efa,
+ };
+ uv_select_linked_multi(
+ scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ }
}
if (sima->sticky == SI_STICKY_VERTEX) {
@@ -3681,6 +3696,8 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
UI_view2d_region_to_view(&region->v2d, x, y, &offset[0], &offset[1]);
+ UV_SELECT_ISLAND_LIMIT;
+
bool changed_multi = false;
uint objects_len = 0;
@@ -3728,14 +3745,29 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+ bool has_selected = false;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (uv_inside_circle(luv->uv, offset, ellipse)) {
- changed = true;
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (uv_inside_circle(luv->uv, offset, ellipse)) {
+ changed = true;
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ has_selected = true;
+ }
}
}
+ if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) {
+ UvNearestHit hit = {
+ .ob = obedit,
+ .efa = efa,
+ };
+ uv_select_linked_multi(
+ scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ }
}
if (sima->sticky == SI_STICKY_VERTEX) {
@@ -3809,6 +3841,8 @@ static bool do_lasso_select_mesh_uv(bContext *C,
bool changed_multi = false;
rcti rect;
+ UV_SELECT_ISLAND_LIMIT;
+
BLI_lasso_boundbox(&rect, mcords, moves);
uint objects_len = 0;
@@ -3857,22 +3891,33 @@ static bool do_lasso_select_mesh_uv(bContext *C,
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (UI_view2d_view_to_region_clip(
- &region->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]) &&
- BLI_rcti_isect_pt_v(&rect, screen_uv) &&
- BLI_lasso_is_point_inside(
- mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- changed = true;
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
- }
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+ bool has_selected = false;
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (UI_view2d_view_to_region_clip(
+ &region->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]) &&
+ BLI_rcti_isect_pt_v(&rect, screen_uv) &&
+ BLI_lasso_is_point_inside(
+ mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ changed = true;
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ has_selected = true;
}
}
}
+ if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) {
+ UvNearestHit hit = {
+ .ob = obedit,
+ .efa = efa,
+ };
+ uv_select_linked_multi(
+ scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ }
}
if (sima->sticky == SI_STICKY_VERTEX) {
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
index 86bb696a031..544fdee519f 100644
--- a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
@@ -35,7 +35,7 @@ class CalligraphicShader : public StrokeShader {
public:
/*! Builds the shader.
* \param iMinThickness:
- * The minimum thickness in the direction perpandicular to the main direction.
+ * The minimum thickness in the direction perpendicular to the main direction.
* \param iMaxThickness:
* The maximum thickness in the main direction.
* \param iOrientation:
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index 709674e6b43..87743911add 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -59,7 +59,6 @@ set(SRC
intern/MOD_gpencilthick.c
intern/MOD_gpenciltime.c
intern/MOD_gpenciltint.c
- intern/MOD_gpencilvertexcolor.c
MOD_gpencil_modifiertypes.h
)
diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
index b8e8e8fc87f..f5c064c1c07 100644
--- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
+++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
@@ -43,7 +43,6 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Offset;
extern GpencilModifierTypeInfo modifierType_Gpencil_Armature;
extern GpencilModifierTypeInfo modifierType_Gpencil_Time;
extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply;
-extern GpencilModifierTypeInfo modifierType_Gpencil_Vertexcolor;
/* MOD_gpencil_util.c */
void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index 1462b6f72c9..6c3815d7c0e 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -72,7 +72,6 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
INIT_GP_TYPE(Armature);
INIT_GP_TYPE(Time);
INIT_GP_TYPE(Multiply);
- INIT_GP_TYPE(Vertexcolor);
#undef INIT_GP_TYPE
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
index 9b3d37bf11f..b8009b8405e 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
@@ -55,7 +55,6 @@ static void initData(GpencilModifierData *md)
{
NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
gpmd->pass_index = 0;
- gpmd->flag |= GP_NOISE_MOD_LOCATION;
gpmd->flag |= GP_NOISE_FULL_STROKE;
gpmd->flag |= GP_NOISE_USE_RANDOM;
gpmd->factor = 0.5f;
@@ -182,7 +181,7 @@ static void deformStroke(GpencilModifierData *md,
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
/* verify vertex group */
- dvert = &gps->dvert[i];
+ dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
float weight = get_modifier_point_weight(dvert, invert_group, def_nr);
if (weight < 0.0f) {
continue;
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index 96f1f004812..6aaa37d494b 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -25,34 +25,64 @@
#include "BLI_utildefines.h"
-#include "BLI_blenlib.h"
-#include "BLI_math_vector.h"
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "DNA_modifier_types.h"
+#include "BKE_action.h"
+#include "BKE_colorband.h"
#include "BKE_colortools.h"
+#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_material.h"
+#include "BKE_layer.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_modifier.h"
+#include "BKE_scene.h"
-#include "DEG_depsgraph.h"
+#include "MEM_guardedalloc.h"
#include "MOD_gpencil_util.h"
#include "MOD_gpencil_modifiertypes.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
static void initData(GpencilModifierData *md)
{
TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
gpmd->pass_index = 0;
- gpmd->factor = 0.5f;
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ gpmd->object = NULL;
+ gpmd->radius = 1.0f;
+ gpmd->factor = 0.5f;
ARRAY_SET_ITEMS(gpmd->rgb, 1.0f, 1.0f, 1.0f);
- gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
+ gpmd->mode = GPPAINT_MODE_BOTH;
+
+ /* Add default color ramp. */
+ gpmd->colorband = BKE_colorband_add(false);
+ if (gpmd->colorband) {
+ BKE_colorband_init(gpmd->colorband, true);
+ CBData *ramp = gpmd->colorband->data;
+ ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f;
+ ramp[0].pos = 0.0f;
+ ramp[1].r = ramp[1].g = ramp[1].b = 0.0f;
+ ramp[1].a = 1.0f;
+ ramp[1].pos = 1.0f;
+
+ gpmd->colorband->tot = 2;
+ }
gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
if (gpmd->curve_intensity) {
@@ -66,6 +96,8 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
TintGpencilModifierData *gmd = (TintGpencilModifierData *)md;
TintGpencilModifierData *tgmd = (TintGpencilModifierData *)target;
+ MEM_SAFE_FREE(tgmd->colorband);
+
if (tgmd->curve_intensity != NULL) {
BKE_curvemapping_free(tgmd->curve_intensity);
tgmd->curve_intensity = NULL;
@@ -73,10 +105,14 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
BKE_gpencil_modifier_copyData_generic(md, target);
+ if (gmd->colorband) {
+ tgmd->colorband = MEM_dupallocN(gmd->colorband);
+ }
+
tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
-/* tint strokes */
+/* deform stroke */
static void deformStroke(GpencilModifierData *md,
Depsgraph *UNUSED(depsgraph),
Object *ob,
@@ -85,6 +121,11 @@ static void deformStroke(GpencilModifierData *md,
bGPDstroke *gps)
{
TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
+ if ((mmd->type == GP_TINT_GRADIENT) && (!mmd->object)) {
+ return;
+ }
+
+ const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
const bool use_curve = (mmd->flag & GP_TINT_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
if (!is_stroke_affected_by_modifier(ob,
@@ -101,10 +142,10 @@ static void deformStroke(GpencilModifierData *md,
mmd->flag & GP_TINT_INVERT_MATERIAL)) {
return;
}
-
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ const bool is_gradient = (mmd->type == GP_TINT_GRADIENT);
- /* if factor > 1.0, affect the strength of the stroke */
+ /* If factor > 1.0, affect the strength of the stroke. */
if (mmd->factor > 1.0f) {
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
@@ -113,67 +154,173 @@ static void deformStroke(GpencilModifierData *md,
}
}
- /* Apply to Vertex Color. */
- float mixfac = mmd->factor;
-
- CLAMP(mixfac, 0.0, 1.0f);
- /* Fill */
- if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- /* If not using Vertex Color, use the material color. */
- if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
- (gp_style->fill_rgba[3] > 0.0f)) {
- copy_v4_v4(gps->vert_color_fill, gp_style->fill_rgba);
- gps->vert_color_fill[3] = 1.0f;
+ float coba_res[4];
+ float matrix[4][4];
+ if (is_gradient) {
+ mul_m4_m4m4(matrix, mmd->object->imat, ob->obmat);
+ }
+
+ /* loop points and apply color. */
+ bool fill_done = false;
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+
+ if (!fill_done) {
+ /* Apply to fill. */
+ if (mmd->mode != GPPAINT_MODE_STROKE) {
+
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
+ (gp_style->fill_rgba[3] > 0.0f)) {
+ copy_v4_v4(gps->vert_color_fill, gp_style->fill_rgba);
+ gps->vert_color_fill[3] = 1.0f;
+ }
+
+ if (is_gradient) {
+ float center[3];
+ add_v3_v3v3(center, gps->boundbox_min, gps->boundbox_max);
+ mul_v3_fl(center, 0.5f);
+ float pt_loc[3];
+ mul_v3_m4v3(pt_loc, matrix, &pt->x);
+ float dist = len_v3(pt_loc);
+ float mix_factor = clamp_f(dist / mmd->radius, 0.0f, 1.0f);
+
+ BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, coba_res, mmd->factor);
+ gps->vert_color_fill[3] = clamp_f(mmd->factor, 0.0f, 1.0f);
+ }
+ else {
+ interp_v3_v3v3(gps->vert_color_fill,
+ gps->vert_color_fill,
+ mmd->rgb,
+ clamp_f(mmd->factor, 0.0f, 1.0f));
+ }
+ /* If no stroke, cancel loop. */
+ if (mmd->mode != GPPAINT_MODE_BOTH) {
+ break;
+ }
+ }
+
+ fill_done = true;
}
- interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, mmd->rgb, mixfac);
- }
+ /* Verify vertex group. */
+ if (mmd->mode != GPPAINT_MODE_FILL) {
+ float weight = get_modifier_point_weight(
+ dvert, (mmd->flag & GP_TINT_INVERT_VGROUP) != 0, def_nr);
+ if (weight < 0.0f) {
+ continue;
+ }
+ /* Custom curve to modulate value. */
+ if (use_curve) {
+ float value = (float)i / (gps->totpoints - 1);
+ weight *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
+ }
- /* Stroke */
- if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
/* If not using Vertex Color, use the material color. */
if ((gp_style != NULL) && (pt->vert_color[3] == 0.0f) && (gp_style->stroke_rgba[3] > 0.0f)) {
copy_v4_v4(pt->vert_color, gp_style->stroke_rgba);
pt->vert_color[3] = 1.0f;
}
- /* Custom curve to modulate value. */
- float mixvalue = mixfac;
- if (use_curve) {
- float value = (float)i / (gps->totpoints - 1);
- mixvalue *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
- }
+ if (is_gradient) {
+ /* Calc world position of point. */
+ float pt_loc[3];
+ mul_v3_m4v3(pt_loc, matrix, &pt->x);
+ float dist = len_v3(pt_loc);
+
+ /* Calc the factor using the distance and get mix color. */
+ float mix_factor = clamp_f(dist / mmd->radius, 0.0f, 1.0f);
+ BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
- interp_v3_v3v3(pt->vert_color, pt->vert_color, mmd->rgb, mixvalue);
+ interp_v3_v3v3(pt->vert_color,
+ pt->vert_color,
+ coba_res,
+ clamp_f(mmd->factor, 0.0f, 1.0f) * weight * coba_res[3]);
+ }
+ else {
+ interp_v3_v3v3(
+ pt->vert_color, pt->vert_color, mmd->rgb, clamp_f(mmd->factor * weight, 0.0, 1.0f));
+ }
}
}
}
-static void bakeModifier(Main *UNUSED(bmain),
- Depsgraph *depsgraph,
- GpencilModifierData *md,
- Object *ob)
+/* FIXME: Ideally we be doing this on a copy of the main depsgraph
+ * (i.e. one where we don't have to worry about restoring state)
+ */
+static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
{
+ TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
bGPdata *gpd = ob->data;
+ int oldframe = (int)DEG_get_ctime(depsgraph);
+
+ if (mmd->object == NULL) {
+ return;
+ }
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ /* apply effects on this frame
+ * NOTE: this assumes that we don't want animation on non-keyframed frames
+ */
+ CFRA = gpf->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+
+ /* compute effects on this frame */
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
}
+
+ /* return frame state and DB to original state */
+ CFRA = oldframe;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
static void freeData(GpencilModifierData *md)
{
- TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
+ TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
+ if (mmd->colorband) {
+ MEM_freeN(mmd->colorband);
+ mmd->colorband = NULL;
+ }
+ if (mmd->curve_intensity) {
+ BKE_curvemapping_free(mmd->curve_intensity);
+ }
+}
- if (gpmd->curve_intensity) {
- BKE_curvemapping_free(gpmd->curve_intensity);
+static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
+{
+ TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
+ if (mmd->type == GP_TINT_UNIFORM) {
+ return false;
+ }
+
+ return !mmd->object;
+}
+
+static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
+{
+ TintGpencilModifierData *lmd = (TintGpencilModifierData *)md;
+ if (lmd->object != NULL) {
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Vertexcolor Modifier");
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Vertexcolor Modifier");
}
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Vertexcolor Modifier");
+}
+
+static void foreachObjectLink(GpencilModifierData *md,
+ Object *ob,
+ ObjectWalkFunc walk,
+ void *userData)
+{
+ TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
+
+ walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
GpencilModifierTypeInfo modifierType_Gpencil_Tint = {
@@ -192,10 +339,10 @@ GpencilModifierTypeInfo modifierType_Gpencil_Tint = {
/* initData */ initData,
/* freeData */ freeData,
- /* isDisabled */ NULL,
- /* updateDepsgraph */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
- /* foreachObjectLink */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c
deleted file mode 100644
index b279d90dd4f..00000000000
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2017, Blender Foundation
- * This is a new part of Blender
- */
-
-/** \file
- * \ingroup modifiers
- */
-
-#include <stdio.h>
-
-#include "BLI_utildefines.h"
-
-#include "BLI_math.h"
-#include "BLI_listbase.h"
-
-#include "DNA_meshdata_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_gpencil_modifier_types.h"
-#include "DNA_modifier_types.h"
-
-#include "BKE_action.h"
-#include "BKE_colorband.h"
-#include "BKE_colortools.h"
-#include "BKE_deform.h"
-#include "BKE_gpencil.h"
-#include "BKE_gpencil_modifier.h"
-#include "BKE_layer.h"
-#include "BKE_lib_query.h"
-#include "BKE_main.h"
-#include "BKE_material.h"
-#include "BKE_modifier.h"
-#include "BKE_scene.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "MOD_gpencil_util.h"
-#include "MOD_gpencil_modifiertypes.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-#include "DEG_depsgraph_query.h"
-
-static void initData(GpencilModifierData *md)
-{
- VertexcolorGpencilModifierData *gpmd = (VertexcolorGpencilModifierData *)md;
- gpmd->pass_index = 0;
- gpmd->layername[0] = '\0';
- gpmd->materialname[0] = '\0';
- gpmd->vgname[0] = '\0';
- gpmd->object = NULL;
- gpmd->radius = 1.0f;
- gpmd->factor = 1.0f;
-
- /* Add default color ramp. */
- gpmd->colorband = BKE_colorband_add(false);
- if (gpmd->colorband) {
- BKE_colorband_init(gpmd->colorband, true);
- CBData *ramp = gpmd->colorband->data;
- ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f;
- ramp[0].pos = 0.0f;
- ramp[1].r = ramp[1].g = ramp[1].b = 0.0f;
- ramp[1].a = 1.0f;
- ramp[1].pos = 1.0f;
-
- gpmd->colorband->tot = 2;
- }
-
- gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
- if (gpmd->curve_intensity) {
- CurveMapping *curve = gpmd->curve_intensity;
- BKE_curvemapping_initialize(curve);
- }
-}
-
-static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
-{
- VertexcolorGpencilModifierData *gmd = (VertexcolorGpencilModifierData *)md;
- VertexcolorGpencilModifierData *tgmd = (VertexcolorGpencilModifierData *)target;
-
- MEM_SAFE_FREE(tgmd->colorband);
-
- if (tgmd->curve_intensity != NULL) {
- BKE_curvemapping_free(tgmd->curve_intensity);
- tgmd->curve_intensity = NULL;
- }
-
- BKE_gpencil_modifier_copyData_generic(md, target);
-
- if (gmd->colorband) {
- tgmd->colorband = MEM_dupallocN(gmd->colorband);
- }
-
- tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
-}
-
-/* deform stroke */
-static void deformStroke(GpencilModifierData *md,
- Depsgraph *UNUSED(depsgraph),
- Object *ob,
- bGPDlayer *gpl,
- bGPDframe *UNUSED(gpf),
- bGPDstroke *gps)
-{
- VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
- if (!mmd->object) {
- return;
- }
-
- const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
- const bool use_curve = (mmd->flag & GP_VERTEXCOL_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
-
- if (!is_stroke_affected_by_modifier(ob,
- mmd->layername,
- mmd->materialname,
- mmd->pass_index,
- mmd->layer_pass,
- 1,
- gpl,
- gps,
- mmd->flag & GP_VERTEXCOL_INVERT_LAYER,
- mmd->flag & GP_VERTEXCOL_INVERT_PASS,
- mmd->flag & GP_VERTEXCOL_INVERT_LAYERPASS,
- mmd->flag & GP_VERTEXCOL_INVERT_MATERIAL)) {
- return;
- }
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
-
- float coba_res[4];
- float matrix[4][4];
- mul_m4_m4m4(matrix, mmd->object->imat, ob->obmat);
-
- /* loop points and apply deform */
- bool fill_done = false;
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
-
- if (!fill_done) {
- /* Apply to fill. */
- if (mmd->mode != GPPAINT_MODE_STROKE) {
-
- /* If not using Vertex Color, use the material color. */
- if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
- (gp_style->fill_rgba[3] > 0.0f)) {
- copy_v4_v4(gps->vert_color_fill, gp_style->fill_rgba);
- gps->vert_color_fill[3] = 1.0f;
- }
-
- float center[3];
- add_v3_v3v3(center, gps->boundbox_min, gps->boundbox_max);
- mul_v3_fl(center, 0.5f);
- float pt_loc[3];
- mul_v3_m4v3(pt_loc, matrix, &pt->x);
- float dist = len_v3(pt_loc);
- float mix_factor = clamp_f(dist / mmd->radius, 0.0f, 1.0f);
-
- BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
- interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, coba_res, mmd->factor);
- gps->vert_color_fill[3] = mmd->factor;
- /* If no stroke, cancel loop. */
- if (mmd->mode != GPPAINT_MODE_BOTH) {
- break;
- }
- }
-
- fill_done = true;
- }
-
- /* Verify vertex group. */
- if (mmd->mode != GPPAINT_MODE_FILL) {
- float weight = get_modifier_point_weight(
- dvert, (mmd->flag & GP_VERTEXCOL_INVERT_VGROUP) != 0, def_nr);
- if (weight < 0.0f) {
- continue;
- }
- /* Custom curve to modulate value. */
- if (use_curve) {
- float value = (float)i / (gps->totpoints - 1);
- weight *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
- }
-
- /* Calc world position of point. */
- float pt_loc[3];
- mul_v3_m4v3(pt_loc, matrix, &pt->x);
- float dist = len_v3(pt_loc);
-
- /* If not using Vertex Color, use the material color. */
- if ((gp_style != NULL) && (pt->vert_color[3] == 0.0f) && (gp_style->stroke_rgba[3] > 0.0f)) {
- copy_v4_v4(pt->vert_color, gp_style->stroke_rgba);
- pt->vert_color[3] = 1.0f;
- }
-
- /* Calc the factor using the distance and get mix color. */
- float mix_factor = clamp_f(dist / mmd->radius, 0.0f, 1.0f);
- BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
-
- interp_v3_v3v3(pt->vert_color, pt->vert_color, coba_res, mmd->factor * weight * coba_res[3]);
- }
- }
-}
-
-/* FIXME: Ideally we be doing this on a copy of the main depsgraph
- * (i.e. one where we don't have to worry about restoring state)
- */
-static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
-{
- VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
- Scene *scene = DEG_get_evaluated_scene(depsgraph);
- bGPdata *gpd = ob->data;
- int oldframe = (int)DEG_get_ctime(depsgraph);
-
- if (mmd->object == NULL) {
- return;
- }
-
- LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
- LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
- /* apply effects on this frame
- * NOTE: this assumes that we don't want animation on non-keyframed frames
- */
- CFRA = gpf->framenum;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
-
- /* compute effects on this frame */
- LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- deformStroke(md, depsgraph, ob, gpl, gpf, gps);
- }
- }
- }
-
- /* return frame state and DB to original state */
- CFRA = oldframe;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
-}
-
-static void freeData(GpencilModifierData *md)
-{
- VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
- if (mmd->colorband) {
- MEM_freeN(mmd->colorband);
- mmd->colorband = NULL;
- }
- if (mmd->curve_intensity) {
- BKE_curvemapping_free(mmd->curve_intensity);
- }
-}
-
-static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
-{
- VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
-
- return !mmd->object;
-}
-
-static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
-{
- VertexcolorGpencilModifierData *lmd = (VertexcolorGpencilModifierData *)md;
- if (lmd->object != NULL) {
- DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Vertexcolor Modifier");
- DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Vertexcolor Modifier");
- }
- DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Vertexcolor Modifier");
-}
-
-static void foreachObjectLink(GpencilModifierData *md,
- Object *ob,
- ObjectWalkFunc walk,
- void *userData)
-{
- VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
-
- walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
-}
-
-GpencilModifierTypeInfo modifierType_Gpencil_Vertexcolor = {
- /* name */ "Vertex Color",
- /* structName */ "VertexcolorGpencilModifierData",
- /* structSize */ sizeof(VertexcolorGpencilModifierData),
- /* type */ eGpencilModifierTypeType_Gpencil,
- /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
-
- /* copyData */ copyData,
-
- /* deformStroke */ deformStroke,
- /* generateStrokes */ NULL,
- /* bakeModifier */ bakeModifier,
- /* remapTime */ NULL,
-
- /* initData */ initData,
- /* freeData */ freeData,
- /* isDisabled */ isDisabled,
- /* updateDepsgraph */ updateDepsgraph,
- /* dependsOnTime */ NULL,
- /* foreachObjectLink */ foreachObjectLink,
- /* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
-};
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 5eae86e50f0..f21cd990a41 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -189,15 +189,17 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim)
* \{ */
/* Returns the Face Set random color for rendering in the overlay given its ID and a color seed. */
+#define GOLDEN_RATIO_CONJUGATE 0.618033988749895f
static void face_set_overlay_color_get(const int face_set, const int seed, uchar *r_color)
{
float rgba[4];
- const float random_mod_hue = BLI_hash_int_01(abs(face_set) + seed);
+ float random_mod_hue = GOLDEN_RATIO_CONJUGATE * (abs(face_set) + (seed % 10));
+ random_mod_hue = random_mod_hue - floorf(random_mod_hue);
const float random_mod_sat = BLI_hash_int_01(abs(face_set) + seed + 1);
const float random_mod_val = BLI_hash_int_01(abs(face_set) + seed + 2);
hsv_to_rgb(random_mod_hue,
- 0.45f + (random_mod_sat * 0.35f),
- 1.0f - (random_mod_val * 0.45f),
+ 0.6f + (random_mod_sat * 0.25f),
+ 1.0f - (random_mod_val * 0.35f),
&rgba[0],
&rgba[1],
&rgba[2]);
@@ -264,8 +266,8 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
}
/* Face Sets. */
- uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
for (uint i = 0; i < buffers->face_indices_len; i++) {
+ uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
if (show_face_sets) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
const int fset = abs(sculpt_face_sets[lt->poly]);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 33bc3ced5b2..348b9dddba9 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -180,27 +180,28 @@ float GPU_get_anisotropic(void)
/* Set OpenGL state for an MTFace */
-static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget)
+static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget, const int multiview_eye)
{
if (textarget == GL_TEXTURE_2D) {
- return &ima->gputexture[TEXTARGET_TEXTURE_2D];
+ return &(ima->gputexture[TEXTARGET_TEXTURE_2D][multiview_eye]);
}
else if (textarget == GL_TEXTURE_CUBE_MAP) {
- return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP];
+ return &(ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP][multiview_eye]);
}
else if (textarget == GL_TEXTURE_2D_ARRAY) {
- return &ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY];
+ return &(ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][multiview_eye]);
}
else if (textarget == GL_TEXTURE_1D_ARRAY) {
- return &ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING];
+ return &(ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING][multiview_eye]);
}
return NULL;
}
-static uint gpu_texture_create_tile_mapping(Image *ima)
+static uint gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye)
{
- GPUTexture *tilearray = ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY];
+ GPUTexture *tilearray = ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][multiview_eye];
+
if (tilearray == NULL) {
return 0;
}
@@ -876,7 +877,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf,
BKE_image_tag_time(ima);
/* Test if we already have a texture. */
- GPUTexture **tex = gpu_get_image_gputexture(ima, textarget);
+ GPUTexture **tex = gpu_get_image_gputexture(ima, textarget, iuser->multiview_eye);
if (*tex) {
return *tex;
}
@@ -904,7 +905,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf,
bindcode = gpu_texture_create_tile_array(ima, ibuf_intern);
}
else if (textarget == GL_TEXTURE_1D_ARRAY) {
- bindcode = gpu_texture_create_tile_mapping(ima);
+ bindcode = gpu_texture_create_tile_mapping(ima, iuser->multiview_eye);
}
else {
bindcode = gpu_texture_create_from_ibuf(ima, ibuf_intern, textarget);
@@ -1288,14 +1289,16 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
if (BKE_image_has_opengl_texture(ima)) {
if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) {
- for (int a = 0; a < TEXTARGET_COUNT; a++) {
- if (ELEM(a, TEXTARGET_TEXTURE_2D, TEXTARGET_TEXTURE_2D_ARRAY)) {
- GPUTexture *tex = ima->gputexture[a];
- if (tex != NULL) {
- GPU_texture_bind(tex, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
- GPU_texture_unbind(tex);
+ for (int eye = 0; eye < 2; eye++) {
+ for (int a = 0; a < TEXTARGET_COUNT; a++) {
+ if (ELEM(a, TEXTARGET_TEXTURE_2D, TEXTARGET_TEXTURE_2D_ARRAY)) {
+ GPUTexture *tex = ima->gputexture[a][eye];
+ if (tex != NULL) {
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
+ GPU_texture_unbind(tex);
+ }
}
}
}
@@ -1312,14 +1315,16 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
else {
for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
if (BKE_image_has_opengl_texture(ima)) {
- for (int a = 0; a < TEXTARGET_COUNT; a++) {
- if (ELEM(a, TEXTARGET_TEXTURE_2D, TEXTARGET_TEXTURE_2D_ARRAY)) {
- GPUTexture *tex = ima->gputexture[a];
- if (tex != NULL) {
- GPU_texture_bind(tex, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
- GPU_texture_unbind(tex);
+ for (int eye = 0; eye < 2; eye++) {
+ for (int a = 0; a < TEXTARGET_COUNT; a++) {
+ if (ELEM(a, TEXTARGET_TEXTURE_2D, TEXTARGET_TEXTURE_2D_ARRAY)) {
+ GPUTexture *tex = ima->gputexture[a][eye];
+ if (tex != NULL) {
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
+ GPU_texture_unbind(tex);
+ }
}
}
}
@@ -1343,14 +1348,14 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
GPU_free_image(ima);
}
- GPUTexture *tex = ima->gputexture[TEXTARGET_TEXTURE_2D];
+ GPUTexture *tex = ima->gputexture[TEXTARGET_TEXTURE_2D][0];
/* Check if we need to update the main gputexture. */
if (tex != NULL && tile == ima->tiles.first) {
gpu_texture_update_from_ibuf(tex, ima, ibuf, NULL, x, y, w, h);
}
/* Check if we need to update the array gputexture. */
- tex = ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY];
+ tex = ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][0];
if (tex != NULL) {
gpu_texture_update_from_ibuf(tex, ima, ibuf, tile, x, y, w, h);
}
@@ -1395,11 +1400,13 @@ void GPU_free_unused_buffers(Main *bmain)
static void gpu_free_image_immediate(Image *ima)
{
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- /* free glsl image binding */
- if (ima->gputexture[i] != NULL) {
- GPU_texture_free(ima->gputexture[i]);
- ima->gputexture[i] = NULL;
+ for (int eye = 0; eye < 2; eye++) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ /* free glsl image binding */
+ if (ima->gputexture[i][eye] != NULL) {
+ GPU_texture_free(ima->gputexture[i][eye]);
+ ima->gputexture[i][eye] = NULL;
+ }
}
}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 351c85aa2d8..941f5049dbf 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -677,7 +677,7 @@ static void gpu_viewport_storage_free(StorageList *stl, int stl_len)
static void gpu_viewport_passes_free(PassList *psl, int psl_len)
{
- memset(psl, 0, sizeof(struct DRWPass *) * psl_len);
+ memset(psl->passes, 0, sizeof(*psl->passes) * psl_len);
}
/* Must be executed inside Drawmanager Opengl Context. */
diff --git a/source/blender/io/avi/intern/avi_rgb.c b/source/blender/io/avi/intern/avi_rgb.c
index d449556e79b..6f4f33d72d1 100644
--- a/source/blender/io/avi/intern/avi_rgb.c
+++ b/source/blender/io/avi/intern/avi_rgb.c
@@ -33,6 +33,8 @@
#include "IMB_imbuf.h"
+#include "BLI_utildefines.h"
+
/* implementation */
void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, unsigned char *buffer, size_t *size)
@@ -97,7 +99,8 @@ void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, unsigned char *buf
if (buf) {
size_t rowstride = movie->header->Width * 3;
- if ((bits != 16) && (movie->header->Width % 2)) {
+ BLI_assert(bits != 16);
+ if (movie->header->Width % 2) {
rowstride++;
}
diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc
index a958a445a3d..50f81c2ffb1 100644
--- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc
+++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc
@@ -25,6 +25,8 @@
extern "C" {
#include "BKE_anim.h"
+#include "BKE_animsys.h"
+#include "BKE_key.h"
#include "BKE_particle.h"
#include "BLI_assert.h"
@@ -33,6 +35,7 @@ extern "C" {
#include "DNA_ID.h"
#include "DNA_layer_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
@@ -76,6 +79,31 @@ AbstractHierarchyWriter::~AbstractHierarchyWriter()
{
}
+bool AbstractHierarchyWriter::check_is_animated(const HierarchyContext &context) const
+{
+ const Object *object = context.object;
+
+ if (BKE_animdata_id_is_animated(static_cast<ID *>(object->data))) {
+ return true;
+ }
+ if (BKE_key_from_object(object) != nullptr) {
+ return true;
+ }
+
+ /* Test modifiers. */
+ /* TODO(Sybren): replace this with a check on the depsgraph to properly check for dependency on
+ * time. */
+ ModifierData *md = static_cast<ModifierData *>(object->modifiers.first);
+ while (md) {
+ if (md->type != eModifierType_Subsurf) {
+ return true;
+ }
+ md = md->next;
+ }
+
+ return false;
+}
+
AbstractHierarchyIterator::AbstractHierarchyIterator(Depsgraph *depsgraph)
: depsgraph_(depsgraph), writers_()
{
diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h b/source/blender/io/usd/intern/abstract_hierarchy_iterator.h
index c121e3b704d..64c831877ab 100644
--- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h
+++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.h
@@ -115,6 +115,8 @@ class AbstractHierarchyWriter {
// TODO(Sybren): add function like absent() that's called when a writer was previously created,
// but wasn't used while exporting the current frame (for example, a particle-instanced mesh of
// which the particle is no longer alive).
+ protected:
+ virtual bool check_is_animated(const HierarchyContext &context) const;
};
/* AbstractHierarchyIterator iterates over objects in a dependency graph, and constructs export
diff --git a/source/blender/io/usd/intern/usd_capi.cc b/source/blender/io/usd/intern/usd_capi.cc
index 83e11cd7bf3..60ab3676847 100644
--- a/source/blender/io/usd/intern/usd_capi.cc
+++ b/source/blender/io/usd/intern/usd_capi.cc
@@ -49,7 +49,6 @@ extern "C" {
namespace USD {
struct ExportJobData {
- ViewLayer *view_layer;
Main *bmain;
Depsgraph *depsgraph;
wmWindowManager *wm;
@@ -57,22 +56,13 @@ struct ExportJobData {
char filename[FILE_MAX];
USDExportParams params;
- short *stop;
- short *do_update;
- float *progress;
-
- bool was_canceled;
bool export_ok;
};
static void export_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
ExportJobData *data = static_cast<ExportJobData *>(customdata);
-
- data->stop = stop;
- data->do_update = do_update;
- data->progress = progress;
- data->was_canceled = false;
+ data->export_ok = false;
G.is_rendering = true;
WM_set_locked_interface(data->wm, true);
@@ -97,7 +87,6 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
* USDC files, and creating a new UsdStage fails. */
WM_reportf(
RPT_ERROR, "USD Export: unable to find suitable USD plugin to write %s", data->filename);
- data->export_ok = false;
return;
}
@@ -150,8 +139,7 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain);
}
- data->export_ok = !data->was_canceled;
-
+ data->export_ok = true;
*progress = 1.0f;
*do_update = true;
}
@@ -162,7 +150,7 @@ static void export_endjob(void *customdata)
DEG_graph_free(data->depsgraph);
- if (data->was_canceled && BLI_exists(data->filename)) {
+ if (!data->export_ok && BLI_exists(data->filename)) {
BLI_delete(data->filename, false, false);
}
diff --git a/source/blender/io/usd/intern/usd_writer_abstract.cc b/source/blender/io/usd/intern/usd_writer_abstract.cc
index 4d0b4364fb5..76a2436ee92 100644
--- a/source/blender/io/usd/intern/usd_writer_abstract.cc
+++ b/source/blender/io/usd/intern/usd_writer_abstract.cc
@@ -21,13 +21,6 @@
#include <pxr/base/tf/stringUtils.h>
-extern "C" {
-#include "BKE_animsys.h"
-#include "BKE_key.h"
-
-#include "DNA_modifier_types.h"
-}
-
/* TfToken objects are not cheap to construct, so we do it once. */
namespace usdtokens {
// Materials
@@ -85,31 +78,6 @@ void USDAbstractWriter::write(HierarchyContext &context)
frame_has_been_written_ = true;
}
-bool USDAbstractWriter::check_is_animated(const HierarchyContext &context) const
-{
- const Object *object = context.object;
-
- if (BKE_animdata_id_is_animated(static_cast<ID *>(object->data))) {
- return true;
- }
- if (BKE_key_from_object(object) != nullptr) {
- return true;
- }
-
- /* Test modifiers. */
- /* TODO(Sybren): replace this with a check on the depsgraph to properly check for dependency on
- * time. */
- ModifierData *md = static_cast<ModifierData *>(object->modifiers.first);
- while (md) {
- if (md->type != eModifierType_Subsurf) {
- return true;
- }
- md = md->next;
- }
-
- return false;
-}
-
const pxr::SdfPath &USDAbstractWriter::usd_path() const
{
return usd_export_context_.usd_path;
diff --git a/source/blender/io/usd/intern/usd_writer_abstract.h b/source/blender/io/usd/intern/usd_writer_abstract.h
index 835d3a42c80..ad8049f499c 100644
--- a/source/blender/io/usd/intern/usd_writer_abstract.h
+++ b/source/blender/io/usd/intern/usd_writer_abstract.h
@@ -66,7 +66,6 @@ class USDAbstractWriter : public AbstractHierarchyWriter {
protected:
virtual void do_write(HierarchyContext &context) = 0;
- virtual bool check_is_animated(const HierarchyContext &context) const;
pxr::UsdTimeCode get_export_time_code() const;
pxr::UsdShadeMaterial ensure_usd_material(Material *material);
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 1121bdf4df0..bc7873adb70 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -47,7 +47,6 @@ typedef enum GpencilModifierType {
eGpencilModifierType_Armature = 15,
eGpencilModifierType_Time = 16,
eGpencilModifierType_Multiply = 17,
- eGpencilModifierType_Vertexcolor = 18,
NUM_GREASEPENCIL_MODIFIER_TYPES,
} GpencilModifierType;
@@ -106,15 +105,15 @@ typedef struct NoiseGpencilModifierData {
typedef enum eNoiseGpencil_Flag {
GP_NOISE_USE_RANDOM = (1 << 0),
- GP_NOISE_MOD_LOCATION = (1 << 1),
- GP_NOISE_MOD_STRENGTH = (1 << 2),
- GP_NOISE_MOD_THICKNESS = (1 << 3),
+ GP_NOISE_MOD_LOCATION = (1 << 1), /* Deprecated (only for versioning). */
+ GP_NOISE_MOD_STRENGTH = (1 << 2), /* Deprecated (only for versioning). */
+ GP_NOISE_MOD_THICKNESS = (1 << 3), /* Deprecated (only for versioning). */
GP_NOISE_FULL_STROKE = (1 << 4),
GP_NOISE_CUSTOM_CURVE = (1 << 5),
GP_NOISE_INVERT_LAYER = (1 << 6),
GP_NOISE_INVERT_PASS = (1 << 7),
GP_NOISE_INVERT_VGROUP = (1 << 8),
- GP_NOISE_MOD_UV = (1 << 9),
+ GP_NOISE_MOD_UV = (1 << 9), /* Deprecated (only for versioning). */
GP_NOISE_INVERT_LAYERPASS = (1 << 10),
GP_NOISE_INVERT_MATERIAL = (1 << 11),
} eNoiseGpencil_Flag;
@@ -223,38 +222,6 @@ typedef enum eOpacityModesGpencil_Flag {
GP_OPACITY_MODE_STRENGTH = 1,
} eOpacityModesGpencil_Flag;
-typedef struct TintGpencilModifierData {
- GpencilModifierData modifier;
- /** Layer name. */
- char layername[64];
- /** Material name. */
- char materialname[64];
- /** Custom index for passes. */
- int pass_index;
- /** Flags. */
- int flag;
- /** Tint color. */
- float rgb[3];
- /** Mix factor. */
- float factor;
- /** Modify stroke, fill or both. */
- char modify_color;
- char _pad[7];
- /** Custom index for passes. */
- int layer_pass;
-
- char _pad1[4];
- struct CurveMapping *curve_intensity;
-} TintGpencilModifierData;
-
-typedef enum eTintGpencil_Flag {
- GP_TINT_INVERT_LAYER = (1 << 1),
- GP_TINT_INVERT_PASS = (1 << 2),
- GP_TINT_INVERT_LAYERPASS = (1 << 3),
- GP_TINT_INVERT_MATERIAL = (1 << 4),
- GP_TINT_CUSTOM_CURVE = (1 << 5),
-} eTintGpencil_Flag;
-
typedef struct ColorGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
@@ -700,7 +667,7 @@ typedef enum eMultiplyGpencil_Flag {
GP_MULTIPLY_ENABLE_FADING = (1 << 2),
} eMultiplyGpencil_Flag;
-typedef struct VertexcolorGpencilModifierData {
+typedef struct TintGpencilModifierData {
GpencilModifierData modifier;
struct Object *object;
@@ -716,25 +683,33 @@ typedef struct VertexcolorGpencilModifierData {
int layer_pass;
/** Flags. */
int flag;
- /** Mode. */
+ /** Mode (Stroke/Fill/Both). */
int mode;
float factor;
float radius;
+ /** Simple Tint color. */
+ float rgb[3];
+ /** Type of Tint. */
+ int type;
struct CurveMapping *curve_intensity;
struct ColorBand *colorband;
-} VertexcolorGpencilModifierData;
-
-typedef enum eVertexcolorGpencil_Flag {
- GP_VERTEXCOL_INVERT_LAYER = (1 << 0),
- GP_VERTEXCOL_INVERT_PASS = (1 << 1),
- GP_VERTEXCOL_INVERT_VGROUP = (1 << 2),
- GP_VERTEXCOL_UNIFORM_SPACE = (1 << 3),
- GP_VERTEXCOL_INVERT_LAYERPASS = (1 << 4),
- GP_VERTEXCOL_INVERT_MATERIAL = (1 << 5),
- GP_VERTEXCOL_CUSTOM_CURVE = (1 << 6),
-} eVertexcolorGpencil_Flag;
+} TintGpencilModifierData;
+
+typedef enum eTintGpencil_Type {
+ GP_TINT_UNIFORM = 0,
+ GP_TINT_GRADIENT = 1,
+} eTintGpencil_Type;
+
+typedef enum eTintGpencil_Flag {
+ GP_TINT_INVERT_LAYER = (1 << 0),
+ GP_TINT_INVERT_PASS = (1 << 1),
+ GP_TINT_INVERT_VGROUP = (1 << 2),
+ GP_TINT_INVERT_LAYERPASS = (1 << 4),
+ GP_TINT_INVERT_MATERIAL = (1 << 5),
+ GP_TINT_CUSTOM_CURVE = (1 << 6),
+} eTintGpencil_Flag;
#endif /* __DNA_GPENCIL_MODIFIER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 6059df6f886..909d65fb5ed 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -28,7 +28,6 @@
#include "DNA_ID.h"
#include "DNA_brush_types.h"
-struct ARegion;
struct AnimData;
struct MDeformVert;
@@ -481,8 +480,6 @@ typedef enum eGPLayerBlendModes {
/* Runtime temp data for bGPdata */
typedef struct bGPdata_Runtime {
- /** Last region where drawing was originated. */
- struct ARegion *ar;
/** Stroke buffer. */
void *sbuffer;
/** Temp batches cleared after drawing. */
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index 03de4fb0473..d443d7806ad 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -133,8 +133,8 @@ typedef struct Image {
/** Not written in file. */
struct MovieCache *cache;
- /** Not written in file 4 = TEXTARGET_COUNT. */
- struct GPUTexture *gputexture[4];
+ /** Not written in file 4 = TEXTARGET_COUNT, 2 = stereo eyes. */
+ struct GPUTexture *gputexture[4][2];
/* sources from: */
ListBase anims;
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index b2d02600124..7e8b888b82c 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -4348,7 +4348,9 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const
/* include the generated prototypes header */
fprintf(f, "#include \"rna_prototypes_gen.h\"\n\n");
- fprintf(f, "#include \"%s\"\n", filename);
+ if (filename) {
+ fprintf(f, "#include \"%s\"\n", filename);
+ }
if (api_filename) {
fprintf(f, "#include \"%s\"\n", api_filename);
}
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 5c824dc6e93..bd5c7e755d6 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -1468,6 +1468,15 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_FAKE_USER_OFF, true);
RNA_def_property_boolean_funcs(prop, NULL, "rna_ID_fake_user_set");
+ prop = RNA_def_property(srna, "is_embedded_data", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LIB_EMBEDDED_DATA);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(
+ prop,
+ "Embedded Data",
+ "This data-block is not an independant one, but is actually a sub-data of another ID "
+ "(typical example: root node trees or master collections)");
+
prop = RNA_def_property(srna, "tag", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "tag", LIB_TAG_DOIT);
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 0caa93940c8..00188ac0887 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -129,11 +129,6 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = {
"Opacity",
"Opacity of the strokes"},
{eGpencilModifierType_Tint, "GP_TINT", ICON_MOD_TINT, "Tint", "Tint strokes with new color"},
- {eGpencilModifierType_Vertexcolor,
- "GP_VERTEXCOLOR",
- ICON_MOD_NORMALEDIT,
- "Vertex Color",
- "Apply color changes to Vertex Color"},
{0, NULL, 0, NULL, NULL},
};
@@ -170,6 +165,11 @@ static const EnumPropertyItem gpencil_subdivision_type_items[] = {
{GP_SUBDIV_SIMPLE, "SIMPLE", 0, "Simple", ""},
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem gpencil_tint_type_items[] = {
+ {GP_TINT_UNIFORM, "UNIFORM", 0, "Uniform", ""},
+ {GP_TINT_GRADIENT, "GRADIENT", 0, "Gradient", ""},
+ {0, NULL, 0, NULL, NULL},
+};
#endif
#ifdef RNA_RUNTIME
@@ -226,8 +226,6 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr)
return &RNA_ArmatureGpencilModifier;
case eGpencilModifierType_Multiply:
return &RNA_MultiplyGpencilModifier;
- case eGpencilModifierType_Vertexcolor:
- return &RNA_VertexcolorGpencilModifier;
/* Default */
case eGpencilModifierType_None:
case NUM_GREASEPENCIL_MODIFIER_TYPES:
@@ -342,11 +340,11 @@ static void rna_HookGpencilModifier_object_set(PointerRNA *ptr,
BKE_object_modifier_gpencil_hook_reset(ob, hmd);
}
-static void rna_VertexcolorGpencilModifier_object_set(PointerRNA *ptr,
- PointerRNA value,
- struct ReportList *UNUSED(reports))
+static void rna_TintGpencilModifier_object_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
- VertexcolorGpencilModifierData *hmd = ptr->data;
+ TintGpencilModifierData *hmd = ptr->data;
Object *ob = (Object *)value.data;
hmd->object = ob;
@@ -480,12 +478,6 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Seed", "Random seed");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "use_edit_position", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_MOD_LOCATION);
- RNA_def_property_ui_text(
- prop, "Affect Position", "The modifier affects the position of the point");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
prop = RNA_def_property(srna, "noise_scale", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "noise_scale");
RNA_def_property_range(prop, 0.0, 1.0);
@@ -1018,15 +1010,25 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ /* modes */
+ static EnumPropertyItem tint_mode_types_items[] = {
+ {GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Vertex Color affects to Stroke only"},
+ {GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Vertex Color affects to Fill only"},
+ {GPPAINT_MODE_BOTH, "BOTH", 0, "Both", "Vertex Color affects to Stroke and Fill"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
srna = RNA_def_struct(brna, "TintGpencilModifier", "GpencilModifier");
- RNA_def_struct_ui_text(srna, "Tint Modifier", "Tint Stroke Color modifier");
+ RNA_def_struct_ui_text(srna, "Tint Modifier", "Tint modifier");
RNA_def_struct_sdna(srna, "TintGpencilModifierData");
RNA_def_struct_ui_icon(srna, ICON_COLOR);
- prop = RNA_def_property(srna, "modify_color", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, modifier_modify_color_items); /* share the enum */
- RNA_def_property_ui_text(prop, "Mode", "Set what colors of the stroke are affected");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Parent object to define the center of the effect");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_TintGpencilModifier_object_set", NULL, NULL);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "layername");
@@ -1038,17 +1040,10 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Material", "Material name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_float_sdna(prop, NULL, "rgb");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Color", "Color used for tinting");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "factor");
- RNA_def_property_ui_range(prop, 0, 2.0, 0.1, 2);
- RNA_def_property_ui_text(prop, "Factor", "Factor for mixing color");
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_HookGpencilModifier_vgname_set");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
@@ -1072,6 +1067,11 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse Vertex Group", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "layer_pass");
RNA_def_property_range(prop, 0, 100);
@@ -1083,10 +1083,54 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_range(prop, 0, 2.0);
+ RNA_def_property_ui_range(prop, 0, 2.0, 0.1, 2);
+ RNA_def_property_ui_text(prop, "Strength", "Factor for tinting");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "radius");
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 1, 3);
+ RNA_def_property_ui_text(prop, "Radius", "Defines the maximum distance of the effect");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Mode type. */
+ prop = RNA_def_property(srna, "vertex_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, tint_mode_types_items);
+ RNA_def_property_ui_text(prop, "Mode", "Defines how vertex color affect to the strokes");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Type of Tint. */
+ prop = RNA_def_property(srna, "tint_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, gpencil_tint_type_items);
+ RNA_def_property_ui_text(prop, "Tint Type", "Select type of tinting algorithm");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Simple Color. */
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rgb");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Color", "Color used for tinting");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Color band. */
+ prop = RNA_def_property(srna, "colors", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "colorband");
+ RNA_def_property_struct_type(prop, "ColorRamp");
+ RNA_def_property_ui_text(prop, "Colors", "Color ramp used to define tinting colors");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "use_custom_curve", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_CUSTOM_CURVE);
RNA_def_property_ui_text(
- prop, "Custom Curve", "Use a custom curve to define tint effect along the strokes");
+ prop, "Custom Curve", "Use a custom curve to define vertex color effect along the strokes");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
@@ -2078,125 +2122,6 @@ static void rna_def_modifier_gpencilmultiply(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
}
-static void rna_def_modifier_gpencilvertexcolor(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- /* modes */
- static EnumPropertyItem vertexcol_mode_types_items[] = {
- {GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Vertex Color affects to Stroke only"},
- {GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Vertex Color affects to Fill only"},
- {GPPAINT_MODE_BOTH, "BOTH", 0, "Both", "Vertex Color affects to Stroke and Fill"},
- {0, NULL, 0, NULL, NULL},
- };
-
- srna = RNA_def_struct(brna, "VertexcolorGpencilModifier", "GpencilModifier");
- RNA_def_struct_ui_text(srna, "Vertexcolor Modifier", "Vertex color modifier");
- RNA_def_struct_sdna(srna, "VertexcolorGpencilModifierData");
- RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT);
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Object", "Parent object to define the center of the effect");
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_pointer_funcs(
- prop, NULL, "rna_VertexcolorGpencilModifier_object_set", NULL, NULL);
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
-
- prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "layername");
- RNA_def_property_ui_text(prop, "Layer", "Layer name");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "materialname");
- RNA_def_property_ui_text(prop, "Material", "Material name");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "vgname");
- RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_HookGpencilModifier_vgname_set");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "pass_index");
- RNA_def_property_range(prop, 0, 100);
- RNA_def_property_ui_text(prop, "Pass", "Pass index");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_VERTEXCOL_INVERT_LAYER);
- RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_VERTEXCOL_INVERT_MATERIAL);
- RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_VERTEXCOL_INVERT_PASS);
- RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_VERTEXCOL_INVERT_VGROUP);
- RNA_def_property_ui_text(prop, "Inverse Vertex Group", "Inverse filter");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "layer_pass");
- RNA_def_property_range(prop, 0, 100);
- RNA_def_property_ui_text(prop, "Pass", "Layer pass index");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "invert_layer_pass", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_VERTEXCOL_INVERT_LAYERPASS);
- RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "factor");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Factor", "Factor of tinting");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_float_sdna(prop, NULL, "radius");
- RNA_def_property_range(prop, 1e-6f, FLT_MAX);
- RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 1, 3);
- RNA_def_property_ui_text(prop, "Radius", "Defines the maximum distance of the effect");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- /* Mode type. */
- prop = RNA_def_property(srna, "vertex_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode");
- RNA_def_property_enum_items(prop, vertexcol_mode_types_items);
- RNA_def_property_ui_text(prop, "Mode", "Defines how vertex color affect to the strokes");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- /* Color band */
- prop = RNA_def_property(srna, "colors", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "colorband");
- RNA_def_property_struct_type(prop, "ColorRamp");
- RNA_def_property_ui_text(prop, "Colors", "Color ramp used to define tinting colors");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "use_custom_curve", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_VERTEXCOL_CUSTOM_CURVE);
- RNA_def_property_ui_text(
- prop, "Custom Curve", "Use a custom curve to define vertex color effect along the strokes");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "curve_intensity");
- RNA_def_property_ui_text(prop, "Curve", "Custom curve to apply effect");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-}
-
void RNA_def_greasepencil_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2270,7 +2195,6 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna)
rna_def_modifier_gpencilhook(brna);
rna_def_modifier_gpencilarmature(brna);
rna_def_modifier_gpencilmultiply(brna);
- rna_def_modifier_gpencilvertexcolor(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index b8174f094ec..8f2a841b55c 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -398,7 +398,7 @@ static void rna_Image_resolution_set(PointerRNA *ptr, const float *values)
static int rna_Image_bindcode_get(PointerRNA *ptr)
{
Image *ima = (Image *)ptr->data;
- GPUTexture *tex = ima->gputexture[TEXTARGET_TEXTURE_2D];
+ GPUTexture *tex = ima->gputexture[TEXTARGET_TEXTURE_2D][0];
return (tex) ? GPU_texture_opengl_bindcode(tex) : 0;
}
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index 883c17aa1e1..2068c747f4e 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -60,7 +60,7 @@ static void initData(ModifierData *md)
mmd->renderlvl = 0;
mmd->totlvl = 0;
mmd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
- mmd->quality = 3;
+ mmd->quality = 4;
mmd->flags |= eMultiresModifierFlag_UseCrease;
}
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 605919662f7..743c2227981 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -1121,20 +1121,25 @@ static void deformVert(void *__restrict userdata,
{
const SDefDeformData *const data = (SDefDeformData *)userdata;
const SDefBind *sdbind = data->bind_verts[index].binds;
+ const int num_binds = data->bind_verts[index].numbinds;
float *const vertexCos = data->vertexCos[index];
float norm[3], temp[3];
zero_v3(vertexCos);
- for (int j = 0; j < data->bind_verts[index].numbinds; j++, sdbind++) {
- /* Mode-generic operations (allocate poly coordinates) */
- float(*coords)[3] = MEM_malloc_arrayN(sdbind->numverts, sizeof(*coords), "SDefDoPolyCoords");
+ /* Allocate a `coords_buffer` that fits all the temp-data. */
+ int max_verts = 0;
+ for (int j = 0; j < num_binds; j++) {
+ max_verts = MAX2(max_verts, sdbind[j].numverts);
+ }
+ float(*coords_buffer)[3] = MEM_malloc_arrayN(max_verts, sizeof(*coords_buffer), __func__);
+ for (int j = 0; j < num_binds; j++, sdbind++) {
for (int k = 0; k < sdbind->numverts; k++) {
- copy_v3_v3(coords[k], data->targetCos[sdbind->vert_inds[k]]);
+ copy_v3_v3(coords_buffer[k], data->targetCos[sdbind->vert_inds[k]]);
}
- normal_poly_v3(norm, coords, sdbind->numverts);
+ normal_poly_v3(norm, coords_buffer, sdbind->numverts);
zero_v3(temp);
/* ---------- looptri mode ---------- */
@@ -1147,14 +1152,14 @@ static void deformVert(void *__restrict userdata,
/* ---------- ngon mode ---------- */
if (sdbind->mode == MOD_SDEF_MODE_NGON) {
for (int k = 0; k < sdbind->numverts; k++) {
- madd_v3_v3fl(temp, coords[k], sdbind->vert_weights[k]);
+ madd_v3_v3fl(temp, coords_buffer[k], sdbind->vert_weights[k]);
}
}
/* ---------- centroid mode ---------- */
else if (sdbind->mode == MOD_SDEF_MODE_CENTROID) {
float cent[3];
- mid_v3_v3_array(cent, coords, sdbind->numverts);
+ mid_v3_v3_array(cent, coords_buffer, sdbind->numverts);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
@@ -1162,13 +1167,12 @@ static void deformVert(void *__restrict userdata,
}
}
- MEM_freeN(coords);
-
/* Apply normal offset (generic for all modes) */
madd_v3_v3fl(temp, norm, sdbind->normal_dist);
madd_v3_v3fl(vertexCos, temp, sdbind->influence);
}
+ MEM_freeN(coords_buffer);
}
static void surfacedeformModifier_do(ModifierData *md,
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 41227a14fb3..a2f825ee454 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -206,10 +206,10 @@ set(SRC
shader/nodes/node_shader_uvmap.c
shader/nodes/node_shader_valToRgb.c
shader/nodes/node_shader_value.c
- shader/nodes/node_shader_vector_rotate.c
shader/nodes/node_shader_vectTransform.c
shader/nodes/node_shader_vector_displacement.c
shader/nodes/node_shader_vector_math.c
+ shader/nodes/node_shader_vector_rotate.c
shader/nodes/node_shader_vertex_color.c
shader/nodes/node_shader_volume_absorption.c
shader/nodes/node_shader_volume_info.c
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 93f2ba44a3a..8c224eb335f 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -101,9 +101,8 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
bNode *node = ntree->nodes.first;
bNode *local_node = localtree->nodes.first;
while (node != NULL) {
- local_node->original = node;
- /* ensure new user input gets handled ok */
+ /* Ensure new user input gets handled ok. */
node->need_exec = 0;
local_node->original = node;
diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c
index 504126cb387..73e86a21ebe 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keying.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keying.c
@@ -57,7 +57,6 @@ static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node)
data->despill_factor = 1.0f;
data->edge_kernel_radius = 3;
data->edge_kernel_tolerance = 0.1f;
- data->clip_white = 1.0f;
data->clip_black = 0.0f;
data->clip_white = 1.0f;
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index c32ef3e6624..92230ece35e 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -5424,6 +5424,174 @@ static PyObject *pyrna_prop_collection_foreach_set(BPy_PropertyRNA *self, PyObje
return foreach_getset(self, args, 1);
}
+static PyObject *pyprop_array_foreach_getset(BPy_PropertyArrayRNA *self,
+ PyObject *args,
+ const bool do_set)
+{
+ PyObject *item = NULL;
+ Py_ssize_t i, seq_size, size;
+ void *array = NULL;
+ PropertyType prop_type = RNA_property_type(self->prop);
+
+ /* Get/set both take the same args currently. */
+ PyObject *seq;
+
+ if (prop_type != PROP_INT && prop_type != PROP_FLOAT) {
+ PyErr_Format(PyExc_TypeError, "foreach_get/set available only for int and float");
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(args, "O:foreach_get/set", &seq)) {
+ return NULL;
+ }
+
+ if (!PySequence_Check(seq) && PyObject_CheckBuffer(seq)) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "foreach_get/set expected second argument to be a sequence or buffer, not a %.200s",
+ Py_TYPE(seq)->tp_name);
+ return NULL;
+ }
+
+ size = pyrna_prop_array_length(self);
+ seq_size = PySequence_Size(seq);
+
+ if (size != seq_size) {
+ PyErr_Format(PyExc_TypeError, "expected sequence size %d, got %d", size, seq_size);
+ return NULL;
+ }
+
+ Py_buffer buf;
+ if (PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT) == -1) {
+ PyErr_Clear();
+
+ switch (prop_type) {
+ case PROP_INT:
+ array = PyMem_Malloc(sizeof(int) * size);
+ if (do_set) {
+ for (i = 0; i < size; i++) {
+ item = PySequence_GetItem(seq, i);
+ ((int *)array)[i] = (int)PyLong_AsLong(item);
+ Py_DECREF(item);
+ }
+
+ RNA_property_int_set_array(&self->ptr, self->prop, array);
+ }
+ else {
+ RNA_property_int_get_array(&self->ptr, self->prop, array);
+
+ for (i = 0; i < size; i++) {
+ item = PyLong_FromLong((long)((int *)array)[i]);
+ PySequence_SetItem(seq, i, item);
+ Py_DECREF(item);
+ }
+ }
+
+ break;
+ case PROP_FLOAT:
+ array = PyMem_Malloc(sizeof(float) * size);
+ if (do_set) {
+ for (i = 0; i < size; i++) {
+ item = PySequence_GetItem(seq, i);
+ ((float *)array)[i] = (float)PyFloat_AsDouble(item);
+ Py_DECREF(item);
+ }
+
+ RNA_property_float_set_array(&self->ptr, self->prop, array);
+ }
+ else {
+ RNA_property_float_get_array(&self->ptr, self->prop, array);
+
+ for (i = 0; i < size; i++) {
+ item = PyFloat_FromDouble((double)((float *)array)[i]);
+ PySequence_SetItem(seq, i, item);
+ Py_DECREF(item);
+ }
+ }
+ break;
+ case PROP_BOOLEAN:
+ case PROP_STRING:
+ case PROP_ENUM:
+ case PROP_POINTER:
+ case PROP_COLLECTION:
+ /* Should never happen. */
+ BLI_assert(false);
+ break;
+ }
+
+ PyMem_Free(array);
+
+ if (PyErr_Occurred()) {
+ /* Maybe we could make our own error. */
+ PyErr_Print();
+ PyErr_SetString(PyExc_TypeError, "couldn't access the py sequence");
+ return NULL;
+ }
+ }
+ else {
+ char f = buf.format ? buf.format[0] : 0;
+ if ((prop_type == PROP_INT && (buf.itemsize != sizeof(int) || (f != 'l' && f != 'i'))) ||
+ (prop_type == PROP_FLOAT && (buf.itemsize != sizeof(float) || f != 'f'))) {
+ PyBuffer_Release(&buf);
+ PyErr_Format(PyExc_TypeError, "incorrect sequence item type: %s", buf.format);
+ return NULL;
+ }
+
+ switch (prop_type) {
+ case PROP_INT:
+ if (do_set) {
+ RNA_property_int_set_array(&self->ptr, self->prop, buf.buf);
+ }
+ else {
+ RNA_property_int_get_array(&self->ptr, self->prop, buf.buf);
+ }
+ break;
+ case PROP_FLOAT:
+ if (do_set) {
+ RNA_property_float_set_array(&self->ptr, self->prop, buf.buf);
+ }
+ else {
+ RNA_property_float_get_array(&self->ptr, self->prop, buf.buf);
+ }
+ break;
+ case PROP_BOOLEAN:
+ case PROP_STRING:
+ case PROP_ENUM:
+ case PROP_POINTER:
+ case PROP_COLLECTION:
+ /* Should never happen. */
+ BLI_assert(false);
+ break;
+ }
+
+ PyBuffer_Release(&buf);
+ }
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pyrna_prop_array_foreach_get_doc,
+ ".. method:: foreach_get(seq)\n"
+ "\n"
+ " This is a function to give fast access to array data.\n");
+static PyObject *pyrna_prop_array_foreach_get(BPy_PropertyArrayRNA *self, PyObject *args)
+{
+ PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
+
+ return pyprop_array_foreach_getset(self, args, false);
+}
+
+PyDoc_STRVAR(pyrna_prop_array_foreach_set_doc,
+ ".. method:: foreach_set(seq)\n"
+ "\n"
+ " This is a function to give fast access to array data.\n");
+static PyObject *pyrna_prop_array_foreach_set(BPy_PropertyArrayRNA *self, PyObject *args)
+{
+ PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
+
+ return pyprop_array_foreach_getset(self, args, true);
+}
+
/* A bit of a kludge, make a list out of a collection or array,
* then return the list's iter function, not especially fast, but convenient for now. */
static PyObject *pyrna_prop_array_iter(BPy_PropertyArrayRNA *self)
@@ -5572,6 +5740,15 @@ static struct PyMethodDef pyrna_prop_methods[] = {
};
static struct PyMethodDef pyrna_prop_array_methods[] = {
+ {"foreach_get",
+ (PyCFunction)pyrna_prop_array_foreach_get,
+ METH_VARARGS,
+ pyrna_prop_array_foreach_get_doc},
+ {"foreach_set",
+ (PyCFunction)pyrna_prop_array_foreach_set,
+ METH_VARARGS,
+ pyrna_prop_array_foreach_set_doc},
+
{NULL, NULL, 0, NULL},
};
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 88614de1641..38cba264a01 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -198,7 +198,7 @@ void RE_engine_set_error_message(RenderEngine *engine, const char *msg);
int RE_engine_render(struct Render *re, int do_all);
-bool RE_engine_is_external(struct Render *re);
+bool RE_engine_is_external(const struct Render *re);
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe);
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 3c089335115..fabbd5fb096 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -57,7 +57,7 @@ struct RenderResult *render_result_new_from_exr(
void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
void render_result_view_new(struct RenderResult *rr, const char *viewname);
-void render_result_views_new(struct RenderResult *rr, struct RenderData *rd);
+void render_result_views_new(struct RenderResult *rr, const struct RenderData *rd);
/* Merge */
@@ -110,7 +110,7 @@ bool render_result_exr_file_cache_read(struct Render *re);
/* Combined Pixel Rect */
struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr,
- struct RenderData *rd,
+ const struct RenderData *rd,
const int view_id);
void render_result_rect_fill_zero(struct RenderResult *rr, const int view_id);
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 598f300cf86..4fcb5f5f16e 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -116,7 +116,7 @@ RenderEngineType *RE_engines_find(const char *idname)
return type;
}
-bool RE_engine_is_external(Render *re)
+bool RE_engine_is_external(const Render *re)
{
return (re->engine && re->engine->type && re->engine->type->render);
}
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 2021967b05d..4e20dd51122 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -798,7 +798,7 @@ void render_result_view_new(RenderResult *rr, const char *viewname)
BLI_strncpy(rv->name, viewname, sizeof(rv->name));
}
-void render_result_views_new(RenderResult *rr, RenderData *rd)
+void render_result_views_new(RenderResult *rr, const RenderData *rd)
{
SceneRenderView *srv;
@@ -1459,7 +1459,7 @@ bool render_result_exr_file_cache_read(Render *re)
/*************************** Combined Pixel Rect *****************************/
-ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id)
+ImBuf *render_result_rect_to_ibuf(RenderResult *rr, const RenderData *rd, const int view_id)
{
ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
RenderView *rv = RE_RenderViewGetById(rr, view_id);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 83355ecb786..c8c86ade07a 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -113,6 +113,7 @@
#include "GHOST_Path-api.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -2817,7 +2818,7 @@ static uiBlock *block_create_autorun_warning(struct bContext *C,
void *UNUSED(arg1))
{
wmWindowManager *wm = CTX_wm_manager(C);
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
uiBlock *block = UI_block_begin(C, region, "autorun_warning_popup", UI_EMBOSS);
UI_block_flag_enable(
@@ -3055,58 +3056,77 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C,
{
wmGenericCallback *post_action = (wmGenericCallback *)arg1;
Main *bmain = CTX_data_main(C);
- uiStyle *style = UI_style_get();
- uiFontStyle *fs = &style->widgetlabel;
+ const uiStyle *style = UI_style_get_dpi();
+ const int dialog_width = U.widget_unit * 22;
+ const short icon_size = 64 * U.dpi_fac;
- /* Filename */
- const char *blendfile_pathpath = BKE_main_blendfile_path(bmain);
- char filename[FILE_MAX];
- if (blendfile_pathpath[0] != '\0') {
- BLI_split_file_part(blendfile_pathpath, filename, sizeof(filename));
- BLI_path_extension_replace(filename, sizeof(filename), "");
- }
- else {
- STRNCPY(filename, IFACE_("Untitled"));
- }
+ /* Calculate icon column factor. */
+ const float split_factor = (float)icon_size / (float)(dialog_width - style->columnspace);
- /* Title */
- char title[FILE_MAX + 100];
- UI_text_clip_middle_ex(
- fs, filename, U.widget_unit * 9, U.widget_unit * 2, sizeof(filename), '\0');
- BLI_snprintf(title, sizeof(title), TIP_("Save changes to \"%s\" before closing?"), filename);
- int title_width = MAX2(UI_fontstyle_string_width(fs, title), U.widget_unit * 22);
-
- /* Create dialog */
uiBlock *block = UI_block_begin(C, region, close_file_dialog_name, UI_EMBOSS);
- style = UI_style_get_dpi();
UI_block_flag_enable(
block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
UI_block_emboss_set(block, UI_EMBOSS);
- uiLayout *layout = UI_block_layout(block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- 10,
- 2,
- U.widget_unit * 2 + title_width,
- U.widget_unit * 6,
- 0,
- style);
+ uiLayout *block_layout = UI_block_layout(
+ block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style);
+
+ /* Split layout to put alert icon on left side. */
+ uiLayout *split_block = uiLayoutSplit(block_layout, split_factor, false);
+
+ /* Alert Icon. */
+ uiLayout *layout = uiLayoutColumn(split_block, false);
+ uiDefButAlert(block, ALERT_ICON_WARNING, 0, 0, 0, icon_size);
- /* Title */
- uiItemL_ex(layout, title, ICON_ERROR, true, false);
+ /* The rest of the content on the right. */
+ layout = uiLayoutColumn(split_block, false);
- /* Image Saving */
+ /* Title. */
+ uiItemL_ex(layout, TIP_("Save changes before closing?"), ICON_NONE, true, false);
+
+ /* Filename. */
+ const char *blendfile_pathpath = BKE_main_blendfile_path(CTX_data_main(C));
+ char filename[FILE_MAX];
+ if (blendfile_pathpath[0] != '\0') {
+ BLI_split_file_part(blendfile_pathpath, filename, sizeof(filename));
+ BLI_path_extension_replace(filename, sizeof(filename), "");
+ }
+ else {
+ STRNCPY(filename, IFACE_("Untitled"));
+ }
+ uiItemL(layout, filename, ICON_NONE);
+
+ /* Image Saving Warnings. */
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
uint modified_images_count = ED_image_save_all_modified_info(bmain, &reports);
LISTBASE_FOREACH (Report *, report, &reports.list) {
- uiItemL_ex(layout, report->message, ICON_CANCEL, false, true);
+ uiLayout *row = uiLayoutColumn(layout, false);
+ uiLayoutSetScaleY(row, 0.6f);
+ uiItemS_ex(row, 1.2f);
+
+ /* Error messages created in ED_image_save_all_modified_info() can be long,
+ * but are made to separate into two parts at first colon between text and paths.
+ */
+ char *message = BLI_strdupn(report->message, report->len);
+ char *path_info = strstr(message, ": ");
+ if (path_info) {
+ /* Terminate message string at colon. */
+ path_info[1] = '\0';
+ /* Skip over the ": " */
+ path_info += 2;
+ }
+ uiItemL_ex(row, message, ICON_NONE, false, true);
+ if (path_info) {
+ uiItemL_ex(row, path_info, ICON_NONE, false, true);
+ }
+ MEM_freeN(message);
}
+ /* Modified Images Checkbox. */
if (modified_images_count > 0) {
char message[64];
BLI_snprintf(message,
@@ -3114,7 +3134,7 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C,
(modified_images_count == 1) ? "Save %u modified image" :
"Save %u modified images",
modified_images_count);
- uiItemS(layout);
+ uiItemS_ex(layout, 2.0f);
uiDefButBitC(block,
UI_BTYPE_CHECKBOX,
1,
@@ -3134,9 +3154,9 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C,
BKE_reports_clear(&reports);
- uiItemS_ex(layout, 3.0f);
+ uiItemS_ex(layout, 1.0f);
- /* Buttons */
+ /* Buttons. */
#ifdef _WIN32
const bool windows_layout = true;
#else
@@ -3146,37 +3166,44 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C,
if (windows_layout) {
/* Windows standard layout. */
- uiLayout *split = uiLayoutSplit(layout, 0.18f, true);
+ uiLayout *split = uiLayoutSplit(block_layout, 0.174f, true);
uiLayoutSetScaleY(split, 1.2f);
- uiLayout *col = uiLayoutColumn(split, false);
- uiItemS(col);
+ uiLayoutColumn(split, false);
+ uiItemS(layout);
- col = uiLayoutColumn(split, false);
+ uiLayoutColumn(split, false);
wm_block_file_close_save_button(block, post_action);
- col = uiLayoutColumn(split, false);
+ uiLayoutColumn(split, false);
wm_block_file_close_discard_button(block, post_action);
- col = uiLayoutColumn(split, false);
+ uiLayoutColumn(split, false);
wm_block_file_close_cancel_button(block, post_action);
}
else {
/* macOS and Linux standard layout. */
- uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
+ uiLayout *split = uiLayoutSplit(block_layout, 0.167f, true);
uiLayoutSetScaleY(split, 1.2f);
- uiLayout *col = uiLayoutColumn(split, true);
+ layout = uiLayoutColumn(split, false);
+ uiItemS(layout);
+
+ /* Split button area into two sections: 40/60. */
+ uiLayout *mac_left = uiLayoutSplit(split, 0.40f, true);
+
+ /* First button uses 75% of left side (30% of original). */
+ uiLayoutSplit(mac_left, 0.75f, true);
wm_block_file_close_discard_button(block, post_action);
- col = uiLayoutColumn(split, true);
- uiItemS(col);
+ /* The right side is split 50/50 (each 30% of original). */
+ uiLayout *mac_right = uiLayoutSplit(mac_left, 0.50f, true);
- col = uiLayoutColumn(split, true);
+ uiLayoutColumn(mac_right, false);
wm_block_file_close_cancel_button(block, post_action);
- col = uiLayoutColumn(split, false);
+ uiLayoutColumn(mac_right, false);
wm_block_file_close_save_button(block, post_action);
}
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 1cc9c82ec60..9dedab8cc55 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -76,17 +76,30 @@ struct wmJob {
/** Should store entire own context, for start, update, free */
void *customdata;
- /** To prevent cpu overhead,
- * use this one which only gets called when job really starts, not in thread */
+ /**
+ * To prevent cpu overhead, use this one which only gets called when job really starts.
+ * Executed in main thread.
+ */
void (*initjob)(void *);
- /** This runs inside thread, and does full job */
+ /**
+ * This performs the actual parallel work.
+ * Executed in worker thread(s).
+ */
void (*startjob)(void *, short *stop, short *do_update, float *progress);
- /** Update gets called if thread defines so, and max once per timerstep
- * it runs outside thread, blocking blender, no drawing! */
+ /**
+ * Called if thread defines so (see `do_update` flag), and max once per timer step.
+ * Executed in main thread.
+ */
void (*update)(void *);
- /** Free entire customdata, doesn't run in thread */
+ /**
+ * Free callback (typically for customdata).
+ * Executed in main thread.
+ */
void (*free)(void *);
- /** Gets called when job is stopped, not in thread */
+ /**
+ * Called when job is stopped.
+ * Executed in main thread.
+ */
void (*endjob)(void *);
/** Running jobs each have own timer */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index aab2acaac76..80116507c4a 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1319,7 +1319,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op)
wmOperator *op = arg_op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
int width = 15 * UI_UNIT_X;
block = UI_block_begin(C, region, __func__, UI_EMBOSS);
@@ -1401,7 +1401,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *userD
wmOperator *op = data->op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
block = UI_block_begin(C, region, __func__, UI_EMBOSS);
UI_block_flag_disable(block, UI_BLOCK_LOOP);
@@ -1450,7 +1450,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *region, void *userDa
wmOperator *op = data->op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
block = UI_block_begin(C, region, __func__, UI_EMBOSS);
UI_block_flag_disable(block, UI_BLOCK_LOOP);
@@ -2308,7 +2308,7 @@ static void radial_control_paint_curve(uint pos, Brush *br, float radius, int li
static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void *customdata)
{
RadialControl *rc = customdata;
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
const uiFontStyle *fstyle = &style->widget;
const int fontid = fstyle->uifont_id;
short fstyle_points = fstyle->points;
@@ -3516,7 +3516,7 @@ static int previews_clear_exec(bContext *C, wmOperator *op)
BKE_idcode_to_idfilter(GS(id->name)) & id_filters);
#endif
- if (!id || !(BKE_idcode_to_idfilter(GS(id->name)) & id_filters)) {
+ if (!(BKE_idcode_to_idfilter(GS(id->name)) & id_filters)) {
continue;
}
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 51dccf5bb8b..ac5fd522664 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -525,9 +525,7 @@ static void build_pict_list_ex(
BLI_stringenc(filepath, fp_decoded.head, fp_decoded.tail, fp_decoded.digits, fp_framenr);
while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0))) {
- if (hasevent) {
- GHOST_DispatchEvents(g_WS.ghost_system);
- }
+ GHOST_DispatchEvents(g_WS.ghost_system);
if (ps->loading == false) {
return;
}
diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c
index 97490f7cc3b..dcf09e9cbc5 100644
--- a/source/blender/windowmanager/intern/wm_splash_screen.c
+++ b/source/blender/windowmanager/intern/wm_splash_screen.c
@@ -81,7 +81,7 @@ static void wm_block_splash_add_label(uiBlock *block, const char *label, int x,
return;
}
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.pixelsize * U.dpi);
int label_width = BLF_width(style->widgetlabel.uifont_id, label, strlen(label));
@@ -259,7 +259,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *UNUSE
{
uiBlock *block;
uiBut *but;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
block = UI_block_begin(C, region, "splash", UI_EMBOSS);
@@ -272,21 +272,13 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *UNUSE
/* Size before dpi scaling (halved for hi-dpi image). */
int ibuf_unit_size[2];
ImBuf *ibuf = wm_block_splash_image(ibuf_unit_size);
- but = uiDefBut(block,
- UI_BTYPE_IMAGE,
- 0,
- "",
- 0,
- 0.5f * U.widget_unit,
- U.dpi_fac * ibuf_unit_size[0],
- U.dpi_fac * ibuf_unit_size[1],
- /* Button owns the imbuf now. */
- ibuf,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
+ but = uiDefButImage(block,
+ ibuf,
+ 0,
+ 0.5f * U.widget_unit,
+ U.dpi_fac * ibuf_unit_size[0],
+ U.dpi_fac * ibuf_unit_size[1],
+ NULL);
UI_but_func_set(but, wm_block_splash_close, block, NULL);
UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL);
diff --git a/source/tools b/source/tools
-Subproject 4a6f1706258439db3ee5a50ec6938fef79c7cb9
+Subproject 603f076606f052adc97d937633bfeb9b268ec20
diff --git a/tests/gtests/blenlib/BLI_delaunay_2d_test.cc b/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
index 40b607fa807..79e47211049 100644
--- a/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
+++ b/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
@@ -489,7 +489,7 @@ TEST(delaunay, Quad0)
int e_diag_out;
const char *spec = R"(4 0 0
0.0 1.0
- 1,0. 0.0
+ 1.0 0.0
2.0 0.1
2.25 0.5
)";
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index 2b47995095a..401ba2d5ffb 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -123,10 +123,10 @@ TEST(path_util, Clean)
int index_output, len_output; \
const bool ret = BLI_path_name_at_index(path, index_input, &index_output, &len_output); \
if (expect == NULL) { \
- EXPECT_EQ(ret, false); \
+ EXPECT_FALSE(ret); \
} \
else { \
- EXPECT_EQ(ret, true); \
+ EXPECT_TRUE(ret); \
EXPECT_EQ(strlen(expect), len_output); \
path[index_output + len_output] = '\0'; \
EXPECT_STREQ(&path[index_output], expect); \
@@ -355,42 +355,42 @@ TEST(path_util, Frame)
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 1);
- EXPECT_EQ(ret, 1);
+ EXPECT_TRUE(ret);
EXPECT_STREQ("123", path);
}
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 12);
- EXPECT_EQ(ret, 1);
+ EXPECT_TRUE(ret);
EXPECT_STREQ("000000000123", path);
}
{
char path[FILE_MAX] = "test_";
ret = BLI_path_frame(path, 123, 1);
- EXPECT_EQ(ret, 1);
+ EXPECT_TRUE(ret);
EXPECT_STREQ("test_123", path);
}
{
char path[FILE_MAX] = "test_";
ret = BLI_path_frame(path, 1, 12);
- EXPECT_EQ(ret, 1);
+ EXPECT_TRUE(ret);
EXPECT_STREQ("test_000000000001", path);
}
{
char path[FILE_MAX] = "test_############";
ret = BLI_path_frame(path, 1, 0);
- EXPECT_EQ(ret, 1);
+ EXPECT_TRUE(ret);
EXPECT_STREQ("test_000000000001", path);
}
{
char path[FILE_MAX] = "test_#_#_middle";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(ret, 1);
+ EXPECT_TRUE(ret);
EXPECT_STREQ("test_#_123_middle", path);
}
@@ -398,14 +398,14 @@ TEST(path_util, Frame)
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(ret, 0);
+ EXPECT_FALSE(ret);
EXPECT_STREQ("", path);
}
{
char path[FILE_MAX] = "test_middle";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(ret, 0);
+ EXPECT_FALSE(ret);
EXPECT_STREQ("test_middle", path);
}
}
diff --git a/tests/gtests/blenlib/BLI_polyfill_2d_test.cc b/tests/gtests/blenlib/BLI_polyfill_2d_test.cc
index 264ed8fadbc..bb9f739a71e 100644
--- a/tests/gtests/blenlib/BLI_polyfill_2d_test.cc
+++ b/tests/gtests/blenlib/BLI_polyfill_2d_test.cc
@@ -111,7 +111,7 @@ static void test_polyfill_topology(const float poly[][2],
const unsigned int v1 = i;
const unsigned int v2 = (i + 1) % poly_tot;
void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
- EXPECT_EQ((void *)p != NULL, 1);
+ EXPECT_NE((void *)p, nullptr);
EXPECT_EQ((intptr_t)*p, 1);
}
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index c47c7a5b4fc..82eef36fb78 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -120,6 +120,11 @@ add_blender_test(
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_idprop_datablock.py
)
+add_blender_test(
+ script_pyapi_prop_array
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_prop_array.py
+)
+
# ------------------------------------------------------------------------------
# DATA MANAGEMENT TESTS
diff --git a/tests/python/bl_pyapi_prop_array.py b/tests/python/bl_pyapi_prop_array.py
new file mode 100644
index 00000000000..ac1082c009e
--- /dev/null
+++ b/tests/python/bl_pyapi_prop_array.py
@@ -0,0 +1,85 @@
+# Apache License, Version 2.0
+
+# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_prop_array.py -- --verbose
+import bpy
+import unittest
+import numpy as np
+
+
+class TestPropArray(unittest.TestCase):
+ def setUp(self):
+ bpy.types.Scene.test_array_f = bpy.props.FloatVectorProperty(size=10)
+ bpy.types.Scene.test_array_i = bpy.props.IntVectorProperty(size=10)
+ scene = bpy.context.scene
+ self.array_f = scene.test_array_f
+ self.array_i = scene.test_array_i
+
+ def test_foreach_getset_i(self):
+ with self.assertRaises(TypeError):
+ self.array_i.foreach_set(range(5))
+
+ self.array_i.foreach_set(range(5, 15))
+
+ with self.assertRaises(TypeError):
+ self.array_i.foreach_set(np.arange(5, dtype=np.int32))
+
+ with self.assertRaises(TypeError):
+ self.array_i.foreach_set(np.arange(10, dtype=np.int64))
+
+ with self.assertRaises(TypeError):
+ self.array_i.foreach_get(np.arange(10, dtype=np.float32))
+
+ a = np.arange(10, dtype=np.int32)
+ self.array_i.foreach_set(a)
+
+ with self.assertRaises(TypeError):
+ self.array_i.foreach_set(a[:5])
+
+ for v1, v2 in zip(a, self.array_i[:]):
+ self.assertEqual(v1, v2)
+
+ b = np.empty(10, dtype=np.int32)
+ self.array_i.foreach_get(b)
+ for v1, v2 in zip(a, b):
+ self.assertEqual(v1, v2)
+
+ b = [None] * 10
+ self.array_f.foreach_get(b)
+ for v1, v2 in zip(a, b):
+ self.assertEqual(v1, v2)
+
+ def test_foreach_getset_f(self):
+ with self.assertRaises(TypeError):
+ self.array_i.foreach_set(range(5))
+
+ self.array_f.foreach_set(range(5, 15))
+
+ with self.assertRaises(TypeError):
+ self.array_f.foreach_set(np.arange(5, dtype=np.float32))
+
+ with self.assertRaises(TypeError):
+ self.array_f.foreach_set(np.arange(10, dtype=np.int32))
+
+ with self.assertRaises(TypeError):
+ self.array_f.foreach_get(np.arange(10, dtype=np.float64))
+
+ a = np.arange(10, dtype=np.float32)
+ self.array_f.foreach_set(a)
+ for v1, v2 in zip(a, self.array_f[:]):
+ self.assertEqual(v1, v2)
+
+ b = np.empty(10, dtype=np.float32)
+ self.array_f.foreach_get(b)
+ for v1, v2 in zip(a, b):
+ self.assertEqual(v1, v2)
+
+ b = [None] * 10
+ self.array_f.foreach_get(b)
+ for v1, v2 in zip(a, b):
+ self.assertEqual(v1, v2)
+
+
+if __name__ == '__main__':
+ import sys
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])
+ unittest.main()
diff --git a/tests/python/eevee_render_tests.py b/tests/python/eevee_render_tests.py
index 0d9fd37b0d7..a7130136d0a 100755
--- a/tests/python/eevee_render_tests.py
+++ b/tests/python/eevee_render_tests.py
@@ -35,13 +35,6 @@ def setup():
# mat.use_screen_refraction = True
mat.use_sss_translucency = True
- # Workaround for crash with Mantaflow (T73921).
- use_light_cache_bake = True
- for ob in bpy.data.objects:
- for mod in ob.modifiers:
- if mod.type == 'FLUID':
- use_light_cache_bake = False
-
cubemap = None
grid = None
# Does not work in edit mode
@@ -86,8 +79,7 @@ def setup():
eevee.gi_visibility_resolution = '16'
eevee.gi_irradiance_smoothing = 0
- if use_light_cache_bake:
- bpy.ops.scene.light_cache_bake()
+ bpy.ops.scene.light_cache_bake()
# When run from inside Blender, render and exit.