diff options
135 files changed, 3170 insertions, 1889 deletions
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 772fac56f63..f9055f02bcf 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "V2.92" +PROJECT_NUMBER = "V2.93" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/intern/guardedalloc/CMakeLists.txt b/intern/guardedalloc/CMakeLists.txt index 0d46e81cd87..b47565b8ef9 100644 --- a/intern/guardedalloc/CMakeLists.txt +++ b/intern/guardedalloc/CMakeLists.txt @@ -49,12 +49,6 @@ set(LIB ) if(WIN32 AND NOT UNIX) - list(APPEND SRC - intern/mmap_win.c - - mmap_win.h - ) - list(APPEND INC_SYS ${PTHREADS_INC} ) diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c deleted file mode 100644 index a02a0f88fa9..00000000000 --- a/intern/guardedalloc/intern/mmap_win.c +++ /dev/null @@ -1,294 +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) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup MEM - */ - -#ifdef WIN32 - -# include <errno.h> -# include <io.h> -# include <stdio.h> -# include <sys/types.h> -# include <windows.h> - -# include "mmap_win.h" - -# ifndef FILE_MAP_EXECUTE -// not defined in earlier versions of the Platform SDK (before February 2003) -# define FILE_MAP_EXECUTE 0x0020 -# endif - -/* copied from BLI_utildefines.h, ugh */ -# ifdef __GNUC__ -# define UNUSED(x) UNUSED_##x __attribute__((__unused__)) -# else -# define UNUSED(x) x -# endif - -/* --------------------------------------------------------------------- */ -/* local storage definitions */ -/* --------------------------------------------------------------------- */ -/* all memory mapped chunks are put in linked lists */ -typedef struct mmapLink { - struct mmapLink *next, *prev; -} mmapLink; - -typedef struct mmapListBase { - void *first, *last; -} mmapListBase; - -typedef struct MemMap { - struct MemMap *next, *prev; - void *mmap; - HANDLE fhandle; - HANDLE maphandle; -} MemMap; - -/* --------------------------------------------------------------------- */ -/* local functions */ -/* --------------------------------------------------------------------- */ - -static void mmap_addtail(volatile mmapListBase *listbase, void *vlink); -static void mmap_remlink(volatile mmapListBase *listbase, void *vlink); -static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr); - -static int mmap_get_prot_flags(int flags); -static int mmap_get_access_flags(int flags); - -/* --------------------------------------------------------------------- */ -/* vars */ -/* --------------------------------------------------------------------- */ -volatile static struct mmapListBase _mmapbase; -volatile static struct mmapListBase *mmapbase = &_mmapbase; - -/* --------------------------------------------------------------------- */ -/* implementation */ -/* --------------------------------------------------------------------- */ - -/* mmap for windows */ -void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t offset) -{ - HANDLE fhandle = INVALID_HANDLE_VALUE; - HANDLE maphandle; - int prot_flags = mmap_get_prot_flags(prot); - int access_flags = mmap_get_access_flags(prot); - MemMap *mm = NULL; - void *ptr = NULL; - - if (flags & MAP_FIXED) { - return MAP_FAILED; - } - -# if 0 - if (fd == -1) { - _set_errno(EBADF); - return MAP_FAILED; - } -# endif - - if (fd != -1) { - fhandle = (HANDLE)_get_osfhandle(fd); - } - if (fhandle == INVALID_HANDLE_VALUE) { - if (!(flags & MAP_ANONYMOUS)) { - errno = EBADF; - return MAP_FAILED; - } - } - else { - if (!DuplicateHandle(GetCurrentProcess(), - fhandle, - GetCurrentProcess(), - &fhandle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) { - return MAP_FAILED; - } - } - - /* Split 64 bit size into low and high bits. */ - DWORD len_bits_high = len >> 32; - DWORD len_bits_low = len & 0xFFFFFFFF; - - maphandle = CreateFileMapping(fhandle, NULL, prot_flags, len_bits_high, len_bits_low, NULL); - if (maphandle == 0) { - errno = EBADF; - return MAP_FAILED; - } - - ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0); - if (ptr == NULL) { - DWORD dwLastErr = GetLastError(); - if (dwLastErr == ERROR_MAPPED_ALIGNMENT) { - errno = EINVAL; - } - else { - errno = EACCES; - } - CloseHandle(maphandle); - return MAP_FAILED; - } - - mm = (MemMap *)malloc(sizeof(MemMap)); - if (!mm) { - errno = ENOMEM; - } - mm->fhandle = fhandle; - mm->maphandle = maphandle; - mm->mmap = ptr; - mmap_addtail(mmapbase, mm); - - return ptr; -} - -/* munmap for windows */ -intptr_t munmap(void *ptr, size_t UNUSED(size)) -{ - MemMap *mm = mmap_findlink(mmapbase, ptr); - if (!mm) { - errno = EINVAL; - return -1; - } - UnmapViewOfFile(mm->mmap); - CloseHandle(mm->maphandle); - CloseHandle(mm->fhandle); - mmap_remlink(mmapbase, mm); - free(mm); - return 0; -} - -/* --------------------------------------------------------------------- */ -/* local functions */ -/* --------------------------------------------------------------------- */ - -static void mmap_addtail(volatile mmapListBase *listbase, void *vlink) -{ - struct mmapLink *link = vlink; - - if (link == NULL) { - return; - } - if (listbase == NULL) { - return; - } - - link->next = 0; - link->prev = listbase->last; - - if (listbase->last) { - ((struct mmapLink *)listbase->last)->next = link; - } - if (listbase->first == NULL) { - listbase->first = link; - } - listbase->last = link; -} - -static void mmap_remlink(volatile mmapListBase *listbase, void *vlink) -{ - struct mmapLink *link = vlink; - - if (link == NULL) { - return; - } - if (listbase == NULL) { - return; - } - if (link->next) { - link->next->prev = link->prev; - } - if (link->prev) { - link->prev->next = link->next; - } - - if (listbase->last == link) { - listbase->last = link->prev; - } - if (listbase->first == link) { - listbase->first = link->next; - } -} - -static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr) -{ - MemMap *mm; - - if (ptr == NULL) { - return NULL; - } - if (listbase == NULL) { - return NULL; - } - - mm = (MemMap *)listbase->first; - while (mm) { - if (mm->mmap == ptr) { - return mm; - } - mm = mm->next; - } - return NULL; -} - -static int mmap_get_prot_flags(int flags) -{ - int prot = PAGE_NOACCESS; - - if ((flags & PROT_READ) == PROT_READ) { - if ((flags & PROT_WRITE) == PROT_WRITE) { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; - } - else { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY; - } - } - else if ((flags & PROT_WRITE) == PROT_WRITE) { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY; - } - else if ((flags & PROT_EXEC) == PROT_EXEC) { - prot = PAGE_EXECUTE_READ; - } - return prot; -} - -static int mmap_get_access_flags(int flags) -{ - int access = 0; - - if ((flags & PROT_READ) == PROT_READ) { - if ((flags & PROT_WRITE) == PROT_WRITE) { - access = FILE_MAP_WRITE; - } - else { - access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ; - } - } - else if ((flags & PROT_WRITE) == PROT_WRITE) { - access = FILE_MAP_COPY; - } - else if ((flags & PROT_EXEC) == PROT_EXEC) { - access = FILE_MAP_EXECUTE; - } - return access; -} - -#endif // WIN32 diff --git a/intern/guardedalloc/mmap_win.h b/intern/guardedalloc/mmap_win.h deleted file mode 100644 index c0cbaa0e512..00000000000 --- a/intern/guardedalloc/mmap_win.h +++ /dev/null @@ -1,50 +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) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup MEM - */ - -#ifndef __MMAP_WIN_H__ -#define __MMAP_WIN_H__ - -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 - -#define MAP_FILE 0 -#define MAP_SHARED 1 -#define MAP_PRIVATE 2 -#define MAP_TYPE 0xF -#define MAP_FIXED 0x10 -#define MAP_ANONYMOUS 0x20 -#define MAP_ANON MAP_ANONYMOUS - -#define MAP_FAILED ((void *)-1) - -/* needed for uintptr_t, exception, dont use BLI anywhere else in MEM_* */ -#include "../../source/blender/blenlib/BLI_sys_types.h" - -#include <sys/types.h> - -void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset); -intptr_t munmap(void *ptr, size_t size); - -#endif diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png Binary files differindex 858709833fb..babb3e30c6d 100644 --- a/release/datafiles/splash.png +++ b/release/datafiles/splash.png 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 8b404c4a306..fecc09da539 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -759,6 +759,16 @@ class GreasePencilLayerAdjustmentsPanel: col = layout.row(align=True) col.prop(gpl, "lock_material") + # Transforms + row = layout.row(align=True) + row.prop(gpl, "location") + + row = layout.row(align=True) + row.prop(gpl, "rotation") + + row = layout.row(align=True) + row.prop(gpl, "scale") + class GPENCIL_UL_masks(UIList): def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index): diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 495bf77b0e7..7fe1c3b29f4 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -502,7 +502,9 @@ class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel): col = layout.column(align=True) row = col.row(align=True) row.label(text="Merge:") - row.operator("clip.join_tracks", text="Join Tracks") + sub = row.column() + sub.operator("clip.join_tracks", text="Join Tracks") + sub.operator("clip.average_tracks", text="Average Tracks") class CLIP_PT_tools_plane_tracking(CLIP_PT_tracking_panel, Panel): @@ -1482,6 +1484,7 @@ class CLIP_MT_track(Menu): layout.separator() layout.operator("clip.join_tracks") + layout.operator("clip.average_tracks") layout.separator() @@ -1608,6 +1611,7 @@ class CLIP_MT_tracking_context_menu(Menu): layout.separator() layout.operator("clip.join_tracks") + layout.operator("clip.average_tracks") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index e6af83b61f4..a9934850acd 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -678,16 +678,8 @@ class NODE_UL_interface_sockets(bpy.types.UIList): if self.layout_type in {'DEFAULT', 'COMPACT'}: row = layout.row(align=True) - # inputs get icon on the left - if not socket.is_output: - row.template_node_socket(color=color) - + row.template_node_socket(color=color) row.prop(socket, "name", text="", emboss=False, icon_value=icon) - - # outputs get icon on the right - if socket.is_output: - row.template_node_socket(color=color) - elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.template_node_socket(color=color) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 577f9678a62..60982421318 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1435,7 +1435,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel): row.prop(gp_settings, "fill_layer_mode", text="Layers") col.separator() - col.prop(gp_settings, "fill_factor", text="Resolution") + col.prop(gp_settings, "fill_factor") if gp_settings.fill_draw_mode != 'STROKE': col = layout.column(align=False, heading="Ignore Transparent") col.use_property_decorate = False diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 8d904bd6019..2fce4bfc5b8 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -212,8 +212,7 @@ struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( struct ListBase *cache, struct PointerRNA *ptr, struct AnimData *adt, - const struct AnimationEvalContext *anim_eval_context, - const bool flush_to_original); + const struct AnimationEvalContext *anim_eval_context); bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, struct PointerRNA *prop_ptr, struct PropertyRNA *prop, diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh new file mode 100644 index 00000000000..b8bb2048d9d --- /dev/null +++ b/source/blender/blenkernel/BKE_attribute_math.hh @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#include "BLI_color.hh" +#include "BLI_float2.hh" +#include "BLI_float3.hh" +#include "DNA_customdata_types.h" + +namespace blender::attribute_math { + +/** + * Utility function that simplifies calling a templated function based on a custom data type. + */ +template<typename Func> +void convert_to_static_type(const CustomDataType data_type, const Func &func) +{ + switch (data_type) { + case CD_PROP_FLOAT: + func(float()); + break; + case CD_PROP_FLOAT2: + func(float2()); + break; + case CD_PROP_FLOAT3: + func(float3()); + break; + case CD_PROP_INT32: + func(int()); + break; + case CD_PROP_BOOL: + func(bool()); + break; + case CD_PROP_COLOR: + func(Color4f()); + break; + default: + BLI_assert(false); + break; + } +} + +/* Interpolate between three values. */ +template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2); + +template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2) +{ + return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f; +} + +template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2) +{ + return static_cast<int>(weights.x * v0 + weights.y * v1 + weights.z * v2); +} + +template<> +inline float mix3(const float3 &weights, const float &v0, const float &v1, const float &v2) +{ + return weights.x * v0 + weights.y * v1 + weights.z * v2; +} + +template<> +inline float2 mix3(const float3 &weights, const float2 &v0, const float2 &v1, const float2 &v2) +{ + return weights.x * v0 + weights.y * v1 + weights.z * v2; +} + +template<> +inline float3 mix3(const float3 &weights, const float3 &v0, const float3 &v1, const float3 &v2) +{ + return weights.x * v0 + weights.y * v1 + weights.z * v2; +} + +template<> +inline Color4f mix3(const float3 &weights, const Color4f &v0, const Color4f &v1, const Color4f &v2) +{ + Color4f result; + interp_v4_v4v4v4(result, v0, v1, v2, weights); + return result; +} + +} // namespace blender::attribute_math diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 4ee96d1ab8d..8752fd9c8cd 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -31,15 +31,15 @@ extern "C" { */ /* Blender major and minor version. */ -#define BLENDER_VERSION 292 +#define BLENDER_VERSION 293 /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 14 +#define BLENDER_FILE_SUBVERSION 1 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index df5711f5120..8903abee432 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -280,12 +280,12 @@ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig const struct bGPDframe *gpf_eval); void BKE_gpencil_update_orig_pointers(const struct Object *ob_orig, const struct Object *ob_eval); -void BKE_gpencil_parent_matrix_get(const struct Depsgraph *depsgraph, - struct Object *obact, - struct bGPDlayer *gpl, - float diff_mat[4][4]); +void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, + struct Object *obact, + struct bGPDlayer *gpl, + float diff_mat[4][4]); -void BKE_gpencil_update_layer_parent(const struct Depsgraph *depsgraph, struct Object *ob); +void BKE_gpencil_update_layer_transforms(const struct Depsgraph *depsgraph, struct Object *ob); int BKE_gpencil_material_find_index_by_name_prefix(struct Object *ob, const char *name_prefix); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 79bc00766fd..6ab401a2d41 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -463,8 +463,8 @@ void ntreeSetOutput(struct bNodeTree *ntree); void ntreeFreeCache(struct bNodeTree *ntree); -bool ntreeNodeExists(struct bNodeTree *ntree, struct bNode *testnode); -bool ntreeOutputExists(struct bNode *node, struct bNodeSocket *testsock); +bool ntreeNodeExists(const struct bNodeTree *ntree, const struct bNode *testnode); +bool ntreeOutputExists(const struct bNode *node, const struct bNodeSocket *testsock); void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable); struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree); void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree); @@ -501,7 +501,7 @@ struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree struct bNodeSocket *from_sock); void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock); -struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create); +struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, bool create); void ntreeInterfaceTypeFree(struct bNodeTree *ntree); void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree); @@ -624,12 +624,12 @@ struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); -bool nodeLinkIsHidden(struct bNodeLink *link); +bool nodeLinkIsHidden(const struct bNodeLink *link); void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node); -void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry); -void nodeFromView(struct bNode *node, float x, float y, float *rx, float *ry); -bool nodeAttachNodeCheck(struct bNode *node, struct bNode *parent); +void nodeToView(const struct bNode *node, float x, float y, float *rx, float *ry); +void nodeFromView(const struct bNode *node, float x, float y, float *rx, float *ry); +bool nodeAttachNodeCheck(const struct bNode *node, const struct bNode *parent); void nodeAttachNode(struct bNode *node, struct bNode *parent); void nodeDetachNode(struct bNode *node); @@ -661,9 +661,9 @@ void nodeChainIterBackwards(const bNodeTree *ntree, void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata); struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, - struct bNodeSocket *from, - struct bNodeSocket *to); -int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); + const struct bNodeSocket *from, + const struct bNodeSocket *to); +int nodeCountSocketLinks(const struct bNodeTree *ntree, const struct bNodeSocket *sock); void nodeSetSelected(struct bNode *node, bool select); void nodeSetActive(struct bNodeTree *ntree, struct bNode *node); @@ -678,11 +678,11 @@ void nodeUpdate(struct bNodeTree *ntree, struct bNode *node); bool nodeUpdateID(struct bNodeTree *ntree, struct ID *id); void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node); -int nodeSocketIsHidden(struct bNodeSocket *sock); +int nodeSocketIsHidden(const struct bNodeSocket *sock); void ntreeTagUsedSockets(struct bNodeTree *ntree); void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available); -int nodeSocketLinkLimit(struct bNodeSocket *sock); +int nodeSocketLinkLimit(const struct bNodeSocket *sock); /* Node Clipboard */ void BKE_node_clipboard_init(struct bNodeTree *ntree); @@ -767,7 +767,7 @@ BLI_INLINE bool BKE_node_instance_hash_iterator_done(bNodeInstanceHashIterator * /* Node Previews */ -int BKE_node_preview_used(struct bNode *node); +bool BKE_node_preview_used(const struct bNode *node); bNodePreview *BKE_node_preview_verify( struct bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, bool create); bNodePreview *BKE_node_preview_copy(struct bNodePreview *preview); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 7b5df98d148..e9a141709b5 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -67,6 +67,13 @@ struct wmWindowManager; #define BKE_ST_MAXNAME 64 +typedef struct wmSpaceTypeListenerParams { + struct wmWindow *window; + struct ScrArea *area; + struct wmNotifier *notifier; + const struct Scene *scene; +} wmSpaceTypeListenerParams; + typedef struct SpaceType { struct SpaceType *next, *prev; @@ -85,10 +92,7 @@ typedef struct SpaceType { /* exit is called when the area is hidden or removed */ void (*exit)(struct wmWindowManager *wm, struct ScrArea *area); /* Listeners can react to bContext changes */ - void (*listener)(struct wmWindow *win, - struct ScrArea *area, - struct wmNotifier *wmn, - struct Scene *scene); + void (*listener)(const wmSpaceTypeListenerParams *params); /* called when the mouse moves out of the area */ void (*deactivate)(struct ScrArea *area); @@ -134,6 +138,23 @@ typedef struct SpaceType { /* region types are also defined using spacetypes_init, via a callback */ +typedef struct wmRegionListenerParams { + struct ScrArea *area; /* Can be NULL when the region is not part of an area. */ + struct ARegion *region; + struct wmNotifier *notifier; + const struct Scene *scene; +} wmRegionListenerParams; + +typedef struct wmRegionMessageSubscribeParams { + const struct bContext *context; + struct wmMsgBus *message_bus; + struct WorkSpace *workspace; + struct Scene *scene; + struct bScreen *screen; + struct ScrArea *area; + struct ARegion *region; +} wmRegionMessageSubscribeParams; + typedef struct ARegionType { struct ARegionType *next, *prev; @@ -158,19 +179,9 @@ typedef struct ARegionType { /* snap the size of the region (can be NULL for no snapping). */ int (*snap_size)(const struct ARegion *region, int size, int axis); /* contextual changes should be handled here */ - void (*listener)(struct wmWindow *win, - struct ScrArea *area, - struct ARegion *region, - struct wmNotifier *wmn, - const struct Scene *scene); + void (*listener)(const wmRegionListenerParams *params); /* Optional callback to generate subscriptions. */ - void (*message_subscribe)(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); + void (*message_subscribe)(const wmRegionMessageSubscribeParams *params); void (*free)(struct ARegion *); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 4dbc22ae18f..c2544c06514 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -89,6 +89,23 @@ struct MovieTrackingTrack *BKE_tracking_track_duplicate(struct MovieTrackingTrac void BKE_tracking_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); void BKE_tracking_track_free(struct MovieTrackingTrack *track); +void BKE_tracking_track_first_last_frame_get(const struct MovieTrackingTrack *track, + int *r_first_frame, + int *r_last_frame); + +void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ struct MovieTrackingTrack **tracks, + const int num_tracks, + int *r_first_frame, + int *r_last_frame); + +int BKE_tracking_count_selected_tracks_in_list(const struct ListBase *tracks_list); +int BKE_tracking_count_selected_tracks_in_active_object(/*const*/ struct MovieTracking *tracking); + +/* Get array of selected tracks from the current active object in the tracking structure. + * If nothing is selected then the result is nullptr and `r_num_tracks` is set to 0. */ +struct MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object( + struct MovieTracking *tracking, int *r_num_tracks); + void BKE_tracking_track_flag_set(struct MovieTrackingTrack *track, int area, int flag); void BKE_tracking_track_flag_clear(struct MovieTrackingTrack *track, int area, int flag); @@ -96,10 +113,15 @@ bool BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, in bool BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr); void BKE_tracking_track_path_clear(struct MovieTrackingTrack *track, int ref_frame, int action); + void BKE_tracking_tracks_join(struct MovieTracking *tracking, struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); +void BKE_tracking_tracks_average(struct MovieTrackingTrack *dst_track, + /*const*/ struct MovieTrackingTrack **src_tracks, + const int num_src_tracks); + struct MovieTrackingTrack *BKE_tracking_track_get_named(struct MovieTracking *tracking, struct MovieTrackingObject *object, const char *name); @@ -139,6 +161,17 @@ struct MovieTrackingMarker *BKE_tracking_marker_get_exact(struct MovieTrackingTr struct MovieTrackingMarker *BKE_tracking_marker_ensure(struct MovieTrackingTrack *track, int framenr); +/* Get marker position, possibly interpolating interpolating gap between keyframed/tracked markers. + * + * The result marker frame number is set to the requested frame number. Its flags are 0 if the + * marker is interpolated, and is set to original marker flag if there were no interpolation + * involved. + * + * Returns truth if the result is usable. */ +bool BKE_tracking_marker_get_interpolated(struct MovieTrackingTrack *track, + const int framenr, + struct MovieTrackingMarker *r_marker); + void BKE_tracking_marker_pattern_minmax(const struct MovieTrackingMarker *marker, float min[2], float max[2]); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 5021736dbfe..82f985a3227 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -275,6 +275,7 @@ set(SRC BKE_asset.h BKE_attribute.h BKE_attribute_access.hh + BKE_attribute_math.hh BKE_autoexec.h BKE_blender.h BKE_blender_copybuffer.h diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 20956d6eb18..00c245a797f 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -362,6 +362,20 @@ void BKE_keyingsets_blend_read_expand(BlendExpander *expander, ListBase *list) /* ***************************************** */ /* Evaluation Data-Setting Backend */ +static bool is_fcurve_evaluatable(FCurve *fcu) +{ + if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) { + return false; + } + if (fcu->grp != NULL && (fcu->grp->flag & AGRP_MUTED)) { + return false; + } + if (BKE_fcurve_is_empty(fcu)) { + return false; + } + return true; +} + bool BKE_animsys_store_rna_setting(PointerRNA *ptr, /* typically 'fcu->rna_path', 'fcu->array_index' */ const char *rna_path, @@ -594,18 +608,11 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, { /* Calculate then execute each curve. */ LISTBASE_FOREACH (FCurve *, fcu, list) { - /* Check if this F-Curve doesn't belong to a muted group. */ - if ((fcu->grp != NULL) && (fcu->grp->flag & AGRP_MUTED)) { - continue; - } - /* Check if this curve should be skipped. */ - if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED))) { - continue; - } - /* Skip empty curves, as if muted. */ - if (BKE_fcurve_is_empty(fcu)) { + + if (!is_fcurve_evaluatable(fcu)) { continue; } + PathResolvedRNA anim_rna; if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context); @@ -979,6 +986,19 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, return nes; } +static NlaEvalStrip *nlastrips_ctime_get_strip_single( + ListBase *dst_list, + NlaStrip *single_strip, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) +{ + ListBase single_tracks_list; + single_tracks_list.first = single_tracks_list.last = single_strip; + + return nlastrips_ctime_get_strip( + dst_list, &single_tracks_list, -1, anim_eval_context, flush_to_original); +} + /* ---------------------- */ /* Initialize a valid mask, allocating memory if necessary. */ @@ -1152,7 +1172,7 @@ static void nlaeval_snapshot_free_data(NlaEvalSnapshot *snapshot) /* Free memory owned by this evaluation channel. */ static void nlaevalchan_free_data(NlaEvalChannel *nec) { - nlavalidmask_free(&nec->valid); + nlavalidmask_free(&nec->domain); if (nec->blend_snapshot != NULL) { nlaevalchan_snapshot_free(nec->blend_snapshot); @@ -1353,7 +1373,7 @@ static NlaEvalChannel *nlaevalchan_verify_key(NlaEvalData *nlaeval, nec->mix_mode = nlaevalchan_detect_mix_mode(key, length); - nlavalidmask_init(&nec->valid, length); + nlavalidmask_init(&nec->domain, length); nec->base_snapshot.channel = nec; nec->base_snapshot.length = length; @@ -1682,14 +1702,6 @@ static bool nlaeval_blend_value(NlaBlendData *blend, return false; } - if (nec->mix_mode == NEC_MIX_QUATERNION) { - /* For quaternion properties, always output all sub-channels. */ - BLI_bitmap_set_all(nec->valid.ptr, true, 4); - } - else { - BLI_BITMAP_ENABLE(nec->valid.ptr, array_index); - } - NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_ensure_channel(blend->snapshot, nec); float *p_value = &nec_snapshot->values[array_index]; @@ -1889,16 +1901,8 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, /* Evaluate all the F-Curves in the action, * saving the relevant pointers to data that will need to be used. */ for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) { - float value = 0.0f; - /* check if this curve should be skipped */ - if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) { - continue; - } - if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) { - continue; - } - if (BKE_fcurve_is_empty(fcu)) { + if (!is_fcurve_evaluatable(fcu)) { continue; } @@ -1906,7 +1910,7 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, * NOTE: we use the modified time here, since strip's F-Curve Modifiers * are applied on top of this. */ - value = evaluate_fcurve(fcu, evaltime); + float value = evaluate_fcurve(fcu, evaltime); /* apply strip's F-Curve Modifiers on this value * NOTE: we apply the strip's original evaluation time not the modified one @@ -2099,12 +2103,21 @@ void nladata_flush_channels(PointerRNA *ptr, /* for each channel with accumulated values, write its value on the property it affects */ LISTBASE_FOREACH (NlaEvalChannel *, nec, &channels->channels) { + /** + * The bitmask is set for all channels touched by NLA due to the domain() function. + * Channels touched by current set of evaluated strips will have a snapshot channel directly + * from the evaluation snapshot. + * + * This function falls back to the default value if the snapshot channel doesn't exist. + * Thus channels, touched by NLA but not by the current set of evaluated strips, will be + * reset to default. If channel not touched by NLA then it's value is unchanged. + */ NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_find_channel(snapshot, nec); PathResolvedRNA rna = {nec->key.ptr, nec->key.prop, -1}; for (int i = 0; i < nec_snapshot->length; i++) { - if (BLI_BITMAP_TEST(nec->valid.ptr, i)) { + if (BLI_BITMAP_TEST(nec->domain.ptr, i)) { float value = nec_snapshot->values[i]; if (nec->is_array) { rna.prop_index = i; @@ -2131,13 +2144,7 @@ static void nla_eval_domain_action(PointerRNA *ptr, LISTBASE_FOREACH (FCurve *, fcu, &act->curves) { /* check if this curve should be skipped */ - if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) { - continue; - } - if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) { - continue; - } - if (BKE_fcurve_is_empty(fcu)) { + if (!is_fcurve_evaluatable(fcu)) { continue; } @@ -2146,14 +2153,14 @@ static void nla_eval_domain_action(PointerRNA *ptr, if (nec != NULL) { /* For quaternion properties, enable all sub-channels. */ if (nec->mix_mode == NEC_MIX_QUATERNION) { - BLI_bitmap_set_all(nec->valid.ptr, true, 4); + BLI_bitmap_set_all(nec->domain.ptr, true, 4); continue; } int idx = nlaevalchan_validate_index(nec, fcu->array_index); if (idx >= 0) { - BLI_BITMAP_ENABLE(nec->valid.ptr, idx); + BLI_BITMAP_ENABLE(nec->domain.ptr, idx); } } } @@ -2212,190 +2219,344 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels, /* ---------------------- */ +/** Tweaked strip is evaluated differently from other strips. Adjacent strips are ignored + * and includes a workaround for when user is not editing in place. */ +static void animsys_create_tweak_strip(const AnimData *adt, + const bool keyframing_to_strip, + NlaStrip *r_tweak_strip) + +{ + /* Copy active strip so we can modify how it evaluates without affecting user data. */ + memcpy(r_tweak_strip, adt->actstrip, sizeof(NlaStrip)); + r_tweak_strip->next = r_tweak_strip->prev = NULL; + + /* If tweaked strip is syncing action length, then evaluate using action length. */ + if (r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) { + BKE_nlastrip_recalculate_bounds_sync_action(r_tweak_strip); + } + + /* Strips with a user-defined time curve don't get properly remapped for editing + * at the moment, so mapping them just for display may be confusing. */ + const bool is_inplace_tweak = !(adt->flag & ADT_NLA_EDIT_NOMAP) && + !(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME); + + if (!is_inplace_tweak) { + /* Use Hold due to no proper remapping yet (the note above). */ + r_tweak_strip->extendmode = NLASTRIP_EXTEND_HOLD; + + /* Disable range. */ + r_tweak_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP; + } + + /** Controls whether able to keyframe outside range of tweaked strip. */ + if (keyframing_to_strip) { + r_tweak_strip->extendmode = (is_inplace_tweak && + !(r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ? + NLASTRIP_EXTEND_NOTHING : + NLASTRIP_EXTEND_HOLD; + } +} + +/** Action track and strip are associated with the non-pushed action. */ +static void animsys_create_action_track_strip(const AnimData *adt, + const bool keyframing_to_strip, + NlaStrip *r_action_strip) +{ + memset(r_action_strip, 0, sizeof(NlaStrip)); + + bAction *action = adt->action; + + if ((adt->flag & ADT_NLA_EDIT_ON)) { + action = adt->tmpact; + } + + /* Set settings of dummy NLA strip from AnimData settings. */ + r_action_strip->act = action; + + /* Action range is calculated taking F-Modifiers into account + * (which making new strips doesn't do due to the troublesome nature of that). */ + calc_action_range(r_action_strip->act, &r_action_strip->actstart, &r_action_strip->actend, 1); + r_action_strip->start = r_action_strip->actstart; + r_action_strip->end = (IS_EQF(r_action_strip->actstart, r_action_strip->actend)) ? + (r_action_strip->actstart + 1.0f) : + (r_action_strip->actend); + + r_action_strip->blendmode = adt->act_blendmode; + r_action_strip->extendmode = adt->act_extendmode; + r_action_strip->influence = adt->act_influence; + + /* NOTE: must set this, or else the default setting overrides, + * and this setting doesn't work. */ + r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE; + + /* Unless extendmode is Nothing (might be useful for flattening NLA evaluation), disable range. + * Extendmode Nothing and Hold will behave as normal. Hold Forward will behave just like Hold. + */ + if (r_action_strip->extendmode != NLASTRIP_EXTEND_NOTHING) { + r_action_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP; + } + + const bool tweaking = (adt->flag & ADT_NLA_EDIT_ON) != 0; + const bool soloing = (adt->flag & ADT_NLA_SOLO_TRACK) != 0; + const bool actionstrip_evaluated = r_action_strip->act && !soloing && !tweaking; + if (!actionstrip_evaluated) { + r_action_strip->flag |= NLASTRIP_FLAG_MUTED; + } + + /** If we're keyframing, then we must allow keyframing outside fcurve bounds. */ + if (keyframing_to_strip) { + r_action_strip->extendmode = NLASTRIP_EXTEND_HOLD; + } +} + +static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt) +{ + /* Skip disabled tracks unless it contains the tweaked strip. */ + const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) && + (nlt->index == adt->act_track->index); + if ((nlt->flag & NLATRACK_DISABLED) && !contains_tweak_strip) { + return false; + } + + /* Solo and muting are mutually exclusive. */ + if (adt->flag & ADT_NLA_SOLO_TRACK) { + /* Skip if there is a solo track, but this isn't it. */ + if ((nlt->flag & NLATRACK_SOLO) == 0) { + return false; + } + } + else { + /* Skip track if muted. */ + if (nlt->flag & NLATRACK_MUTED) { + return false; + } + } + + return true; +} + +/** Check for special case of non-pushed action being evaluated with no NLA influence (off and no + * strips evaluated) nor NLA interference (ensure NLA not soloing). */ +static bool is_action_track_evaluated_without_nla(const AnimData *adt, + const bool any_strip_evaluated) +{ + if (adt->action == NULL) { + return false; + } + + if (any_strip_evaluated) { + return false; + } + + /** NLA settings interference. */ + if ((adt->flag & (ADT_NLA_SOLO_TRACK | ADT_NLA_EDIT_ON)) == 0) { + return false; + } + + /** Allow action track to evaluate as if there isn't any NLA data. */ + return true; +} + +/** XXX Wayde Moss: BKE_nlatrack_find_tweaked() exists within nla.c, but it doesn't appear to + * work as expected. From animsys_evaluate_nla_for_flush(), it returns NULL in tweak mode. I'm not + * sure why. Preferably, it would be as simple as checking for (adt->act_Track == nlt) but that + * doesn't work either, neither does comparing indices. + * + * This function is a temporary work around. The first disabled track is always the tweaked track. + */ +static NlaTrack *nlatrack_find_tweaked(const AnimData *adt) +{ + NlaTrack *nlt; + + if (adt == NULL) { + return NULL; + } + + /* Since the track itself gets disabled, we want the first disabled. */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + if (nlt->flag & NLATRACK_DISABLED) { + return nlt; + } + } + + return NULL; +} + /** * NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels" - * * \param[out] echannels: Evaluation channels with calculated values - * \param[out] r_context: If not NULL, - * data about the currently edited strip is stored here and excluded from value calculation. - * \return false if NLA evaluation isn't actually applicable. */ -static bool animsys_evaluate_nla(NlaEvalData *echannels, - PointerRNA *ptr, - AnimData *adt, - const AnimationEvalContext *anim_eval_context, - const bool flush_to_original, - NlaKeyframingContext *r_context) +static bool animsys_evaluate_nla_for_flush(NlaEvalData *echannels, + PointerRNA *ptr, + const AnimData *adt, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) { NlaTrack *nlt; short track_index = 0; bool has_strips = false; - ListBase estrips = {NULL, NULL}; NlaEvalStrip *nes; - NlaStrip dummy_strip_buf; - /* dummy strip for active action */ - NlaStrip *dummy_strip = r_context ? &r_context->strip : &dummy_strip_buf; + NlaStrip tweak_strip; - memset(dummy_strip, 0, sizeof(*dummy_strip)); + NlaTrack *tweaked_track = nlatrack_find_tweaked(adt); - /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ + /* Get the stack of strips to evaluate at current time (influence calculated here). */ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) { - /* stop here if tweaking is on and this strip is the tweaking track - * (it will be the first one that's 'disabled')... */ - if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) { - break; + + if (!is_nlatrack_evaluatable(adt, nlt)) { + continue; } - /* solo and muting are mutually exclusive... */ - if (adt->flag & ADT_NLA_SOLO_TRACK) { - /* skip if there is a solo track, but this isn't it */ - if ((nlt->flag & NLATRACK_SOLO) == 0) { - continue; - } - /* else - mute doesn't matter */ + if (nlt->strips.first) { + has_strips = true; + } + + /** Append strip to evaluate for this track. */ + if (nlt == tweaked_track) { + /** Tweaked strip is evaluated differently. */ + animsys_create_tweak_strip(adt, false, &tweak_strip); + nes = nlastrips_ctime_get_strip_single( + &estrips, &tweak_strip, anim_eval_context, flush_to_original); } else { - /* no solo tracks - skip track if muted */ - if (nlt->flag & NLATRACK_MUTED) { - continue; - } + nes = nlastrips_ctime_get_strip( + &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original); + } + if (nes) { + nes->track = nlt; + } + } + + if (is_action_track_evaluated_without_nla(adt, has_strips)) { + BLI_freelistN(&estrips); + return false; + } + + NlaStrip action_strip = {0}; + animsys_create_action_track_strip(adt, false, &action_strip); + nlastrips_ctime_get_strip_single(&estrips, &action_strip, anim_eval_context, flush_to_original); + + /* Per strip, evaluate and accumulate on top of existing channels. */ + for (nes = estrips.first; nes; nes = nes->next) { + nlastrip_evaluate(ptr, + echannels, + NULL, + nes, + &echannels->eval_snapshot, + anim_eval_context, + flush_to_original); + } + + /* Free temporary evaluation data that's not used elsewhere. */ + BLI_freelistN(&estrips); + return true; +} + +/** Lower blended values are calculated and accumulated into r_context->lower_eval_data. */ +static void animsys_evaluate_nla_for_keyframing(PointerRNA *ptr, + const AnimData *adt, + const AnimationEvalContext *anim_eval_context, + NlaKeyframingContext *r_context) +{ + if (!r_context) { + return; + } + + /* Early out. If NLA track is soloing and tweaked action isn't it, then don't allow keyframe + * insertion. */ + if (adt->flag & ADT_NLA_SOLO_TRACK) { + if (!(adt->act_track && (adt->act_track->flag & NLATRACK_SOLO))) { + r_context->eval_strip = NULL; + return; + } + } + + NlaTrack *nlt; + short track_index = 0; + bool has_strips = false; + + ListBase lower_estrips = {NULL, NULL}; + NlaEvalStrip *nes; + + NlaTrack *tweaked_track = nlatrack_find_tweaked(adt); + + /* Get the lower stack of strips to evaluate at current time (influence calculated here). */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) { + + if (!is_nlatrack_evaluatable(adt, nlt)) { + continue; + } + + /* Tweaked strip effect should not be stored in any snapshot. */ + if (nlt == tweaked_track) { + break; } - /* if this track has strips (but maybe they won't be suitable), set has_strips - * - used for mainly for still allowing normal action evaluation... - */ if (nlt->strips.first) { has_strips = true; } - /* otherwise, get strip to evaluate for this channel */ + /* Get strip to evaluate for this channel. */ nes = nlastrips_ctime_get_strip( - &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original); + &lower_estrips, &nlt->strips, track_index, anim_eval_context, false); if (nes) { nes->track = nlt; } } - /* add 'active' Action (may be tweaking track) as last strip to evaluate in NLA stack - * - only do this if we're not exclusively evaluating the 'solo' NLA-track - * - however, if the 'solo' track houses the current 'tweaking' strip, - * then we should allow this to play, otherwise nothing happens + /** Note: Although we early out, we can still keyframe to the non-pushed action since the + * keyframe remap function detects (r_context->strip.act == NULL) and will keyframe without + * remapping. */ - if ((adt->action) && ((adt->flag & ADT_NLA_SOLO_TRACK) == 0 || (adt->flag & ADT_NLA_EDIT_ON))) { - /* if there are strips, evaluate action as per NLA rules */ - if ((has_strips) || (adt->actstrip)) { - /* make dummy NLA strip, and add that to the stack */ - ListBase dummy_trackslist; - - dummy_trackslist.first = dummy_trackslist.last = dummy_strip; - - /* Strips with a user-defined time curve don't get properly remapped for editing - * at the moment, so mapping them just for display may be confusing. */ - bool is_inplace_tweak = (nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP) && - !(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME); - - if (is_inplace_tweak) { - /* edit active action in-place according to its active strip, so copy the data */ - memcpy(dummy_strip, adt->actstrip, sizeof(NlaStrip)); - /* Prevents nla eval from considering active strip's adj strips. - * For user, this means entering tweak mode on a strip ignores evaluating adjacent strips - * in the same track. */ - dummy_strip->next = dummy_strip->prev = NULL; - - /* If tweaked strip is syncing action length, then evaluate using action length. */ - if (dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) { - BKE_nlastrip_recalculate_bounds_sync_action(dummy_strip); - } - } - else { - /* set settings of dummy NLA strip from AnimData settings */ - dummy_strip->act = adt->action; - - /* action range is calculated taking F-Modifiers into account - * (which making new strips doesn't do due to the troublesome nature of that) */ - calc_action_range(dummy_strip->act, &dummy_strip->actstart, &dummy_strip->actend, 1); - dummy_strip->start = dummy_strip->actstart; - dummy_strip->end = (IS_EQF(dummy_strip->actstart, dummy_strip->actend)) ? - (dummy_strip->actstart + 1.0f) : - (dummy_strip->actend); - - /* Always use the blend mode of the strip in tweak mode, even if not in-place. */ - if (nlt && adt->actstrip) { - dummy_strip->blendmode = adt->actstrip->blendmode; - dummy_strip->extendmode = NLASTRIP_EXTEND_HOLD; - } - else { - dummy_strip->blendmode = adt->act_blendmode; - dummy_strip->extendmode = adt->act_extendmode; - } + if (is_action_track_evaluated_without_nla(adt, has_strips)) { + BLI_freelistN(&lower_estrips); + return; + } - /* Unless extend-mode is Nothing (might be useful for flattening NLA evaluation), - * disable range. */ - if (dummy_strip->extendmode != NLASTRIP_EXTEND_NOTHING) { - dummy_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP; - } + /* Write r_context->eval_strip. */ + if (adt->flag & ADT_NLA_EDIT_ON) { - dummy_strip->influence = adt->act_influence; + NlaStrip *tweak_strip = &r_context->strip; + animsys_create_tweak_strip(adt, true, tweak_strip); + r_context->eval_strip = nlastrips_ctime_get_strip_single( + NULL, tweak_strip, anim_eval_context, false); + } + else { - /* NOTE: must set this, or else the default setting overrides, - * and this setting doesn't work. */ - dummy_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE; - } + NlaStrip *action_strip = &r_context->strip; + animsys_create_action_track_strip(adt, true, action_strip); + r_context->eval_strip = nlastrips_ctime_get_strip_single( + NULL, action_strip, anim_eval_context, false); + } - /* add this to our list of evaluation strips */ - if (r_context == NULL) { - nlastrips_ctime_get_strip( - &estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original); - } - /* If computing the context for keyframing, store data there instead of the list. */ - else { - /* The extend mode here effectively controls - * whether it is possible to key-frame beyond the ends.*/ - dummy_strip->extendmode = (is_inplace_tweak && - !(dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ? - NLASTRIP_EXTEND_NOTHING : - NLASTRIP_EXTEND_HOLD; - - r_context->eval_strip = nes = nlastrips_ctime_get_strip( - NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original); - - /* These setting combinations require no data from strips below, so exit immediately. */ - if ((nes == NULL) || - (dummy_strip->blendmode == NLASTRIP_MODE_REPLACE && dummy_strip->influence == 1.0f)) { - BLI_freelistN(&estrips); - return true; - } - } - } - else { - /* special case - evaluate as if there isn't any NLA data */ - BLI_freelistN(&estrips); - return false; - } + /* If NULL, then keyframing will fail. No need to do any more processing. */ + if (!r_context->eval_strip) { + BLI_freelistN(&lower_estrips); + return; } - /* only continue if there are strips to evaluate */ - if (BLI_listbase_is_empty(&estrips)) { - return true; + /* If tweak strip is full REPLACE, then lower strips not needed. */ + if (r_context->strip.blendmode == NLASTRIP_MODE_REPLACE && + IS_EQF(r_context->strip.influence, 1.0f)) { + BLI_freelistN(&lower_estrips); + return; } - /* 2. for each strip, evaluate then accumulate on top of existing channels, - * but don't set values yet. */ - for (nes = estrips.first; nes; nes = nes->next) { + /* For each strip, evaluate then accumulate on top of existing channels. */ + for (nes = lower_estrips.first; nes; nes = nes->next) { nlastrip_evaluate(ptr, - echannels, + &r_context->lower_eval_data, NULL, nes, - &echannels->eval_snapshot, + &r_context->lower_eval_data.eval_snapshot, anim_eval_context, - flush_to_original); + false); } - /* 3. free temporary evaluation data that's not used elsewhere */ - BLI_freelistN(&estrips); - return true; + /* Free temporary evaluation data that's not used elsewhere. */ + BLI_freelistN(&lower_estrips); } /* NLA Evaluation function (mostly for use through do_animdata) @@ -2412,7 +2573,7 @@ static void animsys_calculate_nla(PointerRNA *ptr, nlaeval_init(&echannels); /* evaluate the NLA stack, obtaining a set of values to flush */ - if (animsys_evaluate_nla(&echannels, ptr, adt, anim_eval_context, flush_to_original, NULL)) { + if (animsys_evaluate_nla_for_flush(&echannels, ptr, adt, anim_eval_context, flush_to_original)) { /* reset any channels touched by currently inactive actions to default value */ animsys_evaluate_nla_domain(ptr, &echannels, adt); @@ -2448,8 +2609,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( struct ListBase *cache, struct PointerRNA *ptr, struct AnimData *adt, - const AnimationEvalContext *anim_eval_context, - const bool flush_to_original) + const AnimationEvalContext *anim_eval_context) { /* No remapping needed if NLA is off or no action. */ if ((adt == NULL) || (adt->action == NULL) || (adt->nla_tracks.first == NULL) || @@ -2472,8 +2632,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( ctx->adt = adt; nlaeval_init(&ctx->lower_eval_data); - animsys_evaluate_nla( - &ctx->lower_eval_data, ptr, adt, anim_eval_context, flush_to_original, ctx); + animsys_evaluate_nla_for_keyframing(ptr, adt, anim_eval_context, ctx); BLI_assert(ELEM(ctx->strip.act, NULL, adt->action)); BLI_addtail(cache, ctx); diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 2e1094364fd..21ab7f61447 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -526,6 +526,10 @@ static ReadAttributePtr read_attribute_from_custom_data(const CustomData &custom case CD_PROP_BOOL: return std::make_unique<ArrayReadAttribute<bool>>( domain, Span(static_cast<bool *>(layer.data), size)); + case CD_MLOOPUV: + auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); }; + return std::make_unique<DerivedArrayReadAttribute<MLoopUV, float2, decltype(get_uv)>>( + domain, Span(static_cast<MLoopUV *>(layer.data), size), get_uv); } } } @@ -570,6 +574,12 @@ static WriteAttributePtr write_attribute_from_custom_data( case CD_PROP_BOOL: return std::make_unique<ArrayWriteAttribute<bool>>( domain, MutableSpan(static_cast<bool *>(layer.data), size)); + case CD_MLOOPUV: + auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); }; + auto set_uv = [](MLoopUV &uv, const float2 value) { copy_v2_v2(uv.uv, value); }; + return std::make_unique< + DerivedArrayWriteAttribute<MLoopUV, float2, decltype(get_uv), decltype(set_uv)>>( + domain, MutableSpan(static_cast<MLoopUV *>(layer.data), size), get_uv, set_uv); } } } @@ -597,8 +607,9 @@ static void get_custom_data_layer_attribute_names(const CustomData &custom_data, Set<std::string> &r_names) { for (const CustomDataLayer &layer : blender::Span(custom_data.layers, custom_data.totlayer)) { - if (component.attribute_domain_with_type_supported(domain, - static_cast<CustomDataType>(layer.type))) { + const CustomDataType data_type = static_cast<CustomDataType>(layer.type); + if (component.attribute_domain_with_type_supported(domain, data_type) || + ELEM(data_type, CD_MLOOPUV)) { r_names.add(layer.name); } } @@ -1318,7 +1329,7 @@ Set<std::string> MeshComponent::attribute_names() const for (StringRef name : vertex_group_names_.keys()) { names.add(name); } - get_custom_data_layer_attribute_names(mesh_->pdata, *this, ATTR_DOMAIN_CORNER, names); + get_custom_data_layer_attribute_names(mesh_->ldata, *this, ATTR_DOMAIN_CORNER, names); get_custom_data_layer_attribute_names(mesh_->vdata, *this, ATTR_DOMAIN_POINT, names); get_custom_data_layer_attribute_names(mesh_->edata, *this, ATTR_DOMAIN_EDGE, names); get_custom_data_layer_attribute_names(mesh_->pdata, *this, ATTR_DOMAIN_POLYGON, names); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 9a954a89cad..ea1b0f8c1cc 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -978,7 +978,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->fill_leak = 3; brush->gpencil_settings->fill_threshold = 0.1f; brush->gpencil_settings->fill_simplylvl = 1; - brush->gpencil_settings->fill_factor = 1; + brush->gpencil_settings->fill_factor = 1.0f; brush->gpencil_settings->draw_strength = 1.0f; brush->gpencil_settings->hardeness = 1.0f; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 375792a02c2..98af3575081 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -488,6 +488,7 @@ void BKE_displist_fill(ListBase *dispbase, while (cont) { int dl_flag_accum = 0; + int dl_rt_accum = 0; cont = 0; totvert = 0; nextcol = 0; @@ -535,6 +536,7 @@ void BKE_displist_fill(ListBase *dispbase, } } dl_flag_accum |= dl->flag; + dl_rt_accum |= dl->rt; } } @@ -544,6 +546,7 @@ void BKE_displist_fill(ListBase *dispbase, dlnew = MEM_callocN(sizeof(DispList), "filldisplist"); dlnew->type = DL_INDEX3; dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE)); + dlnew->rt = (dl_rt_accum & CU_SMOOTH); dlnew->col = colnr; dlnew->nr = totvert; dlnew->parts = tot; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index f68a390db64..453960fbd61 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -95,6 +95,32 @@ static void greasepencil_copy_data(Main *UNUSED(bmain), /* TODO here too could add unused flags... */ bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); + /* Apply local layer transform to all frames. Calc the active frame is not enough + * because onion skin can use more frames. This is more slow but required here. */ + if (gpl_dst->actframe != NULL) { + bool transfomed = ((!is_zero_v3(gpl_dst->location)) || (!is_zero_v3(gpl_dst->rotation)) || + (!is_one_v3(gpl_dst->scale))); + if (transfomed) { + loc_eul_size_to_mat4( + gpl_dst->layer_mat, gpl_dst->location, gpl_dst->rotation, gpl_dst->scale); + bool do_onion = ((gpl_dst->onion_flag & GP_LAYER_ONIONSKIN) != 0); + bGPDframe *init_gpf = (do_onion) ? gpl_dst->frames.first : gpl_dst->actframe; + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + mul_m4_v3(gpl_dst->layer_mat, &pt->x); + } + } + /* if not onion, exit loop. */ + if (!do_onion) { + break; + } + } + } + } + BLI_addtail(&gpd_dst->layers, gpl_dst); } } @@ -686,6 +712,14 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti /* Enable always affected by scene lights. */ gpl->flag |= GP_LAYER_USE_LIGHTS; + + /* Init transform. */ + zero_v3(gpl->location); + zero_v3(gpl->rotation); + copy_v3_fl(gpl->scale, 1.0f); + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* make this one the active one */ if (setactive) { BKE_gpencil_layer_active_set(gpd, gpl); @@ -2519,7 +2553,7 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, int cfra) { bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd))); const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0); const bool is_drawing = (gpd->runtime.sbuffer_used > 0); @@ -2541,6 +2575,11 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, continue; } + /* If scale to 0 the layer must be invisible. */ + if (is_zero_v3(gpl->scale)) { + continue; + } + /* Hide the layer if it's defined a view layer filter. This is used to * generate renders, putting only selected GP layers for each View Layer. * This is used only in final render and never in Viewport. */ @@ -2759,10 +2798,10 @@ void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_ev * \param gpl: Grease pencil layer * \param diff_mat: Result parent matrix */ -void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, - Object *obact, - bGPDlayer *gpl, - float diff_mat[4][4]) +void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, + Object *obact, + bGPDlayer *gpl, + float diff_mat[4][4]) { Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact; Object *obparent = gpl->parent; @@ -2771,11 +2810,10 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, /* if not layer parented, try with object parented */ if (obparent_eval == NULL) { - if (ob_eval != NULL) { - if (ob_eval->type == OB_GPENCIL) { - copy_m4_m4(diff_mat, ob_eval->obmat); - return; - } + if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) { + copy_m4_m4(diff_mat, ob_eval->obmat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); + return; } /* not gpencil object */ unit_m4(diff_mat); @@ -2785,6 +2823,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); add_v3_v3(diff_mat[3], ob_eval->obmat[3]); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; } if (gpl->partype == PARBONE) { @@ -2800,6 +2839,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); add_v3_v3(diff_mat[3], ob_eval->obmat[3]); } + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; } @@ -2807,11 +2847,11 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, } /** - * Update parent matrix. + * Update parent matrix and local transforms. * \param depsgraph: Depsgraph * \param ob: Grease pencil object */ -void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob) +void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob) { if (ob->type != OB_GPENCIL) { return; @@ -2820,31 +2860,50 @@ void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob) bGPdata *gpd = (bGPdata *)ob->data; float cur_mat[4][4]; + bool changed = false; LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if ((gpl->parent != NULL) && (gpl->actframe != NULL)) { - Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); - /* calculate new matrix */ - if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { - copy_m4_m4(cur_mat, ob_parent->obmat); - } - else if (gpl->partype == PARBONE) { - bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); - if (pchan != NULL) { - copy_m4_m4(cur_mat, ob->imat); - mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat); + unit_m4(cur_mat); + if (gpl->actframe != NULL) { + if (gpl->parent != NULL) { + Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); + /* calculate new matrix */ + if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { + copy_m4_m4(cur_mat, ob_parent->obmat); } - else { - unit_m4(cur_mat); + else if (gpl->partype == PARBONE) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); + if (pchan != NULL) { + copy_m4_m4(cur_mat, ob->imat); + mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat); + } + else { + unit_m4(cur_mat); + } } + changed = !equals_m4m4(gpl->inverse, cur_mat); } + + /* Calc local layer transform. */ + bool transfomed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || + (!is_one_v3(gpl->scale))); + if (transfomed) { + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + } + /* only redo if any change */ - if (!equals_m4m4(gpl->inverse, cur_mat)) { + if (changed || transfomed) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { bGPDspoint *pt; int i; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - mul_m4_v3(gpl->inverse, &pt->x); - mul_m4_v3(cur_mat, &pt->x); + if (changed) { + mul_m4_v3(gpl->inverse, &pt->x); + mul_m4_v3(cur_mat, &pt->x); + } + + if (transfomed) { + mul_m4_v3(gpl->layer_mat, &pt->x); + } } } } diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 1be2cba31b5..8b12e1b5fca 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -701,13 +701,18 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o Object *ob_orig = (Object *)DEG_get_original_id(&ob->id); bGPdata *gpd_orig = (bGPdata *)ob_orig->data; - /* Need check if some layer is parented. */ + /* Need check if some layer is parented or transformed. */ bool do_parent = false; + bool do_transform = false; LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) { if (gpl->parent != NULL) { do_parent = true; break; } + if ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || (!is_one_v3(gpl->scale))) { + do_transform = true; + break; + } } const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_eval); @@ -715,7 +720,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o const bool do_modifiers = (bool)((!is_multiedit) && (!is_curve_edit) && (ob->greasepencil_modifiers.first != NULL) && (!GPENCIL_SIMPLIFY_MODIF(scene))); - if ((!do_modifiers) && (!do_parent)) { + if ((!do_modifiers) && (!do_parent) && (!do_transform)) { return; } DEG_debug_print_eval(depsgraph, __func__, gpd_eval->id.name, gpd_eval); diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index e4094c48368..a7e2394e7ad 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1922,7 +1922,9 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain, ID *local) { if (ID_IS_OVERRIDE_LIBRARY_TEMPLATE(local) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(local)) { - /* This is actually purely local data with an override template, nothing to do here! */ + /* This is actually purely local data with an override template, or one of those embedded IDs + * (root node trees, master collections or shapekeys) that cannot have their own override. + * Nothing to do here! */ return NULL; } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 76885eadaae..52de4b108b9 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2149,7 +2149,7 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) ntree->update |= NTREE_UPDATE_LINKS; } -bool nodeLinkIsHidden(bNodeLink *link) +bool nodeLinkIsHidden(const bNodeLink *link) { return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock); } @@ -2200,7 +2200,7 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node) } } -void nodeToView(bNode *node, float x, float y, float *rx, float *ry) +void nodeToView(const bNode *node, float x, float y, float *rx, float *ry) { if (node->parent) { nodeToView(node->parent, x + node->locx, y + node->locy, rx, ry); @@ -2211,7 +2211,7 @@ void nodeToView(bNode *node, float x, float y, float *rx, float *ry) } } -void nodeFromView(bNode *node, float x, float y, float *rx, float *ry) +void nodeFromView(const bNode *node, float x, float y, float *rx, float *ry) { if (node->parent) { nodeFromView(node->parent, x, y, rx, ry); @@ -2224,10 +2224,10 @@ void nodeFromView(bNode *node, float x, float y, float *rx, float *ry) } } -bool nodeAttachNodeCheck(bNode *node, bNode *parent) +bool nodeAttachNodeCheck(const bNode *node, const bNode *parent) { - for (bNode *parent_recurse = node; parent_recurse; parent_recurse = parent_recurse->parent) { - if (parent_recurse == parent) { + for (const bNode *parent_iter = node; parent_iter; parent_iter = parent_iter->parent) { + if (parent_iter == parent) { return true; } } @@ -2317,8 +2317,6 @@ void nodePositionPropagate(bNode *node) bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) { - bNodeTree *ntree; - /* trees are created as local trees for compositor, material or texture nodes, * node groups and other tree types are created as library data. */ @@ -2327,7 +2325,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) if (is_embedded) { flag |= LIB_ID_CREATE_NO_MAIN; } - ntree = BKE_libblock_alloc(bmain, ID_NT, name, flag); + bNodeTree *ntree = BKE_libblock_alloc(bmain, ID_NT, name, flag); if (is_embedded) { ntree->id.flag |= LIB_EMBEDDED_DATA; } @@ -2362,7 +2360,7 @@ bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree) * using BKE_node_preview_init_tree to set up previews for a whole node tree in advance. * This should be left more to the individual node tree implementations. */ -int BKE_node_preview_used(bNode *node) +bool BKE_node_preview_used(const bNode *node) { /* XXX check for closed nodes? */ return (node->typeinfo->flag & NODE_PREVIEW) != 0; @@ -2959,9 +2957,9 @@ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree) return NULL; } -bool ntreeNodeExists(bNodeTree *ntree, bNode *testnode) +bool ntreeNodeExists(const bNodeTree *ntree, const bNode *testnode) { - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + LISTBASE_FOREACH (const bNode *, node, &ntree->nodes) { if (node == testnode) { return true; } @@ -2969,9 +2967,9 @@ bool ntreeNodeExists(bNodeTree *ntree, bNode *testnode) return false; } -bool ntreeOutputExists(bNode *node, bNodeSocket *testsock) +bool ntreeOutputExists(const bNode *node, const bNodeSocket *testsock) { - LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + LISTBASE_FOREACH (const bNodeSocket *, sock, &node->outputs) { if (sock == testsock) { return true; } @@ -3246,7 +3244,7 @@ static void ntree_interface_type_create(bNodeTree *ntree) } } -StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create) +StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, bool create) { if (ntree->interface_type) { /* strings are generated from base string + ID name, sizes are sufficient */ @@ -3333,7 +3331,7 @@ bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup) return false; } -bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to) +bNodeLink *nodeFindLink(bNodeTree *ntree, const bNodeSocket *from, const bNodeSocket *to) { LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { if (link->fromsock == from && link->tosock == to) { @@ -3346,10 +3344,10 @@ bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to) return NULL; } -int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock) +int nodeCountSocketLinks(const bNodeTree *ntree, const bNodeSocket *sock) { int tot = 0; - LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + LISTBASE_FOREACH (const bNodeLink *, link, &ntree->links) { if (link->fromsock == sock || link->tosock == sock) { tot++; } @@ -3515,7 +3513,7 @@ void nodeSetActive(bNodeTree *ntree, bNode *node) } } -int nodeSocketIsHidden(bNodeSocket *sock) +int nodeSocketIsHidden(const bNodeSocket *sock) { return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0); } @@ -3530,7 +3528,7 @@ void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available) } } -int nodeSocketLinkLimit(struct bNodeSocket *sock) +int nodeSocketLinkLimit(const bNodeSocket *sock) { bNodeSocketType *stype = sock->typeinfo; if (stype != NULL && stype->use_link_limits_of_type) { diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 1d79f871fa2..69442b7646c 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -225,7 +225,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o case OB_GPENCIL: { BKE_gpencil_prepare_eval_data(depsgraph, scene, ob); BKE_gpencil_modifiers_calc(depsgraph, scene, ob); - BKE_gpencil_update_layer_parent(depsgraph, ob); + BKE_gpencil_update_layer_transforms(depsgraph, ob); break; } case OB_HAIR: diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 52c41c9fd05..64f08e10c98 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -1599,8 +1599,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) BLO_read_list(reader, &snode->treepath); snode->edittree = NULL; - snode->iofsd = NULL; - BLI_listbase_clear(&snode->linkdrag); + snode->runtime = NULL; } else if (sl->spacetype == SPACE_TEXT) { SpaceText *st = (SpaceText *)sl; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index e5f9d59270e..7a7ff5e9acb 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -587,15 +587,15 @@ MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking, { const MovieTrackingSettings *settings = &tracking->settings; + MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase); + MovieTrackingMarker marker; + const float half_pattern_px = settings->default_pattern_size / 2.0f; const float half_search_px = settings->default_search_size / 2.0f; const float pattern_size[2] = {half_pattern_px / width, half_pattern_px / height}; const float search_size[2] = {half_search_px / width, half_search_px / height}; - MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase); - - MovieTrackingMarker marker; memset(&marker, 0, sizeof(marker)); marker.pos[0] = x; marker.pos[1] = y; @@ -665,6 +665,86 @@ void BKE_tracking_track_free(MovieTrackingTrack *track) } } +/* Get frame numbers of the very first and last markers. + * There is no check on whether the marker is enabled or not. */ +void BKE_tracking_track_first_last_frame_get(const MovieTrackingTrack *track, + int *r_first_frame, + int *r_last_frame) +{ + BLI_assert(track->markersnr > 0); + const int last_marker_index = track->markersnr - 1; + *r_first_frame = track->markers[0].framenr; + *r_last_frame = track->markers[last_marker_index].framenr; +} + +/* Find the minimum starting frame and maximum ending frame within given set of + * tracks. + */ +void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ MovieTrackingTrack **tracks, + const int num_tracks, + int *r_first_frame, + int *r_last_frame) +{ + *r_first_frame = INT_MAX; + *r_last_frame = INT_MIN; + for (int i = 0; i < num_tracks; ++i) { + const struct MovieTrackingTrack *track = tracks[i]; + int track_first_frame, track_last_frame; + BKE_tracking_track_first_last_frame_get(track, &track_first_frame, &track_last_frame); + *r_first_frame = min_ii(*r_first_frame, track_first_frame); + *r_last_frame = max_ii(*r_last_frame, track_last_frame); + } +} + +int BKE_tracking_count_selected_tracks_in_list(const ListBase *tracks_list) +{ + int num_selected_tracks = 0; + LISTBASE_FOREACH (const MovieTrackingTrack *, track, tracks_list) { + if (TRACK_SELECTED(track)) { + ++num_selected_tracks; + } + } + return num_selected_tracks; +} + +int BKE_tracking_count_selected_tracks_in_active_object(/*const*/ MovieTracking *tracking) +{ + ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking); + return BKE_tracking_count_selected_tracks_in_list(tracks_list); +} + +MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object(MovieTracking *tracking, + int *r_num_tracks) +{ + *r_num_tracks = 0; + + ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking); + if (tracks_list == NULL) { + return NULL; + } + + /* Initialize input. */ + const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking); + if (num_selected_tracks == 0) { + return NULL; + } + + MovieTrackingTrack **source_tracks = MEM_malloc_arrayN( + num_selected_tracks, sizeof(MovieTrackingTrack *), "selected tracks array"); + int source_track_index = 0; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks_list) { + if (!TRACK_SELECTED(track)) { + continue; + } + source_tracks[source_track_index] = track; + ++source_track_index; + } + + *r_num_tracks = num_selected_tracks; + + return source_tracks; +} + /* Set flag for all specified track's areas. * * area - which part of marker should be selected. see TRACK_AREA_* constants. @@ -918,6 +998,96 @@ void BKE_tracking_tracks_join(MovieTracking *tracking, BKE_tracking_dopesheet_tag_update(tracking); } +static void accumulate_marker(MovieTrackingMarker *dst_marker, + const MovieTrackingMarker *src_marker) +{ + BLI_assert(dst_marker->framenr == src_marker->framenr); + + if (src_marker->flag & MARKER_DISABLED) { + return; + } + + add_v2_v2(dst_marker->pos, src_marker->pos); + for (int corner = 0; corner < 4; ++corner) { + add_v2_v2(dst_marker->pattern_corners[corner], src_marker->pattern_corners[corner]); + } + add_v2_v2(dst_marker->search_min, src_marker->search_min); + add_v2_v2(dst_marker->search_max, src_marker->search_max); + + BLI_assert(is_finite_v2(src_marker->search_min)); + BLI_assert(is_finite_v2(src_marker->search_max)); + + dst_marker->flag &= ~MARKER_DISABLED; + if ((src_marker->flag & MARKER_TRACKED) == 0) { + dst_marker->flag &= ~MARKER_TRACKED; + } +} + +static void multiply_marker(MovieTrackingMarker *marker, const float multiplier) +{ + mul_v2_fl(marker->pos, multiplier); + for (int corner = 0; corner < 4; ++corner) { + mul_v2_fl(marker->pattern_corners[corner], multiplier); + } + mul_v2_fl(marker->search_min, multiplier); + mul_v2_fl(marker->search_max, multiplier); +} + +void BKE_tracking_tracks_average(MovieTrackingTrack *dst_track, + /*const*/ MovieTrackingTrack **src_tracks, + const int num_src_tracks) +{ + /* Get global range of frames within which averaging would happen. */ + int first_frame, last_frame; + BKE_tracking_tracks_first_last_frame_minmax( + src_tracks, num_src_tracks, &first_frame, &last_frame); + if (last_frame < first_frame) { + return; + } + const int num_frames = last_frame - first_frame + 1; + + /* Allocate temporary array where averaging will happen into. */ + MovieTrackingMarker *accumulator = MEM_calloc_arrayN( + num_frames, sizeof(MovieTrackingMarker), "tracks average accumulator"); + int *counters = MEM_calloc_arrayN(num_frames, sizeof(int), "tracks accumulator counters"); + for (int frame = first_frame; frame <= last_frame; ++frame) { + const int frame_index = frame - first_frame; + accumulator[frame_index].framenr = frame; + accumulator[frame_index].flag |= (MARKER_DISABLED | MARKER_TRACKED); + } + + /* Accumulate track markers. */ + for (int track_index = 0; track_index < num_src_tracks; ++track_index) { + /*const*/ MovieTrackingTrack *track = src_tracks[track_index]; + for (int frame = first_frame; frame <= last_frame; ++frame) { + MovieTrackingMarker interpolated_marker; + if (!BKE_tracking_marker_get_interpolated(track, frame, &interpolated_marker)) { + continue; + } + const int frame_index = frame - first_frame; + accumulate_marker(&accumulator[frame_index], &interpolated_marker); + ++counters[frame_index]; + } + } + + /* Average and store the result. */ + for (int frame = first_frame; frame <= last_frame; ++frame) { + /* Average. */ + const int frame_index = frame - first_frame; + if (!counters[frame_index]) { + continue; + } + const float multiplier = 1.0f / (float)counters[frame_index]; + multiply_marker(&accumulator[frame_index], multiplier); + /* Store the result. */ + BKE_tracking_marker_insert(dst_track, &accumulator[frame_index]); + } + + /* Free memory. */ + MEM_freeN(accumulator); + MEM_freeN(counters); +} + MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieTrackingObject *object, const char *name) @@ -1224,8 +1394,6 @@ MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, /* put new marker */ track->markers[a + 1] = *marker; - track->last_marker = a + 1; - return &track->markers[a + 1]; } @@ -1314,51 +1482,45 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) } } +/* Get marker closest to the given frame number. + * + * If there is maker with exact frame number it returned. + * Otherwise, marker with higherst frame number but lower than the requested + * frame is returned if such marker exists. Otherwise, the marker with lowest + * frame number greater than the requested frame number is returned. + * + * This function has complexity of O(log number_of_markers). */ MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr) { - int a = track->markersnr - 1; + const int num_markers = track->markersnr; - if (!track->markersnr) { + if (num_markers == 0) { + BLI_assert(!"Detected degenerated track, should never happen."); return NULL; } - /* approximate pre-first framenr marker with first marker */ - if (framenr < track->markers[0].framenr) { - return &track->markers[0]; - } + int left_boundary = 0; + int right_boundary = num_markers; + while (left_boundary < right_boundary) { + const int median_index = (left_boundary + right_boundary) / 2; + MovieTrackingMarker *marker = &track->markers[median_index]; - if (track->last_marker < track->markersnr) { - a = track->last_marker; - } - - if (track->markers[a].framenr <= framenr) { - while (a < track->markersnr && track->markers[a].framenr <= framenr) { - if (track->markers[a].framenr == framenr) { - track->last_marker = a; - - return &track->markers[a]; - } - a++; + if (marker->framenr == framenr) { + return marker; } - /* if there's no marker for exact position, use nearest marker from left side */ - return &track->markers[a - 1]; - } - - while (a >= 0 && track->markers[a].framenr >= framenr) { - if (track->markers[a].framenr == framenr) { - track->last_marker = a; - - return &track->markers[a]; + if (marker->framenr < framenr) { + left_boundary = median_index + 1; + } + else { + BLI_assert(marker->framenr > framenr); + right_boundary = median_index - 1; } - - a--; } - /* if there's no marker for exact position, use nearest marker from left side */ - return &track->markers[a]; + const int closest_index = clamp_i(right_boundary, 0, num_markers - 1); - return NULL; + return &track->markers[closest_index]; } MovieTrackingMarker *BKE_tracking_marker_get_exact(MovieTrackingTrack *track, int framenr) @@ -1389,6 +1551,84 @@ MovieTrackingMarker *BKE_tracking_marker_ensure(MovieTrackingTrack *track, int f return marker; } +static const MovieTrackingMarker *get_usable_marker_for_interpolation( + struct MovieTrackingTrack *track, + const MovieTrackingMarker *anchor_marker, + const int direction) +{ + BLI_assert(direction == -1 || direction == 1); + + const MovieTrackingMarker *last_marker = track->markers + track->markersnr - 1; + const MovieTrackingMarker *current_marker = anchor_marker; + + while (current_marker >= track->markers && current_marker <= last_marker) { + if ((current_marker->flag & MARKER_DISABLED) == 0) { + return current_marker; + } + current_marker += direction; + } + + return NULL; +} + +bool BKE_tracking_marker_get_interpolated(struct MovieTrackingTrack *track, + const int framenr, + struct MovieTrackingMarker *r_marker) +{ + const MovieTrackingMarker *closest_marker = BKE_tracking_marker_get(track, framenr); + if (closest_marker == NULL) { + return false; + } + if (closest_marker->framenr == framenr && (closest_marker->flag & MARKER_DISABLED) == 0) { + *r_marker = *closest_marker; + return true; + } + + const MovieTrackingMarker *left_marker = get_usable_marker_for_interpolation( + track, closest_marker, -1); + if (left_marker == NULL) { + return false; + } + + const MovieTrackingMarker *right_marker = get_usable_marker_for_interpolation( + track, closest_marker + 1, 1); + if (right_marker == NULL) { + return false; + } + + if (left_marker == right_marker) { + *r_marker = *left_marker; + return true; + } + + const float factor = (float)(framenr - left_marker->framenr) / + (right_marker->framenr - left_marker->framenr); + + interp_v2_v2v2(r_marker->pos, left_marker->pos, right_marker->pos, factor); + + for (int i = 0; i < 4; i++) { + interp_v2_v2v2(r_marker->pattern_corners[i], + left_marker->pattern_corners[i], + right_marker->pattern_corners[i], + factor); + } + + interp_v2_v2v2(r_marker->search_min, left_marker->search_min, right_marker->search_min, factor); + interp_v2_v2v2(r_marker->search_max, left_marker->search_max, right_marker->search_max, factor); + + r_marker->framenr = framenr; + r_marker->flag = 0; + + if (framenr == left_marker->framenr) { + r_marker->flag = left_marker->flag; + } + else if (framenr == right_marker->framenr) { + r_marker->flag = right_marker->flag; + } + + return true; +} + void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2]) @@ -1683,7 +1923,6 @@ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTra /* Put new marker to an array. */ plane_track->markers[a + 1] = *plane_marker; - plane_track->last_marker = a + 1; return &plane_track->markers[a + 1]; } diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index 6f58416924f..46589a578a8 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -311,11 +311,7 @@ static void retrieve_next_lower_usable_frame( * translation stabilization, which has an enabled tracking marker at this very * frame. We search both for the next lower and next higher position, to allow * the caller to interpolate gaps and to extrapolate at the ends of the - * definition range. - * - * NOTE: Regarding performance note that the individual tracks will cache the - * last search position. - */ + * definition range. */ static void find_next_working_frames(StabContext *ctx, int framenr, int *next_lower, diff --git a/source/blender/blenkernel/intern/tracking_test.cc b/source/blender/blenkernel/intern/tracking_test.cc index 6afcf6872eb..2877d8db358 100644 --- a/source/blender/blenkernel/intern/tracking_test.cc +++ b/source/blender/blenkernel/intern/tracking_test.cc @@ -5,15 +5,23 @@ #include "DNA_tracking_types.h" #include "BKE_tracking.h" +#include "BLI_float2.hh" + +namespace blender { namespace { class TrackingTest : public ::testing::Test { protected: - MovieTrackingMarker *addMarkerToTrack(MovieTrackingTrack *track, int frame_number) + MovieTrackingMarker *addMarkerToTrack(MovieTrackingTrack *track, + int frame_number, + const float2 &position = float2(0.0f, 0.0f), + int flag = 0) { MovieTrackingMarker marker = {{0.0f}}; + copy_v2_v2(marker.pos, position); marker.framenr = frame_number; + marker.flag = flag; return BKE_tracking_marker_insert(track, &marker); } }; @@ -22,24 +30,58 @@ class TrackingTest : public ::testing::Test { TEST_F(TrackingTest, BKE_tracking_marker_get) { - MovieTrackingTrack track = {nullptr}; + { + MovieTrackingTrack track = {nullptr}; - addMarkerToTrack(&track, 1); - addMarkerToTrack(&track, 10); + addMarkerToTrack(&track, 10); - { - const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 1); - EXPECT_NE(marker, nullptr); - EXPECT_EQ(marker->framenr, 1); + EXPECT_EQ(BKE_tracking_marker_get(&track, 0), &track.markers[0]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 10), &track.markers[0]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 20), &track.markers[0]); + + BKE_tracking_track_free(&track); } { - const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 5); - EXPECT_NE(marker, nullptr); - EXPECT_EQ(marker->framenr, 1); + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1); + addMarkerToTrack(&track, 10); + + { + const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 1); + EXPECT_NE(marker, nullptr); + EXPECT_EQ(marker->framenr, 1); + } + + { + const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 5); + EXPECT_NE(marker, nullptr); + EXPECT_EQ(marker->framenr, 1); + } + + BKE_tracking_track_free(&track); } - BKE_tracking_track_free(&track); + { + { + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1); + addMarkerToTrack(&track, 2); + addMarkerToTrack(&track, 10); + + EXPECT_EQ(BKE_tracking_marker_get(&track, 0), &track.markers[0]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 1), &track.markers[0]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 2), &track.markers[1]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 3), &track.markers[1]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 9), &track.markers[1]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 10), &track.markers[2]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 11), &track.markers[2]); + + BKE_tracking_track_free(&track); + } + } } TEST_F(TrackingTest, BKE_tracking_marker_get_exact) @@ -62,3 +104,107 @@ TEST_F(TrackingTest, BKE_tracking_marker_get_exact) BKE_tracking_track_free(&track); } + +TEST_F(TrackingTest, BKE_tracking_marker_get_interpolated) +{ + /* Simple case, no disabled markers in a way. */ + { + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1, float2(1.0f, 5.0f)); + addMarkerToTrack(&track, 10, float2(2.0f, 1.0f)); + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 1); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.0f, 5.0f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 10); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(2.0f, 1.0f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 4); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.3333333f, 3.6666666f), 1e-6f); + } + + BKE_tracking_track_free(&track); + } + + /* More comprehensive test, which resembles real life trackign scenario better. */ + { + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1, float2(1.0f, 5.0f)); + addMarkerToTrack(&track, 2, float2(0.0f, 0.0f), MARKER_DISABLED); + addMarkerToTrack(&track, 9, float2(0.0f, 0.0f), MARKER_DISABLED); + addMarkerToTrack(&track, 10, float2(2.0f, 1.0f)); + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 1); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.0f, 5.0f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 10); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(2.0f, 1.0f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 4); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.3333333f, 3.6666666f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 9, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 9); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.888888f, 1.4444444f), 1e-6f); + } + + BKE_tracking_track_free(&track); + } + + /* Tracked/keyframed flag check. */ + { + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1, float2(1.0f, 5.0f), MARKER_TRACKED); + addMarkerToTrack(&track, 10, float2(2.0f, 1.0f), MARKER_TRACKED); + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.flag, MARKER_TRACKED); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.flag, MARKER_TRACKED); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.flag, 0); + } + + BKE_tracking_track_free(&track); + } +} + +} // namespace blender diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 7257be66b79..034f3f39fd3 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -112,8 +112,8 @@ typedef struct NlaEvalChannel { struct NlaEvalChannel *next_blend; NlaEvalChannelSnapshot *blend_snapshot; - /* Mask of array items controlled by NLA. */ - NlaValidMask valid; + /* Associated with the RNA property's value(s), marks which elements are affected by NLA. */ + NlaValidMask domain; /* Base set of values. */ NlaEvalChannelSnapshot base_snapshot; diff --git a/source/blender/blenlib/BLI_float2.hh b/source/blender/blenlib/BLI_float2.hh index 2a5320e4c35..84dd0e358a2 100644 --- a/source/blender/blenlib/BLI_float2.hh +++ b/source/blender/blenlib/BLI_float2.hh @@ -29,6 +29,14 @@ struct float2 { { } + explicit float2(float value) : x(value), y(value) + { + } + + explicit float2(int value) : x(value), y(value) + { + } + float2(float x, float y) : x(x), y(y) { } @@ -52,6 +60,11 @@ struct float2 { return len_v2(*this); } + float length_squared() const + { + return len_squared_v2(*this); + } + float2 &operator+=(const float2 &other) { x += other.x; diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index c0a9ea91e75..e7dd1821a82 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -826,6 +826,11 @@ MINLINE float shell_v2v2_mid_normalized_to_dist(const float a[2], const float b[ float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3]); +/********************************** Geodesics *********************************/ + +float geodesic_distance_propagate_across_triangle( + const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2); + /**************************** Inline Definitions ******************************/ #if BLI_MATH_DO_INLINE diff --git a/source/blender/blenlib/BLI_mmap.h b/source/blender/blenlib/BLI_mmap.h new file mode 100644 index 00000000000..4920152c9d1 --- /dev/null +++ b/source/blender/blenlib/BLI_mmap.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + +#pragma once + +/** \file + * \ingroup bli + */ + +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Memory-mapped file IO that implements all the OS-specific details and error handling. */ + +struct BLI_mmap_file; + +typedef struct BLI_mmap_file BLI_mmap_file; + +/* Prepares an opened file for memory-mapped IO. + * May return NULL if the operation fails. + * Note that this seeks to the end of the file to determine its length. */ +BLI_mmap_file *BLI_mmap_open(int fd) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; + +/* Reads length bytes from file at the given offset into dest. + * Returns whether the operation was successful (may fail when reading beyond the file + * end or when IO errors occur). */ +bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); + +void *BLI_mmap_get_pointer(BLI_mmap_file *file) ATTR_WARN_UNUSED_RESULT; + +void BLI_mmap_free(BLI_mmap_file *file) ATTR_NONNULL(1); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index aa4c4efe7d4..b7a13596dd0 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -54,6 +54,7 @@ set(SRC intern/BLI_memblock.c intern/BLI_memiter.c intern/BLI_mempool.c + intern/BLI_mmap.c intern/BLI_timer.c intern/DLRB_tree.c intern/array_store.c @@ -243,6 +244,7 @@ set(SRC BLI_mempool.h BLI_mesh_boolean.hh BLI_mesh_intersect.hh + BLI_mmap.h BLI_mpq2.hh BLI_mpq3.hh BLI_multi_value_map.hh diff --git a/source/blender/blenlib/intern/BLI_mmap.c b/source/blender/blenlib/intern/BLI_mmap.c new file mode 100644 index 00000000000..f0b13183c68 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_mmap.c @@ -0,0 +1,233 @@ +/* + * 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 bli + */ + +#include "BLI_mmap.h" +#include "BLI_fileops.h" +#include "BLI_listbase.h" +#include "MEM_guardedalloc.h" + +#include <string.h> + +#ifndef WIN32 +# include <stdlib.h> +# include <signal.h> +# include <sys/mman.h> // for mmap +# include <unistd.h> // for read close +#else +# include "BLI_winstuff.h" +# include <io.h> // for open close read +#endif + +struct BLI_mmap_file { + /* The address to which the file was mapped. */ + char *memory; + + /* The length of the file (and therefore the mapped region). */ + size_t length; + + /* Platform-specific handle for the mapping. */ + void *handle; + + /* Flag to indicate IO errors. Needs to be volatile since it's being set from + * within the signal handler, which is not part of the normal execution flow. */ + volatile bool io_error; +}; + +#ifndef WIN32 +/* When using memory-mapped files, any IO errors will result in a SIGBUS signal. + * Therefore, we need to catch that signal and stop reading the file in question. + * To do so, we keep a list of all current FileDatas that use memory-mapped files, + * and if a SIGBUS is caught, we check if the failed address is inside one of the + * mapped regions. + * If it is, we set a flag to indicate a failed read and remap the memory in + * question to a zero-backed region in order to avoid additional signals. + * The code that actually reads the memory area has to check whether the flag was + * set after it's done reading. + * If the error occurred outside of a memory-mapped region, we call the previous + * handler if one was configured and abort the process otherwise. + */ + +struct error_handler_data { + ListBase open_mmaps; + char configured; + void (*next_handler)(int, siginfo_t *, void *); +} error_handler = {0}; + +static void sigbus_handler(int sig, siginfo_t *siginfo, void *ptr) +{ + /* We only handle SIGBUS here for now. */ + BLI_assert(sig == SIGBUS); + + char *error_addr = (char *)siginfo->si_addr; + /* Find the file that this error belongs to. */ + LISTBASE_FOREACH (LinkData *, link, &error_handler.open_mmaps) { + BLI_mmap_file *file = link->data; + + /* Is the address where the error occurred in this file's mapped range? */ + if (error_addr >= file->memory && error_addr < file->memory + file->length) { + file->io_error = true; + + /* Replace the mapped memory with zeroes. */ + mmap(file->memory, file->length, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + + return; + } + } + + /* Fall back to other handler if there was one. */ + if (error_handler.next_handler) { + error_handler.next_handler(sig, siginfo, ptr); + } + else { + fprintf(stderr, "Unhandled SIGBUS caught\n"); + abort(); + } +} + +/* Ensures that the error handler is set up and ready. */ +static bool sigbus_handler_setup(void) +{ + if (!error_handler.configured) { + struct sigaction newact = {0}, oldact = {0}; + + newact.sa_sigaction = sigbus_handler; + newact.sa_flags = SA_SIGINFO; + + if (sigaction(SIGBUS, &newact, &oldact)) { + return false; + } + + /* Remember the previously configured handler to fall back to it if the error + * does not belong to any of the mapped files. */ + error_handler.next_handler = oldact.sa_sigaction; + error_handler.configured = 1; + } + + return true; +} + +/* Adds a file to the list that the error handler checks. */ +static void sigbus_handler_add(BLI_mmap_file *file) +{ + BLI_addtail(&error_handler.open_mmaps, BLI_genericNodeN(file)); +} + +/* Removes a file from the list that the error handler checks. */ +static void sigbus_handler_remove(BLI_mmap_file *file) +{ + LinkData *link = BLI_findptr(&error_handler.open_mmaps, file, offsetof(LinkData, data)); + BLI_freelinkN(&error_handler.open_mmaps, link); +} +#endif + +BLI_mmap_file *BLI_mmap_open(int fd) +{ + void *memory, *handle = NULL; + size_t length = BLI_lseek(fd, 0, SEEK_END); + +#ifndef WIN32 + /* Ensure that the SIGBUS handler is configured. */ + if (!sigbus_handler_setup()) { + return NULL; + } + + /* Map the given file to memory. */ + memory = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0); + if (memory == MAP_FAILED) { + return NULL; + } +#else + /* Convert the POSIX-style file descriptor to a Windows handle. */ + void *file_handle = (void *)_get_osfhandle(fd); + /* Memory mapping on Windows is a two-step process - first we create a mapping, + * then we create a view into that mapping. + * In our case, one view that spans the entire file is enough. */ + handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL); + if (handle == NULL) { + return NULL; + } + memory = MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0); + if (memory == NULL) { + CloseHandle(handle); + return NULL; + } +#endif + + /* Now that the mapping was successful, allocate memory and set up the BLI_mmap_file. */ + BLI_mmap_file *file = MEM_callocN(sizeof(BLI_mmap_file), __func__); + file->memory = memory; + file->handle = handle; + file->length = length; + +#ifndef WIN32 + /* Register the file with the error handler. */ + sigbus_handler_add(file); +#endif + + return file; +} + +bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length) +{ + /* If a previous read has already failed or we try to read past the end, + * don't even attempt to read any further. */ + if (file->io_error || (offset + length > file->length)) { + return false; + } + +#ifndef WIN32 + /* If an error occurs in this call, sigbus_handler will be called and will set + * file->io_error to true. */ + memcpy(dest, file->memory + offset, length); +#else + /* On Windows, we use exception handling to be notified of errors. */ + __try { + memcpy(dest, file->memory + offset, length); + } + __except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { + file->io_error = true; + return false; + } +#endif + + return !file->io_error; +} + +void *BLI_mmap_get_pointer(BLI_mmap_file *file) +{ + return file->memory; +} + +void BLI_mmap_free(BLI_mmap_file *file) +{ +#ifndef WIN32 + munmap((void *)file->memory, file->length); + sigbus_handler_remove(file); +#else + UnmapViewOfFile(file->memory); + CloseHandle(file->handle); +#endif + + MEM_freeN(file); +} diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 3cc4d03d547..de5f96d3372 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -6246,3 +6246,56 @@ float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3]) const float angle_cos = cosf(angle); return ((1.0f - angle_cos) / (angle_sin * 2.0f)) / angle_sin; } + +/** + * Utility for computing approximate geodesic distances on triangle meshes. + * + * Given triangle with vertex coordinates v0, v1, v2, and known geodesic distances + * dist1 and dist2 at v1 and v2, estimate a geodesic distance at vertex v0. + * + * From "Dart Throwing on Surfaces", EGSR 2009. Section 7, Geodesic Dart Throwing. + */ +float geodesic_distance_propagate_across_triangle( + const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2) +{ + /* Vectors along triangle edges. */ + float v10[3], v12[3]; + sub_v3_v3v3(v10, v0, v1); + sub_v3_v3v3(v12, v2, v1); + + if (dist1 != 0.0f && dist2 != 0.0f) { + /* Local coordinate system in the triangle plane. */ + float u[3], v[3], n[3]; + const float d12 = normalize_v3_v3(u, v12); + + if (d12 * d12 > 0.0f) { + cross_v3_v3v3(n, v12, v10); + normalize_v3(n); + cross_v3_v3v3(v, n, u); + + /* v0 in local coordinates */ + const float v0_[2] = {dot_v3v3(v10, u), fabsf(dot_v3v3(v10, v))}; + + /* Compute virtual source point in local coordinates, that we estimate the geodesic + * distance is being computed from. See figure 9 in the paper for the derivation. */ + const float a = 0.5f * (1.0f + (dist1 * dist1 - dist2 * dist2) / (d12 * d12)); + const float hh = dist1 * dist1 - a * a * d12 * d12; + + if (hh > 0.0f) { + const float h = sqrtf(hh); + const float S_[2] = {a * d12, -h}; + + /* Only valid if the line between the source point and v0 crosses + * the edge between v1 and v2. */ + const float x_intercept = S_[0] + h * (v0_[0] - S_[0]) / (v0_[1] + h); + if (x_intercept >= 0.0f && x_intercept <= d12) { + return len_v2v2(S_, v0_); + } + } + } + } + + /* Fall back to Dijsktra approximation in trivial case, or if no valid source + * point found that connects to v0 across the triangle. */ + return min_ff(dist1 + len_v3(v10), dist2 + len_v3v3(v0, v2)); +} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b61abd4ed06..2192e9a378f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -68,6 +68,7 @@ #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_mempool.h" +#include "BLI_mmap.h" #include "BLI_threads.h" #include "BLT_translation.h" @@ -1179,6 +1180,53 @@ static ssize_t fd_read_from_memory(FileData *filedata, return readsize; } +/* Memory-mapped file reading. + * By using mmap(), we can map a file so that it can be treated like normal memory, + * meaning that we can just read from it with memcpy() etc. + * This avoids system call overhead and can significantly speed up file loading. + */ + +static ssize_t fd_read_from_mmap(FileData *filedata, + void *buffer, + size_t size, + bool *UNUSED(r_is_memchunck_identical)) +{ + /* don't read more bytes than there are available in the buffer */ + size_t readsize = MIN2(size, (size_t)(filedata->buffersize - filedata->file_offset)); + + if (!BLI_mmap_read(filedata->mmap_file, buffer, filedata->file_offset, readsize)) { + return 0; + } + + filedata->file_offset += readsize; + + return readsize; +} + +static off64_t fd_seek_from_mmap(FileData *filedata, off64_t offset, int whence) +{ + off64_t new_pos; + if (whence == SEEK_CUR) { + new_pos = filedata->file_offset + offset; + } + else if (whence == SEEK_SET) { + new_pos = offset; + } + else if (whence == SEEK_END) { + new_pos = filedata->buffersize + offset; + } + else { + return -1; + } + + if (new_pos < 0 || new_pos > filedata->buffersize) { + return -1; + } + + filedata->file_offset = new_pos; + return filedata->file_offset; +} + /* MemFile reading. */ static ssize_t fd_read_from_memfile(FileData *filedata, @@ -1306,6 +1354,8 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, { FileDataReadFn *read_fn = NULL; FileDataSeekFn *seek_fn = NULL; /* Optional. */ + size_t buffersize = 0; + BLI_mmap_file *mmap_file = NULL; gzFile gzfile = (gzFile)Z_NULL; @@ -1322,14 +1372,21 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, return NULL; } - BLI_lseek(file, 0, SEEK_SET); - /* Regular file. */ if (memcmp(header, "BLENDER", sizeof(header)) == 0) { read_fn = fd_read_data_from_file; seek_fn = fd_seek_data_from_file; + + mmap_file = BLI_mmap_open(file); + if (mmap_file != NULL) { + read_fn = fd_read_from_mmap; + seek_fn = fd_seek_from_mmap; + buffersize = BLI_lseek(file, 0, SEEK_END); + } } + BLI_lseek(file, 0, SEEK_SET); + /* Gzip file. */ errno = 0; if ((read_fn == NULL) && @@ -1363,6 +1420,8 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, fd->read = read_fn; fd->seek = seek_fn; + fd->mmap_file = mmap_file; + fd->buffersize = buffersize; return fd; } @@ -1531,6 +1590,11 @@ void blo_filedata_free(FileData *fd) fd->buffer = NULL; } + if (fd->mmap_file) { + BLI_mmap_free(fd->mmap_file); + fd->mmap_file = NULL; + } + /* Free all BHeadN data blocks */ #ifndef NDEBUG BLI_freelistN(&fd->bhead_list); diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index c724cc32051..86f05eda7b7 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -41,6 +41,7 @@ struct Object; struct OldNewMap; struct ReportList; struct UserDef; +struct BLI_mmap_file; typedef struct IDNameLib_Map IDNameLib_Map; @@ -83,8 +84,9 @@ typedef struct FileData { /** Regular file reading. */ int filedes; - /** Variables needed for reading from memory / stream. */ + /** Variables needed for reading from memory / stream / memory-mapped files. */ const char *buffer; + struct BLI_mmap_file *mmap_file; /** Variables needed for reading from memfile (undo). */ struct MemFile *memfile; /** Whether we are undoing (< 0) or redoing (> 0), used to choose which 'unchanged' flag to use diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index ec537e6f3d8..7c5372a22e3 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1547,7 +1547,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) FOREACH_NODETREE_END; } - if (!MAIN_VERSION_ATLEAST(bmain, 292, 13)) { + if (!MAIN_VERSION_ATLEAST(bmain, 293, 1)) { FOREACH_NODETREE_BEGIN (bmain, ntree, id) { if (ntree->type == NTREE_GEOMETRY) { version_node_socket_name(ntree, GEO_NODE_BOOLEAN, "Geometry A", "Geometry 1"); @@ -1572,7 +1572,8 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - if (!MAIN_VERSION_ATLEAST(bmain, 292, 14)) { + if ((!MAIN_VERSION_ATLEAST(bmain, 292, 14)) || + ((bmain->versionfile == 293) && (!MAIN_VERSION_ATLEAST(bmain, 293, 1)))) { FOREACH_NODETREE_BEGIN (bmain, ntree, id) { if (ntree->type != NTREE_GEOMETRY) { continue; @@ -1589,6 +1590,27 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) FOREACH_NODETREE_END; } + if (!MAIN_VERSION_ATLEAST(bmain, 293, 1)) { + /* Grease pencil layer transform matrix. */ + if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "float", "location[0]")) { + LISTBASE_FOREACH (bGPdata *, gpd, &bmain->gpencils) { + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + zero_v3(gpl->location); + zero_v3(gpl->rotation); + copy_v3_fl(gpl->scale, 1.0f); + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + } + } + } + /* Fix Fill factor for grease pencil fill brushes. */ + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if ((brush->gpencil_settings) && (brush->gpencil_settings->fill_factor == 0.0f)) { + brush->gpencil_settings->fill_factor = 1.0f; + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.h b/source/blender/compositor/operations/COM_BokehImageOperation.h index 01ffa026152..2d775bdf738 100644 --- a/source/blender/compositor/operations/COM_BokehImageOperation.h +++ b/source/blender/compositor/operations/COM_BokehImageOperation.h @@ -55,7 +55,7 @@ class BokehImageOperation : public NodeOperation { NodeBokehImage *m_data; /** - * \brief precalced center of the image + * \brief precalculate center of the image */ float m_center[2]; @@ -87,7 +87,7 @@ class BokehImageOperation : public NodeOperation { /** * \brief determine the coordinate of a flap corner. * - * \param r: result in bokehimage space are stored [x,y] + * \param r: result in bokeh-image space are stored [x,y] * \param flapNumber: the flap number to calculate * \param distance: the lens distance is used to simulate lens shifts */ diff --git a/source/blender/compositor/operations/COM_DotproductOperation.cpp b/source/blender/compositor/operations/COM_DotproductOperation.cpp index 750e4308d11..5914be21453 100644 --- a/source/blender/compositor/operations/COM_DotproductOperation.cpp +++ b/source/blender/compositor/operations/COM_DotproductOperation.cpp @@ -39,7 +39,7 @@ void DotproductOperation::deinitExecution() this->m_input2Operation = nullptr; } -/** \todo: current implementation is the inverse of a dotproduct. not 'logically' correct +/** \todo current implementation is the inverse of a dot-product. not 'logically' correct */ void DotproductOperation::executePixelSampled(float output[4], float x, diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 20044fbe3ce..b6f0817adb3 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -214,6 +214,7 @@ void GPENCIL_cache_init(void *ved) NULL : false; pd->do_onion = show_onion && !hide_overlay && !playing; + pd->playing = playing; /* Save simplify flags (can change while drawing, so it's better to save). */ Scene *scene = draw_ctx->scene; pd->simplify_fill = GPENCIL_SIMPLIFY_FILL(scene, playing); @@ -241,6 +242,7 @@ void GPENCIL_cache_init(void *ved) pd->simplify_fill = false; pd->simplify_fx = false; pd->fade_layer_opacity = -1.0f; + pd->playing = false; } { @@ -617,7 +619,7 @@ void GPENCIL_cache_populate(void *ved, Object *ob) /* Special case for rendering onion skin. */ bGPdata *gpd = (bGPdata *)ob->data; bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS); - + gpd->runtime.playing = (short)pd->playing; BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL, ob, gpencil_layer_cache_populate, diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index d0bd56b42dd..2b07ea53187 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -342,6 +342,8 @@ typedef struct GPENCIL_PrivateData { /* Display onion skinning */ bool do_onion; + /* Playing animation */ + bool playing; /* simplify settings */ bool simplify_fill; bool simplify_fx; diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c index 7f9290a6c3a..19af3ae7e5d 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil.c +++ b/source/blender/draw/engines/overlay/overlay_gpencil.c @@ -258,6 +258,16 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) copy_m4_m4(mat, ob->obmat); + /* Rotate and scale except align to cursor. */ + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl != NULL) { + if (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR) { + float matrot[3][3]; + copy_m3_m4(matrot, gpl->layer_mat); + mul_m4_m4m3(mat, mat, matrot); + } + } + float viewinv[4][4]; /* Set the grid in the selected axis */ switch (ts->gp_sculpt.lock_axis) { @@ -294,6 +304,11 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) mul_v2_v2fl(size, gpd->grid.scale, 2.0f * ED_scene_grid_scale(scene, &grid_unit)); rescale_m4(mat, (float[3]){size[0], size[1], 0.0f}); + /* Apply layer loc transform, except cursor mode. */ + if ((gpl != NULL) && (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + add_v3_v3(mat[3], gpl->layer_mat[3]); + } + const int gridlines = (gpd->grid.lines <= 0) ? 1 : gpd->grid.lines; int line_ct = gridlines * 4 + 2; diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index e1523db36c7..8feacf8b026 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -800,20 +800,20 @@ static void gpencil_edit_curve_stroke_iter_cb(bGPDlayer *gpl, }; /* First segment. */ - copy_v3_v3(vert_ptr->pos, bezt->vec[0]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[0]); vert_ptr->data = vflag[0]; vert_ptr++; - copy_v3_v3(vert_ptr->pos, bezt->vec[1]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); vert_ptr->data = vflag[1]; vert_ptr++; /* Second segment. */ - copy_v3_v3(vert_ptr->pos, bezt->vec[1]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); vert_ptr->data = vflag[1]; vert_ptr++; - copy_v3_v3(vert_ptr->pos, bezt->vec[2]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[2]); vert_ptr->data = vflag[2]; vert_ptr++; } diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 05cbb3ef48f..8f6d0045c9c 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -4710,7 +4710,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, (float)CFRA); NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context( - &nla_cache, &id_ptr, adt, &anim_eval_context, false); + &nla_cache, &id_ptr, adt, &anim_eval_context); /* get current frame and apply NLA-mapping to it (if applicable) */ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); @@ -4766,7 +4766,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, (float)CFRA); NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context( - &nla_cache, &id_ptr, key->adt, &anim_eval_context, false); + &nla_cache, &id_ptr, key->adt, &anim_eval_context); /* get current frame and apply NLA-mapping to it (if applicable) */ const float remapped_frame = BKE_nla_tweakedit_remap( diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index e8146ca960a..db3a1b99135 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1384,7 +1384,7 @@ static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval if (adt && adt->action == act) { /* Get NLA context for value remapping. */ *r_nla_context = BKE_animsys_get_nla_keyframing_context( - nla_cache, id_ptr, adt, anim_eval_context, false); + nla_cache, id_ptr, adt, anim_eval_context); /* Apply NLA-mapping to frame. */ const float remapped_frame = BKE_nla_tweakedit_remap( diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 09b57029350..22a628de8b1 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -178,7 +178,7 @@ static void gpencil_strokepoint_convertcoords(bContext *C, /* apply parent transform */ float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); mul_v3_m4v3(fpt, diff_mat, &source_pt->x); copy_v3_v3(&pt->x, fpt); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index ad9b72b713e..8f24ce0ddd8 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -1560,7 +1560,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* some stroke is already at front*/ @@ -1725,7 +1725,7 @@ static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2854,7 +2854,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) float inverse_diff_mat[4][4]; /* recalculate all stroke points */ - BKE_gpencil_parent_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat); invert_m4_m4_safe_ortho(inverse_diff_mat, diff_mat); Material *ma_src = NULL; @@ -3388,7 +3388,7 @@ static int gpencil_material_select_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index d1c8eca1be0..b5269bbfacf 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1867,7 +1867,7 @@ static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op) } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2610,7 +2610,7 @@ static int gpencil_delete_selected_points(bContext *C) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2800,7 +2800,7 @@ static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) float diff_mat[4][4]; /* calculate difference matrix object */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* skip strokes that are invalid for current view */ @@ -2808,7 +2808,7 @@ static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } @@ -2935,7 +2935,7 @@ static int gpencil_snap_to_cursor(bContext *C, wmOperator *op) float diff_mat[4][4]; /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; @@ -2946,7 +2946,7 @@ static int gpencil_snap_to_cursor(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* only continue if this stroke is selected (editable doesn't guarantee this)... */ @@ -3039,7 +3039,7 @@ static bool gpencil_stroke_points_centroid(Depsgraph *depsgraph, float diff_mat[4][4]; /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; @@ -3050,7 +3050,7 @@ static bool gpencil_stroke_points_centroid(Depsgraph *depsgraph, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* only continue if this stroke is selected (editable doesn't guarantee this)... */ @@ -3565,7 +3565,7 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } elem = &strokes_list[tot_strokes]; @@ -3697,7 +3697,7 @@ static int gpencil_stroke_flip_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -4516,7 +4516,7 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Separate selected strokes. */ @@ -4717,7 +4717,7 @@ static int gpencil_stroke_split_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Split selected strokes. */ diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 622556943c9..84447059884 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -81,6 +81,7 @@ #define LEAK_HORZ 0 #define LEAK_VERT 1 +#define MIN_WINDOW_SIZE 128 /* Temporary fill operation data (op->customdata) */ typedef struct tGPDfill { @@ -137,7 +138,7 @@ typedef struct tGPDfill { /** boundary limits drawing mode */ int fill_draw_mode; /* scaling factor */ - short fill_factor; + float fill_factor; /* Frame to use. */ int active_cfra; @@ -262,14 +263,14 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) BLI_assert(gpl_active_index >= 0); LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* calculate parent position */ - BKE_gpencil_parent_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat); - /* do not draw layer if hidden */ if (gpl->flag & GP_LAYER_HIDE) { continue; } + /* calculate parent position */ + BKE_gpencil_layer_transform_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat); + /* Decide if the strokes of layers are included or not depending on the layer mode. * Cannot skip the layer because it can use boundary strokes and must be used. */ bool skip = false; @@ -398,8 +399,8 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) /* resize region */ tgpf->region->winrct.xmin = 0; tgpf->region->winrct.ymin = 0; - tgpf->region->winrct.xmax = (int)tgpf->region->winx * tgpf->fill_factor; - tgpf->region->winrct.ymax = (int)tgpf->region->winy * tgpf->fill_factor; + tgpf->region->winrct.xmax = max_ii((int)tgpf->region->winx * tgpf->fill_factor, MIN_WINDOW_SIZE); + tgpf->region->winrct.ymax = max_ii((int)tgpf->region->winy * tgpf->fill_factor, MIN_WINDOW_SIZE); tgpf->region->winx = (short)abs(tgpf->region->winrct.xmax - tgpf->region->winrct.xmin); tgpf->region->winy = (short)abs(tgpf->region->winrct.ymax - tgpf->region->winrct.ymin); @@ -456,7 +457,7 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) } GPU_matrix_push_projection(); - GPU_matrix_identity_set(); + GPU_matrix_identity_projection_set(); GPU_matrix_push(); GPU_matrix_identity_set(); @@ -1274,7 +1275,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) float origin[3]; ED_gpencil_drawing_reference_get(tgpf->scene, tgpf->ob, ts->gpencil_v3d_align, origin); ED_gpencil_project_stroke_to_plane( - tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1); + tgpf->scene, tgpf->ob, tgpf->rv3d, tgpf->gpl, gps, origin, tgpf->lock_axis - 1); } /* if parented change position relative to parent object */ @@ -1394,11 +1395,12 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); tgpf->brush = brush; tgpf->flag = brush->gpencil_settings->flag; - tgpf->fill_leak = brush->gpencil_settings->fill_leak; tgpf->fill_threshold = brush->gpencil_settings->fill_threshold; tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl; tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode; - tgpf->fill_factor = (short)max_ii(1, min_ii((int)brush->gpencil_settings->fill_factor, 8)); + tgpf->fill_factor = max_ff(GPENCIL_MIN_FILL_FAC, + min_ff(brush->gpencil_settings->fill_factor, 8.0f)); + tgpf->fill_leak = (int)ceil((float)brush->gpencil_settings->fill_leak * tgpf->fill_factor); int totcol = tgpf->ob->totcol; diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 4a908eff92e..5fea46626d5 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -667,7 +667,8 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ bGPDstroke *gpsn_; \ @@ -678,7 +679,7 @@ struct GP_EditableStrokes_Iter { continue; \ } \ /* check if the color is editable */ \ - if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) { \ + if (ED_gpencil_stroke_material_editable(obact_, gpl, gps) == false) { \ continue; \ } \ /* ... Do Stuff With Strokes ... */ @@ -718,7 +719,8 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ bGPDstroke *gpsn_; \ @@ -767,8 +769,10 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ - invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + /* Undo layer transform. */ \ + mul_m4_m4m4(gpstroke_iter.diff_mat, gpstroke_iter.diff_mat, gpl->layer_invmat); \ /* loop over strokes */ \ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf_->strokes) { \ /* skip strokes that are invalid for current view */ \ @@ -776,7 +780,7 @@ struct GP_EditableStrokes_Iter { continue; \ } \ /* check if the color is editable */ \ - if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) { \ + if (ED_gpencil_stroke_material_editable(obact_, gpl, gps) == false) { \ continue; \ } \ /* ... Do Stuff With Strokes ... */ diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 1c967110198..9a952e1a54b 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -229,7 +229,7 @@ static bool gpencil_interpolate_check_todo(bContext *C, bGPdata *gpd) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps_from) == false) { continue; } @@ -315,7 +315,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, tgpil->gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, tgpil->gpl, gps_from) == false) { valid = false; } @@ -1038,7 +1038,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps_from) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 14313a50118..7571f7cded8 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -426,7 +426,7 @@ static void gpencil_reproject_toplane(tGPsdata *p, bGPDstroke *gps) /* get drawing origin */ gpencil_get_3d_reference(p, origin); - ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, gps, origin, p->lock_axis - 1); + ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, p->gpl, gps, origin, p->lock_axis - 1); } /* convert screen-coordinates to buffer-coordinates */ @@ -887,11 +887,13 @@ static short gpencil_stroke_addpoint(tGPsdata *p, gpencil_get_3d_reference(p, origin); /* reproject current */ ED_gpencil_tpoint_to_point(p->region, origin, pt, &spt); - ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt); + ED_gpencil_project_point_to_plane( + p->scene, obact, p->gpl, rv3d, origin, p->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(p->region, origin, ptb, &spt2); - ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2); + ED_gpencil_project_point_to_plane( + p->scene, obact, p->gpl, rv3d, origin, p->lock_axis - 1, &spt2); p->totpixlen += len_v3v3(&spt.x, &spt2.x); pt->uv_fac = p->totpixlen; } @@ -1349,7 +1351,7 @@ static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, float diff_mat[4][4]; /* calculate difference matrix if parent object */ - BKE_gpencil_parent_matrix_get(p->depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(p->depsgraph, obact, gpl, diff_mat); if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) { const float depth_mval = view3d_point_depth(rv3d, mval_3d); @@ -1731,12 +1733,12 @@ static void gpencil_stroke_doeraser(tGPsdata *p) continue; } /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat); + BKE_gpencil_layer_transform_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat); /* loop over strokes, checking segments for intersections */ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(p->ob, gpl, gps) == false) { continue; } @@ -2103,6 +2105,11 @@ static void gpencil_paint_initstroke(tGPsdata *p, copy_v3_v3(p->gpl->color, p->custom_color); } } + + /* Recalculate layer transform matrix to avoid problems if props are animated. */ + loc_eul_size_to_mat4(p->gpl->layer_mat, p->gpl->location, p->gpl->rotation, p->gpl->scale); + invert_m4_m4(p->gpl->layer_invmat, p->gpl->layer_mat); + if ((paintmode != GP_PAINTMODE_ERASER) && (p->gpl->flag & GP_LAYER_LOCKED)) { p->status = GP_STATUS_ERROR; if (G.debug & G_DEBUG) { diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index b457cd819d2..99242e48cc1 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -317,6 +317,10 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) } tgpi->gpl = gpl; + /* Recalculate layer transform matrix to avoid problems if props are animated. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* create a new temporary frame */ tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe"); tgpi->gpf->framenum = tgpi->cframe = cfra; @@ -1004,12 +1008,12 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* reproject current */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tpt, &spt); ED_gpencil_project_point_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); + tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tptb, &spt2); ED_gpencil_project_point_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); + tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x); tpt->uv_fac = tgpi->totpixlen; } @@ -1067,7 +1071,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) float origin[3]; ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin); ED_gpencil_project_stroke_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1); + tgpi->scene, tgpi->ob, tgpi->rv3d, tgpi->gpl, gps, origin, ts->gp_sculpt.lock_axis - 1); } /* if parented change position relative to parent object */ diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index bb9dd8cac5d..0d3ab9011d6 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1441,11 +1441,6 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, bool changed = false; float rot_eval = 0.0f; - /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { - return false; - } - if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; @@ -1577,6 +1572,13 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C, Object *ob = gso->object; bGPdata *gpd = ob->data; char tool = gso->brush->gpencil_sculpt_tool; + GP_SpaceConversion *gsc = &gso->gsc; + Brush *brush = gso->brush; + const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure : + gso->brush->size; + /* Calc bound box matrix. */ + float bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(gso->depsgraph, gso->object, gpl, bound_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* skip strokes that are invalid for current view */ @@ -1584,7 +1586,12 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { + continue; + } + + /* Check if the stroke collide with brush. */ + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { continue; } @@ -1742,7 +1749,8 @@ static bool gpencil_sculpt_brush_apply_standard(bContext *C, tGP_BrushEditData * /* calculate difference matrix */ float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 281ab8c5adc..a00d21bf88a 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -2473,7 +2473,7 @@ static void gpencil_selected_hue_table(bContext *C, if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } if ((gps->flag & GP_STROKE_SELECT) == 0) { diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c index c2504ce329e..d9bc77c8715 100644 --- a/source/blender/editors/gpencil/gpencil_undo.c +++ b/source/blender/editors/gpencil/gpencil_undo.c @@ -61,28 +61,22 @@ int ED_gpencil_session_active(void) return (BLI_listbase_is_empty(&undo_nodes) == false); } -int ED_undo_gpencil_step(bContext *C, int step, const char *name) +int ED_undo_gpencil_step(bContext *C, const int step) { bGPdata **gpd_ptr = NULL, *new_gpd = NULL; gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - if (step == 1) { /* undo */ - // printf("\t\tGP - undo step\n"); + if (step == -1) { /* undo */ if (cur_node->prev) { - if (!name || STREQ(cur_node->name, name)) { - cur_node = cur_node->prev; - new_gpd = cur_node->gpd; - } + cur_node = cur_node->prev; + new_gpd = cur_node->gpd; } } - else if (step == -1) { - // printf("\t\tGP - redo step\n"); + else if (step == 1) { if (cur_node->next) { - if (!name || STREQ(cur_node->name, name)) { - cur_node = cur_node->next; - new_gpd = cur_node->gpd; - } + cur_node = cur_node->next; + new_gpd = cur_node->gpd; } } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 7c796f7b7a1..42e3055ef65 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -579,7 +579,7 @@ bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps) } /* Check whether given stroke can be edited for the current color */ -bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps) +bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps) { /* check if the color is editable */ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); @@ -674,7 +674,7 @@ void gpencil_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, b float inverse_diff_mat[4][4]; float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); for (i = 0; i < gps->totpoints; i++) { @@ -697,10 +697,11 @@ void gpencil_apply_parent_point(Depsgraph *depsgraph, float inverse_diff_mat[4][4]; float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); + copy_v3_v3(&pt->x, fpt); } @@ -997,6 +998,12 @@ void ED_gpencil_drawing_reference_get(const Scene *scene, else { /* use object location */ copy_v3_v3(r_vec, ob->obmat[3]); + /* Apply layer offset. */ + bGPdata *gpd = ob->data; + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl != NULL) { + add_v3_v3(r_vec, gpl->layer_mat[3]); + } } } } @@ -1021,7 +1028,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * /* init space conversion stuff */ gpencil_point_conversion_init(C, &gsc); - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); /* Adjust each point */ @@ -1046,6 +1053,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * void ED_gpencil_project_stroke_to_plane(const Scene *scene, const Object *ob, const RegionView3D *rv3d, + bGPDlayer *gpl, bGPDstroke *gps, const float origin[3], const int axis) @@ -1058,6 +1066,10 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, float ray[3]; float rpoint[3]; + /* Recalculate layer transform matrix. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* normal vector for a plane locked to axis */ zero_v3(plane_normal); if (axis < 0) { @@ -1074,24 +1086,27 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, copy_m4_m4(mat, ob->obmat); /* move origin to cursor */ + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + if (gpl != NULL) { + add_v3_v3(mat[3], gpl->location); + } + } if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { copy_v3_v3(mat[3], cursor->location); } mul_mat3_m4_v3(mat, plane_normal); } + + if ((gpl != NULL) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) { + mul_mat3_m4_v3(gpl->layer_mat, plane_normal); + } } else { const float scale[3] = {1.0f, 1.0f, 1.0f}; plane_normal[2] = 1.0f; float mat[4][4]; loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale); - - /* move origin to object */ - if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { - copy_v3_v3(mat[3], ob->obmat[3]); - } - mul_mat3_m4_v3(mat, plane_normal); } @@ -1127,8 +1142,12 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, ARegion *region = gsc->region; RegionView3D *rv3d = region->regiondata; + /* Recalculate layer transform matrix. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + float diff_mat[4][4], inverse_diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, gsc->ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, gsc->ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); float origin[3]; @@ -1194,7 +1213,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, } } - ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, rv3d, origin, axis, &pt2); + ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, gpl, rv3d, origin, axis, &pt2); copy_v3_v3(&pt->x, &pt2.x); @@ -1250,6 +1269,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, */ void ED_gpencil_project_point_to_plane(const Scene *scene, const Object *ob, + bGPDlayer *gpl, const RegionView3D *rv3d, const float origin[3], const int axis, @@ -1277,6 +1297,11 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, if (ob && (ob->type == OB_GPENCIL)) { float mat[4][4]; copy_m4_m4(mat, ob->obmat); + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + if (gpl != NULL) { + add_v3_v3(mat[3], gpl->location); + } + } /* move origin to cursor */ if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { @@ -1284,6 +1309,10 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, } mul_mat3_m4_v3(mat, plane_normal); + /* Apply layer rotation (local transform). */ + if ((gpl != NULL) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) { + mul_mat3_m4_v3(gpl->layer_mat, plane_normal); + } } } else { @@ -1449,7 +1478,7 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata /* only redo if any change */ if (!equals_m4m4(gpl->inverse, cur_mat)) { /* first apply current transformation to all strokes */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* undo local object */ sub_v3_v3(diff_mat[3], gpl_loc); @@ -2144,7 +2173,7 @@ void ED_gpencil_update_color_uv(Main *bmain, Material *mat) LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* check if it is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } gps_ma = BKE_gpencil_material(ob, gps->mat_nr + 1); @@ -3126,7 +3155,7 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, /* calculate difference matrix object */ float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); /* Calculate the extremes of the stroke in 2D. */ bGPDspoint pt_parent; @@ -3144,15 +3173,13 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, float dist_min = FLT_MAX; LISTBASE_FOREACH (bGPDstroke *, gps_target, &gpf->strokes) { /* Check if the color is editable. */ - if ((gps_target == gps) || (ED_gpencil_stroke_color_use(ob, gpl, gps) == false)) { + if ((gps_target == gps) || (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false)) { continue; } /* Check if one of the ends is inside target stroke bounding box. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, pt2d_start, radius, diff_mat)) { - continue; - } - if (!ED_gpencil_stroke_check_collision(gsc, gps, pt2d_end, radius, diff_mat)) { + if ((!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_start, radius, diff_mat)) && + (!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_end, radius, diff_mat))) { continue; } /* Check the distance of the ends with the ends of target stroke to avoid middle contact. diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index b212872b607..49f45acdb11 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -674,7 +674,7 @@ static bool gpencil_extract_palette_from_vertex(bContext *C, if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); @@ -859,7 +859,7 @@ static int gpencil_material_to_vertex_exec(bContext *C, wmOperator *op) if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index 62ddfaab012..7fb57534638 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -825,7 +825,8 @@ static void gpencil_save_selected_point(tGP_BrushVertexpaintData *gso, static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, bGPDstroke *gps, const char tool, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -846,7 +847,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, bool saved = false; /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { return false; } @@ -991,7 +992,8 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, tGP_BrushVertexpaintData *gso, bGPDlayer *gpl, bGPDframe *gpf, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { Object *ob = CTX_data_active_object(C); const char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool : @@ -1013,12 +1015,12 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Check points below the brush. */ - bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat); + bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat, bound_mat); /* If stroke was hit and has an editcurve the curve needs an update. */ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; @@ -1123,9 +1125,11 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert continue; } - /* calculate difference matrix */ - float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + /* Calculate transform matrix. */ + float diff_mat[4][4], bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + copy_m4_m4(bound_mat, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { @@ -1152,7 +1156,7 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert } /* affect strokes in this frame */ - changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat, bound_mat); } } } @@ -1160,7 +1164,8 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert /* Apply to active frame's strokes */ if (gpl->actframe != NULL) { gso->mf_falloff = 1.0f; - changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame( + C, gso, gpl, gpl->actframe, diff_mat, bound_mat); } } } diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 7fa71fcce3c..a3e5ece5862 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -383,7 +383,8 @@ static void gpencil_save_selected_point(tGP_BrushWeightpaintData *gso, /* Select points in this stroke and add to an array to be used later. */ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, bGPDstroke *gps, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -402,7 +403,7 @@ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, bool include_last = false; /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { return; } @@ -505,7 +506,8 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, tGP_BrushWeightpaintData *gso, bGPDlayer *gpl, bGPDframe *gpf, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { Object *ob = CTX_data_active_object(C); char tool = gso->brush->gpencil_weight_tool; @@ -526,12 +528,12 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Check points below the brush. */ - gpencil_weightpaint_select_stroke(gso, gps, diff_mat); + gpencil_weightpaint_select_stroke(gso, gps, diff_mat, bound_mat); } /*--------------------------------------------------------------------- @@ -578,9 +580,11 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig continue; } - /* calculate difference matrix */ - float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + /* Calculate transform matrix. */ + float diff_mat[4][4], bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + copy_m4_m4(bound_mat, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { @@ -608,7 +612,7 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig } /* affect strokes in this frame */ - changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat, bound_mat); } } } @@ -616,7 +620,8 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig if (gpl->actframe != NULL) { /* Apply to active frame's strokes */ gso->mf_falloff = 1.0f; - changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame( + C, gso, gpl, gpl->actframe, diff_mat, bound_mat); } } } diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1b7caf27ecf..acaa6495ba9 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -147,9 +147,9 @@ bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfr bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *area, const struct bGPDstroke *gps); bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps); -bool ED_gpencil_stroke_color_use(struct Object *ob, - const struct bGPDlayer *gpl, - const struct bGPDstroke *gps); +bool ED_gpencil_stroke_material_editable(struct Object *ob, + const struct bGPDlayer *gpl, + const struct bGPDstroke *gps); /* ----------- Grease Pencil Operators ----------------- */ @@ -213,7 +213,7 @@ bool ED_gpencil_anim_copybuf_paste(struct bAnimContext *ac, const short copy_mod /* ------------ Grease-Pencil Undo System ------------------ */ int ED_gpencil_session_active(void); -int ED_undo_gpencil_step(struct bContext *C, int step, const char *name); +int ED_undo_gpencil_step(struct bContext *C, const int step); /* ------------ Grease-Pencil Armature ------------------ */ bool ED_gpencil_add_armature(const struct bContext *C, @@ -263,11 +263,13 @@ bool ED_object_gpencil_exit(struct Main *bmain, struct Object *ob); void ED_gpencil_project_stroke_to_plane(const struct Scene *scene, const struct Object *ob, const struct RegionView3D *rv3d, + struct bGPDlayer *gpl, struct bGPDstroke *gps, const float origin[3], const int axis); void ED_gpencil_project_point_to_plane(const struct Scene *scene, const struct Object *ob, + struct bGPDlayer *gpl, const struct RegionView3D *rv3d, const float origin[3], const int axis, diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 417cae800ea..78f354a300d 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -51,6 +51,10 @@ typedef enum { #define NODE_GRID_STEPS 5 /* space_node.c */ + +void ED_node_cursor_location_get(const struct SpaceNode *snode, float value[2]); +void ED_node_cursor_location_set(struct SpaceNode *snode, const float value[2]); + int ED_node_tree_path_length(struct SpaceNode *snode); void ED_node_tree_path_get(struct SpaceNode *snode, char *value); void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 20417634020..deb6b7502c7 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -57,15 +57,14 @@ struct wmMsgSubscribeKey; struct wmMsgSubscribeValue; struct wmNotifier; struct wmOperatorType; +struct wmRegionListenerParams; +struct wmRegionMessageSubscribeParams; +struct wmSpaceTypeListenerParams; struct wmWindow; struct wmWindowManager; /* regions */ -void ED_region_do_listen(struct wmWindow *win, - struct ScrArea *area, - struct ARegion *region, - struct wmNotifier *note, - const Scene *scene); +void ED_region_do_listen(struct wmRegionListenerParams *params); void ED_region_do_layout(struct bContext *C, struct ARegion *region); void ED_region_do_draw(struct bContext *C, struct ARegion *region); void ED_region_exit(struct bContext *C, struct ARegion *region); @@ -144,29 +143,11 @@ void ED_area_do_msg_notify_tag_refresh(struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val); -void ED_area_do_mgs_subscribe_for_tool_header(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); -void ED_area_do_mgs_subscribe_for_tool_ui(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_area_do_mgs_subscribe_for_tool_header(const struct wmRegionMessageSubscribeParams *params); +void ED_area_do_mgs_subscribe_for_tool_ui(const struct wmRegionMessageSubscribeParams *params); /* message bus */ -void ED_region_message_subscribe(struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_region_message_subscribe(struct wmRegionMessageSubscribeParams *params); /* spaces */ void ED_spacetypes_keymap(struct wmKeyConfig *keyconf); @@ -178,7 +159,7 @@ void ED_area_exit(struct bContext *C, struct ScrArea *area); int ED_screen_area_active(const struct bContext *C); void ED_screen_global_areas_refresh(struct wmWindow *win); void ED_screen_global_areas_sync(struct wmWindow *win); -void ED_area_do_listen(struct wmWindow *win, ScrArea *area, struct wmNotifier *note, Scene *scene); +void ED_area_do_listen(struct wmSpaceTypeListenerParams *params); void ED_area_tag_redraw(ScrArea *area); void ED_area_tag_redraw_no_rebuild(ScrArea *area); void ED_area_tag_redraw_regiontype(ScrArea *area, int type); @@ -427,13 +408,8 @@ void ED_region_cache_draw_cached_segments(struct ARegion *region, const int efra); /* area_utils.c */ -void ED_region_generic_tools_region_message_subscribe(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_region_generic_tools_region_message_subscribe( + const struct wmRegionMessageSubscribeParams *params); int ED_region_generic_tools_region_snap_size(const struct ARegion *region, int size, int axis); /* area_query.c */ diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 8df29e5b520..64f881052a1 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -231,7 +231,7 @@ struct View2D *UI_view2d_fromcontext(const struct bContext *C); struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C); void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_y); -void UI_view2d_scale_get(struct View2D *v2d, float *r_x, float *r_y); +void UI_view2d_scale_get(const struct View2D *v2d, float *r_x, float *r_y); float UI_view2d_scale_get_x(const struct View2D *v2d); float UI_view2d_scale_get_y(const struct View2D *v2d); void UI_view2d_scale_get_inverse(const struct View2D *v2d, float *r_x, float *r_y); diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 93e3dbb2cc8..62b8ce9d3eb 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -413,12 +413,11 @@ static void ui_block_region_draw(const bContext *C, ARegion *region) /** * Use to refresh centered popups on screen resizing (for splash). */ -static void ui_block_region_popup_window_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void ui_block_region_popup_window_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + switch (wmn->category) { case NC_WINDOW: { switch (wmn->action) { diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f115618c13b..59aee0fde29 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -1895,7 +1895,7 @@ void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y) * * \param r_x, r_y: scale on each axis */ -void UI_view2d_scale_get(View2D *v2d, float *r_x, float *r_y) +void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y) { if (r_x) { *r_x = UI_view2d_scale_get_x(v2d); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index c6d6b8b16b9..4e8936357eb 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -3364,6 +3364,9 @@ static int object_add_named_exec(bContext *C, wmOperator *op) ED_view3d_cursor3d_position(C, mval, false, basen->object->loc); } + /* object_add_duplicate_internal() doesn't deselect other objects, unlike object_add_common() or + * BKE_view_layer_base_deselect_all(). */ + ED_object_base_deselect_all(view_layer, NULL, BA_DESELECT); ED_object_base_select(basen, BA_SELECT); ED_object_base_activate(C, basen); diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 0528d64dca9..13c0740bce6 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1394,7 +1394,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) * (all layers are considered without evaluating lock attributes) */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* undo matrix */ invert_m4_m4(inverse_diff_mat, diff_mat); LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 581169d823e..a11dab0291a 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -141,13 +141,15 @@ void ED_region_pixelspace(ARegion *region) } /* only exported for WM */ -void ED_region_do_listen( - wmWindow *win, ScrArea *area, ARegion *region, wmNotifier *note, const Scene *scene) +void ED_region_do_listen(wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *notifier = params->notifier; + /* generic notes first */ - switch (note->category) { + switch (notifier->category) { case NC_WM: - if (note->data == ND_FILEREAD) { + if (notifier->data == ND_FILEREAD) { ED_region_tag_redraw(region); } break; @@ -157,16 +159,16 @@ void ED_region_do_listen( } if (region->type && region->type->listener) { - region->type->listener(win, area, region, note, scene); + region->type->listener(params); } } /* only exported for WM */ -void ED_area_do_listen(wmWindow *win, ScrArea *area, wmNotifier *note, Scene *scene) +void ED_area_do_listen(wmSpaceTypeListenerParams *params) { /* no generic notes? */ - if (area->type && area->type->listener) { - area->type->listener(win, area, note, scene); + if (params->area->type && params->area->type->listener) { + params->area->type->listener(params); } } @@ -418,16 +420,13 @@ void ED_area_do_msg_notify_tag_refresh( ED_area_tag_refresh(area); } -void ED_area_do_mgs_subscribe_for_tool_header( - /* Follow ARegionType.message_subscribe */ - const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +/* Follow ARegionType.message_subscribe */ +void ED_area_do_mgs_subscribe_for_tool_header(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + BLI_assert(region->regiontype == RGN_TYPE_TOOL_HEADER); wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, @@ -438,16 +437,12 @@ void ED_area_do_mgs_subscribe_for_tool_header( mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw); } -void ED_area_do_mgs_subscribe_for_tool_ui( - /* Follow ARegionType.message_subscribe */ - const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_area_do_mgs_subscribe_for_tool_ui(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + BLI_assert(region->regiontype == RGN_TYPE_UI); const char *panel_category_tool = "Tool"; const char *category = UI_panel_category_active_get(region, false); @@ -634,7 +629,16 @@ void ED_region_do_draw(bContext *C, ARegion *region) WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_region_tag_redraw, __func__); } - ED_region_message_subscribe(C, workspace, scene, screen, area, region, mbus); + wmRegionMessageSubscribeParams message_subscribe_params = { + .context = C, + .message_bus = mbus, + .workspace = workspace, + .scene = scene, + .screen = screen, + .area = area, + .region = region, + }; + ED_region_message_subscribe(&message_subscribe_params); } } @@ -4027,14 +4031,12 @@ void ED_region_cache_draw_cached_segments( /** * Generate subscriptions for this region. */ -void ED_region_message_subscribe(bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_region_message_subscribe(wmRegionMessageSubscribeParams *params) { + ARegion *region = params->region; + const bContext *C = params->context; + struct wmMsgBus *mbus = params->message_bus; + if (region->gizmo_map != NULL) { WM_gizmomap_message_subscribe(C, region->gizmo_map, region, mbus); } @@ -4044,7 +4046,7 @@ void ED_region_message_subscribe(bContext *C, } if (region->type->message_subscribe != NULL) { - region->type->message_subscribe(C, workspace, scene, screen, area, region, mbus); + region->type->message_subscribe(params); } } diff --git a/source/blender/editors/screen/area_utils.c b/source/blender/editors/screen/area_utils.c index 075759f1120..b784a4b0056 100644 --- a/source/blender/editors/screen/area_utils.c +++ b/source/blender/editors/screen/area_utils.c @@ -22,6 +22,8 @@ #include "DNA_userdef_types.h" +#include "BKE_screen.h" + #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -42,14 +44,11 @@ /** * Callback for #ARegionType.message_subscribe */ -void ED_region_generic_tools_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_region_generic_tools_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 1dfe606be78..627a67358f2 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -866,7 +866,7 @@ static eContextResult screen_ctx_editable_gpencil_strokes(const bContext *C, LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if (ED_gpencil_stroke_can_use_direct(area, gps)) { /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index ff0201f9702..691287a543f 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -305,12 +305,11 @@ static void action_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void action_channel_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_channel_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -356,14 +355,13 @@ static void action_channel_region_listener(wmWindow *UNUSED(win), } } -static void saction_channel_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void saction_channel_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, area->spacedata.first, &ptr); @@ -401,12 +399,11 @@ static void saction_channel_region_message_subscribe(const struct bContext *UNUS } } -static void action_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -460,14 +457,14 @@ static void action_main_region_listener(wmWindow *UNUSED(win), } } -static void saction_main_region_message_subscribe(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void saction_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, area->spacedata.first, &ptr); @@ -502,15 +499,14 @@ static void saction_main_region_message_subscribe(const struct bContext *C, } /* Now run the general "channels region" one - since channels and main should be in sync */ - saction_channel_region_message_subscribe(C, workspace, scene, screen, area, region, mbus); + saction_channel_region_message_subscribe(params); } /* editor level listener */ -static void action_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void action_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ @@ -660,12 +656,11 @@ static void action_listener(wmWindow *UNUSED(win), } } -static void action_header_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_header_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ @@ -737,12 +732,11 @@ static void action_buttons_area_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void action_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index e50ca2ec92b..07bc1d42c3f 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -514,12 +514,11 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region) sbuts->mainbo = sbuts->mainb; } -static void buttons_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void buttons_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -567,15 +566,13 @@ static void buttons_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void buttons_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *area, - ARegion *region, - struct wmMsgBus *mbus) +static void buttons_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceProperties *sbuts = area->spacedata.first; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -621,14 +618,12 @@ static void buttons_navigation_bar_region_draw(const bContext *C, ARegion *regio ED_region_panels_draw(C, region); } -static void buttons_navigation_bar_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void buttons_navigation_bar_region_message_subscribe( + const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -657,11 +652,10 @@ static void buttons_area_redraw(ScrArea *area, short buttons) * \{ */ /* reused! */ -static void buttons_area_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void buttons_area_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceProperties *sbuts = area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 4848ec72f79..81df8cc8ecd 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -191,6 +191,7 @@ void CLIP_OT_clear_solution(struct wmOperatorType *ot); void CLIP_OT_clear_track_path(struct wmOperatorType *ot); void CLIP_OT_join_tracks(struct wmOperatorType *ot); +void CLIP_OT_average_tracks(struct wmOperatorType *ot); void CLIP_OT_disable_markers(struct wmOperatorType *ot); void CLIP_OT_hide_tracks(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 3bdf016b64c..d4391fc3ff4 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -229,7 +229,7 @@ static void clip_scopes_check_gpencil_change(ScrArea *area) } } -static void clip_area_sync_frame_from_scene(ScrArea *area, Scene *scene) +static void clip_area_sync_frame_from_scene(ScrArea *area, const Scene *scene) { SpaceClip *space_clip = (SpaceClip *)area->spacedata.first; BKE_movieclip_user_set_frame(&space_clip->user, scene->r.cfra); @@ -334,8 +334,12 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) return (SpaceLink *)scn; } -static void clip_listener(wmWindow *UNUSED(win), ScrArea *area, wmNotifier *wmn, Scene *scene) +static void clip_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + const Scene *scene = params->scene; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -514,6 +518,7 @@ static void clip_operatortypes(void) /* clean-up */ WM_operatortype_append(CLIP_OT_clear_track_path); WM_operatortype_append(CLIP_OT_join_tracks); + WM_operatortype_append(CLIP_OT_average_tracks); WM_operatortype_append(CLIP_OT_track_copy_color); WM_operatortype_append(CLIP_OT_clean_tracks); @@ -988,7 +993,10 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) } /* callback */ + GPU_matrix_push_projection(); + wmOrtho2(region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, region->v2d.cur.ymax); ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); + GPU_matrix_pop_projection(); /* reset view matrix */ UI_view2d_view_restore(C); @@ -1001,12 +1009,11 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D); } -static void clip_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: @@ -1137,11 +1144,7 @@ static void clip_preview_region_draw(const bContext *C, ARegion *region) } } -static void clip_preview_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void clip_preview_region_listener(const wmRegionListenerParams *UNUSED(params)) { } @@ -1182,11 +1185,7 @@ static void clip_channels_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); } -static void clip_channels_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void clip_channels_region_listener(const wmRegionListenerParams *UNUSED(params)) { } @@ -1203,12 +1202,11 @@ static void clip_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void clip_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -1246,12 +1244,11 @@ static void clip_tools_region_draw(const bContext *C, ARegion *region) /****************** tool properties region ******************/ -static void clip_props_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_props_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -1299,12 +1296,11 @@ static void clip_properties_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void clip_properties_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_properties_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 49313005c43..10574063ebd 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1490,6 +1490,97 @@ void CLIP_OT_join_tracks(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/********************** Average tracks operator *********************/ + +static int average_tracks_exec(bContext *C, wmOperator *op) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + MovieTracking *tracking = &clip->tracking; + + /* Collect source tracks. */ + int num_source_tracks; + MovieTrackingTrack **source_tracks = BKE_tracking_selected_tracks_in_active_object( + tracking, &num_source_tracks); + if (num_source_tracks == 0) { + return OPERATOR_CANCELLED; + } + + /* Create new empty track, which will be the averaged result. + * Makes it simple to average all selection to it. */ + ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking); + MovieTrackingTrack *result_track = BKE_tracking_track_add_empty(tracking, tracks_list); + + /* Perform averaging. */ + BKE_tracking_tracks_average(result_track, source_tracks, num_source_tracks); + + const bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); + if (!keep_original) { + for (int i = 0; i < num_source_tracks; i++) { + clip_delete_track(C, clip, source_tracks[i]); + } + } + + /* Update selection, making the result track active and selected. */ + /* TODO(sergey): Should become some sort of utility function available for all operators. */ + + BKE_tracking_track_select(tracks_list, result_track, TRACK_AREA_ALL, 0); + ListBase *plane_tracks_list = BKE_tracking_get_active_plane_tracks(tracking); + BKE_tracking_plane_tracks_deselect_all(plane_tracks_list); + + clip->tracking.act_track = result_track; + clip->tracking.act_plane_track = NULL; + + /* Inform the dependency graph and interface about changes. */ + DEG_id_tag_update(&clip->id, 0); + WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); + + /* Free memory. */ + MEM_freeN(source_tracks); + + return OPERATOR_FINISHED; +} + +static int average_tracks_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + PropertyRNA *prop_keep_original = RNA_struct_find_property(op->ptr, "keep_original"); + if (!RNA_property_is_set(op->ptr, prop_keep_original)) { + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + MovieTracking *tracking = &clip->tracking; + + const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking); + + if (num_selected_tracks == 1) { + RNA_property_boolean_set(op->ptr, prop_keep_original, false); + } + } + + return average_tracks_exec(C, op); +} + +void CLIP_OT_average_tracks(wmOperatorType *ot) +{ + /* Identifiers. */ + ot->name = "Average Tracks"; + ot->description = "Average selected tracks into active"; + ot->idname = "CLIP_OT_average_tracks"; + + /* API callbacks. */ + ot->exec = average_tracks_exec; + ot->invoke = average_tracks_invoke; + ot->poll = ED_space_clip_tracking_poll; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties. */ + PropertyRNA *prop; + + prop = RNA_def_boolean(ot->srna, "keep_original", 1, "Keep Original", "Keep original tracks"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + /********************** lock tracks operator *********************/ enum { diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 9b8e9e0e871..6265cbdd920 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -273,13 +273,11 @@ static void console_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void console_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void console_main_region_listener(const wmRegionListenerParams *params) { - // SpaceInfo *sinfo = area->spacedata.first; + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index aedc6228355..193b141d528 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -104,6 +104,7 @@ static ARegion *file_tool_props_region_ensure(ScrArea *area, ARegion *region_pre BLI_insertlinkafter(&area->regionbase, region_prev, region); region->regiontype = RGN_TYPE_TOOL_PROPS; region->alignment = RGN_ALIGN_RIGHT; + region->flag = RGN_FLAG_HIDDEN; return region; } @@ -246,13 +247,13 @@ static void file_ensure_valid_region_state(bContext *C, BLI_assert(region_tools); if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) { - ARegion *region_execute = file_execute_region_ensure(area, region_tools); - ARegion *region_props = file_tool_props_region_ensure(area, region_execute); - - /* Hide specific regions by default. */ - region_props->flag |= RGN_FLAG_HIDDEN; - region_execute->flag |= RGN_FLAG_HIDDEN; + file_tool_props_region_ensure(area, region_tools); + ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE); + if (region_execute) { + ED_region_remove(C, area, region_execute); + needs_init = true; + } ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI); if (region_ui) { ED_region_remove(C, area, region_ui); @@ -281,11 +282,12 @@ static void file_ensure_valid_region_state(bContext *C, ARegion *region_ui = file_ui_region_ensure(area, region_tools); UNUSED_VARS(region_ui); + if (region_execute) { + ED_region_remove(C, area, region_execute); + needs_init = true; + } if (region_props) { - BLI_assert(region_execute); - ED_region_remove(C, area, region_props); - ED_region_remove(C, area, region_execute); needs_init = true; } } @@ -390,11 +392,10 @@ static void file_refresh(const bContext *C, ScrArea *area) ED_area_tag_redraw(area); } -static void file_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void file_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceFile *sfile = (SpaceFile *)area->spacedata.first; /* context changes */ @@ -445,12 +446,11 @@ static void file_main_region_init(wmWindowManager *wm, ARegion *region) WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); } -static void file_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void file_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SPACE: @@ -466,16 +466,15 @@ static void file_main_region_listener(wmWindow *UNUSED(win), } } -static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void file_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceFile *sfile = area->spacedata.first; - FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); + + FileSelectParams *file_params = ED_fileselect_ensure_active_params(sfile); /* This is a bit odd that a region owns the subscriber for an area, * keep for now since all subscribers for WM are regions. * May be worth re-visiting later. */ @@ -497,7 +496,7 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), /* FileSelectParams */ { PointerRNA ptr; - RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &ptr); + RNA_pointer_create(&screen->id, &RNA_FileSelectParams, file_params, &ptr); /* All properties for this space type. */ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__); @@ -647,18 +646,8 @@ static void file_tools_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_tools_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(params)) { -#if 0 - /* context changes */ - switch (wmn->category) { - /* pass */ - } -#endif } /* add handlers, stuff you only do once or on area/region changes */ @@ -715,12 +704,11 @@ static void file_execution_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_ui_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void file_ui_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SPACE: diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 791039498e8..9f01773eadf 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -403,12 +403,11 @@ static void graph_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void graph_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void graph_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -470,14 +469,14 @@ static void graph_region_listener(wmWindow *UNUSED(win), } } -static void graph_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void graph_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, area->spacedata.first, &ptr); @@ -546,11 +545,10 @@ static void graph_region_message_subscribe(const struct bContext *UNUSED(C), } /* editor level listener */ -static void graph_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void graph_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index d504bfbe276..5e1a6882d56 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -320,8 +320,11 @@ static void image_refresh(const bContext *C, ScrArea *area) } } -static void image_listener(wmWindow *win, ScrArea *area, wmNotifier *wmn, Scene *UNUSED(scene)) +static void image_listener(const wmSpaceTypeListenerParams *params) { + wmWindow *win = params->window; + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceImage *sima = (SpaceImage *)area->spacedata.first; /* context changes */ @@ -723,12 +726,12 @@ static void image_main_region_draw(const bContext *C, ARegion *region) draw_image_cache(C, region); } -static void image_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_main_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GEOM: @@ -838,12 +841,11 @@ static void image_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels_draw(C, region); } -static void image_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_TEXTURE: @@ -901,12 +903,11 @@ static void image_tools_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void image_tools_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_tools_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: @@ -958,12 +959,11 @@ static void image_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void image_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index 8d3f21aefeb..5e44db4c791 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -204,13 +204,10 @@ static void info_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void info_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void info_main_region_listener(const wmRegionListenerParams *params) { - // SpaceInfo *sinfo = area->spacedata.first; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -223,12 +220,11 @@ static void info_main_region_listener(wmWindow *UNUSED(win), } } -static void info_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void info_header_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -259,14 +255,11 @@ static void info_header_listener(wmWindow *UNUSED(win), } } -static void info_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void info_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index c6fe1b8539e..efe851c64ed 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -324,12 +324,11 @@ static void nla_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void nla_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -364,12 +363,11 @@ static void nla_region_listener(wmWindow *UNUSED(win), } } -static void nla_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -423,14 +421,14 @@ static void nla_main_region_listener(wmWindow *UNUSED(win), } } -static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void nla_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr); @@ -465,12 +463,11 @@ static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C), } } -static void nla_channel_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_channel_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -508,14 +505,13 @@ static void nla_channel_region_listener(wmWindow *UNUSED(win), } } -static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void nla_channel_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr); @@ -543,11 +539,11 @@ static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C } /* editor level listener */ -static void nla_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void nla_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index df29950bc59..7b09f681dfa 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -455,7 +455,7 @@ static void node_draw_frame(const bContext *C, } /* label */ - node_draw_frame_label(ntree, node, snode->aspect); + node_draw_frame_label(ntree, node, snode->runtime->aspect); UI_block_end(C, node->block); UI_block_draw(C, node->block); @@ -3825,18 +3825,18 @@ void draw_nodespace_back_pix(const bContext *C, } /* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */ -static bool node_link_bezier_handles(View2D *v2d, - SpaceNode *snode, - bNodeLink *link, +static bool node_link_bezier_handles(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, float vec[4][2]) { float cursor[2] = {0.0f, 0.0f}; /* this function can be called with snode null (via cut_links_intersect) */ - /* XXX map snode->cursor back to view space */ + /* XXX map snode->runtime->cursor back to view space */ if (snode) { - cursor[0] = snode->cursor[0] * UI_DPI_FAC; - cursor[1] = snode->cursor[1] * UI_DPI_FAC; + cursor[0] = snode->runtime->cursor[0] * UI_DPI_FAC; + cursor[1] = snode->runtime->cursor[1] * UI_DPI_FAC; } /* in v0 and v3 we put begin/end points */ @@ -3920,8 +3920,11 @@ static bool node_link_bezier_handles(View2D *v2d, } /* if v2d not NULL, it clips and returns 0 if not visible */ -bool node_link_bezier_points( - View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol) +bool node_link_bezier_points(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, + float coord_array[][2], + const int resol) { float vec[4][2]; @@ -4084,7 +4087,7 @@ static char nodelink_get_color_id(int th_col) return 0; } -static void nodelink_batch_draw(SpaceNode *snode) +static void nodelink_batch_draw(const SpaceNode *snode) { if (g_batch_link.count == 0) { return; @@ -4104,7 +4107,7 @@ static void nodelink_batch_draw(SpaceNode *snode) GPU_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST); GPU_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, colors); - GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH); + GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->runtime->aspect * LINK_WIDTH); GPU_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE); GPU_batch_draw(g_batch_link.batch); @@ -4124,7 +4127,7 @@ void nodelink_batch_end(SpaceNode *snode) g_batch_link.enabled = false; } -static void nodelink_batch_add_link(SpaceNode *snode, +static void nodelink_batch_add_link(const SpaceNode *snode, const float p0[2], const float p1[2], const float p2[2], @@ -4156,8 +4159,12 @@ static void nodelink_batch_add_link(SpaceNode *snode, } /* don't do shadows if th_col3 is -1. */ -void node_draw_link_bezier( - View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int th_col2, int th_col3) +void node_draw_link_bezier(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, + int th_col1, + int th_col2, + int th_col3) { float vec[4][2]; @@ -4187,7 +4194,7 @@ void node_draw_link_bezier( GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK); GPU_batch_uniform_2fv_array(batch, "bezierPts", 4, vec); GPU_batch_uniform_4fv_array(batch, "colors", 3, colors); - GPU_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH); + GPU_batch_uniform_1f(batch, "expandSize", snode->runtime->aspect * LINK_WIDTH); GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE); GPU_batch_uniform_1i(batch, "doArrow", drawarrow); GPU_batch_draw(batch); diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 508c0a47e21..a3e47404c80 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -341,7 +341,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]); + node = node_add_node(C, NULL, type, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!node) { BKE_report(op->reports, RPT_WARNING, "Could not add an image node"); @@ -370,11 +370,14 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even SpaceNode *snode = CTX_wm_space_node(C); /* convert mouse coordinates to v2d space */ - UI_view2d_region_to_view( - ®ion->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]); + UI_view2d_region_to_view(®ion->v2d, + event->mval[0], + event->mval[1], + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name")) { @@ -435,7 +438,8 @@ static int node_add_mask_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]); + node = node_add_node( + C, NULL, CMP_NODE_MASK, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!node) { BKE_report(op->reports, RPT_WARNING, "Could not add a mask node"); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index d3fec7257f5..6ce65cd35cb 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -317,14 +317,14 @@ static void node_uiblocks_init(const bContext *C, bNodeTree *ntree) } } -void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry) +void node_to_view(const bNode *node, float x, float y, float *rx, float *ry) { nodeToView(node, x, y, rx, ry); *rx *= UI_DPI_FAC; *ry *= UI_DPI_FAC; } -void node_to_updated_rect(struct bNode *node, rctf *r_rect) +void node_to_updated_rect(const bNode *node, rctf *r_rect) { node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax); node_to_view(node, @@ -334,7 +334,7 @@ void node_to_updated_rect(struct bNode *node, rctf *r_rect) &r_rect->ymin); } -void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry) +void node_from_view(const bNode *node, float x, float y, float *rx, float *ry) { x /= UI_DPI_FAC; y /= UI_DPI_FAC; @@ -689,11 +689,11 @@ int node_get_colorid(bNode *node) /* note: in cmp_util.c is similar code, for node_compo_pass_on() * the same goes for shader and texture nodes. */ /* note: in node_edit.c is similar code, for untangle node */ -static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) +static void node_draw_mute_line(const View2D *v2d, const SpaceNode *snode, const bNode *node) { GPU_blend(GPU_BLEND_ALPHA); - LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) { + LISTBASE_FOREACH (const bNodeLink *, link, &node->internal_links) { node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1); } @@ -947,14 +947,14 @@ static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_ WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL); } -void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha) +void node_draw_shadow(const SpaceNode *snode, const bNode *node, float radius, float alpha) { - rctf *rct = &node->totr; + const rctf *rct = &node->totr; UI_draw_roundbox_corner_set(UI_CNR_ALL); - ui_draw_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT); + ui_draw_dropshadow(rct, radius, snode->runtime->aspect, alpha, node->flag & SELECT); } -void node_draw_sockets(View2D *v2d, +void node_draw_sockets(const View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, @@ -1118,8 +1118,8 @@ void node_draw_sockets(View2D *v2d, } static void node_draw_basis(const bContext *C, - ARegion *region, - SpaceNode *snode, + const View2D *v2d, + const SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) @@ -1127,8 +1127,6 @@ static void node_draw_basis(const bContext *C, /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */ float iconbutw = 0.8f * UI_UNIT_X; - View2D *v2d = ®ion->v2d; - /* skip if out of view */ if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) { UI_block_end(C, node->block); @@ -1343,8 +1341,8 @@ static void node_draw_basis(const bContext *C, } static void node_draw_hidden(const bContext *C, - ARegion *region, - SpaceNode *snode, + const View2D *v2d, + const SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) @@ -1353,8 +1351,6 @@ static void node_draw_hidden(const bContext *C, float centy = BLI_rctf_cent_y(rct); float hiddenrad = BLI_rctf_size_y(rct) / 2.0f; - View2D *v2d = ®ion->v2d; - float scale; UI_view2d_scale_get(v2d, &scale, NULL); @@ -1438,7 +1434,7 @@ static void node_draw_hidden(const bContext *C, /* disable lines */ if (node->flag & NODE_MUTED) { - node_draw_mute_line(®ion->v2d, snode, node); + node_draw_mute_line(v2d, snode, node); } char showname[128]; /* 128 is used below */ @@ -1477,19 +1473,19 @@ static void node_draw_hidden(const bContext *C, immVertex2f(pos, rct->xmax - dx, centy - 4.0f); immVertex2f(pos, rct->xmax - dx, centy + 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f); immEnd(); immUniformThemeColorShade(color_id, 30); - dx -= snode->aspect; + dx -= snode->runtime->aspect; immBegin(GPU_PRIM_LINES, 4); immVertex2f(pos, rct->xmax - dx, centy - 4.0f); immVertex2f(pos, rct->xmax - dx, centy + 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f); immEnd(); immUnbindProgram(); @@ -1550,11 +1546,12 @@ void node_draw_default(const bContext *C, bNode *node, bNodeInstanceKey key) { + const View2D *v2d = ®ion->v2d; if (node->flag & NODE_HIDDEN) { - node_draw_hidden(C, region, snode, ntree, node, key); + node_draw_hidden(C, v2d, snode, ntree, node, key); } else { - node_draw_basis(C, region, snode, ntree, node, key); + node_draw_basis(C, v2d, snode, ntree, node, key); } } @@ -1607,8 +1604,7 @@ void node_draw_nodetree(const bContext *C, #endif /* draw background nodes, last nodes in front */ - int a = 0; - LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, a) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { #ifdef USE_DRAW_TOT_UPDATE /* unrelated to background nodes, update the v2d->tot, * can be anywhere before we draw the scroll bars */ @@ -1635,8 +1631,7 @@ void node_draw_nodetree(const bContext *C, GPU_blend(GPU_BLEND_NONE); /* draw foreground nodes, last nodes in front */ - a = 0; - LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, a) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & NODE_BACKGROUND) { continue; } @@ -1666,7 +1661,7 @@ static void snode_setup_v2d(SpaceNode *snode, ARegion *region, const float cente UI_view2d_view_ortho(v2d); /* aspect+font, set each time */ - snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx; + snode->runtime->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx; // XXX snode->curfont = uiSetCurFont_ext(snode->aspect); } @@ -1686,8 +1681,8 @@ static void draw_nodetree(const bContext *C, /* shade the parent node group and add a uiBlock to clip mouse events */ static void draw_group_overlay(const bContext *C, ARegion *region) { - View2D *v2d = ®ion->v2d; - rctf rect = v2d->cur; + const View2D *v2d = ®ion->v2d; + const rctf rect = v2d->cur; float color[4]; /* shade node groups to separate them visually */ @@ -1722,14 +1717,15 @@ void node_draw_space(const bContext *C, ARegion *region) GPU_depth_test(GPU_DEPTH_NONE); GPU_scissor_test(true); - /* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */ + /* XXX snode->runtime->cursor set in coordspace for placing new nodes, used for drawing noodles + * too */ UI_view2d_region_to_view(®ion->v2d, win->eventstate->x - region->winrct.xmin, win->eventstate->y - region->winrct.ymin, - &snode->cursor[0], - &snode->cursor[1]); - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; int grid_levels = UI_GetThemeValueType(TH_NODE_GRID_LEVELS, SPACE_NODE); @@ -1819,7 +1815,7 @@ void node_draw_space(const bContext *C, ARegion *region) /* temporary links */ GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); - LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->linkdrag) { + LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) { LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { node_draw_link(v2d, snode, (bNodeLink *)linkdata->data); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 30eee416b12..ced81401874 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -880,8 +880,8 @@ static void node_resize_init( NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data"); op->customdata = nsw; - nsw->mxstart = snode->cursor[0] * UI_DPI_FAC; - nsw->mystart = snode->cursor[1] * UI_DPI_FAC; + nsw->mxstart = snode->runtime->cursor[0] * UI_DPI_FAC; + nsw->mystart = snode->runtime->cursor[1] * UI_DPI_FAC; /* store old */ nsw->oldlocx = node->locx; diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index aa59b7293a3..a2b04fa9665 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -37,6 +37,7 @@ struct bContext; struct bNode; struct bNodeLink; struct bNodeSocket; +struct NodeInsertOfsData; struct wmGizmoGroupType; struct wmKeyConfig; struct wmWindow; @@ -53,6 +54,23 @@ typedef struct bNodeLinkDrag { int in_out; } bNodeLinkDrag; +typedef struct SpaceNode_Runtime { + float aspect; + + /** Mouse position for drawing socket-less links and adding nodes. */ + float cursor[2]; + + /** For auto compositing. */ + bool recalc; + + /** Temporary data for modal linking operator. */ + struct ListBase linkdrag; + + /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ + /** Temporary data for node insert offset (in UI called Auto-offset). */ + struct NodeInsertOfsData *iofsd; +} SpaceNode_Runtime; + /* space_node.c */ /* transform between View2Ds in the tree path */ @@ -61,14 +79,17 @@ void space_node_group_offset(struct SpaceNode *snode, float *x, float *y); /* node_draw.c */ int node_get_colorid(struct bNode *node); int node_get_resize_cursor(int directions); -void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha); +void node_draw_shadow(const struct SpaceNode *snode, + const struct bNode *node, + float radius, + float alpha); void node_draw_default(const struct bContext *C, struct ARegion *region, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key); -void node_draw_sockets(struct View2D *v2d, +void node_draw_sockets(const struct View2D *v2d, const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, @@ -92,9 +113,9 @@ void node_draw_space(const bContext *C, ARegion *region); void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]); /* DPI scaled coords */ -void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry); -void node_to_updated_rect(struct bNode *node, rctf *r_rect); -void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry); +void node_to_view(const struct bNode *node, float x, float y, float *rx, float *ry); +void node_to_updated_rect(const struct bNode *node, rctf *r_rect); +void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry); /* node_buttons.c */ void node_buttons_register(struct ARegionType *art); @@ -145,17 +166,17 @@ void nodelink_batch_start(struct SpaceNode *snode); void nodelink_batch_end(struct SpaceNode *snode); void node_draw_link(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link); -void node_draw_link_bezier(struct View2D *v2d, - struct SpaceNode *snode, - struct bNodeLink *link, +void node_draw_link_bezier(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, int th_col1, int th_col2, int th_col3); -bool node_link_bezier_points(struct View2D *v2d, - struct SpaceNode *snode, - struct bNodeLink *link, +bool node_link_bezier_points(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, float coord_array[][2], - int resol); + const int resol); void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *region, struct SpaceNode *snode, diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index ba1e752e276..ee7c8bca2f8 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -58,7 +58,7 @@ static bool ntree_has_drivers(bNodeTree *ntree) { - AnimData *adt = BKE_animdata_from_id(&ntree->id); + const AnimData *adt = BKE_animdata_from_id(&ntree->id); if (adt == NULL) { return false; } @@ -663,7 +663,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) snode_dag_update(C, snode); } - BLI_remlink(&snode->linkdrag, nldrag); + BLI_remlink(&snode->runtime->linkdrag, nldrag); /* links->data pointers are either held by the tree or freed already */ BLI_freelistN(&nldrag->links); MEM_freeN(nldrag); @@ -903,7 +903,7 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (nldrag) { op->customdata = nldrag; - BLI_addtail(&snode->linkdrag, nldrag); + BLI_addtail(&snode->runtime->linkdrag, nldrag); /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -918,7 +918,7 @@ static void node_link_cancel(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNodeLinkDrag *nldrag = op->customdata; - BLI_remlink(&snode->linkdrag, nldrag); + BLI_remlink(&snode->runtime->linkdrag, nldrag); BLI_freelistN(&nldrag->links); MEM_freeN(nldrag); @@ -1798,7 +1798,7 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); - NodeInsertOfsData *iofsd = snode->iofsd; + NodeInsertOfsData *iofsd = snode->runtime->iofsd; bool redraw = false; if (!snode || event->type != TIMER || iofsd == NULL || iofsd->anim_timer != event->customdata) { @@ -1837,7 +1837,7 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w node->anim_init_locx = node->anim_ofsx = 0.0f; } - snode->iofsd = NULL; + snode->runtime->iofsd = NULL; MEM_freeN(iofsd); return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); @@ -1851,7 +1851,7 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event) { const SpaceNode *snode = CTX_wm_space_node(C); - NodeInsertOfsData *iofsd = snode->iofsd; + NodeInsertOfsData *iofsd = snode->runtime->iofsd; if (!iofsd || !iofsd->insert) { return OPERATOR_CANCELLED; @@ -1927,7 +1927,7 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) iofsd->prev = link->fromnode; iofsd->next = node; - snode->iofsd = iofsd; + snode->runtime->iofsd = iofsd; } ntreeUpdateTree(bmain, snode->edittree); /* needed for pointers */ diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index ad7632377a3..2722b2a8c17 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -321,18 +321,25 @@ static void node_free(SpaceLink *sl) LISTBASE_FOREACH_MUTABLE (bNodeTreePath *, path, &snode->treepath) { MEM_freeN(path); } + + MEM_SAFE_FREE(snode->runtime); } /* spacetype; init callback */ -static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area)) +static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *area) { + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + + if (snode->runtime == NULL) { + snode->runtime = MEM_callocN(sizeof(SpaceNode_Runtime), __func__); + } } -static void node_area_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void node_area_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* note, ED_area_tag_refresh will re-execute compositor */ SpaceNode *snode = area->spacedata.first; /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */ @@ -362,7 +369,7 @@ static void node_area_listener(wmWindow *UNUSED(win), case ND_TRANSFORM_DONE: if (ED_node_is_compositor(snode)) { if (snode->flag & SNODE_AUTO_RENDER) { - snode->recalc = 1; + snode->runtime->recalc = true; ED_area_tag_refresh(area); } } @@ -521,8 +528,8 @@ static void node_area_refresh(const struct bContext *C, ScrArea *area) Scene *scene = (Scene *)snode->id; if (scene->use_nodes) { /* recalc is set on 3d view changes for auto compo */ - if (snode->recalc) { - snode->recalc = 0; + if (snode->runtime->recalc) { + snode->runtime->recalc = false; node_render_changed_exec((struct bContext *)C, NULL); } else { @@ -546,8 +553,10 @@ static SpaceLink *node_duplicate(SpaceLink *sl) BLI_duplicatelist(&snoden->treepath, &snode->treepath); - /* clear or remove stuff from old */ - BLI_listbase_clear(&snoden->linkdrag); + if (snode->runtime != NULL) { + snoden->runtime = MEM_dupallocN(snode->runtime); + BLI_listbase_clear(&snoden->runtime->linkdrag); + } /* Note: no need to set node tree user counts, * the editor only keeps at least 1 (id_us_ensure_real), @@ -589,6 +598,16 @@ static void node_toolbar_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } +void ED_node_cursor_location_get(const SpaceNode *snode, float value[2]) +{ + copy_v2_v2(value, snode->runtime->cursor); +} + +void ED_node_cursor_location_set(SpaceNode *snode, const float value[2]) +{ + copy_v2_v2(snode->runtime->cursor, value); +} + static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) { SpaceNode *snode = area->spacedata.first; @@ -597,15 +616,15 @@ static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) UI_view2d_region_to_view(®ion->v2d, win->eventstate->x - region->winrct.xmin, win->eventstate->y - region->winrct.ymin, - &snode->cursor[0], - &snode->cursor[1]); + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); - /* here snode->cursor is used to detect the node edge for sizing */ - node_set_cursor(win, snode, snode->cursor); + /* here snode->runtime->cursor is used to detect the node edge for sizing */ + node_set_cursor(win, snode, snode->runtime->cursor); - /* XXX snode->cursor is in placing new nodes space */ - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + /* XXX snode->runtime->cursor is in placing new nodes space */ + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; } /* Initialize main region, setting handlers. */ @@ -703,12 +722,10 @@ static void node_header_region_draw(const bContext *C, ARegion *region) } /* used for header + main region */ -static void node_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void node_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; wmGizmoMap *gzmap = region->gizmo_map; /* context changes */ diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 6c9d4433abd..88e88ab0c66 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -102,12 +102,11 @@ static void outliner_main_region_free(ARegion *UNUSED(region)) { } -static void outliner_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void outliner_main_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; SpaceOutliner *space_outliner = area->spacedata.first; /* context changes */ @@ -264,15 +263,13 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), } } -static void outliner_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void outliner_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceOutliner *space_outliner = area->spacedata.first; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -301,12 +298,11 @@ static void outliner_header_region_free(ARegion *UNUSED(region)) { } -static void outliner_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void outliner_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index 3330ba14530..47de18e8faf 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -156,13 +156,8 @@ static void script_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void script_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void script_main_region_listener(const wmRegionListenerParams *UNUSED(params)) { -/* context changes */ /* XXX - Todo, need the ScriptSpace accessible to get the python script to run. */ #if 0 BPY_run_script_space_listener() diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index b11e2a32b87..51c2d3ebdf1 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -334,11 +334,11 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) return (SpaceLink *)sseqn; } -static void sequencer_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void sequencer_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_SCENE: @@ -534,12 +534,11 @@ static void sequencer_main_region_draw_overlay(const bContext *C, ARegion *regio draw_timeline_seq_display(C, region); } -static void sequencer_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_SCENE: @@ -579,14 +578,12 @@ static void sequencer_main_region_listener(wmWindow *UNUSED(win), } } -static void sequencer_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void sequencer_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -746,12 +743,11 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) } } -static void sequencer_preview_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_preview_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_GPENCIL: @@ -816,12 +812,11 @@ static void sequencer_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void sequencer_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_GPENCIL: diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c index ae56b111360..e877cf8ffcf 100644 --- a/source/blender/editors/space_statusbar/space_statusbar.c +++ b/source/blender/editors/space_statusbar/space_statusbar.c @@ -95,12 +95,11 @@ static void statusbar_keymap(struct wmKeyConfig *UNUSED(keyconf)) { } -static void statusbar_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void statusbar_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -131,14 +130,11 @@ static void statusbar_header_region_listener(wmWindow *UNUSED(win), } } -static void statusbar_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void statusbar_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 0f5ac5abe1d..045305e0f5d 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -122,11 +122,10 @@ static SpaceLink *text_duplicate(SpaceLink *sl) return (SpaceLink *)stextn; } -static void text_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void text_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceText *st = area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index dc357cdd355..6a7439df6e3 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -129,12 +129,11 @@ static void topbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *regi ED_region_header_init(region); } -static void topbar_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void topbar_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -160,12 +159,11 @@ static void topbar_main_region_listener(wmWindow *UNUSED(win), } } -static void topbar_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void topbar_header_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -191,14 +189,12 @@ static void topbar_header_listener(wmWindow *UNUSED(win), } } -static void topbar_header_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void topbar_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 3efdee9cec9..d4692f156d3 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -183,46 +183,20 @@ static void userpref_execute_region_init(wmWindowManager *wm, ARegion *region) region->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y; } -static void userpref_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_main_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } -static void userpref_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_header_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ -#if 0 - switch (wmn->category) { - default: - break; - } -#endif } -static void userpref_navigation_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_navigation_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } -static void userpref_execute_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_execute_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } /* only called once, from space/spacetypes.c */ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 34d342ddd94..b5b7f0b22cd 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -783,9 +783,12 @@ static void *view3d_main_region_duplicate(void *poin) return NULL; } -static void view3d_main_region_listener( - wmWindow *UNUSED(win), ScrArea *area, ARegion *region, wmNotifier *wmn, const Scene *scene) +static void view3d_main_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + const Scene *scene = params->scene; View3D *v3d = area->spacedata.first; RegionView3D *rv3d = region->regiondata; wmGizmoMap *gzmap = region->gizmo_map; @@ -1041,14 +1044,13 @@ static void view3d_main_region_listener( } } -static void view3d_main_region_message_subscribe(const struct bContext *C, - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + const bContext *C = params->context; + ScrArea *area = params->area; + ARegion *region = params->region; + /* Developer note: there are many properties that impact 3D view drawing, * so instead of subscribing to individual properties, just subscribe to types * accepting some redundant redraws. @@ -1163,12 +1165,11 @@ static void view3d_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void view3d_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void view3d_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -1233,14 +1234,11 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win), #endif } -static void view3d_header_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void view3d_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgParams_RNA msg_key_params = {{0}}; /* Only subscribe to types. */ @@ -1378,12 +1376,11 @@ static void view3d_buttons_region_layout(const bContext *C, ARegion *region) ED_view3d_buttons_region_layout_ex(C, region, NULL); } -static void view3d_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void view3d_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -1502,11 +1499,10 @@ static void view3d_tools_region_draw(const bContext *C, ARegion *region) } /* area (not region) level listener */ -static void space_view3d_listener(wmWindow *UNUSED(win), - ScrArea *area, - struct wmNotifier *wmn, - Scene *UNUSED(scene)) +static void space_view3d_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; View3D *v3d = area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index 0a742ec4470..17362ae65e5 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -135,7 +135,7 @@ static void createTransGPencil_curves(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* Check if stroke has an editcurve */ @@ -242,7 +242,7 @@ static void createTransGPencil_curves(bContext *C, } /* Calculate difference matrix. */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); copy_m3_m4(mtx, diff_mat); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); @@ -263,7 +263,7 @@ static void createTransGPencil_curves(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* Check if stroke has an editcurve */ @@ -436,7 +436,7 @@ static void createTransGPencil_strokes(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } @@ -507,7 +507,7 @@ static void createTransGPencil_strokes(bContext *C, } /* Calculate difference matrix. */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* Undo matrix. */ invert_m4_m4(inverse_diff_mat, diff_mat); @@ -551,7 +551,7 @@ static void createTransGPencil_strokes(bContext *C, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* What we need to include depends on proportional editing settings... */ diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index b3bd6b31879..c6ea0d80035 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -251,29 +251,55 @@ void transform_convert_mesh_islanddata_free(struct TransIslandData *island_data) * * \{ */ -static bool bmesh_test_dist_add(BMVert *v, - BMVert *v_other, +/* Propagate distance from v1 and v2 to v0. */ +static bool bmesh_test_dist_add(BMVert *v0, + BMVert *v1, + BMVert *v2, float *dists, - const float *dists_prev, /* optionally track original index */ int *index, - const int *index_prev, const float mtx[3][3]) { - if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && - (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) { - const int i = BM_elem_index_get(v); - const int i_other = BM_elem_index_get(v_other); - float vec[3]; - float dist_other; - sub_v3_v3v3(vec, v->co, v_other->co); - mul_m3_v3(mtx, vec); - - dist_other = dists_prev[i] + len_v3(vec); - if (dist_other < dists[i_other]) { - dists[i_other] = dist_other; + if ((BM_elem_flag_test(v0, BM_ELEM_SELECT) == 0) && + (BM_elem_flag_test(v0, BM_ELEM_HIDDEN) == 0)) { + const int i0 = BM_elem_index_get(v0); + const int i1 = BM_elem_index_get(v1); + + BLI_assert(dists[i1] != FLT_MAX); + if (dists[i0] <= dists[i1]) { + return false; + } + + float dist0; + + if (v2) { + /* Distance across triangle. */ + const int i2 = BM_elem_index_get(v2); + BLI_assert(dists[i2] != FLT_MAX); + if (dists[i0] <= dists[i2]) { + return false; + } + + float vm0[3], vm1[3], vm2[3]; + mul_v3_m3v3(vm0, mtx, v0->co); + mul_v3_m3v3(vm1, mtx, v1->co); + mul_v3_m3v3(vm2, mtx, v2->co); + + dist0 = geodesic_distance_propagate_across_triangle(vm0, vm1, vm2, dists[i1], dists[i2]); + } + else { + /* Distance along edge. */ + float vec[3]; + sub_v3_v3v3(vec, v1->co, v0->co); + mul_m3_v3(mtx, vec); + + dist0 = dists[i1] + len_v3(vec); + } + + if (dist0 < dists[i0]) { + dists[i0] = dist0; if (index != NULL) { - index[i_other] = index_prev[i]; + index[i0] = index[i1]; } return true; } @@ -292,15 +318,16 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, float *dists, int *index) { - BLI_LINKSTACK_DECLARE(queue, BMVert *); + BLI_LINKSTACK_DECLARE(queue, BMEdge *); - /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ - BLI_LINKSTACK_DECLARE(queue_next, BMVert *); + /* any BM_ELEM_TAG'd edge is in 'queue_next', so we don't add in twice */ + BLI_LINKSTACK_DECLARE(queue_next, BMEdge *); BLI_LINKSTACK_INIT(queue); BLI_LINKSTACK_INIT(queue_next); { + /* Set indexes and initial distances for selected vertices. */ BMIter viter; BMVert *v; int i; @@ -308,7 +335,6 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { float dist; BM_elem_index_set(v, i); /* set_inline */ - BM_elem_flag_disable(v, BM_ELEM_TAG); if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { dist = FLT_MAX; @@ -317,7 +343,6 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, } } else { - BLI_LINKSTACK_PUSH(queue, v); dist = 0.0f; if (index != NULL) { index[i] = i; @@ -329,103 +354,99 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, bm->elem_index_dirty &= ~BM_VERT; } - /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ - float *dists_prev = MEM_dupallocN(dists); - int *index_prev = MEM_dupallocN(index); /* may be NULL */ + { + /* Add edges with at least one selected vertex to the queue. */ + BMIter eiter; + BMEdge *e; + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + int i1 = BM_elem_index_get(v1); + int i2 = BM_elem_index_get(v2); + + if (dists[i1] != FLT_MAX || dists[i2] != FLT_MAX) { + BLI_LINKSTACK_PUSH(queue, e); + } + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + } do { - BMVert *v; - LinkNode *lnk; - - /* this is correct but slow to do each iteration, - * instead sync the dist's while clearing BM_ELEM_TAG (below) */ -#if 0 - memcpy(dists_prev, dists, sizeof(float) * bm->totvert); -#endif - - while ((v = BLI_LINKSTACK_POP(queue))) { - BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX); - - /* connected edge-verts */ - if (v->e != NULL) { - BMEdge *e_iter, *e_first; - - e_iter = e_first = v->e; - - /* would normally use BM_EDGES_OF_VERT, but this runs so often, - * its faster to iterate on the data directly */ - do { - - if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) { + BMEdge *e; + + while ((e = BLI_LINKSTACK_POP(queue))) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + int i1 = BM_elem_index_get(v1); + int i2 = BM_elem_index_get(v2); + + if (e->l == NULL || (dists[i1] == FLT_MAX || dists[i2] == FLT_MAX)) { + /* Propagate along edge from vertex with smallest to largest distance. */ + if (dists[i1] > dists[i2]) { + SWAP(int, i1, i2); + SWAP(BMVert *, v1, v2); + } - /* edge distance */ - { - BMVert *v_other = BM_edge_other_vert(e_iter, v); - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { - if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { - BM_elem_flag_enable(v_other, BM_ELEM_TAG); - BLI_LINKSTACK_PUSH(queue_next, v_other); - } - } + if (bmesh_test_dist_add(v2, v1, NULL, dists, index, mtx)) { + /* Add adjacent loose edges to the queue, or all edges if this is a loose edge. + * Other edges are handled by propagation across edges below. */ + BMEdge *e_other; + BMIter eiter; + BM_ITER_ELEM (e_other, &eiter, v2, BM_EDGES_OF_VERT) { + if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 && + (e->l == NULL || e_other->l == NULL)) { + BM_elem_flag_enable(e_other, BM_ELEM_TAG); + BLI_LINKSTACK_PUSH(queue_next, e_other); } + } + } + } - /* face distance */ - if (e_iter->l) { - BMLoop *l_iter_radial, *l_first_radial; - /** - * imaginary edge diagonally across quad. - * \note This takes advantage of the rules of winding that we - * know 2 or more of a verts edges wont reference the same face twice. - * Also, if the edge is hidden, the face will be hidden too. - */ - l_iter_radial = l_first_radial = e_iter->l; - - do { - if ((l_iter_radial->v == v) && (l_iter_radial->f->len == 4) && - (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) { - BMVert *v_other = l_iter_radial->next->next->v; - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { - if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { - BM_elem_flag_enable(v_other, BM_ELEM_TAG); - BLI_LINKSTACK_PUSH(queue_next, v_other); - } - } + if (e->l != NULL) { + /* Propagate across edge to vertices in adjacent faces. */ + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { + for (BMLoop *l_other = l->next->next; l_other != l; l_other = l_other->next) { + BMVert *v_other = l_other->v; + BLI_assert(!ELEM(v_other, v1, v2)); + + if (bmesh_test_dist_add(v_other, v1, v2, dists, index, mtx)) { + /* Add adjacent edges to the queue, if they are ready to propagate across/along. + * Always propagate along loose edges, and for other edges only propagate across + * if both vertices have a known distances. */ + BMEdge *e_other; + BMIter eiter; + BM_ITER_ELEM (e_other, &eiter, v_other, BM_EDGES_OF_VERT) { + if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 && + (e_other->l == NULL || + dists[BM_elem_index_get(BM_edge_other_vert(e_other, v_other))] != FLT_MAX)) { + BM_elem_flag_enable(e_other, BM_ELEM_TAG); + BLI_LINKSTACK_PUSH(queue_next, e_other); } - } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial); + } } } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); + } } } - /* clear for the next loop */ - for (lnk = queue_next; lnk; lnk = lnk->next) { - BMVert *v_link = lnk->link; - const int i = BM_elem_index_get(v_link); + /* Clear for the next loop. */ + for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) { + BMEdge *e_link = lnk->link; - BM_elem_flag_disable(v_link, BM_ELEM_TAG); - - /* keep in sync, avoid having to do full memcpy each iteration */ - dists_prev[i] = dists[i]; - if (index != NULL) { - index_prev[i] = index[i]; - } + BM_elem_flag_disable(e_link, BM_ELEM_TAG); } BLI_LINKSTACK_SWAP(queue, queue_next); - /* none should be tagged now since 'queue_next' is empty */ - BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0); - + /* None should be tagged now since 'queue_next' is empty. */ + BLI_assert(BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, BM_ELEM_TAG, true) == 0); } while (BLI_LINKSTACK_SIZE(queue)); BLI_LINKSTACK_FREE(queue); BLI_LINKSTACK_FREE(queue_next); - - MEM_freeN(dists_prev); - if (index_prev != NULL) { - MEM_freeN(index_prev); - } } /** \} */ diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c index 1807e9adcd1..b1024f5efe4 100644 --- a/source/blender/editors/transform/transform_convert_mesh_skin.c +++ b/source/blender/editors/transform/transform_convert_mesh_skin.c @@ -55,9 +55,7 @@ static float *mesh_skin_transdata_center(const struct TransIslandData *island_da if (island_data->center && island_index != -1) { return island_data->center[island_index]; } - else { - return eve->co; - } + return eve->co; } static void mesh_skin_transdata_create(TransDataBasic *td, diff --git a/source/blender/editors/transform/transform_convert_tracking.c b/source/blender/editors/transform/transform_convert_tracking.c index c3f48adca68..f8199e8011f 100644 --- a/source/blender/editors/transform/transform_convert_tracking.c +++ b/source/blender/editors/transform/transform_convert_tracking.c @@ -52,6 +52,7 @@ typedef struct TransDataTracking { float (*smarkers)[2]; int markersnr; + int framenr; MovieTrackingMarker *markers; /* marker transformation from curves editor */ @@ -73,9 +74,25 @@ enum transDataTracking_Mode { * * \{ */ -static void markerToTransDataInit(TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +typedef struct TransformInitContext { + SpaceClip *space_clip; + + TransInfo *t; + TransDataContainer *tc; + + /* MOTE: There pointers will be `nullptr` during counting step. + * This means, that the transformation data initialization functions are to increment + * `tc->data_len` instead of filling in the transformation data when these pointers are + * `nullptr`. For simplicity, check the `current.td` against `nullptr`. + * Do not `tc->data_len` when filling in the transformation data. */ + struct { + TransData *td; + TransData2D *td2d; + TransDataTracking *tdt; + } current; +} TransformInitContext; + +static void markerToTransDataInit(TransformInitContext *init_context, MovieTrackingTrack *track, MovieTrackingMarker *marker, int area, @@ -84,8 +101,19 @@ static void markerToTransDataInit(TransData *td, const float off[2], const float aspect[2]) { + TransData *td = init_context->current.td; + TransData2D *td2d = init_context->current.td2d; + TransDataTracking *tdt = init_context->current.tdt; + + if (td == NULL) { + init_context->tc->data_len++; + return; + } + int anchor = area == TRACK_AREA_POINT && off; + tdt->flag = marker->flag; + tdt->framenr = marker->framenr; tdt->mode = transDataTracking_ModeTracks; if (anchor) { @@ -143,23 +171,20 @@ static void markerToTransDataInit(TransData *td, unit_m3(td->mtx); unit_m3(td->smtx); + + init_context->current.td++; + init_context->current.td2d++; + init_context->current.tdt++; } -static void trackToTransData(const int framenr, - TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void trackToTransData(TransformInitContext *init_context, + const int framenr, MovieTrackingTrack *track, const float aspect[2]) { MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr); - tdt->flag = marker->flag; - marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); - - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_POINT, @@ -170,16 +195,14 @@ static void trackToTransData(const int framenr, if (track->flag & SELECT) { markerToTransDataInit( - td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect); + init_context, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect); } if (track->pat_flag & SELECT) { int a; for (a = 0; a < 4; a++) { - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_PAT, @@ -191,9 +214,7 @@ static void trackToTransData(const int framenr, } if (track->search_flag & SELECT) { - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_SEARCH, @@ -202,9 +223,7 @@ static void trackToTransData(const int framenr, NULL, aspect); - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_SEARCH, @@ -213,15 +232,43 @@ static void trackToTransData(const int framenr, NULL, aspect); } + + if (init_context->current.td != NULL) { + marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); + } } -static void planeMarkerToTransDataInit(TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void trackToTransDataIfNeeded(TransformInitContext *init_context, + const int framenr, + MovieTrackingTrack *track, + const float aspect[2]) +{ + if (!TRACK_VIEW_SELECTED(init_context->space_clip, track)) { + return; + } + if (track->flag & TRACK_LOCKED) { + return; + } + trackToTransData(init_context, framenr, track, aspect); +} + +static void planeMarkerToTransDataInit(TransformInitContext *init_context, MovieTrackingPlaneTrack *plane_track, + MovieTrackingPlaneMarker *plane_marker, float corner[2], const float aspect[2]) { + TransData *td = init_context->current.td; + TransData2D *td2d = init_context->current.td2d; + TransDataTracking *tdt = init_context->current.tdt; + + if (td == NULL) { + init_context->tc->data_len++; + return; + } + + tdt->flag = plane_marker->flag; + tdt->framenr = plane_marker->framenr; tdt->mode = transDataTracking_ModePlaneTracks; tdt->plane_track = plane_track; @@ -247,24 +294,38 @@ static void planeMarkerToTransDataInit(TransData *td, unit_m3(td->mtx); unit_m3(td->smtx); + + init_context->current.td++; + init_context->current.td2d++; + init_context->current.tdt++; } -static void planeTrackToTransData(const int framenr, - TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void planeTrackToTransData(TransformInitContext *init_context, + const int framenr, MovieTrackingPlaneTrack *plane_track, const float aspect[2]) { MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr); - int i; - tdt->flag = plane_marker->flag; - plane_marker->flag &= ~PLANE_MARKER_TRACKED; + for (int i = 0; i < 4; i++) { + planeMarkerToTransDataInit( + init_context, plane_track, plane_marker, plane_marker->corners[i], aspect); + } - for (i = 0; i < 4; i++) { - planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect); + if (init_context->current.td != NULL) { + plane_marker->flag &= ~PLANE_MARKER_TRACKED; + } +} + +static void planeTrackToTransDataIfNeeded(TransformInitContext *init_context, + const int framenr, + MovieTrackingPlaneTrack *plane_track, + const float aspect[2]) +{ + if (!PLANE_TRACK_VIEW_SELECTED(plane_track)) { + return; } + planeTrackToTransData(init_context, framenr, plane_track, aspect); } static void transDataTrackingFree(TransInfo *UNUSED(t), @@ -284,101 +345,53 @@ static void transDataTrackingFree(TransInfo *UNUSED(t), static void createTransTrackingTracksData(bContext *C, TransInfo *t) { - TransData *td; - TransData2D *td2d; - SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip_get_clip(sc); - ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); - ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); - MovieTrackingTrack *track; - MovieTrackingPlaneTrack *plane_track; - TransDataTracking *tdt; - int framenr = ED_space_clip_get_clip_frame_number(sc); + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + const ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); + const ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); + const int framenr = ED_space_clip_get_clip_frame_number(space_clip); TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); - /* count */ - tc->data_len = 0; - - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - tc->data_len++; /* offset */ + TransformInitContext init_context = {NULL}; + init_context.space_clip = space_clip; + init_context.t = t; + init_context.tc = tc; - if (track->flag & SELECT) { - tc->data_len++; - } + /* Count required tranformation data. */ - if (track->pat_flag & SELECT) { - tc->data_len += 4; - } - - if (track->search_flag & SELECT) { - tc->data_len += 2; - } - } + tc->data_len = 0; - track = track->next; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { + trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect); } - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { - if (PLANE_TRACK_VIEW_SELECTED(plane_track)) { - tc->data_len += 4; - } + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { + planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect); } if (tc->data_len == 0) { return; } - td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData"); - td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), - "TransTracking TransData2D"); - tdt = tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking), - "TransTracking TransDataTracking"); - + tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData"); + tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransTracking TransData2D"); + tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking), + "TransTracking TransDataTracking"); tc->custom.type.free_cb = transDataTrackingFree; - /* create actual data */ - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - trackToTransData(framenr, td, td2d, tdt, track, t->aspect); - - /* offset */ - td++; - td2d++; - tdt++; + init_context.current.td = tc->data; + init_context.current.td2d = tc->data_2d; + init_context.current.tdt = tc->custom.type.data; - if (track->flag & SELECT) { - td++; - td2d++; - tdt++; - } - - if (track->pat_flag & SELECT) { - td += 4; - td2d += 4; - tdt += 4; - } + /* Create actual transformation data. */ - if (track->search_flag & SELECT) { - td += 2; - td2d += 2; - tdt += 2; - } - } - - track = track->next; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { + trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect); } - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { - if (PLANE_TRACK_VIEW_SELECTED(plane_track)) { - planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect); - td += 4; - td2d += 4; - tdt += 4; - } + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { + planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect); } } @@ -560,17 +573,17 @@ void createTransTrackingData(bContext *C, TransInfo *t) static void cancelTransTracking(TransInfo *t) { TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); - SpaceClip *sc = t->area->spacedata.first; - int i, framenr = ED_space_clip_get_clip_frame_number(sc); TransDataTracking *tdt_array = tc->custom.type.data; - i = 0; + int i = 0; while (i < tc->data_len) { TransDataTracking *tdt = &tdt_array[i]; if (tdt->mode == transDataTracking_ModeTracks) { MovieTrackingTrack *track = tdt->track; - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, tdt->framenr); + + BLI_assert(marker != NULL); marker->flag = tdt->flag; @@ -606,7 +619,10 @@ static void cancelTransTracking(TransInfo *t) } else if (tdt->mode == transDataTracking_ModePlaneTracks) { MovieTrackingPlaneTrack *plane_track = tdt->plane_track; - MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr); + MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, + tdt->framenr); + + BLI_assert(plane_marker != NULL); plane_marker->flag = tdt->flag; i += 3; diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 3c82365fdb4..7eaed2e1924 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -704,7 +704,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { /* skip strokes that are invalid for current view */ diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index c19dd4598cf..508189c5d77 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -299,83 +299,93 @@ eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event) void applyProject(TransInfo *t) { - /* XXX FLICKER IN OBJECT MODE */ - if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) { - float tvec[3]; - int i; + if (!t->tsnap.project) { + return; + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float iloc[3], loc[3], no[3]; - float mval_fl[2]; - if (td->flag & TD_SKIP) { - continue; - } + if (!activeSnap(t) || (t->flag & T_NO_PROJECT)) { + return; + } - if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { - continue; - } + if (doForceIncrementSnap(t)) { + return; + } - copy_v3_v3(iloc, td->loc); - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, iloc); - } - else if (t->flag & T_OBJECT) { - BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); - } + float tvec[3]; + int i; + + /* XXX FLICKER IN OBJECT MODE */ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float iloc[3], loc[3], no[3]; + float mval_fl[2]; + if (td->flag & TD_SKIP) { + continue; + } + + if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { + continue; + } - if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == - V3D_PROJ_RET_OK) { - if (ED_transform_snap_object_project_view3d( - t->tsnap.object_context, - t->depsgraph, - SCE_SNAP_MODE_FACE, - &(const struct SnapObjectParams){ - .snap_select = t->tsnap.modeSelect, - .use_object_edit_cage = (t->flag & T_EDIT) != 0, - .use_occlusion_test = false, - .use_backface_culling = t->tsnap.use_backface_culling, - }, - mval_fl, - NULL, - 0, - loc, - no)) { + copy_v3_v3(iloc, td->loc); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, iloc); + } + else if (t->flag & T_OBJECT) { + BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); + copy_v3_v3(iloc, td->ob->obmat[3]); + } + + if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == + V3D_PROJ_RET_OK) { + if (ED_transform_snap_object_project_view3d( + t->tsnap.object_context, + t->depsgraph, + SCE_SNAP_MODE_FACE, + &(const struct SnapObjectParams){ + .snap_select = t->tsnap.modeSelect, + .use_object_edit_cage = (t->flag & T_EDIT) != 0, + .use_occlusion_test = false, + .use_backface_culling = t->tsnap.use_backface_culling, + }, + mval_fl, + NULL, + 0, + loc, + no)) { #if 0 if (tc->use_local_mat) { mul_m4_v3(tc->imat, loc); } #endif - sub_v3_v3v3(tvec, loc, iloc); + sub_v3_v3v3(tvec, loc, iloc); - mul_m3_v3(td->smtx, tvec); + mul_m3_v3(td->smtx, tvec); - add_v3_v3(td->loc, tvec); + add_v3_v3(td->loc, tvec); - if (t->tsnap.align && (t->flag & T_OBJECT)) { - /* handle alignment as well */ - const float *original_normal; - float mat[3][3]; + if (t->tsnap.align && (t->flag & T_OBJECT)) { + /* handle alignment as well */ + const float *original_normal; + float mat[3][3]; - /* In pose mode, we want to align normals with Y axis of bones... */ - original_normal = td->axismtx[2]; + /* In pose mode, we want to align normals with Y axis of bones... */ + original_normal = td->axismtx[2]; - rotation_between_vecs_to_mat3(mat, original_normal, no); + rotation_between_vecs_to_mat3(mat, original_normal, no); - transform_data_ext_rotate(td, mat, true); + transform_data_ext_rotate(td, mat, true); - /* TODO support constraints for rotation too? see ElementRotation */ - } + /* TODO support constraints for rotation too? see ElementRotation */ } } + } #if 0 /* TODO: sipport this? */ constraintTransLim(t, td); #endif - } } } } diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 533416bf85e..860eaa37816 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -70,6 +70,17 @@ /** We only need this locally. */ static CLG_LogRef LOG = {"ed.undo"}; +/** + * \warning Values are used in #ED_undo_gpencil_step, + * which should eventually be replaced with the undo-system. + */ +enum eUndoStepDir { + STEP_REDO = 1, + STEP_UNDO = -1, + /** Only used when the undo step name or index is passed to #ed_undo_step_impl. */ + STEP_NONE = 0, +}; + /* -------------------------------------------------------------------- */ /** \name Generic Undo System Access * @@ -171,13 +182,16 @@ void ED_undo_push(bContext *C, const char *str) /** * \note Also check #undo_history_exec in bottom if you change notifiers. */ -static int ed_undo_step_impl( - bContext *C, int step, const char *undoname, int undo_index, ReportList *reports) +static int ed_undo_step_impl(bContext *C, + enum eUndoStepDir step, + const char *undo_name, + const int undo_index, + ReportList *reports) { /* Mutually exclusives, ensure correct input. */ - BLI_assert(((undoname || undo_index != -1) && !step) || - (!(undoname || undo_index != -1) && step)); - CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step); + BLI_assert(((undo_name || undo_index != -1) && (step == STEP_NONE)) || + (!(undo_name || undo_index != -1) && (step != STEP_NONE))); + CLOG_INFO(&LOG, 1, "name='%s', index=%d, step=%d", undo_name, undo_index, step); wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); ScrArea *area = CTX_wm_area(C); @@ -196,8 +210,12 @@ static int ed_undo_step_impl( /* TODO(campbell): undo_system: use undo system */ /* grease pencil can be can be used in plenty of spaces, so check it first */ + /* FIXME: This gpencil undo effectively only supports the one step undo/redo, undo based on name + * or index is fully not implemented. + * FIXME: However, it seems to never be used in current code (`ED_gpencil_session_active` seems + * to always return false). */ if (ED_gpencil_session_active()) { - return ED_undo_gpencil_step(C, step, undoname); + return ED_undo_gpencil_step(C, (int)step); } if (area && (area->spacetype == SPACE_VIEW3D)) { Object *obact = CTX_data_active_object(C); @@ -207,9 +225,9 @@ static int ed_undo_step_impl( } UndoStep *step_data_from_name = NULL; - int step_for_callback = step; - if (undoname != NULL) { - step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undoname); + enum eUndoStepDir step_for_callback = step; + if (undo_name != NULL) { + step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undo_name); if (step_data_from_name == NULL) { return OPERATOR_CANCELLED; } @@ -218,14 +236,14 @@ static int ed_undo_step_impl( /* Pointers match on redo. */ step_for_callback = (BLI_findindex(&wm->undo_stack->steps, step_data_from_name) < BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ? - 1 : - -1; + STEP_UNDO : + STEP_REDO; } else if (undo_index != -1) { step_for_callback = (undo_index < BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ? - 1 : - -1; + STEP_UNDO : + STEP_REDO; } /* App-Handlers (pre). */ @@ -240,14 +258,14 @@ static int ed_undo_step_impl( /* Undo System */ { - if (undoname) { + if (undo_name) { BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data_from_name); } else if (undo_index != -1) { BKE_undosys_step_undo_from_index(wm->undo_stack, C, undo_index); } else { - if (step == 1) { + if (step == STEP_UNDO) { BKE_undosys_step_undo(wm->undo_stack, C); } else { @@ -310,19 +328,19 @@ static int ed_undo_step_impl( return OPERATOR_FINISHED; } -static int ed_undo_step_direction(bContext *C, int step, ReportList *reports) +static int ed_undo_step_direction(bContext *C, enum eUndoStepDir step, ReportList *reports) { return ed_undo_step_impl(C, step, NULL, -1, reports); } static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList *reports) { - return ed_undo_step_impl(C, 0, undo_name, -1, reports); + return ed_undo_step_impl(C, STEP_NONE, undo_name, -1, reports); } -static int ed_undo_step_by_index(bContext *C, int index, ReportList *reports) +static int ed_undo_step_by_index(bContext *C, const int undo_index, ReportList *reports) { - return ed_undo_step_impl(C, 0, NULL, index, reports); + return ed_undo_step_impl(C, STEP_NONE, NULL, undo_index, reports); } void ED_undo_grouped_push(bContext *C, const char *str) @@ -340,11 +358,11 @@ void ED_undo_grouped_push(bContext *C, const char *str) void ED_undo_pop(bContext *C) { - ed_undo_step_direction(C, 1, NULL); + ed_undo_step_direction(C, STEP_UNDO, NULL); } void ED_undo_redo(bContext *C) { - ed_undo_step_direction(C, -1, NULL); + ed_undo_step_direction(C, STEP_REDO, NULL); } void ED_undo_push_op(bContext *C, wmOperator *op) @@ -448,7 +466,7 @@ static int ed_undo_exec(bContext *C, wmOperator *op) { /* "last operator" should disappear, later we can tie this with undo stack nicer */ WM_operator_stack_clear(CTX_wm_manager(C)); - int ret = ed_undo_step_direction(C, 1, op->reports); + int ret = ed_undo_step_direction(C, STEP_UNDO, op->reports); if (ret & OPERATOR_FINISHED) { /* Keep button under the cursor active. */ WM_event_add_mousemove(CTX_wm_window(C)); @@ -477,7 +495,7 @@ static int ed_undo_push_exec(bContext *C, wmOperator *op) static int ed_redo_exec(bContext *C, wmOperator *op) { - int ret = ed_undo_step_direction(C, -1, op->reports); + int ret = ed_undo_step_direction(C, STEP_REDO, op->reports); if (ret & OPERATOR_FINISHED) { /* Keep button under the cursor active. */ WM_event_add_mousemove(CTX_wm_window(C)); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c index e2f4d34ff40..f80ad60eb07 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c @@ -110,11 +110,11 @@ static bool dependsOnTime(GpencilModifierData *md) return (mmd->flag & GP_NOISE_USE_RANDOM) != 0; } -static float *noise_table(int len, int seed) +static float *noise_table(int len, int offset, int seed) { float *table = MEM_callocN(sizeof(float) * len, __func__); for (int i = 0; i < len; i++) { - table[i] = BLI_hash_int_01(BLI_hash_int_2d(seed, i + 1)); + table[i] = BLI_hash_int_01(BLI_hash_int_2d(seed, i + offset + 1)); } return table; } @@ -172,11 +172,19 @@ static void deformStroke(GpencilModifierData *md, /* Sanitize as it can create out of bound reads. */ float noise_scale = clamp_f(mmd->noise_scale, 0.0f, 1.0f); - int len = ceilf(gps->totpoints * noise_scale) + 1; - float *noise_table_position = (mmd->factor > 0.0f) ? noise_table(len, seed + 2) : NULL; - float *noise_table_strength = (mmd->factor_strength > 0.0f) ? noise_table(len, seed + 3) : NULL; - float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ? noise_table(len, seed) : NULL; - float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ? noise_table(len, seed + 4) : NULL; + int len = ceilf(gps->totpoints * noise_scale) + 2; + float *noise_table_position = (mmd->factor > 0.0f) ? + noise_table(len, (int)floor(mmd->noise_offset), seed + 2) : + NULL; + float *noise_table_strength = (mmd->factor_strength > 0.0f) ? + noise_table(len, (int)floor(mmd->noise_offset), seed + 3) : + NULL; + float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ? + noise_table(len, (int)floor(mmd->noise_offset), seed) : + NULL; + float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ? + noise_table(len, (int)floor(mmd->noise_offset), seed + 4) : + NULL; /* Calculate stroke normal. */ if (gps->totpoints > 2) { @@ -225,24 +233,27 @@ static void deformStroke(GpencilModifierData *md, cross_v3_v3v3(vec2, vec1, normal); normalize_v3(vec2); - float noise = table_sample(noise_table_position, i * noise_scale); + float noise = table_sample(noise_table_position, + i * noise_scale + fractf(mmd->noise_offset)); madd_v3_v3fl(&pt->x, vec2, (noise * 2.0f - 1.0f) * weight * mmd->factor * 0.1f); } if (mmd->factor_thickness > 0.0f) { - float noise = table_sample(noise_table_thickness, i * noise_scale); + float noise = table_sample(noise_table_thickness, + i * noise_scale + fractf(mmd->noise_offset)); pt->pressure *= max_ff(1.0f + (noise * 2.0f - 1.0f) * weight * mmd->factor_thickness, 0.0f); CLAMP_MIN(pt->pressure, GPENCIL_STRENGTH_MIN); } if (mmd->factor_strength > 0.0f) { - float noise = table_sample(noise_table_strength, i * noise_scale); + float noise = table_sample(noise_table_strength, + i * noise_scale + fractf(mmd->noise_offset)); pt->strength *= max_ff(1.0f - noise * weight * mmd->factor_strength, 0.0f); CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); } if (mmd->factor_uvs > 0.0f) { - float noise = table_sample(noise_table_uvs, i * noise_scale); + float noise = table_sample(noise_table_uvs, i * noise_scale + fractf(mmd->noise_offset)); pt->uv_rot += (noise * 2.0f - 1.0f) * weight * mmd->factor_uvs * M_PI_2; CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); } @@ -292,6 +303,8 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(col, ptr, "factor_thickness", 0, IFACE_("Thickness"), ICON_NONE); uiItemR(col, ptr, "factor_uvs", 0, IFACE_("UV"), ICON_NONE); uiItemR(col, ptr, "noise_scale", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "noise_offset", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "seed", 0, NULL, ICON_NONE); gpencil_modifier_panel_end(layout, ptr); } @@ -316,7 +329,6 @@ static void random_panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetActive(layout, RNA_boolean_get(ptr, "random")); uiItemR(layout, ptr, "step", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE); } static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel) diff --git a/source/blender/imbuf/intern/IMB_allocimbuf.h b/source/blender/imbuf/intern/IMB_allocimbuf.h index 08aa1936a6f..c92d764a104 100644 --- a/source/blender/imbuf/intern/IMB_allocimbuf.h +++ b/source/blender/imbuf/intern/IMB_allocimbuf.h @@ -32,7 +32,7 @@ struct ImBuf; void imb_refcounter_lock_init(void); void imb_refcounter_lock_exit(void); -#ifdef WIN32 +#ifndef WIN32 void imb_mmap_lock_init(void); void imb_mmap_lock_exit(void); void imb_mmap_lock(void); diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 8dfb3ada7d6..bfb7bc93ac7 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -53,7 +53,7 @@ void imb_refcounter_lock_exit(void) BLI_spin_end(&refcounter_spin); } -#ifdef WIN32 +#ifndef WIN32 static SpinLock mmap_spin; void imb_mmap_lock_init(void) diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index f0daa4543e1..50210650f05 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -23,13 +23,13 @@ */ #ifdef _WIN32 -# include "mmap_win.h" # include <io.h> # include <stddef.h> # include <sys/types.h> #endif #include "BLI_fileops.h" +#include "BLI_mmap.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -186,20 +186,19 @@ ImBuf *IMB_loadifffile( size = BLI_file_descriptor_size(file); imb_mmap_lock(); - mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); + BLI_mmap_file *mmap_file = BLI_mmap_open(file); imb_mmap_unlock(); - - if (mem == (unsigned char *)-1) { + if (mmap_file == NULL) { fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr); return NULL; } + mem = BLI_mmap_get_pointer(mmap_file); + ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr); imb_mmap_lock(); - if (munmap(mem, size)) { - fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr); - } + BLI_mmap_free(mmap_file); imb_mmap_unlock(); return ibuf; @@ -292,14 +291,15 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int size = BLI_file_descriptor_size(file); imb_mmap_lock(); - mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); + BLI_mmap_file *mmap_file = BLI_mmap_open(file); imb_mmap_unlock(); - - if (mem == (unsigned char *)-1) { + if (mmap_file == NULL) { fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename); return; } + mem = BLI_mmap_get_pointer(mmap_file); + const ImFileType *type = IMB_file_type_from_ibuf(ibuf); if (type != NULL) { if (type->load_tile != NULL) { @@ -308,9 +308,7 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int } imb_mmap_lock(); - if (munmap(mem, size)) { - fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename); - } + BLI_mmap_free(mmap_file); imb_mmap_unlock(); } diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 4b020019062..e373500a0ed 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -47,10 +47,13 @@ typedef struct BrushClone { char _pad[4]; } BrushClone; +#define GPENCIL_MIN_FILL_FAC 0.05f + typedef struct BrushGpencilSettings { /** Amount of smoothing to apply to newly created strokes. */ float draw_smoothfac; - char _pad2[4]; + /** Fill zoom factor */ + float fill_factor; /** Amount of alpha strength to apply to newly created strokes. */ float draw_strength; /** Amount of jitter to apply to newly created strokes. */ @@ -75,8 +78,8 @@ typedef struct BrushGpencilSettings { float fill_threshold; /** Number of pixel to consider the leak is too small (x 2). */ short fill_leak; - /** Fill zoom factor */ - short fill_factor; + char _pad2[2]; + int flag2; /** Number of simplify steps. */ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h index fdb77bfd196..399bf6f0a6d 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -152,6 +152,7 @@ .factor_thickness = 0.0f, \ .factor_uvs = 0.0f, \ .noise_scale = 0.0f, \ + .noise_offset = 0.0f, \ .step = 4, \ .layer_pass = 0, \ .seed = 1, \ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 9ac40495887..1f7283a1c70 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -107,6 +107,8 @@ typedef struct NoiseGpencilModifierData { float factor_uvs; /** Noise Frequency scaling */ float noise_scale; + float noise_offset; + char _pad[4]; /** How many frames before recalculate randoms. */ int step; /** Custom index for passes. */ diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 949b0bb5bf5..1dbfd547673 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -512,6 +512,11 @@ typedef struct bGPDlayer { int act_mask; char _pad2[4]; + /** Layer transforms. */ + float location[3], rotation[3], scale[3]; + float layer_mat[4][4], layer_invmat[4][4]; + char _pad3[4]; + bGPDlayer_Runtime runtime; } bGPDlayer; @@ -574,7 +579,9 @@ typedef struct bGPdata_Runtime { /** Temp stroke used for drawing. */ struct bGPDstroke *sbuffer_gps; - char _pad[2]; + /** Animation playing flag. */ + short playing; + /** Material index of the stroke. */ short matid; @@ -840,6 +847,8 @@ typedef enum eGP_DrawMode { ((flag & (GP_VERTEX_MASK_SELECTMODE_POINT | GP_VERTEX_MASK_SELECTMODE_STROKE | \ GP_VERTEX_MASK_SELECTMODE_SEGMENT))) +#define GPENCIL_PLAY_ON(gpd) ((gpd) && ((gpd)->runtime.playing == 1)) + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 03f5d3f8d47..a1ccf11b8e3 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -63,6 +63,9 @@ struct wmTimer; /* Defined in `buttons_intern.h`. */ typedef struct SpaceProperties_Runtime SpaceProperties_Runtime; +/* Defined in `node_intern.h`. */ +typedef struct SpaceNode_Runtime SpaceNode_Runtime; + /* -------------------------------------------------------------------- */ /** \name SpaceLink (Base) * \{ */ @@ -1518,19 +1521,17 @@ typedef struct SpaceNode { /** Context, no need to save in file? well... pinning... */ struct ID *id, *from; - /** Menunr: browse id block in header. */ + short flag; - char _pad1[2]; - /** Internal state variables. */ - float aspect; - char _pad2[4]; + + /** Direction for offsetting nodes on insertion. */ + char insert_ofs_dir; + char _pad1; /** Offset for drawing the backdrop. */ float xof, yof; /** Zoom for backdrop. */ float zoom; - /** Mouse pos for drawing socketless link and adding nodes. */ - float cursor[2]; /** * XXX nodetree pointer info is all in the path stack now, @@ -1541,33 +1542,25 @@ typedef struct SpaceNode { */ ListBase treepath; - struct bNodeTree *nodetree, *edittree; + /* The tree farthest down in the group heirarchy. */ + struct bNodeTree *edittree; + + struct bNodeTree *nodetree; /* tree type for the current node tree */ char tree_idname[64]; /** Treetype: as same nodetree->type. */ int treetype DNA_DEPRECATED; - char _pad3[4]; /** Texfrom object, world or brush. */ short texfrom; /** Shader from object or world. */ short shaderfrom; - /** Currently on 0/1, for auto compo. */ - short recalc; - - /** Direction for offsetting nodes on insertion. */ - char insert_ofs_dir; - char _pad4; - - /** Temporary data for modal linking operator. */ - ListBase linkdrag; - /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ - /** Temporary data for node insert offset (in UI called Auto-offset). */ - struct NodeInsertOfsData *iofsd; /** Grease-pencil data. */ struct bGPdata *gpd; + + SpaceNode_Runtime *runtime; } SpaceNode; /* SpaceNode.flag */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 5b6b706c83c..5a8bbdc08a1 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -141,7 +141,7 @@ typedef struct MovieTrackingTrack { /** Count of markers in track. */ int markersnr; /** Most recently used marker. */ - int last_marker; + int _pad; /** Markers in track. */ MovieTrackingMarker *markers; @@ -251,8 +251,6 @@ typedef struct MovieTrackingPlaneTrack { } MovieTrackingPlaneTrack; typedef struct MovieTrackingSettings { - int flag; - /* ** default tracker settings */ /** Model of the motion for this track. */ short default_motion_model; @@ -309,8 +307,6 @@ typedef struct MovieTrackingSettings { /* set object scale */ /** Distance between two bundles used for object scaling. */ float object_distance; - - char _pad3[4]; } MovieTrackingSettings; typedef struct MovieTrackingStabilization { @@ -526,11 +522,6 @@ typedef enum eTrackFrameMatch { TRACK_MATCH_PREVIOS_FRAME = 1, } eTrackFrameMatch; -/* MovieTrackingSettings->flag */ -enum { - TRACKING_SETTINGS_SHOW_DEFAULT_EXPANDED = (1 << 0), - TRACKING_SETTINGS_SHOW_EXTRA_EXPANDED = (1 << 1), -}; /* MovieTrackingSettings->motion_flag */ enum { diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index a7adaa7e258..5d1ed7b44a1 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -48,12 +48,6 @@ set(SRC ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c ) -if(WIN32 AND NOT UNIX) - list(APPEND SRC - ../../../../intern/guardedalloc/intern/mmap_win.c - ) -endif() - # SRC_DNA_INC is defined in the parent dir add_cc_flags_custom_test(makesdna) diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 72cdaecb2c3..94cfd8464ae 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -189,7 +189,6 @@ set(SRC ../../../../intern/guardedalloc/intern/mallocn.c ../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c - ../../../../intern/guardedalloc/intern/mmap_win.c # Needed for defaults. ../../../../release/datafiles/userdef/userdef_default.c diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index e9e00ff6f71..bec3db10905 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -4758,8 +4758,14 @@ static const char *cpp_classes = "class CollectionIterator {\n" "public:\n" " CollectionIterator() : iter(), t(iter.ptr), init(false) { iter.valid = false; }\n" + " CollectionIterator(const PointerRNA &ptr) : CollectionIterator() { this->begin(ptr); }\n" " ~CollectionIterator(void) { if (init) Tend(&iter); };\n" "\n" + " CollectionIterator(const CollectionIterator &other) = delete;\n" + " CollectionIterator(CollectionIterator &&other) = delete;\n" + " CollectionIterator &operator=(const CollectionIterator &other) = delete;\n" + " CollectionIterator &operator=(CollectionIterator &&other) = delete;\n" + "\n" " operator bool(void)\n" " { return iter.valid != 0; }\n" " const CollectionIterator<T, Tbegin, Tnext, Tend>& operator++() { Tnext(&iter); t = " @@ -4777,9 +4783,6 @@ static const char *cpp_classes = "true; }\n" "\n" "private:\n" - " const CollectionIterator<T, Tbegin, Tnext, Tend>& operator = " - "(const CollectionIterator<T, Tbegin, Tnext, Tend>& /*copy*/) {}\n" - "" " CollectionPropertyIterator iter;\n" " T t;\n" " bool init;\n" @@ -4794,6 +4797,8 @@ static const char *cpp_classes = "\n" " void begin(CollectionIterator<T, Tbegin, Tnext, Tend>& iter)\n" " { iter.begin(ptr); }\n" + " CollectionIterator<T, Tbegin, Tnext, Tend> begin()\n" + " { return CollectionIterator<T, Tbegin, Tnext, Tend>(ptr); }\n" " CollectionIterator<T, Tbegin, Tnext, Tend> end()\n" " { return CollectionIterator<T, Tbegin, Tnext, Tend>(); } /* test */ \n" "" diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 2af6c04147c..4f98c6e8e07 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1464,13 +1464,13 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* fill factor size */ - prop = RNA_def_property(srna, "fill_factor", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "fill_factor"); - RNA_def_property_range(prop, 1, 8); + prop = RNA_def_property(srna, "fill_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fill_factor"); + RNA_def_property_range(prop, GPENCIL_MIN_FILL_FAC, 8.0f); RNA_def_property_ui_text( prop, - "Resolution", - "Multiplier for fill resolution, higher resolution is more accurate but slower"); + "Precision", + "Factor for fill boundary accuracy, higher values are more accurate but slower"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 81e20003d8f..dec25c0143f 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -182,6 +182,16 @@ static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } +static void rna_GpencilLayerMatrix_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bGPDlayer *gpl = (bGPDlayer *)ptr->data; + + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + + rna_GPencil_update(bmain, scene, ptr); +} + static void rna_GPencil_curve_edit_mode_toggle(Main *bmain, Scene *scene, PointerRNA *ptr) { ToolSettings *ts = scene->toolsettings; @@ -2012,6 +2022,45 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Blend Mode", "Blend mode"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + /* Layer transforms. */ + prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "location"); + RNA_def_property_ui_text(prop, "Location", "Values for change location"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); + RNA_def_property_float_sdna(prop, NULL, "rotation"); + RNA_def_property_ui_text(prop, "Rotation", "Values for changes in rotation"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Scale", "Values for changes in scale"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + /* Layer matrix. */ + prop = RNA_def_property(srna, "matrix_layer", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "layer_mat"); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); + RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Matrix Layer", "Local Layer transformation matrix"); + + /* Layer inverse matrix. */ + prop = RNA_def_property(srna, "matrix_inverse_layer", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "layer_invmat"); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); + RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text( + prop, "Matrix Layer Inverse", "Local Layer transformation inverse matrix"); + /* Flags */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE); diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 89eb989a442..71d5a53adb2 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -489,7 +489,7 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "seed", PROP_INT, PROP_UNSIGNED); - RNA_def_property_ui_text(prop, "Seed", "Random seed"); + RNA_def_property_ui_text(prop, "Noise Seed", "Random seed"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "noise_scale", PROP_FLOAT, PROP_FACTOR); @@ -498,6 +498,13 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Noise Scale", "Scale the noise frequency"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "noise_offset", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "noise_offset"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3); + RNA_def_property_ui_text(prop, "Noise Offset", "Offset the noise along the strokes"); + 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_NOISE_CUSTOM_CURVE); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index c929e3ab1aa..826e1202efc 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1279,12 +1279,22 @@ static int rna_property_override_diff_propptr(Main *bmain, 0); if (is_id) { - /* For now, once we deal with nodetrees we'll want to get rid of that one. */ - // BLI_assert(no_ownership); + /* Owned IDs (the ones we want to actually compare in depth, instead of just comparing pointer + * values) should be always properly tagged as 'virtual' overrides. */ + ID *id = propptr_a->owner_id; + if (id != NULL && !ID_IS_OVERRIDE_LIBRARY(id)) { + id = propptr_b->owner_id; + if (id != NULL && !ID_IS_OVERRIDE_LIBRARY(id)) { + id = NULL; + } + } + + BLI_assert(no_ownership || id == NULL || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)); + UNUSED_VARS_NDEBUG(id); } if (override) { - if (no_ownership /* || is_id */ || is_null || is_type_diff || !is_valid_for_diffing) { + if (no_ownership || is_null || is_type_diff || !is_valid_for_diffing) { /* In case this pointer prop does not own its data (or one is NULL), do not compare structs! * This is a quite safe path to infinite loop, among other nasty issues. * Instead, just compare pointers themselves. */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 2ee84f70752..160d93dea58 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2279,6 +2279,20 @@ static bool rna_SpaceNodeEditor_tree_type_poll(void *Cv, bNodeTreeType *type) } } +static void rna_SpaceNodeEditor_cursor_location_get(PointerRNA *ptr, float value[2]) +{ + const SpaceNode *snode = (SpaceNode *)ptr->data; + + ED_node_cursor_location_get(snode, value); +} + +static void rna_SpaceNodeEditor_cursor_location_set(PointerRNA *ptr, const float value[2]) +{ + SpaceNode *snode = (SpaceNode *)ptr->data; + + ED_node_cursor_location_set(snode, value); +} + const EnumPropertyItem *RNA_enum_node_tree_types_itemf_impl(bContext *C, bool *r_free) { return rna_node_tree_type_itemf(C, rna_SpaceNodeEditor_tree_type_poll, r_free); @@ -2346,9 +2360,13 @@ static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode, { ARegion *region = CTX_wm_region(C); - UI_view2d_region_to_view(®ion->v2d, x, y, &snode->cursor[0], &snode->cursor[1]); - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + float cursor_location[2]; + + UI_view2d_region_to_view(®ion->v2d, x, y, &cursor_location[0], &cursor_location[1]); + cursor_location[0] /= UI_DPI_FAC; + cursor_location[1] /= UI_DPI_FAC; + + ED_node_cursor_location_set(snode, cursor_location); } static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, @@ -6815,11 +6833,13 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_enum_items(prop, backdrop_channels_items); RNA_def_property_ui_text(prop, "Display Channels", "Channels of the image to draw"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); - /* the mx/my "cursor" in the node editor is used only by operators to store the mouse position */ prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ); RNA_def_property_array(prop, 2); - RNA_def_property_float_sdna(prop, NULL, "cursor"); + RNA_def_property_float_funcs(prop, + "rna_SpaceNodeEditor_cursor_location_get", + "rna_SpaceNodeEditor_cursor_location_set", + NULL); RNA_def_property_ui_text(prop, "Cursor Location", "Location for adding new nodes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 1870c660efd..bcf75fb284f 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -976,22 +976,6 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_enum_items(prop, cleanup_items); RNA_def_property_ui_text(prop, "Action", "Cleanup action to execute"); - /* ** default tracker settings ** */ - prop = RNA_def_property(srna, "show_default_expanded", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_SETTINGS_SHOW_DEFAULT_EXPANDED); - RNA_def_property_ui_text( - prop, "Show Expanded", "Show default options expanded in the user interface"); - RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1); - - /* ** extra tracker settings ** */ - prop = RNA_def_property(srna, "show_extra_expanded", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_SETTINGS_SHOW_EXTRA_EXPANDED); - RNA_def_property_ui_text( - prop, "Show Expanded", "Show extra options expanded in the user interface"); - RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1); - /* solver settings */ prop = RNA_def_property(srna, "use_tripod_solver", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 5ef17aeddd1..6da2ecba6a7 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -221,18 +221,21 @@ class GeometryNodesEvaluator { const blender::nodes::DataTypeConversions &conversions_; const PersistentDataHandleMap &handle_map_; const Object *self_object_; + Depsgraph *depsgraph_; public: GeometryNodesEvaluator(const Map<const DOutputSocket *, GMutablePointer> &group_input_data, Vector<const DInputSocket *> group_outputs, blender::nodes::MultiFunctionByNode &mf_by_node, const PersistentDataHandleMap &handle_map, - const Object *self_object) + const Object *self_object, + Depsgraph *depsgraph) : group_outputs_(std::move(group_outputs)), mf_by_node_(mf_by_node), conversions_(blender::nodes::get_implicit_type_conversions()), handle_map_(handle_map), - self_object_(self_object) + self_object_(self_object), + depsgraph_(depsgraph) { for (auto item : group_input_data.items()) { this->forward_to_inputs(*item.key, item.value); @@ -306,7 +309,8 @@ class GeometryNodesEvaluator { /* Execute the node. */ GValueMap<StringRef> node_outputs_map{allocator_}; - GeoNodeExecParams params{bnode, node_inputs_map, node_outputs_map, handle_map_, self_object_}; + GeoNodeExecParams params{ + bnode, node_inputs_map, node_outputs_map, handle_map_, self_object_, depsgraph_}; this->execute_node(node, params); /* Forward computed outputs to linked input sockets. */ @@ -926,7 +930,7 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree, group_outputs.append(&socket_to_compute); GeometryNodesEvaluator evaluator{ - group_inputs, group_outputs, mf_by_node, handle_map, ctx->object}; + group_inputs, group_outputs, mf_by_node, handle_map, ctx->object, ctx->depsgraph}; Vector<GMutablePointer> results = evaluator.execute(); BLI_assert(results.size() == 1); GMutablePointer result = results[0]; diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index f278d6b4107..3820c0f0009 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -24,6 +24,8 @@ #include "DNA_node_types.h" +struct Depsgraph; + namespace blender::nodes { using bke::BooleanReadAttribute; @@ -54,18 +56,21 @@ class GeoNodeExecParams { GValueMap<StringRef> &output_values_; const PersistentDataHandleMap &handle_map_; const Object *self_object_; + Depsgraph *depsgraph_; public: GeoNodeExecParams(const bNode &node, GValueMap<StringRef> &input_values, GValueMap<StringRef> &output_values, const PersistentDataHandleMap &handle_map, - const Object *self_object) + const Object *self_object, + Depsgraph *depsgraph) : node_(node), input_values_(input_values), output_values_(output_values), handle_map_(handle_map), - self_object_(self_object) + self_object_(self_object), + depsgraph_(depsgraph) { } @@ -163,6 +168,11 @@ class GeoNodeExecParams { return self_object_; } + Depsgraph *depsgraph() const + { + return depsgraph_; + } + /** * Creates a read-only attribute based on node inputs. The method automatically detects which * input with the given name is available. diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc index 0e7bb25e659..3ee7df7fe72 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc @@ -50,8 +50,7 @@ static void geo_node_attribute_randomize_update(bNodeTree *UNUSED(ntree), bNode bNodeSocket *sock_min_float = sock_max_vector->next; bNodeSocket *sock_max_float = sock_min_float->next; - const int data_type = node->custom1; - + const CustomDataType data_type = static_cast<CustomDataType>(node->custom1); nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3); nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3); nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT); @@ -86,8 +85,11 @@ static void randomize_attribute_bool(BooleanWriteAttribute attribute, attribute.apply_span(); } -static void randomize_attribute_float( - FloatWriteAttribute attribute, float min, float max, Span<uint32_t> hashes, const int seed) +static void randomize_attribute_float(FloatWriteAttribute attribute, + const float min, + const float max, + Span<uint32_t> hashes, + const int seed) { MutableSpan<float> attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { @@ -97,8 +99,11 @@ static void randomize_attribute_float( attribute.apply_span(); } -static void randomize_attribute_float3( - Float3WriteAttribute attribute, float3 min, float3 max, Span<uint32_t> hashes, const int seed) +static void randomize_attribute_float3(Float3WriteAttribute attribute, + const float3 min, + const float3 max, + Span<uint32_t> hashes, + const int seed) { MutableSpan<float3> attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { @@ -129,8 +134,7 @@ Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &compo } else { /* If there is no "id" attribute for per-point variation, just create it here. */ - RandomNumberGenerator rng; - rng.seed(0); + RandomNumberGenerator rng(0); for (const int i : hashes.index_range()) { hashes[i] = rng.get_uint32(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index 2f1aa276532..eaf13b94eb9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -26,6 +26,7 @@ #include "DNA_meshdata_types.h" #include "DNA_pointcloud_types.h" +#include "BKE_attribute_math.hh" #include "BKE_bvhutils.h" #include "BKE_deform.h" #include "BKE_mesh.h" @@ -217,13 +218,141 @@ BLI_NOINLINE static void eliminate_points_based_on_mask(Span<bool> elimination_m } } -BLI_NOINLINE static void compute_remaining_point_data(const Mesh &mesh, - Span<float3> bary_coords, - Span<int> looptri_indices, - MutableSpan<float3> r_normals, - MutableSpan<int> r_ids, - MutableSpan<float3> r_rotations) +template<typename T> +BLI_NOINLINE static void interpolate_attribute_point(const Mesh &mesh, + const Span<float3> bary_coords, + const Span<int> looptri_indices, + const Span<T> data_in, + MutableSpan<T> data_out) { + BLI_assert(data_in.size() == mesh.totvert); + Span<MLoopTri> looptris = get_mesh_looptris(mesh); + + for (const int i : bary_coords.index_range()) { + const int looptri_index = looptri_indices[i]; + const MLoopTri &looptri = looptris[looptri_index]; + const float3 &bary_coord = bary_coords[i]; + + const int v0_index = mesh.mloop[looptri.tri[0]].v; + const int v1_index = mesh.mloop[looptri.tri[1]].v; + const int v2_index = mesh.mloop[looptri.tri[2]].v; + + const T &v0 = data_in[v0_index]; + const T &v1 = data_in[v1_index]; + const T &v2 = data_in[v2_index]; + + const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2); + data_out[i] = interpolated_value; + } +} + +template<typename T> +BLI_NOINLINE static void interpolate_attribute_corner(const Mesh &mesh, + const Span<float3> bary_coords, + const Span<int> looptri_indices, + const Span<T> data_in, + MutableSpan<T> data_out) +{ + BLI_assert(data_in.size() == mesh.totloop); + Span<MLoopTri> looptris = get_mesh_looptris(mesh); + + for (const int i : bary_coords.index_range()) { + const int looptri_index = looptri_indices[i]; + const MLoopTri &looptri = looptris[looptri_index]; + const float3 &bary_coord = bary_coords[i]; + + const int loop_index_0 = looptri.tri[0]; + const int loop_index_1 = looptri.tri[1]; + const int loop_index_2 = looptri.tri[2]; + + const T &v0 = data_in[loop_index_0]; + const T &v1 = data_in[loop_index_1]; + const T &v2 = data_in[loop_index_2]; + + const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2); + data_out[i] = interpolated_value; + } +} + +BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh, + Span<float3> bary_coords, + Span<int> looptri_indices, + const StringRef attribute_name, + const ReadAttribute &attribute_in, + GeometryComponent &component) +{ + const CustomDataType data_type = attribute_in.custom_data_type(); + const AttributeDomain domain = attribute_in.domain(); + if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) { + /* Not supported currently. */ + return; + } + + OutputAttributePtr attribute_out = component.attribute_try_get_for_output( + attribute_name, ATTR_DOMAIN_POINT, data_type); + if (!attribute_out) { + return; + } + + attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + using T = decltype(dummy); + + Span data_in = attribute_in.get_span<T>(); + MutableSpan data_out = attribute_out->get_span_for_write_only<T>(); + + switch (domain) { + case ATTR_DOMAIN_POINT: { + interpolate_attribute_point<T>(mesh, bary_coords, looptri_indices, data_in, data_out); + break; + } + case ATTR_DOMAIN_CORNER: { + interpolate_attribute_corner<T>(mesh, bary_coords, looptri_indices, data_in, data_out); + break; + } + default: { + BLI_assert(false); + break; + } + } + }); + attribute_out.apply_span_and_save(); +} + +BLI_NOINLINE static void interpolate_existing_attributes(const MeshComponent &mesh_component, + GeometryComponent &component, + Span<float3> bary_coords, + Span<int> looptri_indices) +{ + const Mesh &mesh = *mesh_component.get_for_read(); + + Set<std::string> attribute_names = mesh_component.attribute_names(); + for (StringRefNull attribute_name : attribute_names) { + if (ELEM(attribute_name, "position", "normal", "id")) { + continue; + } + + ReadAttributePtr attribute_in = mesh_component.attribute_try_get_for_read(attribute_name); + interpolate_attribute( + mesh, bary_coords, looptri_indices, attribute_name, *attribute_in, component); + } +} + +BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh, + GeometryComponent &component, + Span<float3> bary_coords, + Span<int> looptri_indices) +{ + OutputAttributePtr id_attribute = component.attribute_try_get_for_output( + "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); + OutputAttributePtr normal_attribute = component.attribute_try_get_for_output( + "normal", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); + OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output( + "rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); + + MutableSpan<int> ids = id_attribute->get_span_for_write_only<int>(); + MutableSpan<float3> normals = normal_attribute->get_span_for_write_only<float3>(); + MutableSpan<float3> rotations = rotation_attribute->get_span_for_write_only<float3>(); + Span<MLoopTri> looptris = get_mesh_looptris(mesh); for (const int i : bary_coords.index_range()) { const int looptri_index = looptri_indices[i]; @@ -237,10 +366,24 @@ BLI_NOINLINE static void compute_remaining_point_data(const Mesh &mesh, const float3 v1_pos = mesh.mvert[v1_index].co; const float3 v2_pos = mesh.mvert[v2_index].co; - r_ids[i] = (int)(bary_coord.hash()) + looptri_index; - normal_tri_v3(r_normals[i], v0_pos, v1_pos, v2_pos); - r_rotations[i] = normal_to_euler_rotation(r_normals[i]); + ids[i] = (int)(bary_coord.hash()) + looptri_index; + normal_tri_v3(normals[i], v0_pos, v1_pos, v2_pos); + rotations[i] = normal_to_euler_rotation(normals[i]); } + + id_attribute.apply_span_and_save(); + normal_attribute.apply_span_and_save(); + rotation_attribute.apply_span_and_save(); +} + +BLI_NOINLINE static void add_remaining_point_attributes(const MeshComponent &mesh_component, + GeometryComponent &component, + Span<float3> bary_coords, + Span<int> looptri_indices) +{ + interpolate_existing_attributes(mesh_component, component, bary_coords, looptri_indices); + compute_special_attributes( + *mesh_component.get_for_read(), component, bary_coords, looptri_indices); } static void sample_mesh_surface_with_minimum_distance(const Mesh &mesh, @@ -315,11 +458,6 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) break; } const int tot_points = positions.size(); - Array<float3> normals(tot_points); - Array<int> stable_ids(tot_points); - Array<float3> rotations(tot_points); - compute_remaining_point_data( - *mesh_in, bary_coords, looptri_indices, normals, stable_ids, rotations); PointCloud *pointcloud = BKE_pointcloud_new_nomain(tot_points); memcpy(pointcloud->co, positions.data(), sizeof(float3) * tot_points); @@ -332,29 +470,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) geometry_set_out.get_component_for_write<PointCloudComponent>(); point_component.replace(pointcloud); - { - OutputAttributePtr stable_id_attribute = point_component.attribute_try_get_for_output( - "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); - MutableSpan<int> stable_ids_span = stable_id_attribute->get_span<int>(); - stable_ids_span.copy_from(stable_ids); - stable_id_attribute.apply_span_and_save(); - } - - { - OutputAttributePtr normals_attribute = point_component.attribute_try_get_for_output( - "normal", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); - MutableSpan<float3> normals_span = normals_attribute->get_span<float3>(); - normals_span.copy_from(normals); - normals_attribute.apply_span_and_save(); - } - - { - OutputAttributePtr rotations_attribute = point_component.attribute_try_get_for_output( - "rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); - MutableSpan<float3> rotations_span = rotations_attribute->get_span<float3>(); - rotations_span.copy_from(rotations); - rotations_attribute.apply_span_and_save(); - } + add_remaining_point_attributes(mesh_component, point_component, bary_coords, looptri_indices); params.set_output("Geometry", std::move(geometry_set_out)); } diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc index 2e4196af156..33192648d93 100644 --- a/source/blender/nodes/intern/node_tree_multi_function.cc +++ b/source/blender/nodes/intern/node_tree_multi_function.cc @@ -19,6 +19,7 @@ #include "FN_multi_function_network_evaluation.hh" #include "BLI_color.hh" +#include "BLI_float2.hh" #include "BLI_float3.hh" namespace blender::nodes { @@ -191,27 +192,57 @@ static void add_implicit_conversion(DataTypeConversions &conversions, static DataTypeConversions create_implicit_conversions() { DataTypeConversions conversions; - add_implicit_conversion<float, int32_t>(conversions); + add_implicit_conversion<float, float2>(conversions); add_implicit_conversion<float, float3>(conversions); - add_implicit_conversion<int32_t, float>(conversions); + add_implicit_conversion<float, int32_t>(conversions); add_implicit_conversion<float, bool>(conversions); - add_implicit_conversion<bool, float>(conversions); - add_implicit_conversion<float3, float>( - conversions, "Vector Length", [](float3 a) { return a.length(); }); - add_implicit_conversion<int32_t, float3>( - conversions, "int32 to float3", [](int32_t a) { return float3((float)a); }); - add_implicit_conversion<float3, Color4f>( - conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); }); - add_implicit_conversion<Color4f, float3>( - conversions, "Color4f to float3", [](Color4f a) { return float3(a.r, a.g, a.b); }); add_implicit_conversion<float, Color4f>( conversions, "float to Color4f", [](float a) { return Color4f(a, a, a, 1.0f); }); - add_implicit_conversion<Color4f, float>( - conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); }); + + add_implicit_conversion<float2, float3>(conversions); + add_implicit_conversion<float2, float>( + conversions, "float2 to float", [](float2 a) { return a.length(); }); + add_implicit_conversion<float2, int32_t>( + conversions, "float2 to int32_t", [](float2 a) { return (int32_t)a.length(); }); + add_implicit_conversion<float2, bool>( + conversions, "float2 to bool", [](float2 a) { return a.length_squared() == 0.0f; }); + add_implicit_conversion<float2, Color4f>( + conversions, "float2 to Color4f", [](float2 a) { return Color4f(a.x, a.y, 0.0f, 1.0f); }); + add_implicit_conversion<float3, bool>( conversions, "float3 to boolean", [](float3 a) { return a.length_squared() == 0.0f; }); + add_implicit_conversion<float3, float>( + conversions, "Vector Length", [](float3 a) { return a.length(); }); + add_implicit_conversion<float3, int32_t>( + conversions, "float3 to int32_t", [](float3 a) { return (int)a.length(); }); + add_implicit_conversion<float3, float2>(conversions); + add_implicit_conversion<float3, Color4f>( + conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); }); + + add_implicit_conversion<int32_t, bool>(conversions); + add_implicit_conversion<int32_t, float>(conversions); + add_implicit_conversion<int32_t, float2>( + conversions, "int32 to float2", [](int32_t a) { return float2((float)a); }); + add_implicit_conversion<int32_t, float3>( + conversions, "int32 to float3", [](int32_t a) { return float3((float)a); }); + + add_implicit_conversion<bool, float>(conversions); + add_implicit_conversion<bool, int32_t>(conversions); + add_implicit_conversion<bool, float2>( + conversions, "boolean to float2", [](bool a) { return (a) ? float2(1.0f) : float2(0.0f); }); add_implicit_conversion<bool, float3>( conversions, "boolean to float3", [](bool a) { return (a) ? float3(1.0f) : float3(0.0f); }); + add_implicit_conversion<bool, Color4f>(conversions, "boolean to Color4f", [](bool a) { + return (a) ? Color4f(1.0f, 1.0f, 1.0f, 1.0f) : Color4f(0.0f, 0.0f, 0.0f, 1.0f); + }); + + add_implicit_conversion<Color4f, float>( + conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); }); + add_implicit_conversion<Color4f, float2>( + conversions, "Color4f to float2", [](Color4f a) { return float2(a.r, a.g); }); + add_implicit_conversion<Color4f, float3>( + conversions, "Color4f to float3", [](Color4f a) { return float3(a.r, a.g, a.b); }); + return conversions; } diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 38122c45ef1..22c7a394906 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -1079,7 +1079,12 @@ PyDoc_STRVAR( " :arg cage: Get the mesh as a deformed cage.\n" " :type cage: boolean\n" " :arg face_normals: Calculate face normals.\n" - " :type face_normals: boolean\n"); + " :type face_normals: boolean\n" + "\n" + " .. deprecated:: 2.93\n" + "\n" + " The deform parameter is deprecated, assumed to be True, and will be removed in version " + "3.0.\n"); static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject *kw) { static const char *kwlist[] = {"object", "depsgraph", "deform", "cage", "face_normals", NULL}; @@ -1120,45 +1125,36 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject return NULL; } + if (use_deform == false) { + PyErr_WarnEx(PyExc_FutureWarning, + "from_object(...): the deform parameter is deprecated, assumed to be True, and " + "will be removed in version 3.0", + 1); + } + const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER; scene_eval = DEG_get_evaluated_scene(depsgraph); ob_eval = DEG_get_evaluated_object(depsgraph, ob); bool need_free = false; /* Write the display mesh into the dummy mesh */ - if (use_deform) { - if (use_render) { - if (use_cage) { - PyErr_SetString(PyExc_ValueError, - "from_object(...): cage arg is unsupported when dependency graph " - "evaluation mode is RENDER"); - return NULL; - } - - me_eval = BKE_mesh_new_from_object(depsgraph, ob_eval, true); - need_free = true; - } - else { - if (use_cage) { - me_eval = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &data_masks); - } - else { - me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &data_masks); - } - } - } - else { - /* !use_deform */ + if (use_render) { if (use_cage) { PyErr_SetString(PyExc_ValueError, - "from_object(...): cage arg is unsupported when deform=False"); + "from_object(...): cage arg is unsupported when dependency graph " + "evaluation mode is RENDER"); return NULL; } - if (use_render) { - me_eval = mesh_create_eval_no_deform_render(depsgraph, scene_eval, ob, &data_masks); + + me_eval = BKE_mesh_new_from_object(depsgraph, ob_eval, true); + need_free = true; + } + else { + if (use_cage) { + me_eval = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &data_masks); } else { - me_eval = mesh_create_eval_no_deform(depsgraph, scene_eval, ob, &data_masks); + me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &data_masks); } } diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h index 70ddae4d724..cf1a7628267 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h @@ -301,7 +301,7 @@ void WM_gizmomap_draw(struct wmGizmoMap *gzmap, void WM_gizmomap_add_handlers(struct ARegion *region, struct wmGizmoMap *gzmap); bool WM_gizmomap_select_all(struct bContext *C, struct wmGizmoMap *gzmap, const int action); bool WM_gizmomap_cursor_set(const struct wmGizmoMap *gzmap, struct wmWindow *win); -void WM_gizmomap_message_subscribe(struct bContext *C, +void WM_gizmomap_message_subscribe(const struct bContext *C, struct wmGizmoMap *gzmap, struct ARegion *region, struct wmMsgBus *mbus); diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index 479768c3536..12c6eb46c12 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -1156,7 +1156,7 @@ ListBase *wm_gizmomap_groups_get(wmGizmoMap *gzmap) return &gzmap->groups; } -void WM_gizmomap_message_subscribe(bContext *C, +void WM_gizmomap_message_subscribe(const bContext *C, wmGizmoMap *gzmap, ARegion *region, struct wmMsgBus *mbus) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 859336d0338..d08051dd5fb 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -543,13 +543,31 @@ void wm_event_do_notifiers(bContext *C) ED_screen_do_listen(C, note); LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { - ED_region_do_listen(win, NULL, region, note, scene); + wmRegionListenerParams region_params = { + .area = NULL, + .region = region, + .scene = scene, + .notifier = note, + }; + ED_region_do_listen(®ion_params); } ED_screen_areas_iter (win, screen, area) { - ED_area_do_listen(win, area, note, scene); + wmSpaceTypeListenerParams area_params = { + .window = win, + .area = area, + .notifier = note, + .scene = scene, + }; + ED_area_do_listen(&area_params); LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - ED_region_do_listen(win, area, region, note, scene); + wmRegionListenerParams region_params = { + .area = area, + .region = region, + .scene = scene, + .notifier = note, + }; + ED_region_do_listen(®ion_params); } } } |